-
Notifications
You must be signed in to change notification settings - Fork 27
/
app.py
143 lines (117 loc) · 5.24 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""
app.py
"""
import os
import streamlit as st
from openai import OpenAI
from openai.types.beta.thread_create_params import CodeInterpreterToolParam
from utils import (
delete_files,
delete_thread,
EventHandler,
initialise_session_state,
moderation_endpoint,
render_custom_css,
render_download_files,
retrieve_messages_from_thread,
retrieve_assistant_created_files
)
# Get secrets
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", st.secrets["OPENAI_API_KEY"])
ASSISTANT_ID = os.environ.get("OPENAI_ASSISTANT_ID", st.secrets["OPENAI_ASSISTANT_ID"])
# Initialise the OpenAI client, and retrieve the assistant
client = OpenAI(api_key=OPENAI_API_KEY)
assistant = client.beta.assistants.retrieve(ASSISTANT_ID)
st.set_page_config(page_title="DAVE",
page_icon="🕵️")
# Apply custom CSS
render_custom_css()
# Initialise session state variables
initialise_session_state()
# UI
st.subheader("🔮 DAVE: Data Analysis & Visualisation Engine")
file_upload_box = st.empty()
upload_btn = st.empty()
text_box = st.empty()
qn_btn = st.empty()
# File Upload
if not st.session_state["file_uploaded"]:
st.session_state["files"] = file_upload_box.file_uploader("Please upload your dataset(s)",
accept_multiple_files=True,
type=["csv"])
if upload_btn.button("Upload"):
st.session_state["file_id"] = []
# Upload the file
for file in st.session_state["files"]:
oai_file = client.files.create(
file=file,
purpose='assistants'
)
# Append the file ID to the list
st.session_state["file_id"].append(oai_file.id)
print(f"Uploaded new file: \t {oai_file.id}")
st.toast("File(s) uploaded successfully", icon="🚀")
st.session_state["file_uploaded"] = True
file_upload_box.empty()
upload_btn.empty()
# The re-run is to trigger the next section of the code
st.rerun()
if st.session_state["file_uploaded"]:
question = text_box.text_area("Ask a question")
# If the button is clicked
if qn_btn.button("Ask DAVE"):
# Clear the UI
text_box.empty()
qn_btn.empty()
# Check if the question is flagged
if moderation_endpoint(question):
# if flagged, return a warning message, delete the files and stop the app
st.warning("Your question has been flagged. Refresh page to try again.")
delete_files(st.session_state.file_id)
st.stop()
# If there is no text boxes in the session state, create an empty list
# This list will store the text boxes created by the Assistant
if "text_boxes" not in st.session_state:
st.session_state.text_boxes = []
# Create a new thread if not already created
if "thread_id" not in st.session_state:
thread = client.beta.threads.create()
st.session_state.thread_id = thread.id
print(f"Created new thread: \t {st.session_state.thread_id}")
# Update the thread to attach the file(s)
client.beta.threads.update(
thread_id=st.session_state.thread_id,
tool_resources={"code_interpreter": {"file_ids": [file_id for file_id in st.session_state.file_id]}}
)
# Ask the question
client.beta.threads.messages.create(
thread_id=st.session_state.thread_id,
role="user",
content=question,
)
# Create a new text box to display the question
st.session_state.text_boxes.append(st.empty())
st.session_state.text_boxes[-1].success(f"**> 🤔 User:** {question}")
# Run the Assistant and the EventHandler handles the stream
with client.beta.threads.runs.stream(thread_id=st.session_state.thread_id,
assistant_id=assistant.id,
tool_choice={"type": "code_interpreter"},
event_handler=EventHandler(),
temperature=0) as stream:
stream.until_done()
st.toast("DAVE has finished analysing the data", icon="🕵️")
# Prepare the files for download
with st.spinner("Preparing the files for download..."):
# Retrieve the messages by the Assistant from the thread
assistant_messages = retrieve_messages_from_thread(st.session_state.thread_id)
# For each assistant message, retrieve the file(s) created by the Assistant
st.session_state.assistant_created_file_ids = retrieve_assistant_created_files(assistant_messages)
# Download these files
st.session_state.download_files, st.session_state.download_file_names = render_download_files(st.session_state.assistant_created_file_ids)
# Clean-up
# Delete the file(s) uploaded
delete_files(st.session_state.file_id)
# Delete the file(s) created by the Assistant
delete_files(st.session_state.assistant_created_file_ids)
# Delete the thread
delete_thread(st.session_state.thread_id)