sumit1703 commited on
Commit
06094f8
·
verified ·
1 Parent(s): 42f6460

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +146 -47
app.py CHANGED
@@ -1,34 +1,135 @@
 
 
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
  """
24
- Fetches all questions, runs the BasicAgent on them, submits all answers,
25
- and displays the results.
26
  """
27
- # --- Determine HF Space Runtime URL and Repo URL ---
28
- space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
29
 
30
  if profile:
31
- username= f"{profile.username}"
32
  print(f"User logged in: {username}")
33
  else:
34
  print("User not logged in.")
@@ -38,65 +139,66 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
38
  questions_url = f"{api_url}/questions"
39
  submit_url = f"{api_url}/submit"
40
 
41
- # 1. Instantiate Agent ( modify this part to create your agent)
42
  try:
43
- agent = BasicAgent()
44
  except Exception as e:
45
  print(f"Error instantiating agent: {e}")
46
  return f"Error initializing agent: {e}", None
47
- # 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)
48
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
49
  print(agent_code)
50
 
51
- # 2. Fetch Questions
52
  print(f"Fetching questions from: {questions_url}")
53
  try:
54
  response = requests.get(questions_url, timeout=15)
55
  response.raise_for_status()
56
  questions_data = response.json()
57
  if not questions_data:
58
- print("Fetched questions list is empty.")
59
- return "Fetched questions list is empty or invalid format.", None
60
  print(f"Fetched {len(questions_data)} questions.")
61
  except requests.exceptions.RequestException as e:
62
  print(f"Error fetching questions: {e}")
63
  return f"Error fetching questions: {e}", None
64
  except requests.exceptions.JSONDecodeError as e:
65
- print(f"Error decoding JSON response from questions endpoint: {e}")
66
- print(f"Response text: {response.text[:500]}")
67
- return f"Error decoding server response for questions: {e}", None
68
  except Exception as e:
69
  print(f"An unexpected error occurred fetching questions: {e}")
70
  return f"An unexpected error occurred fetching questions: {e}", None
71
 
72
- # 3. Run your Agent
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.")
92
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
93
 
94
- # 4. Prepare Submission
95
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
96
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
97
  print(status_update)
98
 
99
- # 5. Submit
100
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
101
  try:
102
  response = requests.post(submit_url, json=submission_data, timeout=60)
@@ -146,15 +248,14 @@ with gr.Blocks() as demo:
146
  gr.Markdown(
147
  """
148
  **Instructions:**
149
-
150
- 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
151
- 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
152
- 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
153
 
154
  ---
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
 
@@ -163,7 +264,6 @@ with gr.Blocks() as demo:
163
  run_button = gr.Button("Run Evaluation & Submit All Answers")
164
 
165
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
166
- # Removed max_rows=10 from DataFrame constructor
167
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
168
 
169
  run_button.click(
@@ -172,25 +272,24 @@ with gr.Blocks() as demo:
172
  )
173
 
174
  if __name__ == "__main__":
175
- print("\n" + "-"*30 + " App Starting " + "-"*30)
176
- # Check for SPACE_HOST and SPACE_ID at startup for information
177
  space_host_startup = os.getenv("SPACE_HOST")
178
- space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
179
 
180
  if space_host_startup:
181
  print(f"✅ SPACE_HOST found: {space_host_startup}")
182
  print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
183
  else:
184
- print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
185
 
186
- if space_id_startup: # Print repo URLs if SPACE_ID is found
187
  print(f"✅ SPACE_ID found: {space_id_startup}")
188
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
189
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
190
  else:
191
- print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
192
 
193
- print("-"*(60 + len(" App Starting ")) + "\n")
194
 
195
  print("Launching Gradio Interface for Basic Agent Evaluation...")
196
  demo.launch(debug=True, share=False)
 
1
+ import spaces # must be the first import — required by ZeroGPU Spaces
2
+
3
  import os
4
+ import tempfile
5
+ from pathlib import Path
6
+ from typing import Optional
7
+
8
  import gradio as gr
9
  import requests
 
10
  import pandas as pd
11
 
12
+ from smolagents import CodeAgent, InferenceClientModel
13
+
14
  # --- Constants ---
15
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
16
 
17
+ # This Space's free-tier hardware is ZeroGPU, which refuses to start unless
18
+ # at least one function is decorated with @spaces.GPU. The agent itself never
19
+ # touches a GPU (it only calls HF Inference Providers over HTTP), so this
20
+ # function exists purely to satisfy that startup check and is never called.
21
+ @spaces.GPU
22
+ def _zerogpu_startup_check():
23
+ return None
24
+
25
+ # Instructions appended to every question so the CodeAgent behaves like a
26
+ # GAIA-solving agent rather than a free-form chatbot. Kept as plain task
27
+ # framing (not a tool) to avoid adding moving parts.
28
+ TASK_RULES = """
29
+ Rules:
30
+ 1. Think step by step. Break multi-part questions into sub-steps before acting.
31
+ 2. Use web search for anything requiring current facts, names, dates, or
32
+ information you are not already certain of. Never invent facts or sources.
33
+ 3. Use Python (you write code as your actions) for arithmetic, counting,
34
+ sorting, filtering, or any data processing rather than doing it in your head.
35
+ 4. If an attachment path is given below, open and inspect it with Python
36
+ before answering — never guess its contents.
37
+ 5. Where practical, verify an important intermediate result a second way
38
+ before finalizing.
39
+ 6. Call final_answer(...) with ONLY the exact value requested:
40
+ - a bare number (no commas, no units unless the question asks for units)
41
+ - a bare string (no "The answer is", no trailing period, no quotes)
42
+ - a comma-separated list only if asked for a list, formatted exactly as
43
+ requested (spacing, order, etc.)
44
+ Do not include your reasoning or the words "FINAL ANSWER" in that value.
45
+ """
46
+
47
+ MAX_STEPS = 10
48
+ ADDITIONAL_IMPORTS = [
49
+ "pandas", "numpy", "csv", "json", "re", "math", "statistics",
50
+ "datetime", "itertools", "collections", "io", "os", "pypdf", "openpyxl",
51
+ ]
52
+
53
+
54
+ class GAIAAgent:
55
+ """
56
+ Wraps a smolagents CodeAgent for GAIA-style questions: general reasoning,
57
+ Python for calculation/data processing, web search, and local-file
58
+ inspection when a question ships an attachment.
59
+ """
60
+
61
  def __init__(self):
62
+ hf_token = os.environ.get("HF_TOKEN")
63
+ model_id = os.environ.get("GAIA_MODEL_ID") # optional override
64
+
65
+ model_kwargs = {}
66
+ if hf_token:
67
+ model_kwargs["token"] = hf_token
68
+ if model_id:
69
+ model_kwargs["model_id"] = model_id
70
+ model = InferenceClientModel(**model_kwargs)
71
+
72
+ self.agent = CodeAgent(
73
+ tools=[],
74
+ model=model,
75
+ add_base_tools=True, # gives web search + python interpreter + friends
76
+ additional_authorized_imports=ADDITIONAL_IMPORTS,
77
+ max_steps=MAX_STEPS,
78
+ )
79
+ print("GAIAAgent initialized (smolagents CodeAgent).")
80
+
81
+ def __call__(self, question: str, file_path: Optional[str] = None) -> str:
82
+ task = question + "\n\n" + TASK_RULES
83
+ if file_path:
84
+ task += (
85
+ f"\nAn attachment for this task was downloaded to this local "
86
+ f"path: {file_path}\nOpen it with Python and inspect its "
87
+ f"contents before answering.\n"
88
+ )
89
+ raw_answer = self.agent.run(task)
90
+ return clean_final_answer(raw_answer)
91
+
92
+
93
+ def clean_final_answer(raw) -> str:
94
+ """Light, conservative cleanup only — no aggressive normalization that
95
+ could alter a valid exact-match answer."""
96
+ text = str(raw).strip()
97
+ if len(text) >= 2 and text[0] == text[-1] and text[0] in "\"'":
98
+ text = text[1:-1].strip()
99
+ for prefix in ("FINAL ANSWER:", "Final answer:", "Answer:", "answer:"):
100
+ if text.startswith(prefix):
101
+ text = text[len(prefix):].strip()
102
+ return text
103
+
104
+
105
+ def download_task_file(api_url: str, task_id: str, file_name: str) -> Optional[str]:
106
+ """Downloads the attachment for a task via the existing /files/{task_id}
107
+ endpoint. Returns a local path, or None if there's no file or the
108
+ download fails (failure here must not crash the whole run)."""
109
+ if not file_name:
110
+ return None
111
+ try:
112
+ resp = requests.get(f"{api_url}/files/{task_id}", timeout=30)
113
+ resp.raise_for_status()
114
+ out_dir = Path(tempfile.gettempdir()) / "gaia_files"
115
+ out_dir.mkdir(exist_ok=True)
116
+ out_path = out_dir / file_name
117
+ out_path.write_bytes(resp.content)
118
+ return str(out_path)
119
+ except Exception as e:
120
+ print(f"Could not download file for task {task_id}: {e}")
121
+ return None
122
+
123
+
124
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
125
  """
126
+ Fetches all questions, runs the GAIAAgent on them (downloading any
127
+ attachment first), submits all answers, and displays the results.
128
  """
129
+ space_id = os.getenv("SPACE_ID")
 
130
 
131
  if profile:
132
+ username = f"{profile.username}"
133
  print(f"User logged in: {username}")
134
  else:
135
  print("User not logged in.")
 
139
  questions_url = f"{api_url}/questions"
140
  submit_url = f"{api_url}/submit"
141
 
 
142
  try:
143
+ agent = GAIAAgent()
144
  except Exception as e:
145
  print(f"Error instantiating agent: {e}")
146
  return f"Error initializing agent: {e}", None
147
+
148
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
149
  print(agent_code)
150
 
 
151
  print(f"Fetching questions from: {questions_url}")
152
  try:
153
  response = requests.get(questions_url, timeout=15)
154
  response.raise_for_status()
155
  questions_data = response.json()
156
  if not questions_data:
157
+ print("Fetched questions list is empty.")
158
+ return "Fetched questions list is empty or invalid format.", None
159
  print(f"Fetched {len(questions_data)} questions.")
160
  except requests.exceptions.RequestException as e:
161
  print(f"Error fetching questions: {e}")
162
  return f"Error fetching questions: {e}", None
163
  except requests.exceptions.JSONDecodeError as e:
164
+ print(f"Error decoding JSON response from questions endpoint: {e}")
165
+ print(f"Response text: {response.text[:500]}")
166
+ return f"Error decoding server response for questions: {e}", None
167
  except Exception as e:
168
  print(f"An unexpected error occurred fetching questions: {e}")
169
  return f"An unexpected error occurred fetching questions: {e}", None
170
 
 
171
  results_log = []
172
  answers_payload = []
173
  print(f"Running agent on {len(questions_data)} questions...")
174
  for item in questions_data:
175
  task_id = item.get("task_id")
176
  question_text = item.get("question")
177
+ file_name = item.get("file_name")
178
  if not task_id or question_text is None:
179
  print(f"Skipping item with missing task_id or question: {item}")
180
  continue
181
+
182
+ file_path = None
183
+ if file_name:
184
+ file_path = download_task_file(api_url, task_id, file_name)
185
+
186
  try:
187
+ submitted_answer = agent(question_text, file_path=file_path)
188
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
189
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
190
  except Exception as e:
191
+ print(f"Error running agent on task {task_id}: {e}")
192
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
193
 
194
  if not answers_payload:
195
  print("Agent did not produce any answers to submit.")
196
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
197
 
 
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
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
203
  try:
204
  response = requests.post(submit_url, json=submission_data, timeout=60)
 
248
  gr.Markdown(
249
  """
250
  **Instructions:**
251
+ 1. Log in to your Hugging Face account using the button below.
252
+ 2. Click 'Run Evaluation & Submit All Answers' to fetch questions, run the agent,
253
+ submit answers, and see the score.
 
254
 
255
  ---
256
  **Disclaimers:**
257
+ This can take a while — the agent works through each GAIA question in turn,
258
+ calling the model and, when needed, web search or Python execution.
259
  """
260
  )
261
 
 
264
  run_button = gr.Button("Run Evaluation & Submit All Answers")
265
 
266
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
267
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
268
 
269
  run_button.click(
 
272
  )
273
 
274
  if __name__ == "__main__":
275
+ print("\n" + "-" * 30 + " App Starting " + "-" * 30)
 
276
  space_host_startup = os.getenv("SPACE_HOST")
277
+ space_id_startup = os.getenv("SPACE_ID")
278
 
279
  if space_host_startup:
280
  print(f"✅ SPACE_HOST found: {space_host_startup}")
281
  print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
282
  else:
283
+ print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
284
 
285
+ if space_id_startup:
286
  print(f"✅ SPACE_ID found: {space_id_startup}")
287
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
288
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
289
  else:
290
+ print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
291
 
292
+ print("-" * (60 + len(" App Starting ")) + "\n")
293
 
294
  print("Launching Gradio Interface for Basic Agent Evaluation...")
295
  demo.launch(debug=True, share=False)