Added Streamlit Dashboard
Browse files
app.py
CHANGED
@@ -1,33 +1,68 @@
|
|
1 |
import streamlit as st
|
|
|
2 |
import openai
|
3 |
import subprocess
|
4 |
import re
|
5 |
import os
|
6 |
import pandas as pd
|
7 |
-
|
|
|
8 |
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
with open("code.py", "w") as file:
|
18 |
file.write(code)
|
19 |
|
|
|
|
|
|
|
20 |
try:
|
21 |
-
|
22 |
-
["
|
|
|
|
|
|
|
23 |
)
|
24 |
-
output = "Output Generated Successfully" + "\n" + result.stdout
|
25 |
-
except subprocess.CalledProcessError as e:
|
26 |
-
output = f"An error occurred while running the code:\nSTDOUT:\n{e.stdout}\nSTDERR:\n{e.stderr}"
|
27 |
-
except Exception as e:
|
28 |
-
output = f"An unexpected error occurred: {str(e)}"
|
29 |
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
|
32 |
|
33 |
class Agent:
|
@@ -37,7 +72,7 @@ class Agent:
|
|
37 |
self.known_actions = known_actions if known_actions is not None else {}
|
38 |
|
39 |
self.client = openai.OpenAI(
|
40 |
-
api_key=os.environ.get('TOGETHER_API_KEY'),
|
41 |
base_url="https://api.together.xyz/v1",
|
42 |
)
|
43 |
self.messages.append({"role": "system", "content": self.system})
|
@@ -66,6 +101,7 @@ class Agent:
|
|
66 |
i += 1
|
67 |
result = self(next_prompt)
|
68 |
st.session_state.logs += f"Assistant: {result}\n"
|
|
|
69 |
action_re = re.search(r"Action: (\w+): (.*)", result, re.DOTALL)
|
70 |
if action_re:
|
71 |
action = action_re.group(1)
|
@@ -73,8 +109,11 @@ class Agent:
|
|
73 |
st.session_state.logs += (
|
74 |
f"Action: {action}\nAction Input: {action_input}\n"
|
75 |
)
|
|
|
76 |
if action not in self.known_actions:
|
77 |
-
|
|
|
|
|
78 |
st.session_state.logs += (
|
79 |
f" ------------------------\n running {action} {action_input}\n"
|
80 |
)
|
@@ -82,23 +121,21 @@ class Agent:
|
|
82 |
st.session_state.logs += f"Observation: {observation}\n"
|
83 |
next_prompt = f"Observation: {observation}"
|
84 |
else:
|
|
|
85 |
return
|
86 |
|
87 |
|
88 |
known_actions = {"runcode": runcode}
|
89 |
prompt = f"""
|
90 |
-
You are an expert in
|
91 |
At the end of the loop you output an Answer
|
92 |
Use Thought to describe your thoughts about the question you have been asked.
|
93 |
Use Action to run one of the actions available to you - then return PAUSE.
|
94 |
Observation will be the result of running those actions.
|
95 |
|
96 |
-
|
97 |
-
for Graphing library use Plotly and save the plot as graph.html
|
98 |
-
Always save generated plot as 'graph.html'
|
99 |
Always return just code no need of ```
|
100 |
|
101 |
-
Your Task is help user get result of query about below dataset,Decide based on user query to make
|
102 |
Here is the metadata of the dataset and name of dataset is Financial_Sample.csv:
|
103 |
|
104 |
Columns: {metadata['columns']}
|
@@ -115,64 +152,87 @@ Action : action_name: input_to_action
|
|
115 |
if input_to_action is code then don't use ``` just write code
|
116 |
Example session:
|
117 |
|
118 |
-
Question:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
|
120 |
-
|
|
|
|
|
|
|
121 |
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
PAUSE
|
128 |
|
129 |
Observation : understand the output based its stdout and take necessary steps.
|
130 |
|
131 |
-
Answer: Final Answer for User Request if its
|
132 |
""".strip()
|
133 |
|
134 |
-
|
135 |
-
bot = Agent(system_prompt=prompt, known_actions=known_actions)
|
136 |
|
137 |
st.set_page_config(layout="wide")
|
138 |
st.title("Customer Data Analysis")
|
139 |
|
140 |
-
|
|
|
141 |
|
142 |
-
st.
|
143 |
-
st.
|
144 |
-
st.sidebar.write("Dtypes:", metadata["dtypes"])
|
145 |
-
st.sidebar.write("Shape:", metadata["shape"])
|
146 |
-
st.sidebar.write("Sample Data:")
|
147 |
-
st.sidebar.write(df.head())
|
148 |
|
149 |
-
|
|
|
|
|
150 |
|
151 |
-
if "
|
|
|
|
|
|
|
152 |
st.session_state.logs = ""
|
|
|
|
|
153 |
|
154 |
-
|
155 |
-
if st.button("Submit"):
|
156 |
-
if not query:
|
157 |
-
st.error("Please enter a query.")
|
158 |
-
else:
|
159 |
-
if "graph.html" in os.listdir():
|
160 |
-
os.remove("graph.html")
|
161 |
-
st.session_state.logs = ""
|
162 |
-
with st.spinner("Generating response..."):
|
163 |
-
bot.query(query)
|
164 |
-
answer_match = re.search(r"Answer:", st.session_state.logs)
|
165 |
-
if answer_match:
|
166 |
-
answer_end_index = answer_match.end()
|
167 |
-
subsequent_text = st.session_state.logs[answer_end_index:].strip()
|
168 |
-
st.success(subsequent_text)
|
169 |
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
st.components.v1.html(open("graph.html", "r").read(), height=600)
|
174 |
else:
|
175 |
-
st.
|
176 |
-
|
177 |
-
with st.
|
178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
+
import streamlit.components.v1 as components
|
3 |
import openai
|
4 |
import subprocess
|
5 |
import re
|
6 |
import os
|
7 |
import pandas as pd
|
8 |
+
import socket
|
9 |
+
import time
|
10 |
|
11 |
+
csv_name = "./Financial_Sample.csv"
|
12 |
+
try:
|
13 |
+
df = pd.read_csv(csv_name)
|
14 |
+
metadata = {
|
15 |
+
"columns": df.columns.tolist(),
|
16 |
+
"dtypes": df.dtypes.apply(lambda x: x.name).to_dict(),
|
17 |
+
"shape": df.shape,
|
18 |
+
}
|
19 |
+
except Exception as e:
|
20 |
+
st.error(f"Error loading CSV file: {e}")
|
21 |
+
st.stop()
|
22 |
|
23 |
+
|
24 |
+
def is_port_in_use(port: int) -> bool:
|
25 |
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
26 |
+
return s.connect_ex(("localhost", port)) == 0
|
27 |
+
|
28 |
+
|
29 |
+
def find_free_port(starting_port: int) -> int:
|
30 |
+
port = starting_port
|
31 |
+
while is_port_in_use(port):
|
32 |
+
port += 1
|
33 |
+
return port
|
34 |
+
|
35 |
+
|
36 |
+
def runcode(code: str) -> tuple:
|
37 |
with open("code.py", "w") as file:
|
38 |
file.write(code)
|
39 |
|
40 |
+
starting_port = 8501
|
41 |
+
free_port = find_free_port(starting_port)
|
42 |
+
|
43 |
try:
|
44 |
+
process = subprocess.Popen(
|
45 |
+
["streamlit", "run", "code.py", "--server.port", str(free_port)],
|
46 |
+
stdout=subprocess.PIPE,
|
47 |
+
stderr=subprocess.PIPE,
|
48 |
+
text=True,
|
49 |
)
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
+
time.sleep(5)
|
52 |
+
|
53 |
+
if process.poll() is None:
|
54 |
+
return (
|
55 |
+
free_port,
|
56 |
+
f"Streamlit process started successfully on port {free_port}",
|
57 |
+
)
|
58 |
+
else:
|
59 |
+
stdout, stderr = process.communicate()
|
60 |
+
return (None, f"Streamlit process exited unexpectedly. Error: {stderr}")
|
61 |
+
|
62 |
+
except FileNotFoundError:
|
63 |
+
return (None, "Error: Streamlit is not installed or not in PATH")
|
64 |
+
except Exception as e:
|
65 |
+
return (None, f"An unexpected error occurred: {str(e)}")
|
66 |
|
67 |
|
68 |
class Agent:
|
|
|
72 |
self.known_actions = known_actions if known_actions is not None else {}
|
73 |
|
74 |
self.client = openai.OpenAI(
|
75 |
+
api_key= os.environ.get('TOGETHER_API_KEY'),
|
76 |
base_url="https://api.together.xyz/v1",
|
77 |
)
|
78 |
self.messages.append({"role": "system", "content": self.system})
|
|
|
101 |
i += 1
|
102 |
result = self(next_prompt)
|
103 |
st.session_state.logs += f"Assistant: {result}\n"
|
104 |
+
|
105 |
action_re = re.search(r"Action: (\w+): (.*)", result, re.DOTALL)
|
106 |
if action_re:
|
107 |
action = action_re.group(1)
|
|
|
109 |
st.session_state.logs += (
|
110 |
f"Action: {action}\nAction Input: {action_input}\n"
|
111 |
)
|
112 |
+
|
113 |
if action not in self.known_actions:
|
114 |
+
error_msg = f"Unknown action: {action}: {action_input}"
|
115 |
+
raise Exception(error_msg)
|
116 |
+
|
117 |
st.session_state.logs += (
|
118 |
f" ------------------------\n running {action} {action_input}\n"
|
119 |
)
|
|
|
121 |
st.session_state.logs += f"Observation: {observation}\n"
|
122 |
next_prompt = f"Observation: {observation}"
|
123 |
else:
|
124 |
+
print("No action found, ending query")
|
125 |
return
|
126 |
|
127 |
|
128 |
known_actions = {"runcode": runcode}
|
129 |
prompt = f"""
|
130 |
+
You are an expert in creating advanced Interactive Streamlit Dashboards in python based on user Query and you run in a loop of Thought, Action, PAUSE, Observation.
|
131 |
At the end of the loop you output an Answer
|
132 |
Use Thought to describe your thoughts about the question you have been asked.
|
133 |
Use Action to run one of the actions available to you - then return PAUSE.
|
134 |
Observation will be the result of running those actions.
|
135 |
|
|
|
|
|
|
|
136 |
Always return just code no need of ```
|
137 |
|
138 |
+
Your Task is help user get result of query about below dataset,Decide based on user query to make Dashboard or Just Textual Answer.
|
139 |
Here is the metadata of the dataset and name of dataset is Financial_Sample.csv:
|
140 |
|
141 |
Columns: {metadata['columns']}
|
|
|
152 |
if input_to_action is code then don't use ``` just write code
|
153 |
Example session:
|
154 |
|
155 |
+
Question: Give me a dashboard to visualize the people height and age
|
156 |
+
|
157 |
+
Thought: I need to run a create a dashboard where i can visualize the Subscriptions and Country data
|
158 |
+
|
159 |
+
Action: runcode: import streamlit as st
|
160 |
+
import pandas as pd
|
161 |
+
import plotly.express as px
|
162 |
+
from datetime import datetime
|
163 |
|
164 |
+
@st.cache_data
|
165 |
+
def load_data():
|
166 |
+
df = pd.read_csv(f{csv_name})
|
167 |
+
return df
|
168 |
|
169 |
+
df = load_data()
|
170 |
+
st.title("Height vs Age Visualization")
|
171 |
+
fig = px.scatter(df, x='age', y='height', opacity=0.6)
|
172 |
+
fig.update_layout(
|
173 |
+
xaxis_title="Age (years)",
|
174 |
+
yaxis_title="Height (cm)",
|
175 |
+
title="Height vs Age Scatter Plot"
|
176 |
+
)
|
177 |
+
|
178 |
+
st.plotly_chart(fig, use_container_width=True)
|
179 |
|
180 |
PAUSE
|
181 |
|
182 |
Observation : understand the output based its stdout and take necessary steps.
|
183 |
|
184 |
+
Answer: Final Answer for User Request if its Dashboard send "Please visit link to view dashboard"or Textual Answer "Your Interpretation of Answer"
|
185 |
""".strip()
|
186 |
|
187 |
+
if "bot" not in st.session_state:
|
188 |
+
st.session_state.bot = Agent(system_prompt=prompt, known_actions=known_actions)
|
189 |
|
190 |
st.set_page_config(layout="wide")
|
191 |
st.title("Customer Data Analysis")
|
192 |
|
193 |
+
if "logs" not in st.session_state:
|
194 |
+
st.session_state.logs = ""
|
195 |
|
196 |
+
if "messages" not in st.session_state:
|
197 |
+
st.session_state.messages = []
|
|
|
|
|
|
|
|
|
198 |
|
199 |
+
for message in st.session_state.messages:
|
200 |
+
with st.chat_message(message["role"]):
|
201 |
+
st.markdown(message["content"])
|
202 |
|
203 |
+
if query := st.chat_input("Enter your query about the dataset"):
|
204 |
+
st.session_state.messages.append({"role": "user", "content": query})
|
205 |
+
with st.chat_message("user"):
|
206 |
+
st.markdown(query)
|
207 |
st.session_state.logs = ""
|
208 |
+
with st.spinner("Generating response..."):
|
209 |
+
st.session_state.bot.query(query)
|
210 |
|
211 |
+
answer_match = re.search(r"Answer:", st.session_state.logs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
|
213 |
+
if answer_match:
|
214 |
+
answer_end_index = answer_match.end()
|
215 |
+
subsequent_text = st.session_state.logs[answer_end_index:].strip()
|
|
|
216 |
else:
|
217 |
+
st.warning("No answer found in the generated response.")
|
218 |
+
|
219 |
+
with st.chat_message("assistant"):
|
220 |
+
url_pattern = r"(https?://[^\s]+)"
|
221 |
+
url = re.findall(url_pattern, subsequent_text)
|
222 |
+
if url:
|
223 |
+
components.iframe(src=url[0], width=800, height=600)
|
224 |
+
st.write(subsequent_text)
|
225 |
+
else:
|
226 |
+
st.success(subsequent_text)
|
227 |
+
st.session_state.messages.append({"role": "assistant", "content": subsequent_text})
|
228 |
+
|
229 |
+
with st.sidebar:
|
230 |
+
st.title("Dataset Metadata")
|
231 |
+
st.write("Columns:", metadata["columns"])
|
232 |
+
st.write("Dtypes:", metadata["dtypes"])
|
233 |
+
st.write("Shape:", metadata["shape"])
|
234 |
+
st.write("Sample Data:")
|
235 |
+
st.write(df.head())
|
236 |
+
|
237 |
+
with st.expander("Logs"):
|
238 |
+
st.code(st.session_state.logs)
|