Mouhamedamar commited on
Commit
b6af4aa
Β·
verified Β·
1 Parent(s): 2922cb7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +143 -65
app.py CHANGED
@@ -1,77 +1,156 @@
1
  import os
2
  import gradio as gr
3
  import requests
4
- import inspect
5
  import pandas as pd
6
- from smolagents import CodeAgent, DuckDuckGoSearchTool, VisitWebpageTool, LiteLLMModel
7
 
8
- # (Keep Constants as is)
9
  # --- Constants ---
10
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
11
 
12
- # --- Basic Agent Definition ---
13
- # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
14
- class BasicAgent:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  def __init__(self):
16
- print("=" * 50)
17
- print("Initializing GAIA Agent...")
18
- print("=" * 50)
19
-
20
- # Initialize the model
21
- self.model = LiteLLMModel(
22
- model_id="huggingface/Qwen/Qwen2.5-Coder-32B-Instruct",
23
- max_tokens=4096,
24
- temperature=0.1
25
  )
26
-
27
- # Create CodeAgent with web tools
28
  self.agent = CodeAgent(
29
  tools=[
30
  DuckDuckGoSearchTool(),
31
- VisitWebpageTool(),
 
 
32
  ],
33
- model=self.model,
34
- max_steps=15,
35
- verbosity_level=0
36
  )
37
- print("βœ… Agent initialized successfully!")
38
- print("=" * 50)
39
-
40
  def __call__(self, question: str) -> str:
41
- print(f"πŸ“ Question: {question[:80]}...")
42
  try:
43
- # Prompt for exact answer
44
- prompt = f"""Answer this question with ONLY the exact answer. No explanations, no extra text.
45
-
46
- Question: {question}
47
-
48
- Answer:"""
49
-
50
  result = self.agent.run(prompt)
51
- answer = result.strip()
52
-
53
- # Clean up common prefixes
54
- prefixes = ["final answer:", "answer:", "the answer is"]
55
- for prefix in prefixes:
56
- if answer.lower().startswith(prefix):
57
  answer = answer[len(prefix):].strip()
58
-
59
- print(f"βœ… Answer: {answer[:80]}")
60
- return answer if answer else "No answer found"
61
  except Exception as e:
62
- print(f"❌ Error: {e}")
63
- return ""
 
64
 
65
- def run_and_submit_all( profile: gr.OAuthProfile | None):
 
 
 
 
66
  """
67
- Fetches all questions, runs the BasicAgent on them, submits all answers,
68
  and displays the results.
69
  """
70
- # --- Determine HF Space Runtime URL and Repo URL ---
71
- space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
72
 
73
  if profile:
74
- username= f"{profile.username}"
75
  print(f"User logged in: {username}")
76
  else:
77
  print("User not logged in.")
@@ -81,13 +160,13 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
81
  questions_url = f"{api_url}/questions"
82
  submit_url = f"{api_url}/submit"
83
 
84
- # 1. Instantiate Agent ( modify this part to create your agent)
85
  try:
86
- agent = BasicAgent()
87
  except Exception as e:
88
  print(f"Error instantiating agent: {e}")
89
  return f"Error initializing agent: {e}", None
90
- # 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)
91
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
92
  print(agent_code)
93
 
@@ -98,16 +177,16 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
98
  response.raise_for_status()
99
  questions_data = response.json()
100
  if not questions_data:
101
- print("Fetched questions list is empty.")
102
- return "Fetched questions list is empty or invalid format.", None
103
  print(f"Fetched {len(questions_data)} questions.")
104
  except requests.exceptions.RequestException as e:
105
  print(f"Error fetching questions: {e}")
106
  return f"Error fetching questions: {e}", None
107
  except requests.exceptions.JSONDecodeError as e:
108
- print(f"Error decoding JSON response from questions endpoint: {e}")
109
- print(f"Response text: {response.text[:500]}")
110
- return f"Error decoding server response for questions: {e}", None
111
  except Exception as e:
112
  print(f"An unexpected error occurred fetching questions: {e}")
113
  return f"An unexpected error occurred fetching questions: {e}", None
@@ -123,18 +202,20 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
123
  print(f"Skipping item with missing task_id or question: {item}")
124
  continue
125
  try:
126
- submitted_answer = agent(question_text)
 
 
127
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
128
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
129
  except Exception as e:
130
- print(f"Error running agent on task {task_id}: {e}")
131
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
132
 
133
  if not answers_payload:
134
  print("Agent did not produce any answers to submit.")
135
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
136
 
137
- # 4. Prepare Submission
138
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
139
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
140
  print(status_update)
@@ -206,7 +287,6 @@ with gr.Blocks() as demo:
206
  run_button = gr.Button("Run Evaluation & Submit All Answers")
207
 
208
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
209
- # Removed max_rows=10 from DataFrame constructor
210
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
211
 
212
  run_button.click(
@@ -216,9 +296,8 @@ with gr.Blocks() as demo:
216
 
217
  if __name__ == "__main__":
218
  print("\n" + "-"*30 + " App Starting " + "-"*30)
219
- # Check for SPACE_HOST and SPACE_ID at startup for information
220
  space_host_startup = os.getenv("SPACE_HOST")
221
- space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
222
 
223
  if space_host_startup:
224
  print(f"βœ… SPACE_HOST found: {space_host_startup}")
@@ -226,7 +305,7 @@ if __name__ == "__main__":
226
  else:
227
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
228
 
229
- if space_id_startup: # Print repo URLs if SPACE_ID is found
230
  print(f"βœ… SPACE_ID found: {space_id_startup}")
231
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
232
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
@@ -234,6 +313,5 @@ if __name__ == "__main__":
234
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
235
 
236
  print("-"*(60 + len(" App Starting ")) + "\n")
237
-
238
  print("Launching Gradio Interface for Basic Agent Evaluation...")
239
  demo.launch(debug=True, share=False)
 
1
  import os
2
  import gradio as gr
3
  import requests
 
4
  import pandas as pd
 
5
 
 
6
  # --- Constants ---
7
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
8
 
9
+ # ─────────────────────────────────────────────────────────────
10
+ # AGENT DEFINITION β€” smolagents + Qwen2.5-72B (HF Inference)
11
+ # ─────────────────────────────────────────────────────────────
12
+ from smolagents import (
13
+ CodeAgent,
14
+ HfApiModel,
15
+ DuckDuckGoSearchTool,
16
+ WikipediaSearchTool,
17
+ tool,
18
+ )
19
+
20
+ @tool
21
+ def download_file_for_task(task_id: str) -> str:
22
+ """
23
+ Downloads the file associated with a GAIA task_id from the scoring API.
24
+ Returns the file content as text (or a description if binary).
25
+ Args:
26
+ task_id: The GAIA task identifier.
27
+ """
28
+ try:
29
+ url = f"{DEFAULT_API_URL}/files/{task_id}"
30
+ resp = requests.get(url, timeout=30)
31
+ if resp.status_code != 200:
32
+ return f"No file found for task {task_id} (HTTP {resp.status_code})"
33
+ content_type = resp.headers.get("Content-Type", "")
34
+ content = resp.content
35
+
36
+ # --- TEXT / JSON / CSV ---
37
+ if any(t in content_type for t in ["text", "json", "csv"]):
38
+ return content.decode("utf-8", errors="replace")[:4000]
39
+
40
+ # --- EXCEL ---
41
+ if "excel" in content_type or "spreadsheet" in content_type or task_id.endswith(".xlsx"):
42
+ import io, openpyxl
43
+ wb = openpyxl.load_workbook(io.BytesIO(content))
44
+ ws = wb.active
45
+ rows = ["\t".join(str(c) if c is not None else "" for c in row)
46
+ for row in ws.iter_rows(values_only=True)]
47
+ return "\n".join(rows[:300])
48
+
49
+ # --- PDF ---
50
+ if "pdf" in content_type:
51
+ import io
52
+ try:
53
+ import pypdf
54
+ reader = pypdf.PdfReader(io.BytesIO(content))
55
+ text = "\n".join(p.extract_text() or "" for p in reader.pages[:10])
56
+ return text[:4000]
57
+ except Exception as e:
58
+ return f"[PDF parse error: {e}]"
59
+
60
+ # --- Fallback: try decoding as UTF-8 ---
61
+ return content.decode("utf-8", errors="replace")[:4000]
62
+
63
+ except Exception as e:
64
+ return f"Error downloading file: {e}"
65
+
66
+
67
+ @tool
68
+ def python_calculator(code: str) -> str:
69
+ """
70
+ Executes a Python code snippet and returns the printed output.
71
+ Use this for arithmetic, data processing, pandas operations, etc.
72
+ Args:
73
+ code: Valid Python code to execute. Use print() to output results.
74
+ """
75
+ import io, sys, traceback
76
+ old_stdout = sys.stdout
77
+ sys.stdout = buf = io.StringIO()
78
+ try:
79
+ exec(code, {"__builtins__": __builtins__, "pd": pd})
80
+ return buf.getvalue() or "Executed (no output). Use print() to see results."
81
+ except Exception:
82
+ return traceback.format_exc()
83
+ finally:
84
+ sys.stdout = old_stdout
85
+
86
+
87
+ class GAIAAgent:
88
+ """
89
+ Wraps a smolagents CodeAgent powered by Qwen2.5-72B-Instruct.
90
+ Exposes a __call__(question) interface compatible with the template.
91
+ """
92
+
93
+ SYSTEM_PROMPT = """You are an expert AI assistant solving GAIA benchmark questions.
94
+ Your answers must be SHORT and EXACT β€” a number, a name, a short phrase, or a comma-separated list.
95
+ Never include explanations, preambles, or units unless explicitly asked.
96
+ If you need to look something up, use your tools.
97
+ At the end, output ONLY the final answer with no extra words."""
98
+
99
  def __init__(self):
100
+ hf_token = os.getenv("HF_TOKEN", "")
101
+ model = HfApiModel(
102
+ model_id="Qwen/Qwen2.5-72B-Instruct",
103
+ token=hf_token,
 
 
 
 
 
104
  )
 
 
105
  self.agent = CodeAgent(
106
  tools=[
107
  DuckDuckGoSearchTool(),
108
+ WikipediaSearchTool(),
109
+ download_file_for_task,
110
+ python_calculator,
111
  ],
112
+ model=model,
113
+ max_steps=6,
114
+ verbosity_level=1,
115
  )
116
+ print("GAIAAgent initialized with Qwen2.5-72B + smolagents tools.")
117
+
 
118
  def __call__(self, question: str) -> str:
119
+ print(f"Agent received question (first 50 chars): {question[:50]}...")
120
  try:
121
+ # Inject task_id hint if present (not standard but useful for file tool)
122
+ prompt = (
123
+ f"{self.SYSTEM_PROMPT}\n\n"
124
+ f"Question: {question}\n\n"
125
+ "Give ONLY the final answer. No explanation. No sentence. Just the answer."
126
+ )
 
127
  result = self.agent.run(prompt)
128
+ # smolagents returns the final answer as a string
129
+ answer = str(result).strip()
130
+ # Clean up common LLM verbosity
131
+ for prefix in ["Final answer:", "Answer:", "ANSWER:", "The answer is", "Result:"]:
132
+ if answer.lower().startswith(prefix.lower()):
 
133
  answer = answer[len(prefix):].strip()
134
+ print(f"Agent answer: {answer}")
135
+ return answer
 
136
  except Exception as e:
137
+ print(f"Agent error: {e}")
138
+ return "I don't know"
139
+
140
 
141
+ # ─────────────────────────────────────────────────────────────
142
+ # run_and_submit_all β€” structure du template conservΓ©e Γ  100%
143
+ # ─────────────────────────────────────────────────────────────
144
+
145
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
146
  """
147
+ Fetches all questions, runs the GAIAAgent on them, submits all answers,
148
  and displays the results.
149
  """
150
+ space_id = os.getenv("SPACE_ID")
 
151
 
152
  if profile:
153
+ username = f"{profile.username}"
154
  print(f"User logged in: {username}")
155
  else:
156
  print("User not logged in.")
 
160
  questions_url = f"{api_url}/questions"
161
  submit_url = f"{api_url}/submit"
162
 
163
+ # 1. Instantiate Agent
164
  try:
165
+ agent = GAIAAgent()
166
  except Exception as e:
167
  print(f"Error instantiating agent: {e}")
168
  return f"Error initializing agent: {e}", None
169
+
170
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
171
  print(agent_code)
172
 
 
177
  response.raise_for_status()
178
  questions_data = response.json()
179
  if not questions_data:
180
+ print("Fetched questions list is empty.")
181
+ return "Fetched questions list is empty or invalid format.", None
182
  print(f"Fetched {len(questions_data)} questions.")
183
  except requests.exceptions.RequestException as e:
184
  print(f"Error fetching questions: {e}")
185
  return f"Error fetching questions: {e}", None
186
  except requests.exceptions.JSONDecodeError as e:
187
+ print(f"Error decoding JSON response from questions endpoint: {e}")
188
+ print(f"Response text: {response.text[:500]}")
189
+ return f"Error decoding server response for questions: {e}", None
190
  except Exception as e:
191
  print(f"An unexpected error occurred fetching questions: {e}")
192
  return f"An unexpected error occurred fetching questions: {e}", None
 
202
  print(f"Skipping item with missing task_id or question: {item}")
203
  continue
204
  try:
205
+ # Pass task_id via question context so file tool can use it
206
+ question_with_id = f"[task_id={task_id}] {question_text}"
207
+ submitted_answer = agent(question_with_id)
208
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
209
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
210
  except Exception as e:
211
+ print(f"Error running agent on task {task_id}: {e}")
212
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
213
 
214
  if not answers_payload:
215
  print("Agent did not produce any answers to submit.")
216
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
217
 
218
+ # 4. Prepare Submission
219
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
220
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
221
  print(status_update)
 
287
  run_button = gr.Button("Run Evaluation & Submit All Answers")
288
 
289
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
290
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
291
 
292
  run_button.click(
 
296
 
297
  if __name__ == "__main__":
298
  print("\n" + "-"*30 + " App Starting " + "-"*30)
 
299
  space_host_startup = os.getenv("SPACE_HOST")
300
+ space_id_startup = os.getenv("SPACE_ID")
301
 
302
  if space_host_startup:
303
  print(f"βœ… SPACE_HOST found: {space_host_startup}")
 
305
  else:
306
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
307
 
308
+ if space_id_startup:
309
  print(f"βœ… SPACE_ID found: {space_id_startup}")
310
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
311
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
 
313
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
314
 
315
  print("-"*(60 + len(" App Starting ")) + "\n")
 
316
  print("Launching Gradio Interface for Basic Agent Evaluation...")
317
  demo.launch(debug=True, share=False)