OlexandrPaz commited on
Commit
8b602ea
·
verified ·
1 Parent(s): 8e2f440

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +269 -288
app.py CHANGED
@@ -1,4 +1,6 @@
1
  import os
 
 
2
 
3
  import gradio as gr
4
  import pandas as pd
@@ -8,22 +10,27 @@ from smolagents import (
8
  CodeAgent,
9
  DuckDuckGoSearchTool,
10
  InferenceClientModel,
 
11
  )
12
 
13
 
14
- # ---------------------------------------------------------
15
- # Configuration
16
- # ---------------------------------------------------------
17
 
18
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
19
 
 
 
20
 
21
- # ---------------------------------------------------------
22
- # Agent
23
- # ---------------------------------------------------------
 
24
 
25
  class BasicAgent:
26
  def __init__(self):
 
27
  print("Initializing GAIA agent...")
28
 
29
  hf_token = os.getenv("HF_TOKEN")
@@ -31,18 +38,28 @@ class BasicAgent:
31
  if not hf_token:
32
  raise RuntimeError(
33
  "HF_TOKEN is missing. "
34
- "Add it in Space -> Settings -> Variables and secrets."
35
  )
36
 
 
 
37
  self.model = InferenceClientModel(
38
- token=hf_token
 
 
39
  )
40
 
41
  self.agent = CodeAgent(
 
42
  tools=[
43
- DuckDuckGoSearchTool(),
 
 
 
 
 
 
44
  ],
45
- model=self.model,
46
  additional_authorized_imports=[
47
  "requests",
48
  "re",
@@ -52,284 +69,306 @@ class BasicAgent:
52
  "statistics",
53
  "collections",
54
  "itertools",
 
55
  ],
56
- max_steps=12,
57
  )
58
 
59
  print("GAIA agent initialized successfully.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  def __call__(self, question: str) -> str:
62
  print("\n" + "=" * 80)
63
- print("QUESTION:")
 
64
  print(question)
65
  print("=" * 80)
66
 
67
  prompt = f"""
68
- You are an autonomous agent solving a GAIA benchmark question.
69
-
70
- Your objective is to determine the exact final answer.
71
-
72
- You may use:
73
- - web search
74
- - Python/code
75
- - HTTP requests
76
- - calculations
77
- - text processing
78
-
79
- Instructions:
80
 
81
- 1. Read the question extremely carefully.
 
82
 
83
- 2. Determine whether the answer can be derived directly or whether
84
- external research is necessary.
85
 
86
- 3. When current or factual information is required, use web search.
87
 
88
- 4. When calculations, transformations, counting, decoding, reversing
89
- text, parsing, or similar operations are required, use Python.
90
 
91
- 5. Verify important facts whenever possible.
92
 
93
- 6. Pay very close attention to requested formatting.
94
 
95
- 7. The final response MUST contain ONLY the answer.
 
96
 
97
- Do NOT include:
98
- - explanations
99
- - reasoning
100
- - citations
101
- - "FINAL ANSWER:"
102
- - introductory text
103
 
104
- Examples of valid final responses:
 
 
105
 
106
- 7
107
 
108
- Mercedes Sosa
109
 
110
- Paris
 
 
 
 
 
111
 
112
- 12, 15, 18
 
113
 
114
- The answer should be as short and exact as possible.
 
115
 
116
  QUESTION:
117
 
118
  {question}
 
 
119
  """
120
 
121
- try:
122
- result = self.agent.run(prompt)
123
 
124
- answer = str(result).strip()
125
 
126
- # Some models may still prepend FINAL ANSWER.
127
- prefixes = [
128
- "FINAL ANSWER:",
129
- "Final Answer:",
130
- "Final answer:",
131
- ]
132
 
133
- for prefix in prefixes:
134
- if answer.startswith(prefix):
135
- answer = answer[len(prefix):].strip()
 
136
 
137
- print("\nAGENT FINAL ANSWER:")
138
- print(answer)
139
 
140
- return answer
141
 
142
- except Exception as e:
143
- print(f"Agent error: {e}")
144
- return ""
145
 
 
 
146
 
147
- # ---------------------------------------------------------
148
- # Evaluation
149
- # ---------------------------------------------------------
150
 
151
- def run_and_submit_all(profile: gr.OAuthProfile | None):
 
 
 
152
 
153
- space_id = os.getenv("SPACE_ID")
154
 
155
- if profile:
156
- username = f"{profile.username}"
157
- print(f"User logged in: {username}")
158
- else:
159
- print("User not logged in.")
160
- return "Please Login to Hugging Face with the button.", None
161
 
162
- api_url = DEFAULT_API_URL
 
 
 
163
 
164
- questions_url = f"{api_url}/questions"
165
- submit_url = f"{api_url}/submit"
166
 
167
- # -----------------------------------------------------
168
- # Initialize agent
169
- # -----------------------------------------------------
170
 
171
- try:
172
- agent = BasicAgent()
173
 
174
- except Exception as e:
175
- print(f"Error instantiating agent: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
 
177
  return (
178
- f"Error initializing agent: {e}",
179
- None,
180
  )
181
 
182
- # Public link to your agent source code
183
  agent_code = (
184
- f"https://huggingface.co/spaces/"
185
- f"{space_id}/tree/main"
186
  )
187
 
188
- print(f"Agent code: {agent_code}")
189
-
190
  # -----------------------------------------------------
191
- # Fetch questions
192
  # -----------------------------------------------------
193
 
194
- print(f"Fetching questions from: {questions_url}")
195
-
196
  try:
197
- response = requests.get(
198
- questions_url,
199
- timeout=30,
200
- )
201
-
202
- response.raise_for_status()
203
-
204
- questions_data = response.json()
205
 
206
- if not questions_data:
207
- return (
208
- "Fetched questions list is empty or invalid.",
209
- None,
210
- )
211
 
212
- print(
213
- f"Fetched {len(questions_data)} questions."
 
214
  )
215
 
216
- except requests.exceptions.RequestException as e:
217
-
218
- print(f"Error fetching questions: {e}")
219
 
220
- return (
221
- f"Error fetching questions: {e}",
222
- None,
223
- )
224
 
225
  except Exception as e:
226
-
227
- print(
228
- f"Unexpected error fetching questions: {e}"
229
- )
230
 
231
  return (
232
- f"Unexpected error fetching questions: {e}",
233
- None,
234
  )
235
 
236
  # -----------------------------------------------------
237
- # Run agent
238
  # -----------------------------------------------------
239
 
240
  results_log = []
241
  answers_payload = []
242
 
243
- print(
244
- f"Running agent on "
245
- f"{len(questions_data)} questions..."
246
- )
247
 
248
- for index, item in enumerate(
249
- questions_data,
250
- start=1,
251
- ):
252
 
 
253
  task_id = item.get("task_id")
254
- question_text = item.get("question")
255
 
256
- if not task_id or question_text is None:
257
- print(
258
- f"Skipping invalid question: {item}"
259
- )
260
  continue
261
 
262
  print("\n" + "#" * 80)
 
 
 
263
 
264
- print(
265
- f"QUESTION "
266
- f"{index}/{len(questions_data)}"
267
- )
268
 
269
- print(f"Task ID: {task_id}")
270
 
271
- try:
272
- submitted_answer = agent(
273
- question_text
 
 
 
 
 
 
 
 
 
 
 
274
  )
275
 
276
  except Exception as e:
 
277
 
278
- print(
279
- f"Error running agent on "
280
- f"{task_id}: {e}"
 
281
  )
282
 
283
- submitted_answer = ""
 
 
 
284
 
285
- answers_payload.append(
286
- {
287
- "task_id": task_id,
288
- "submitted_answer":
289
- submitted_answer,
290
- }
291
- )
 
 
 
292
 
293
- results_log.append(
294
- {
295
- "Task ID": task_id,
296
- "Question": question_text,
297
- "Submitted Answer":
298
- submitted_answer,
299
- }
300
- )
301
 
302
  # -----------------------------------------------------
303
- # Ensure answers exist
304
  # -----------------------------------------------------
305
 
306
- if not answers_payload:
307
-
308
  return (
309
- "Agent did not produce any answers.",
310
- pd.DataFrame(results_log),
 
 
 
 
 
311
  )
312
 
 
 
 
 
 
 
313
  # -----------------------------------------------------
314
- # Submission payload
315
  # -----------------------------------------------------
316
 
317
  submission_data = {
318
- "username": username.strip(),
319
  "agent_code": agent_code,
320
  "answers": answers_payload,
321
  }
322
 
 
 
323
  print(
324
- f"Agent finished. Submitting "
325
- f"{len(answers_payload)} answers "
326
- f"for user '{username}'..."
327
  )
328
 
329
- # -----------------------------------------------------
330
- # Submit
331
- # -----------------------------------------------------
332
-
333
  try:
334
  response = requests.post(
335
  submit_url,
@@ -339,137 +378,88 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
339
 
340
  response.raise_for_status()
341
 
342
- result_data = response.json()
343
-
344
- final_status = (
345
- "Submission Successful!\n"
346
- f"User: "
347
- f"{result_data.get('username')}\n"
348
- f"Overall Score: "
349
- f"{result_data.get('score', 'N/A')}% "
350
- f"("
351
- f"{result_data.get('correct_count', '?')}/"
352
- f"{result_data.get('total_attempted', '?')}"
353
- f" correct)\n"
354
- f"Message: "
355
- f"{result_data.get('message', 'No message received.')}"
356
- )
357
-
358
- print(final_status)
359
-
360
- return (
361
- final_status,
362
- pd.DataFrame(results_log),
363
- )
364
-
365
- except requests.exceptions.HTTPError as e:
366
-
367
- error_detail = (
368
- f"Server responded with status "
369
- f"{e.response.status_code}."
370
- )
371
-
372
- try:
373
- error_json = e.response.json()
374
-
375
- error_detail += (
376
- f" Detail: "
377
- f"{error_json.get('detail', e.response.text)}"
378
- )
379
 
380
- except Exception:
381
- error_detail += (
382
- f" Response: "
383
- f"{e.response.text[:500]}"
384
- )
385
-
386
- status_message = (
387
- f"Submission Failed: {error_detail}"
388
  )
389
 
390
- print(status_message)
391
-
392
- return (
393
- status_message,
394
- pd.DataFrame(results_log),
 
 
 
395
  )
396
 
397
- except requests.exceptions.Timeout:
398
-
399
- status_message = (
400
- "Submission Failed: "
401
- "The request timed out."
402
- )
403
 
404
- print(status_message)
405
 
406
- return (
407
- status_message,
408
- pd.DataFrame(results_log),
409
- )
410
-
411
- except requests.exceptions.RequestException as e:
412
-
413
- status_message = (
414
- f"Submission Failed: "
415
- f"Network error - {e}"
416
- )
417
 
418
- print(status_message)
 
 
 
419
 
420
  return (
421
- status_message,
422
- pd.DataFrame(results_log),
 
 
423
  )
424
 
425
  except Exception as e:
426
-
427
- status_message = (
428
- f"Unexpected submission error: {e}"
429
- )
430
-
431
- print(status_message)
432
 
433
  return (
434
- status_message,
435
- pd.DataFrame(results_log),
 
436
  )
437
 
438
 
439
- # ---------------------------------------------------------
440
- # Gradio UI
441
- # ---------------------------------------------------------
442
 
443
  with gr.Blocks() as demo:
444
-
445
- gr.Markdown(
446
- "# GAIA Agent Evaluation Runner"
447
- )
448
-
449
  gr.Markdown(
450
  """
 
 
451
  ### Instructions
452
 
453
  1. Log in with your Hugging Face account.
454
  2. Click **Run Evaluation & Submit All Answers**.
455
- 3. The agent will fetch the GAIA questions.
456
- 4. It will solve each question.
457
- 5. Answers will automatically be submitted.
458
- 6. Your score will appear below.
 
459
 
460
- The evaluation can take several minutes.
461
  """
462
  )
463
 
464
  gr.LoginButton()
465
 
466
  run_button = gr.Button(
467
- "Run Evaluation & Submit All Answers"
 
468
  )
469
 
470
  status_output = gr.Textbox(
471
  label="Run Status / Submission Result",
472
- lines=6,
473
  interactive=False,
474
  )
475
 
@@ -487,26 +477,17 @@ The evaluation can take several minutes.
487
  )
488
 
489
 
490
- # ---------------------------------------------------------
491
- # Start
492
- # ---------------------------------------------------------
493
 
494
  if __name__ == "__main__":
495
-
496
  print("\n" + "=" * 80)
497
-
498
- print("Starting GAIA Agent Space")
499
-
500
- print(
501
- f"SPACE_ID: "
502
- f"{os.getenv('SPACE_ID', 'not found')}"
503
- )
504
-
505
- print(
506
- f"SPACE_HOST: "
507
- f"{os.getenv('SPACE_HOST', 'not found')}"
508
- )
509
-
510
  print("=" * 80 + "\n")
511
 
512
  demo.launch(
 
1
  import os
2
+ import re
3
+ import traceback
4
 
5
  import gradio as gr
6
  import pandas as pd
 
10
  CodeAgent,
11
  DuckDuckGoSearchTool,
12
  InferenceClientModel,
13
+ VisitWebpageTool,
14
  )
15
 
16
 
17
+ # =========================================================
18
+ # CONFIG
19
+ # =========================================================
20
 
21
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
22
 
23
+ # Explicit model instead of relying on a changing default.
24
+ MODEL_ID = "Qwen/Qwen3-Next-80B-A3B-Thinking"
25
 
26
+
27
+ # =========================================================
28
+ # AGENT
29
+ # =========================================================
30
 
31
  class BasicAgent:
32
  def __init__(self):
33
+ print("=" * 80)
34
  print("Initializing GAIA agent...")
35
 
36
  hf_token = os.getenv("HF_TOKEN")
 
38
  if not hf_token:
39
  raise RuntimeError(
40
  "HF_TOKEN is missing. "
41
+ "Add HF_TOKEN in Space -> Settings -> Variables and secrets."
42
  )
43
 
44
+ print(f"Using model: {MODEL_ID}")
45
+
46
  self.model = InferenceClientModel(
47
+ model_id=MODEL_ID,
48
+ token=hf_token,
49
+ timeout=180,
50
  )
51
 
52
  self.agent = CodeAgent(
53
+ model=self.model,
54
  tools=[
55
+ DuckDuckGoSearchTool(
56
+ max_results=10,
57
+ rate_limit=1.0,
58
+ ),
59
+ VisitWebpageTool(
60
+ max_output_length=30000,
61
+ ),
62
  ],
 
63
  additional_authorized_imports=[
64
  "requests",
65
  "re",
 
69
  "statistics",
70
  "collections",
71
  "itertools",
72
+ "urllib.parse",
73
  ],
74
+ max_steps=15,
75
  )
76
 
77
  print("GAIA agent initialized successfully.")
78
+ print("=" * 80)
79
+
80
+ def clean_answer(self, value) -> str:
81
+ if value is None:
82
+ return ""
83
+
84
+ answer = str(value).strip()
85
+
86
+ # Remove common prefixes if model ignored instructions.
87
+ answer = re.sub(
88
+ r"^\s*(FINAL\s+ANSWER|Final\s+Answer|Final\s+answer)\s*:\s*",
89
+ "",
90
+ answer,
91
+ flags=re.IGNORECASE,
92
+ )
93
+
94
+ # Remove surrounding whitespace/newlines.
95
+ answer = answer.strip()
96
+
97
+ return answer
98
 
99
  def __call__(self, question: str) -> str:
100
  print("\n" + "=" * 80)
101
+ print("QUESTION")
102
+ print("=" * 80)
103
  print(question)
104
  print("=" * 80)
105
 
106
  prompt = f"""
107
+ You are solving one GAIA benchmark question.
 
 
 
 
 
 
 
 
 
 
 
108
 
109
+ Your goal is to obtain the exact answer, not merely explain how to
110
+ find it.
111
 
112
+ You have web-search and webpage-reading tools. You can also execute
113
+ Python code.
114
 
115
+ Work autonomously.
116
 
117
+ Rules:
 
118
 
119
+ 1. Carefully determine exactly what the question asks.
120
 
121
+ 2. If the question requires factual information, search the web.
122
 
123
+ 3. Do not trust only a search-result snippet when the underlying page
124
+ can be inspected. Open relevant pages and verify the information.
125
 
126
+ 4. If Wikipedia is explicitly mentioned, search for the relevant
127
+ Wikipedia page and inspect the required information.
 
 
 
 
128
 
129
+ 5. For counting, arithmetic, dates, string transformations, reversing
130
+ text, decoding, sorting, comparison, or other deterministic work,
131
+ use Python when useful.
132
 
133
+ 6. Cross-check ambiguous information when possible.
134
 
135
+ 7. Pay extremely close attention to the requested output format.
136
 
137
+ 8. Your final answer must be minimal. Examples:
138
+ 7
139
+ Paris
140
+ Mercedes Sosa
141
+ 12, 15, 18
142
+ Qh4
143
 
144
+ 9. Do NOT put explanations, citations, reasoning, Markdown, or
145
+ "FINAL ANSWER:" in the final answer.
146
 
147
+ 10. If the question contains a URL, investigate that URL or search for
148
+ information related to it when useful.
149
 
150
  QUESTION:
151
 
152
  {question}
153
+
154
+ Solve the problem and return only the exact final answer.
155
  """
156
 
157
+ result = self.agent.run(prompt)
 
158
 
159
+ answer = self.clean_answer(result)
160
 
161
+ if not answer:
162
+ raise RuntimeError(
163
+ "The agent completed without returning a final answer."
164
+ )
 
 
165
 
166
+ print("\n" + "-" * 80)
167
+ print("FINAL ANSWER:")
168
+ print(answer)
169
+ print("-" * 80)
170
 
171
+ return answer
 
172
 
 
173
 
174
+ # =========================================================
175
+ # FETCH QUESTIONS
176
+ # =========================================================
177
 
178
+ def fetch_questions():
179
+ questions_url = f"{DEFAULT_API_URL}/questions"
180
 
181
+ print(f"Fetching questions from: {questions_url}")
 
 
182
 
183
+ response = requests.get(
184
+ questions_url,
185
+ timeout=30,
186
+ )
187
 
188
+ response.raise_for_status()
189
 
190
+ data = response.json()
 
 
 
 
 
191
 
192
+ if not isinstance(data, list) or not data:
193
+ raise RuntimeError(
194
+ "The scoring API returned an empty or invalid questions list."
195
+ )
196
 
197
+ print(f"Fetched {len(data)} questions.")
 
198
 
199
+ return data
 
 
200
 
 
 
201
 
202
+ # =========================================================
203
+ # EVALUATION
204
+ # =========================================================
205
+
206
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
207
+ if not profile:
208
+ return (
209
+ "Please log in to Hugging Face first.",
210
+ pd.DataFrame(),
211
+ )
212
+
213
+ username = str(profile.username).strip()
214
+
215
+ print("\n" + "#" * 80)
216
+ print(f"USER: {username}")
217
+ print("#" * 80)
218
+
219
+ space_id = os.getenv("SPACE_ID")
220
 
221
+ if not space_id:
222
  return (
223
+ "SPACE_ID environment variable is missing.",
224
+ pd.DataFrame(),
225
  )
226
 
 
227
  agent_code = (
228
+ f"https://huggingface.co/spaces/{space_id}/tree/main"
 
229
  )
230
 
 
 
231
  # -----------------------------------------------------
232
+ # Initialize agent
233
  # -----------------------------------------------------
234
 
 
 
235
  try:
236
+ agent = BasicAgent()
 
 
 
 
 
 
 
237
 
238
+ except Exception as e:
239
+ traceback.print_exc()
 
 
 
240
 
241
+ return (
242
+ f"Error initializing agent:\n{type(e).__name__}: {e}",
243
+ pd.DataFrame(),
244
  )
245
 
246
+ # -----------------------------------------------------
247
+ # Fetch questions
248
+ # -----------------------------------------------------
249
 
250
+ try:
251
+ questions_data = fetch_questions()
 
 
252
 
253
  except Exception as e:
254
+ traceback.print_exc()
 
 
 
255
 
256
  return (
257
+ f"Error fetching questions:\n{type(e).__name__}: {e}",
258
+ pd.DataFrame(),
259
  )
260
 
261
  # -----------------------------------------------------
262
+ # Solve
263
  # -----------------------------------------------------
264
 
265
  results_log = []
266
  answers_payload = []
267
 
268
+ success_count = 0
269
+ error_count = 0
 
 
270
 
271
+ total = len(questions_data)
 
 
 
272
 
273
+ for index, item in enumerate(questions_data, start=1):
274
  task_id = item.get("task_id")
275
+ question = item.get("question")
276
 
277
+ if not task_id or question is None:
278
+ print(f"Skipping malformed task: {item}")
 
 
279
  continue
280
 
281
  print("\n" + "#" * 80)
282
+ print(f"TASK {index}/{total}")
283
+ print(f"TASK ID: {task_id}")
284
+ print("#" * 80)
285
 
286
+ try:
287
+ answer = agent(question)
 
 
288
 
289
+ success_count += 1
290
 
291
+ answers_payload.append(
292
+ {
293
+ "task_id": task_id,
294
+ "submitted_answer": answer,
295
+ }
296
+ )
297
+
298
+ results_log.append(
299
+ {
300
+ "Task ID": task_id,
301
+ "Question": question,
302
+ "Submitted Answer": answer,
303
+ "Status": "OK",
304
+ }
305
  )
306
 
307
  except Exception as e:
308
+ error_count += 1
309
 
310
+ traceback.print_exc()
311
+
312
+ error_message = (
313
+ f"{type(e).__name__}: {str(e)}"
314
  )
315
 
316
+ print(
317
+ f"\nERROR ON TASK {task_id}: "
318
+ f"{error_message}"
319
+ )
320
 
321
+ # IMPORTANT:
322
+ # Do NOT send an empty answer to the scoring API.
323
+ results_log.append(
324
+ {
325
+ "Task ID": task_id,
326
+ "Question": question,
327
+ "Submitted Answer": "",
328
+ "Status": error_message,
329
+ }
330
+ )
331
 
332
+ results_df = pd.DataFrame(results_log)
 
 
 
 
 
 
 
333
 
334
  # -----------------------------------------------------
335
+ # Prevent another useless 0/20 submission
336
  # -----------------------------------------------------
337
 
338
+ if success_count == 0:
 
339
  return (
340
+ "Evaluation stopped.\n\n"
341
+ f"Successful answers: 0/{total}\n"
342
+ f"Errors: {error_count}/{total}\n\n"
343
+ "Nothing was submitted because the model failed to "
344
+ "produce any answers.\n\n"
345
+ "Open Logs and inspect the Status column below.",
346
+ results_df,
347
  )
348
 
349
+ print("\n" + "=" * 80)
350
+ print("AGENT RUN COMPLETE")
351
+ print(f"Successful answers: {success_count}")
352
+ print(f"Errors: {error_count}")
353
+ print("=" * 80)
354
+
355
  # -----------------------------------------------------
356
+ # Submit only successfully generated answers
357
  # -----------------------------------------------------
358
 
359
  submission_data = {
360
+ "username": username,
361
  "agent_code": agent_code,
362
  "answers": answers_payload,
363
  }
364
 
365
+ submit_url = f"{DEFAULT_API_URL}/submit"
366
+
367
  print(
368
+ f"Submitting {len(answers_payload)} answers "
369
+ f"to {submit_url}"
 
370
  )
371
 
 
 
 
 
372
  try:
373
  response = requests.post(
374
  submit_url,
 
378
 
379
  response.raise_for_status()
380
 
381
+ result = response.json()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
 
383
+ score = result.get("score", "N/A")
384
+ correct = result.get("correct_count", "?")
385
+ attempted = result.get("total_attempted", "?")
386
+ message = result.get(
387
+ "message",
388
+ "No message received.",
 
 
389
  )
390
 
391
+ status = (
392
+ "Submission Successful!\n\n"
393
+ f"User: {result.get('username', username)}\n"
394
+ f"Generated answers: {success_count}/{total}\n"
395
+ f"Agent errors: {error_count}/{total}\n"
396
+ f"Score: {score}%\n"
397
+ f"Correct: {correct}/{attempted}\n\n"
398
+ f"{message}"
399
  )
400
 
401
+ print(status)
 
 
 
 
 
402
 
403
+ return status, results_df
404
 
405
+ except requests.exceptions.HTTPError as e:
406
+ traceback.print_exc()
 
 
 
 
 
 
 
 
 
407
 
408
+ try:
409
+ detail = e.response.json()
410
+ except Exception:
411
+ detail = e.response.text[:1000]
412
 
413
  return (
414
+ "Submission failed.\n\n"
415
+ f"HTTP {e.response.status_code}\n"
416
+ f"{detail}",
417
+ results_df,
418
  )
419
 
420
  except Exception as e:
421
+ traceback.print_exc()
 
 
 
 
 
422
 
423
  return (
424
+ "Submission failed.\n\n"
425
+ f"{type(e).__name__}: {e}",
426
+ results_df,
427
  )
428
 
429
 
430
+ # =========================================================
431
+ # UI
432
+ # =========================================================
433
 
434
  with gr.Blocks() as demo:
 
 
 
 
 
435
  gr.Markdown(
436
  """
437
+ # GAIA Agent Evaluation Runner
438
+
439
  ### Instructions
440
 
441
  1. Log in with your Hugging Face account.
442
  2. Click **Run Evaluation & Submit All Answers**.
443
+ 3. The agent will fetch the course questions.
444
+ 4. It will research and solve them.
445
+ 5. Successful answers will be submitted to the course scoring API.
446
+ 6. Errors will be displayed in the table instead of silently
447
+ submitting blank answers.
448
 
449
+ Evaluation may take several minutes.
450
  """
451
  )
452
 
453
  gr.LoginButton()
454
 
455
  run_button = gr.Button(
456
+ "Run Evaluation & Submit All Answers",
457
+ variant="primary",
458
  )
459
 
460
  status_output = gr.Textbox(
461
  label="Run Status / Submission Result",
462
+ lines=10,
463
  interactive=False,
464
  )
465
 
 
477
  )
478
 
479
 
480
+ # =========================================================
481
+ # START
482
+ # =========================================================
483
 
484
  if __name__ == "__main__":
 
485
  print("\n" + "=" * 80)
486
+ print("STARTING GAIA AGENT SPACE")
487
+ print(f"SPACE_ID: {os.getenv('SPACE_ID', 'NOT FOUND')}")
488
+ print(f"SPACE_HOST: {os.getenv('SPACE_HOST', 'NOT FOUND')}")
489
+ print(f"HF_TOKEN configured: {bool(os.getenv('HF_TOKEN'))}")
490
+ print(f"MODEL: {MODEL_ID}")
 
 
 
 
 
 
 
 
491
  print("=" * 80 + "\n")
492
 
493
  demo.launch(