maodd commited on
Commit
62e7e53
·
verified ·
1 Parent(s): 81917a3

Implement smolagents CodeAgent (Claude) for GAIA evaluation

Browse files

Replaces the stub BasicAgent with a real agent using smolagents' CodeAgent, LiteLLMModel (Anthropic Claude), web search/wikipedia/webpage tools, and GAIA-style answer formatting. Also downloads per-question attached files and hands their local path to the agent.

Files changed (1) hide show
  1. app.py +80 -17
app.py CHANGED
@@ -1,23 +1,69 @@
1
  import os
 
2
  import gradio as gr
3
  import requests
4
  import inspect
5
  import pandas as pd
6
 
 
 
 
 
 
 
 
 
7
  # (Keep Constants as is)
8
  # --- Constants ---
9
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
10
 
 
 
 
 
 
 
 
 
 
11
  # --- Basic Agent Definition ---
12
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
13
  class BasicAgent:
14
  def __init__(self):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  print("BasicAgent initialized.")
16
- def __call__(self, question: str) -> str:
 
17
  print(f"Agent received question (first 50 chars): {question[:50]}...")
18
- fixed_answer = "This is a default answer."
19
- print(f"Agent returning fixed answer: {fixed_answer}")
20
- return fixed_answer
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  def run_and_submit_all( profile: gr.OAuthProfile | None):
23
  """
@@ -73,19 +119,34 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
73
  results_log = []
74
  answers_payload = []
75
  print(f"Running agent on {len(questions_data)} questions...")
76
- for item in questions_data:
77
- task_id = item.get("task_id")
78
- question_text = item.get("question")
79
- if not task_id or question_text is None:
80
- print(f"Skipping item with missing task_id or question: {item}")
81
- continue
82
- try:
83
- submitted_answer = agent(question_text)
84
- answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
85
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
86
- except Exception as e:
87
- print(f"Error running agent on task {task_id}: {e}")
88
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
  if not answers_payload:
91
  print("Agent did not produce any answers to submit.")
@@ -155,6 +216,8 @@ with gr.Blocks() as demo:
155
  **Disclaimers:**
156
  Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
157
  This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a seperate action or even to answer the questions in async.
 
 
158
  """
159
  )
160
 
 
1
  import os
2
+ import tempfile
3
  import gradio as gr
4
  import requests
5
  import inspect
6
  import pandas as pd
7
 
8
+ from smolagents import (
9
+ CodeAgent,
10
+ LiteLLMModel,
11
+ WebSearchTool,
12
+ VisitWebpageTool,
13
+ WikipediaSearchTool,
14
+ )
15
+
16
  # (Keep Constants as is)
17
  # --- Constants ---
18
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
19
 
20
+ # GAIA benchmark expects a terse, exact-match final answer.
21
+ GAIA_ANSWER_FORMAT_INSTRUCTIONS = """You are a general AI assistant. I will ask you a question.
22
+ Report your thoughts, and finish your work by calling final_answer() with your answer.
23
+ Your final answer should be a number OR as few words as possible OR a comma separated list of numbers and/or strings.
24
+ If you are asked for a number, don't use commas to write it, and don't use units such as $ or % unless specified otherwise.
25
+ If you are asked for a string, don't use articles or abbreviations (e.g. for cities), and write digits in plain text unless specified otherwise.
26
+ If you are asked for a comma separated list, apply the above rules to each element depending on whether it's a number or a string.
27
+ """
28
+
29
  # --- Basic Agent Definition ---
30
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
31
  class BasicAgent:
32
  def __init__(self):
33
+ model_id = os.getenv("AGENT_MODEL_ID", "anthropic/claude-sonnet-4-5")
34
+ api_key = os.getenv("ANTHROPIC_API_KEY")
35
+ if not api_key:
36
+ print("Warning: ANTHROPIC_API_KEY is not set - the agent will fail to call the model.")
37
+
38
+ self.model = LiteLLMModel(model_id=model_id, api_key=api_key, temperature=0)
39
+ self.agent = CodeAgent(
40
+ model=self.model,
41
+ tools=[WebSearchTool(), VisitWebpageTool(), WikipediaSearchTool()],
42
+ add_base_tools=True, # adds DuckDuckGo search + Whisper audio transcriber
43
+ additional_authorized_imports=[
44
+ "pandas", "numpy", "math", "re", "json", "itertools",
45
+ "collections", "statistics", "datetime", "io", "openpyxl", "PIL",
46
+ ],
47
+ max_steps=12,
48
+ )
49
  print("BasicAgent initialized.")
50
+
51
+ def __call__(self, question: str, file_path: str | None = None) -> str:
52
  print(f"Agent received question (first 50 chars): {question[:50]}...")
53
+ task = GAIA_ANSWER_FORMAT_INSTRUCTIONS + f"\nQuestion: {question}"
54
+ if file_path:
55
+ task += (
56
+ f"\n\nA file for this question was downloaded locally to: {file_path}\n"
57
+ "Open/read it with Python (pandas, openpyxl, PIL, etc. as appropriate) to answer the question."
58
+ )
59
+ try:
60
+ answer = self.agent.run(task)
61
+ except Exception as e:
62
+ print(f"Agent run failed: {e}")
63
+ return f"AGENT ERROR: {e}"
64
+ answer = str(answer).strip()
65
+ print(f"Agent returning answer: {answer}")
66
+ return answer
67
 
68
  def run_and_submit_all( profile: gr.OAuthProfile | None):
69
  """
 
119
  results_log = []
120
  answers_payload = []
121
  print(f"Running agent on {len(questions_data)} questions...")
122
+ with tempfile.TemporaryDirectory() as tmp_dir:
123
+ for item in questions_data:
124
+ task_id = item.get("task_id")
125
+ question_text = item.get("question")
126
+ file_name = item.get("file_name")
127
+ if not task_id or question_text is None:
128
+ print(f"Skipping item with missing task_id or question: {item}")
129
+ continue
130
+
131
+ file_path = None
132
+ if file_name:
133
+ try:
134
+ file_response = requests.get(f"{api_url}/files/{task_id}", timeout=30)
135
+ file_response.raise_for_status()
136
+ file_path = os.path.join(tmp_dir, file_name)
137
+ with open(file_path, "wb") as f:
138
+ f.write(file_response.content)
139
+ except requests.exceptions.RequestException as e:
140
+ print(f"Could not download attached file for task {task_id}: {e}")
141
+ file_path = None
142
+
143
+ try:
144
+ submitted_answer = agent(question_text, file_path=file_path)
145
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
146
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
147
+ except Exception as e:
148
+ print(f"Error running agent on task {task_id}: {e}")
149
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
150
 
151
  if not answers_payload:
152
  print("Agent did not produce any answers to submit.")
 
216
  **Disclaimers:**
217
  Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
218
  This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a seperate action or even to answer the questions in async.
219
+
220
+ **Setup:** This agent calls Anthropic's Claude via `smolagents`. Set the `ANTHROPIC_API_KEY` secret in this Space's settings before running.
221
  """
222
  )
223