MickyWin22 commited on
Commit
2cbacd8
·
verified ·
1 Parent(s): 53e5ab8

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +269 -0
app.py ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import requests
4
+ import pandas as pd
5
+ import traceback
6
+ import time
7
+
8
+ # Import smol-agent and tool components
9
+ from smolagents import CodeAgent, LiteLLMModel, tool
10
+ from smolagents import DuckDuckGoSearchTool
11
+ from unstructured.partition.auto import partition
12
+
13
+ # --- Constants ---
14
+ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
15
+
16
+ # --- Tool Definition ---
17
+ @tool
18
+ def file_reader(file_path: str) -> str:
19
+ """Reads the content of a file and returns its text content.
20
+
21
+ This tool supports various file types like PDF, TXT, CSV, etc., from either
22
+ a local path or a web URL.
23
+
24
+ Args:
25
+ file_path (str): The local path or web URL of the file to be read.
26
+ """
27
+ try:
28
+ if file_path.startswith("http://") or file_path.startswith("https://"):
29
+ response = requests.get(file_path, timeout=20)
30
+ response.raise_for_status()
31
+ with open("temp_file", "wb") as f:
32
+ f.write(response.content)
33
+ elements = partition("temp_file")
34
+ os.remove("temp_file") # Clean up
35
+ else:
36
+ elements = partition(file_path)
37
+ return "\n\n".join([str(el) for el in elements])
38
+ except Exception as e:
39
+ return f"Error reading or processing file '{file_path}': {e}"
40
+
41
+ # --- Agent Class (Now using a free Open-Source LLM) ---
42
+ class GaiaSmolAgent:
43
+ def __init__(self):
44
+ #print("Initializing GaiaSmolAgent with a free Open-Source LLM via Groq...")
45
+ api_key = os.getenv("GEMINI_API_KEY")
46
+ if not api_key:
47
+ raise ValueError("API key 'GEMINI_API_KEY' not found in environment secrets.")
48
+
49
+ #model = InferenceClientModel(model_id="Qwen/Qwen2.5-Coder-32B-Instruct", provider="together")
50
+
51
+
52
+ self.planner_model = LiteLLMModel(
53
+ #model_id="groq/llama3-8b-8192",
54
+ model_id="gemini/gemini-1.5-pro-latest",
55
+ api_key=api_key,
56
+ temperature=0.0,
57
+ )
58
+
59
+ # Initialize the agent with the tools it can use.
60
+ self.executor_agent = CodeAgent(
61
+ model=self.planner_model,
62
+ tools=[file_reader, DuckDuckGoSearchTool()],
63
+ add_base_tools=True, # Provides a python interpreter
64
+ )
65
+ print("GaiaSmolAgent initialized successfully.")
66
+
67
+ def _generate_script(self, question: str) -> str:
68
+ """Generates a self-contained Python script to answer the question."""
69
+ print(f"Generating script for question: {question[:100]}...")
70
+
71
+ prompt = f"""
72
+ You are an expert Python programmer. Your task is to write a single, self-contained Python script to answer the user's question.
73
+
74
+ You have access to the following functions which are pre-imported and ready to use:
75
+ - `duck_duck_go_search(query: str) -> str`: Searches the web and returns a string with the results.
76
+ - `file_reader(file_path: str) -> str`: Reads a file and returns its contents as a string.
77
+
78
+ CRITICAL INSTRUCTIONS:
79
+ 1. Your output must be ONLY the Python code for the script. Do not add any explanation or markdown formatting like ```python.
80
+ 2. The script MUST end with a call to a function `final_answer(answer: str)`.
81
+ 3. The `answer` passed to `final_answer` must be a single, concise string.
82
+ 4. All logic, including processing the string outputs from the tools, must be included in this single script. State is preserved within the script.
83
+
84
+ Question: "{question}"
85
+
86
+ Example for "What is the capital of France?":
87
+ search_result = duck_duck_go_search("capital of France")
88
+ # In a real scenario, you would parse this string to find the answer.
89
+ # For this example, we'll just summarize the string.
90
+ answer = "Based on the search, the capital is likely Paris." # Replace with actual logic
91
+ final_answer(answer)
92
+
93
+ Now, write the Python script to answer the user's question.
94
+ """
95
+ messages = [{"role": "user", "content": [{"type": "text", "text": prompt}]}]
96
+ response_object = self.planner_model.generate(messages)
97
+
98
+ # --- THIS IS THE FIX ---
99
+ # The response is an object, not a string. We need to access its .content attribute.
100
+ response_content = response_object.content
101
+
102
+ if "```python" in response_content:
103
+ response_content = response_content.split("```python")[1].split("```")[0].strip()
104
+
105
+ print(f"--- Generated Script ---\n{response_content}\n------------------------")
106
+ return response_content
107
+
108
+ def __call__(self, question: str) -> str:
109
+ """Generates and executes a single script to answer the question."""
110
+ print(f"Agent received question: {question[:100]}...")
111
+
112
+ try:
113
+ script_to_execute = self._generate_script(question)
114
+ final_answer = self.executor_agent.run(script_to_execute)
115
+
116
+ except Exception as e:
117
+ print(f"FATAL AGENT ERROR: An exception occurred during agent execution: {e}")
118
+ print(traceback.format_exc()) # Print the full traceback for debugging
119
+ return f"FATAL AGENT ERROR: {e}"
120
+
121
+ print(f"Agent returning final answer: {final_answer}")
122
+ return str(final_answer)
123
+
124
+ # --- Main Application Logic (Unchanged) ---
125
+ def run_and_submit_all( profile: gr.OAuthProfile | None):
126
+ """
127
+ Fetches all questions, runs the BasicAgent on them, submits all answers,
128
+ and displays the results.
129
+ """
130
+ # --- Determine HF Space Runtime URL and Repo URL ---
131
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
132
+
133
+ if profile:
134
+ username= f"{profile.username}"
135
+ print(f"User logged in: {username}")
136
+ else:
137
+ print("User not logged in.")
138
+ return "Please Login to Hugging Face with the button.", None
139
+
140
+ api_url = DEFAULT_API_URL
141
+ questions_url = f"{api_url}/questions"
142
+ submit_url = f"{api_url}/submit"
143
+
144
+ # 1. Instantiate Agent ( modify this part to create your agent)
145
+ try:
146
+ agent = BasicAgent()
147
+ except Exception as e:
148
+ print(f"Error instantiating agent: {e}")
149
+ return f"Error initializing agent: {e}", None
150
+ # In the case of an app running as a hugging Face space, this link points toward your codebase ( usefull for others so please keep it public)
151
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
152
+ print(agent_code)
153
+
154
+ # 2. Fetch Questions
155
+ print(f"Fetching questions from: {questions_url}")
156
+ try:
157
+ response = requests.get(questions_url, timeout=15)
158
+ response.raise_for_status()
159
+ questions_data = response.json()
160
+ if not questions_data:
161
+ print("Fetched questions list is empty.")
162
+ return "Fetched questions list is empty or invalid format.", None
163
+ print(f"Fetched {len(questions_data)} questions.")
164
+ except requests.exceptions.RequestException as e:
165
+ print(f"Error fetching questions: {e}")
166
+ return f"Error fetching questions: {e}", None
167
+ except requests.exceptions.JSONDecodeError as e:
168
+ print(f"Error decoding JSON response from questions endpoint: {e}")
169
+ print(f"Response text: {response.text[:500]}")
170
+ return f"Error decoding server response for questions: {e}", None
171
+ except Exception as e:
172
+ print(f"An unexpected error occurred fetching questions: {e}")
173
+ return f"An unexpected error occurred fetching questions: {e}", None
174
+
175
+ # 3. Run your Agent
176
+ results_log = []
177
+ answers_payload = []
178
+ print(f"Running agent on {len(questions_data)} questions...")
179
+ for item in questions_data:
180
+ task_id = item.get("task_id")
181
+ question_text = item.get("question")
182
+ if not task_id or question_text is None:
183
+ print(f"Skipping item with missing task_id or question: {item}")
184
+ continue
185
+ try:
186
+ submitted_answer = agent(question_text)
187
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
188
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
189
+ except Exception as e:
190
+ print(f"Error running agent on task {task_id}: {e}")
191
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
192
+
193
+ if not answers_payload:
194
+ print("Agent did not produce any answers to submit.")
195
+ return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
196
+
197
+ # 4. Prepare Submission
198
+ submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
199
+ status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
200
+ print(status_update)
201
+
202
+ # 5. Submit
203
+ print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
204
+ try:
205
+ response = requests.post(submit_url, json=submission_data, timeout=60)
206
+ response.raise_for_status()
207
+ result_data = response.json()
208
+ final_status = (
209
+ f"Submission Successful!\n"
210
+ f"User: {result_data.get('username')}\n"
211
+ f"Overall Score: {result_data.get('score', 'N/A')}% "
212
+ f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
213
+ f"Message: {result_data.get('message', 'No message received.')}"
214
+ )
215
+ print("Submission successful.")
216
+ results_df = pd.DataFrame(results_log)
217
+ return final_status, results_df
218
+ except requests.exceptions.HTTPError as e:
219
+ error_detail = f"Server responded with status {e.response.status_code}."
220
+ try:
221
+ error_json = e.response.json()
222
+ error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
223
+ except requests.exceptions.JSONDecodeError:
224
+ error_detail += f" Response: {e.response.text[:500]}"
225
+ status_message = f"Submission Failed: {error_detail}"
226
+ print(status_message)
227
+ results_df = pd.DataFrame(results_log)
228
+ return status_message, results_df
229
+ except requests.exceptions.Timeout:
230
+ status_message = "Submission Failed: The request timed out."
231
+ print(status_message)
232
+ results_df = pd.DataFrame(results_log)
233
+ return status_message, results_df
234
+ except requests.exceptions.RequestException as e:
235
+ status_message = f"Submission Failed: Network error - {e}"
236
+ print(status_message)
237
+ results_df = pd.DataFrame(results_log)
238
+ return status_message, results_df
239
+ except Exception as e:
240
+ status_message = f"An unexpected error occurred during submission: {e}"
241
+ print(status_message)
242
+ results_df = pd.DataFrame(results_log)
243
+ return status_message, results_df
244
+
245
+
246
+ # --- Gradio Interface (Updated Instructions) ---
247
+ with gr.Blocks() as demo:
248
+ gr.Markdown("# GAIA Agent Evaluation Runner (smol-agent)")
249
+ gr.Markdown(
250
+ """
251
+ **Instructions:**
252
+ 1. Ensure you have added your **GEMINI API key** (as `GEMINI_API_KEY`) in the Space's secrets.
253
+ 2. Log in to your Hugging Face account using the button below.
254
+ 3. Click 'Run Evaluation & Submit All Answers' to run your agent and see the score.
255
+ """
256
+ )
257
+ gr.LoginButton()
258
+ run_button = gr.Button("Run Evaluation & Submit All Answers")
259
+ status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
260
+ results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
261
+
262
+ run_button.click(
263
+ fn=run_and_submit_all,
264
+ outputs=[status_output, results_table]
265
+ )
266
+
267
+ if __name__ == "__main__":
268
+ print("Launching Gradio Interface for GAIA Agent Evaluation...")
269
+ demo.launch(debug=True, share=False)