MickyWin22 commited on
Commit
1e0a3d8
·
verified ·
1 Parent(s): 214f31c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +248 -0
app.py ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import requests
4
+ import pandas as pd
5
+
6
+ # Import smol-agent and tool components
7
+ from smolagents import CodeAgent, LiteLLMModel, tool
8
+ from smolagents.tool import WebSearchTool
9
+ from unstructured.partition.auto import partition
10
+
11
+
12
+ # --- Constants ---
13
+ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
14
+
15
+ # --- Agent Definition ---
16
+
17
+ # 1. Define Your Tools
18
+ @tool
19
+ def file_reader(file_path: str) -> str:
20
+ """
21
+ Reads the content of a file at the given URL or local path and returns its text content.
22
+ Supports various file types like PDF, TXT, CSV, etc.
23
+ """
24
+ try:
25
+ if file_path.startswith("http://") or file_path.startswith("https://"):
26
+ response = requests.get(file_path, timeout=20)
27
+ response.raise_for_status()
28
+ with open("temp_file", "wb") as f:
29
+ f.write(response.content)
30
+ elements = partition("temp_file")
31
+ os.remove("temp_file") # Clean up
32
+ else:
33
+ elements = partition(file_path)
34
+ return "\n\n".join([str(el) for el in elements])
35
+ except Exception as e:
36
+ return f"Error reading or processing file '{file_path}': {e}"
37
+
38
+ # 2. Define Your Agent Class
39
+ class GaiaSmolAgent:
40
+ def __init__(self):
41
+ print("Initializing GaiaSmolAgent with OpenAI...")
42
+ # --- MODIFICATION 1: Use OPENAI_API_KEY ---
43
+ # Ensure you have set your OPENAI_API_KEY as a secret in your HF Space
44
+ api_key = os.getenv("OPENAI_API_KEY")
45
+ if not api_key:
46
+ raise ValueError("API key 'OPENAI_API_KEY' not found in environment secrets.")
47
+
48
+ # --- MODIFICATION 2: Use an OpenAI Model ID ---
49
+ # The "Planner" model - for high-level reasoning
50
+ self.planner_model = LiteLLMModel(
51
+ model_id="gpt-4o", # Using OpenAI's gpt-4o model
52
+ api_key=api_key,
53
+ temperature=0.0,
54
+ )
55
+
56
+ # The "Executor" agent - for executing tasks with tools
57
+ self.executor_agent = CodeAgent(
58
+ model=self.planner_model, # Can use the same model
59
+ tools=[file_reader, WebSearchTool()],
60
+ # add_base_tools=True will add a Python interpreter
61
+ add_base_tools=True,
62
+ )
63
+ print("GaiaSmolAgent initialized successfully with OpenAI.")
64
+
65
+ def _generate_plan(self, question: str) -> list[str]:
66
+ """Generates a step-by-step plan to answer the question."""
67
+ print(f"Generating plan for question: {question[:100]}...")
68
+ prompt = f"""
69
+ You are an expert planner. Your job is to create a clear, step-by-step plan to answer the given question.
70
+ The final step must be to output the answer using the `final_answer` tool.
71
+ Each step should be a clear instruction for an agent to follow.
72
+
73
+ Question: "{question}"
74
+
75
+ Provide the plan as a Python list of strings. For example:
76
+ ["Search the web for the latest news on topic X.", "Analyze the search results to find the key person.", "final_answer('The key person is John Doe.')"]
77
+ """
78
+ response = self.planner_model.generate(prompt)
79
+ print(f"Generated plan: {response}")
80
+ try:
81
+ # Safely evaluate the string to a Python list
82
+ plan = eval(response)
83
+ if isinstance(plan, list):
84
+ return plan
85
+ else:
86
+ return [f"final_answer('Error: Plan generation failed. Could not parse plan: {response}')"]
87
+ except Exception as e:
88
+ print(f"Error parsing plan: {e}")
89
+ return [f"final_answer('Error: Plan generation failed. Could not parse plan: {response}')"]
90
+
91
+
92
+ def __call__(self, question: str) -> str:
93
+ """Runs the planner and executor to answer the question."""
94
+ print(f"Agent received question: {question[:100]}...")
95
+
96
+ # Step 1: Generate the plan
97
+ plan = self._generate_plan(question)
98
+
99
+ # Step 2: Execute the plan
100
+ final_answer = self.executor_agent.run(plan)
101
+
102
+ print(f"Agent returning final answer: {final_answer}")
103
+ return str(final_answer)
104
+
105
+
106
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
107
+ """
108
+ Fetches all questions, runs the GaiaSmolAgent on them, submits all answers,
109
+ and displays the results.
110
+ """
111
+ # --- Determine HF Space Runtime URL and Repo URL ---
112
+ space_id = os.getenv("SPACE_ID")
113
+
114
+ if profile:
115
+ username = f"{profile.username}"
116
+ print(f"User logged in: {username}")
117
+ else:
118
+ print("User not logged in.")
119
+ return "Please Login to Hugging Face with the button.", None
120
+
121
+ api_url = DEFAULT_API_URL
122
+ questions_url = f"{api_url}/questions"
123
+ submit_url = f"{api_url}/submit"
124
+
125
+ # 1. Instantiate Agent
126
+ try:
127
+ # **MODIFIED PART: Instantiate your new agent**
128
+ agent = GaiaSmolAgent()
129
+ except Exception as e:
130
+ print(f"Error instantiating agent: {e}")
131
+ return f"Error initializing agent: {e}", None
132
+
133
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
134
+ print(agent_code)
135
+
136
+ # 2. Fetch Questions
137
+ print(f"Fetching questions from: {questions_url}")
138
+ try:
139
+ response = requests.get(questions_url, timeout=15)
140
+ response.raise_for_status()
141
+ questions_data = response.json()
142
+ if not questions_data:
143
+ print("Fetched questions list is empty.")
144
+ return "Fetched questions list is empty or invalid format.", None
145
+ print(f"Fetched {len(questions_data)} questions.")
146
+ except Exception as e:
147
+ print(f"Error fetching questions: {e}")
148
+ return f"Error fetching questions: {e}", None
149
+
150
+
151
+ # 3. Run your Agent
152
+ results_log = []
153
+ answers_payload = []
154
+ print(f"Running agent on {len(questions_data)} questions...")
155
+ for item in questions_data:
156
+ task_id = item.get("task_id")
157
+ # GAIA questions can include file paths
158
+ question_text = item.get("question")
159
+ file_path = item.get("file") # Get the file URL if it exists
160
+ if file_path:
161
+ question_text += f"\n\nRelevant file is available at: {file_path}"
162
+
163
+ if not task_id or question_text is None:
164
+ print(f"Skipping item with missing task_id or question: {item}")
165
+ continue
166
+ try:
167
+ submitted_answer = agent(question_text)
168
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
169
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
170
+ except Exception as e:
171
+ print(f"Error running agent on task {task_id}: {e}")
172
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
173
+
174
+ if not answers_payload:
175
+ print("Agent did not produce any answers to submit.")
176
+ return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
177
+
178
+ # 4. Prepare Submission
179
+ submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
180
+ status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
181
+ print(status_update)
182
+
183
+ # 5. Submit
184
+ print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
185
+ try:
186
+ response = requests.post(submit_url, json=submission_data, timeout=60)
187
+ response.raise_for_status()
188
+ result_data = response.json()
189
+ final_status = (
190
+ f"Submission Successful!\n"
191
+ f"User: {result_data.get('username')}\n"
192
+ f"Overall Score: {result_data.get('score', 'N/A')}% "
193
+ f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
194
+ f"Message: {result_data.get('message', 'No message received.')}"
195
+ )
196
+ print("Submission successful.")
197
+ results_df = pd.DataFrame(results_log)
198
+ return final_status, results_df
199
+ except requests.exceptions.HTTPError as e:
200
+ error_detail = f"Server responded with status {e.response.status_code}."
201
+ try:
202
+ error_json = e.response.json()
203
+ error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
204
+ except requests.exceptions.JSONDecodeError:
205
+ error_detail += f" Response: {e.response.text[:500]}"
206
+ status_message = f"Submission Failed: {error_detail}"
207
+ print(status_message)
208
+ results_df = pd.DataFrame(results_log)
209
+ return status_message, results_df
210
+ except Exception as e:
211
+ status_message = f"An unexpected error occurred during submission: {e}"
212
+ print(status_message)
213
+ results_df = pd.DataFrame(results_log)
214
+ return status_message, results_df
215
+
216
+ # --- Gradio Interface ---
217
+ # (This part remains unchanged)
218
+ with gr.Blocks() as demo:
219
+ gr.Markdown("# GAIA Agent Evaluation Runner (smol-agent)")
220
+ gr.Markdown(
221
+ """
222
+ **Instructions:**
223
+
224
+ 1. Ensure you have added your **OpenAI API key** (as `OPENAI_API_KEY`) in the Space's secrets.
225
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
226
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
227
+ """
228
+ )
229
+
230
+ gr.LoginButton()
231
+
232
+ run_button = gr.Button("Run Evaluation & Submit All Answers")
233
+
234
+ status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
235
+ results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
236
+
237
+ # This is the new way to bind the OAuth profile to the function
238
+ run_button.click(
239
+ fn=run_and_submit_all,
240
+ inputs=None, # No direct input components
241
+ outputs=[status_output, results_table],
242
+ api_name="run_evaluation" # Add an API name for programmatic access
243
+ )
244
+
245
+ # The __main__ block remains the same
246
+ if __name__ == "__main__":
247
+ print("Launching Gradio Interface for GAIA Agent Evaluation...")
248
+ demo.launch(debug=True, share=False)