Shiverion's picture
1
6a0be2a
Raw History Blame Contribute Delete
5.02 kB
import gradio as gr
import os
import time
from openai import OpenAI
from dotenv import load_dotenv
# --- Load Environment Variables and Initialize Client ---
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# --- Configuration ---
ASSISTANT_INSTRUCTIONS = """
You are an expert data analyst. When the user uploads a file and asks a question,
your role is to use your Code Interpreter tool to write and run Python code to answer the question.
- Analyze the data thoroughly.
- If the user asks for a visualization, create it and display it as an image in your response.
- If the user doesn't asks for visualization, just make the analysis or whatever user ask.
- Provide a text explanation of your findings and describe any visualizations you create.
- Use Markdown formatting for all text in your output.This includes headings, bullet points, code blocks (if any), and emphasis for clarity.
"""
PLOT_FILENAME = "assistant_plot.png"
# --- Assistant Logic ---
def analyze_with_assistant(file_obj, user_prompt):
"""
Orchestrates the OpenAI Assistant to analyze a user-provided file.
"""
# 1. Input Validation
if file_obj is None:
return "Error: Please upload a file first.", None
if not user_prompt:
return "Error: Please enter a question.", None
# Cleanup old plot file
if os.path.exists(PLOT_FILENAME):
os.remove(PLOT_FILENAME)
try:
# 2. Upload the user's file to OpenAI
uploaded_file = client.files.create(
file=open(file_obj.name, "rb"),
purpose="assistants"
)
# 3. Create an Assistant
# This defines the agent's behavior and tools.
assistant = client.beta.assistants.create(
name="Data Analyst Assistant",
instructions=ASSISTANT_INSTRUCTIONS,
tools=[{"type": "code_interpreter"}],
model="gpt-4-turbo",
tool_resources={"code_interpreter": {"file_ids": [uploaded_file.id]}}
)
# 4. Create a Thread (a conversation session)
thread = client.beta.threads.create()
# 5. Add the User's Message to the Thread
client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content=user_prompt
)
# 6. Run the Assistant
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id,
)
# 7. Wait for the Run to complete
while run.status in ['queued', 'in_progress', 'cancelling']:
time.sleep(1)
run = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id)
if run.status != 'completed':
return f"Error: The Assistant run failed with status {run.status}", None
# 8. Retrieve and Process Messages
messages = client.beta.threads.messages.list(thread_id=thread.id)
assistant_response = ""
image_file_id = None
# The latest message is from the assistant
for content_part in messages.data[0].content:
if content_part.type == "text":
assistant_response += content_part.text.value
elif content_part.type == "image_file":
image_file_id = content_part.image_file.file_id
# 9. Download the image if it exists
image_path = None
if image_file_id:
image_data = client.files.content(image_file_id)
image_data_bytes = image_data.read()
with open(PLOT_FILENAME, "wb") as f:
f.write(image_data_bytes)
image_path = PLOT_FILENAME
return assistant_response, image_path
except Exception as e:
error_message = f"An unexpected error occurred: {str(e)}"
print(error_message)
return error_message, None
# --- Gradio UI (Largely unchanged) ---
with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange")) as demo:
gr.Markdown(
"""
# πŸ€– Agentic Data Analysis with OpenAI Assistants
This version uses the official OpenAI Assistants API with the Code Interpreter tool.
"""
)
with gr.Row():
with gr.Column(scale=1):
file_input = gr.File(label="Upload your CSV", file_types=[".csv"])
text_input = gr.Textbox(
label="What would you like to know?",
placeholder="e.g., 'What is the correlation between column A and B?' or 'Create a bar chart of sales by category.'"
)
submit_button = gr.Button("πŸš€ Run Analysis", variant="primary")
with gr.Column(scale=2):
text_output = gr.Markdown(label="πŸ“ Agent's Answer")
plot_output = gr.Image(label="πŸ“Š Generated Visualization", type="filepath")
submit_button.click(
fn=analyze_with_assistant,
inputs=[file_input, text_input],
outputs=[text_output, plot_output]
)
if __name__ == "__main__":
demo.launch()