dracero commited on
Commit
1a16fc7
·
verified ·
1 Parent(s): 40bc73d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -360
app.py CHANGED
@@ -3,440 +3,166 @@ import gradio as gr
3
  import requests
4
  import inspect
5
  import pandas as pd
6
- import google.generativeai as genai
7
- from langchain_core.prompts import ChatPromptTemplate
8
- from langchain_core.output_parsers import StrOutputParser
9
- from langchain_core.messages import HumanMessage, SystemMessage
10
- from typing import Dict, List, Any, Tuple, Optional
11
- import json
12
- from langchain_google_genai import ChatGoogleGenerativeAI
13
- from langgraph.graph import END, StateGraph
14
- from langgraph.prebuilt import ToolExecutor, ToolInvocation
15
 
 
16
  # --- Constants ---
17
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
18
- GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "") # Asegúrate de configurar esta variable de entorno
19
 
20
- # Configuración de Gemini
21
- if GEMINI_API_KEY:
22
- genai.configure(api_key=GEMINI_API_KEY)
23
- else:
24
- print("WARNING: GEMINI_API_KEY not set. The agent will not function properly.")
25
-
26
- # --- Definición de herramientas ---
27
- def search_web(query: str) -> str:
28
- """Simula una búsqueda web para obtener información relevante."""
29
- # En un entorno real, aquí se conectaría a un servicio de búsqueda
30
- return f"Resultados simulados de búsqueda para: {query}"
31
-
32
- def calculate(expression: str) -> str:
33
- """Realiza cálculos matemáticos básicos."""
34
- try:
35
- result = eval(expression)
36
- return f"El resultado de {expression} es {result}"
37
- except Exception as e:
38
- return f"Error al calcular: {str(e)}"
39
-
40
- # Definición de herramientas disponibles
41
- tools = [
42
- {
43
- "name": "search_web",
44
- "description": "Busca información en la web sobre un tema específico",
45
- "parameters": {
46
- "type": "object",
47
- "properties": {
48
- "query": {
49
- "type": "string",
50
- "description": "La consulta de búsqueda"
51
- }
52
- },
53
- "required": ["query"]
54
- },
55
- "function": search_web
56
- },
57
- {
58
- "name": "calculate",
59
- "description": "Realiza cálculos matemáticos",
60
- "parameters": {
61
- "type": "object",
62
- "properties": {
63
- "expression": {
64
- "type": "string",
65
- "description": "La expresión matemática a calcular"
66
- }
67
- },
68
- "required": ["expression"]
69
- },
70
- "function": calculate
71
- }
72
- ]
73
-
74
- # Crear el ejecutor de herramientas
75
- tool_executor = ToolExecutor(tools)
76
-
77
- # --- Componentes del Sistema Multiagente ---
78
- class AgentState(Dict):
79
- """Estado del agente que se pasa entre nodos del grafo."""
80
- question: str
81
- thoughts: List[str]
82
- tool_calls: List[Dict]
83
- tool_results: List[Dict]
84
- answer: Optional[str] = None
85
-
86
- # Componente para analizar la pregunta
87
- def analyze_question(state: AgentState) -> AgentState:
88
- """Analiza la pregunta para determinar cómo abordarla."""
89
- llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0)
90
-
91
- prompt = ChatPromptTemplate.from_messages([
92
- SystemMessage(content="""Eres un agente analítico que examina preguntas para determinar su naturaleza y cómo abordarlas.
93
- Analiza la pregunta proporcionada y describe brevemente:
94
- 1. Tipo de pregunta (factual, opinión, cálculo, etc.)
95
- 2. Conocimiento necesario para responder
96
- 3. Si se necesita alguna herramienta específica
97
- Proporciona tu análisis en formato conciso."""),
98
- HumanMessage(content=f"Analiza esta pregunta: {state['question']}")
99
- ])
100
-
101
- chain = prompt | llm | StrOutputParser()
102
- analysis = chain.invoke({})
103
-
104
- state["thoughts"] = state.get("thoughts", []) + [f"Análisis: {analysis}"]
105
- return state
106
-
107
- # Componente para decidir si usar herramientas
108
- def decide_tool_use(state: AgentState) -> str:
109
- """Decide si usar herramientas o responder directamente."""
110
- llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0)
111
-
112
- tools_descriptions = "\n".join([f"- {tool['name']}: {tool['description']}" for tool in tools])
113
-
114
- prompt = ChatPromptTemplate.from_messages([
115
- SystemMessage(content=f"""Eres un agente que decide si necesita usar herramientas para responder preguntas.
116
- Las herramientas disponibles son:
117
- {tools_descriptions}
118
-
119
- Si la pregunta requiere usar una herramienta, responde con "use_tool" e indica qué herramienta usar.
120
- Si puedes responder directamente sin herramientas, responde con "direct_answer"."""),
121
- HumanMessage(content=f"""
122
- Pregunta: {state['question']}
123
- Pensamientos previos: {state['thoughts']}
124
-
125
- ¿Debo usar una herramienta o responder directamente?""")
126
- ])
127
-
128
- chain = prompt | llm | StrOutputParser()
129
- decision = chain.invoke({})
130
-
131
- state["thoughts"] = state.get("thoughts", []) + [f"Decisión: {decision}"]
132
-
133
- if "use_tool" in decision.lower():
134
- return "use_tool"
135
- else:
136
- return "direct_answer"
137
-
138
- # Componente para seleccionar y usar herramientas
139
- def select_and_use_tool(state: AgentState) -> AgentState:
140
- """Selecciona una herramienta apropiada y la utiliza."""
141
- llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0)
142
-
143
- tools_descriptions = json.dumps(tools, indent=2)
144
-
145
- prompt = ChatPromptTemplate.from_messages([
146
- SystemMessage(content=f"""Eres un agente que selecciona y usa herramientas.
147
- Las herramientas disponibles son:
148
- {tools_descriptions}
149
-
150
- Selecciona la herramienta más apropiada para la pregunta y proporciona los parámetros necesarios.
151
- Responde con un JSON exactamente en este formato:
152
- {{
153
- "tool_name": "nombre_de_la_herramienta",
154
- "parameters": {{
155
- "param1": "valor1",
156
- ...
157
- }}
158
- }}"""),
159
- HumanMessage(content=f"""
160
- Pregunta: {state['question']}
161
- Pensamientos previos: {state['thoughts']}
162
-
163
- ¿Qué herramienta debo usar y con qué parámetros?""")
164
- ])
165
-
166
- chain = prompt | llm | StrOutputParser()
167
- tool_selection = chain.invoke({})
168
-
169
- # Procesar la selección de herramienta
170
- try:
171
- tool_data = json.loads(tool_selection)
172
- tool_name = tool_data.get("tool_name")
173
- parameters = tool_data.get("parameters", {})
174
-
175
- # Verificar que la herramienta existe
176
- tool_exists = any(tool["name"] == tool_name for tool in tools)
177
- if not tool_exists:
178
- state["thoughts"] = state.get("thoughts", []) + [f"Error: La herramienta '{tool_name}' no existe."]
179
- return state
180
-
181
- # Preparar la invocación de la herramienta
182
- tool_invocation = ToolInvocation(
183
- name=tool_name,
184
- parameters=parameters
185
- )
186
-
187
- # Ejecutar la herramienta
188
- result = tool_executor.invoke(tool_invocation)
189
-
190
- # Almacenar el resultado
191
- state["tool_calls"] = state.get("tool_calls", []) + [{"tool": tool_name, "parameters": parameters}]
192
- state["tool_results"] = state.get("tool_results", []) + [{"tool": tool_name, "result": result}]
193
- state["thoughts"] = state.get("thoughts", []) + [f"Resultado de {tool_name}: {result}"]
194
-
195
- except Exception as e:
196
- state["thoughts"] = state.get("thoughts", []) + [f"Error al usar herramienta: {str(e)}"]
197
-
198
- return state
199
-
200
- # Componente para formular la respuesta final
201
- def formulate_answer(state: AgentState) -> AgentState:
202
- """Formula la respuesta final basada en toda la información recopilada."""
203
- llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0)
204
-
205
- # Preparar el contexto para la respuesta
206
- tool_results = "\n".join([
207
- f"- {result['tool']}: {result['result']}"
208
- for result in state.get("tool_results", [])
209
- ])
210
-
211
- prompt = ChatPromptTemplate.from_messages([
212
- SystemMessage(content="""Eres un agente experto que formula respuestas precisas y útiles.
213
- Usa toda la información disponible para proporcionar la mejor respuesta posible.
214
- Sé conciso pero completo. No menciones tu proceso de pensamiento en la respuesta final."""),
215
- HumanMessage(content=f"""
216
- Pregunta original: {state['question']}
217
-
218
- Pensamientos previos: {state['thoughts']}
219
-
220
- Resultados de herramientas:
221
- {tool_results if tool_results else "No se usaron herramientas"}
222
-
223
- Por favor, formula una respuesta final a la pregunta original.""")
224
- ])
225
-
226
- chain = prompt | llm | StrOutputParser()
227
- final_answer = chain.invoke({})
228
-
229
- state["answer"] = final_answer
230
- return state
231
-
232
- # --- Definición del Grafo del Sistema Multiagente ---
233
- def build_agent_graph():
234
- """Construye el grafo de flujo del sistema multiagente."""
235
- # Crear el grafo
236
- graph = StateGraph(AgentState)
237
-
238
- # Añadir nodos
239
- graph.add_node("analyze_question", analyze_question)
240
- graph.add_node("decide_tool_use", decide_tool_use)
241
- graph.add_node("select_and_use_tool", select_and_use_tool)
242
- graph.add_node("formulate_answer", formulate_answer)
243
-
244
- # Definir el flujo
245
- graph.add_edge("analyze_question", "decide_tool_use")
246
- graph.add_conditional_edges(
247
- "decide_tool_use",
248
- {
249
- "use_tool": "select_and_use_tool",
250
- "direct_answer": "formulate_answer"
251
- }
252
- )
253
- graph.add_edge("select_and_use_tool", "formulate_answer")
254
- graph.add_edge("formulate_answer", END)
255
-
256
- # Compilar el grafo
257
- return graph.compile()
258
-
259
- # --- Implementación del Agente Principal ---
260
- class MultiAgentSystem:
261
  def __init__(self):
262
- print("Inicializando Sistema Multiagente con LangGraph y Gemini 2.5 Flash...")
263
- if not GEMINI_API_KEY:
264
- print("ADVERTENCIA: GEMINI_API_KEY no está configurado. El sistema no funcionará correctamente.")
265
- self.agent_graph = build_agent_graph()
266
-
267
  def __call__(self, question: str) -> str:
268
- print(f"Recibiendo pregunta: {question[:50]}...")
269
-
270
- if not GEMINI_API_KEY:
271
- return "Error: GEMINI_API_KEY no está configurado. No se puede procesar la pregunta."
272
-
273
- try:
274
- # Inicializar el estado
275
- initial_state = AgentState(
276
- question=question,
277
- thoughts=[],
278
- tool_calls=[],
279
- tool_results=[]
280
- )
281
-
282
- # Ejecutar el grafo de agentes
283
- print("Procesando con el sistema multiagente...")
284
- final_state = self.agent_graph.invoke(initial_state)
285
-
286
- # Obtener y devolver la respuesta
287
- answer = final_state.get("answer", "No se pudo generar una respuesta.")
288
- print(f"Respuesta generada: {answer[:50]}...")
289
- return answer
290
-
291
- except Exception as e:
292
- error_msg = f"Error al procesar la pregunta: {str(e)}"
293
- print(error_msg)
294
- return error_msg
295
 
296
- # --- Función para ejecutar la evaluación y enviar respuestas ---
297
- def run_and_submit_all(profile: gr.OAuthProfile | None):
298
  """
299
- Obtiene todas las preguntas, ejecuta el Sistema Multiagente en ellas, envía todas las respuestas,
300
- y muestra los resultados.
301
  """
302
- # --- Determinar URL de ejecución de HF Space y URL del repositorio ---
303
- space_id = os.getenv("SPACE_ID") # Obtener SPACE_ID para enviar enlace al código
304
 
305
  if profile:
306
- username = f"{profile.username}"
307
- print(f"Usuario conectado: {username}")
308
  else:
309
- print("Usuario no conectado.")
310
- return "Por favor, inicia sesión en Hugging Face con el botón.", None
311
 
312
  api_url = DEFAULT_API_URL
313
  questions_url = f"{api_url}/questions"
314
  submit_url = f"{api_url}/submit"
315
 
316
- # 1. Instanciar el Sistema Multiagente
317
  try:
318
- agent = MultiAgentSystem()
319
  except Exception as e:
320
- print(f"Error al instanciar el sistema multiagente: {e}")
321
- return f"Error al inicializar el sistema multiagente: {e}", None
322
-
323
- # En caso de una aplicación ejecutándose como espacio de Hugging Face, este enlace apunta a tu código base
324
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
325
  print(agent_code)
326
 
327
- # 2. Obtener preguntas
328
- print(f"Obteniendo preguntas de: {questions_url}")
329
  try:
330
  response = requests.get(questions_url, timeout=15)
331
  response.raise_for_status()
332
  questions_data = response.json()
333
  if not questions_data:
334
- print("La lista de preguntas obtenida está vacía.")
335
- return "La lista de preguntas obtenida está vacía o tiene un formato no válido.", None
336
- print(f"Obtenidas {len(questions_data)} preguntas.")
337
  except requests.exceptions.RequestException as e:
338
- print(f"Error al obtener preguntas: {e}")
339
- return f"Error al obtener preguntas: {e}", None
340
  except requests.exceptions.JSONDecodeError as e:
341
- print(f"Error al decodificar la respuesta JSON del endpoint de preguntas: {e}")
342
- print(f"Texto de respuesta: {response.text[:500]}")
343
- return f"Error al decodificar la respuesta del servidor para preguntas: {e}", None
344
  except Exception as e:
345
- print(f"Ocurrió un error inesperado al obtener preguntas: {e}")
346
- return f"Ocurrió un error inesperado al obtener preguntas: {e}", None
347
 
348
- # 3. Ejecutar el Sistema Multiagente
349
  results_log = []
350
  answers_payload = []
351
- print(f"Ejecutando el sistema multiagente en {len(questions_data)} preguntas...")
352
  for item in questions_data:
353
  task_id = item.get("task_id")
354
  question_text = item.get("question")
355
  if not task_id or question_text is None:
356
- print(f"Omitiendo elemento con task_id o pregunta faltante: {item}")
357
  continue
358
  try:
359
  submitted_answer = agent(question_text)
360
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
361
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
362
  except Exception as e:
363
- print(f"Error al ejecutar el sistema multiagente en la tarea {task_id}: {e}")
364
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"ERROR DE AGENTE: {e}"})
365
 
366
  if not answers_payload:
367
- print("El sistema multiagente no produjo ninguna respuesta para enviar.")
368
- return "El sistema multiagente no produjo ninguna respuesta para enviar.", pd.DataFrame(results_log)
369
 
370
- # 4. Preparar envío
371
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
372
- status_update = f"Sistema multiagente finalizado. Enviando {len(answers_payload)} respuestas para el usuario '{username}'..."
373
  print(status_update)
374
 
375
- # 5. Enviar
376
- print(f"Enviando {len(answers_payload)} respuestas a: {submit_url}")
377
  try:
378
  response = requests.post(submit_url, json=submission_data, timeout=60)
379
  response.raise_for_status()
380
  result_data = response.json()
381
  final_status = (
382
- f"¡Envío exitoso!\n"
383
- f"Usuario: {result_data.get('username')}\n"
384
- f"Puntuación general: {result_data.get('score', 'N/A')}% "
385
- f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correctas)\n"
386
- f"Mensaje: {result_data.get('message', 'No se recibió mensaje.')}"
387
  )
388
- print("Envío exitoso.")
389
  results_df = pd.DataFrame(results_log)
390
  return final_status, results_df
391
  except requests.exceptions.HTTPError as e:
392
- error_detail = f"El servidor respondió con estado {e.response.status_code}."
393
  try:
394
  error_json = e.response.json()
395
- error_detail += f" Detalle: {error_json.get('detail', e.response.text)}"
396
  except requests.exceptions.JSONDecodeError:
397
- error_detail += f" Respuesta: {e.response.text[:500]}"
398
- status_message = f"Envío fallido: {error_detail}"
399
  print(status_message)
400
  results_df = pd.DataFrame(results_log)
401
  return status_message, results_df
402
  except requests.exceptions.Timeout:
403
- status_message = "Envío fallido: La solicitud se agotó."
404
  print(status_message)
405
  results_df = pd.DataFrame(results_log)
406
  return status_message, results_df
407
  except requests.exceptions.RequestException as e:
408
- status_message = f"Envío fallido: Error de red - {e}"
409
  print(status_message)
410
  results_df = pd.DataFrame(results_log)
411
  return status_message, results_df
412
  except Exception as e:
413
- status_message = f"Ocurrió un error inesperado durante el envío: {e}"
414
  print(status_message)
415
  results_df = pd.DataFrame(results_log)
416
  return status_message, results_df
417
 
418
- # --- Construir interfaz Gradio usando Blocks ---
 
419
  with gr.Blocks() as demo:
420
- gr.Markdown("# Sistema Multiagente para GAIA Level 1")
421
  gr.Markdown(
422
  """
423
- **Instrucciones:**
424
- 1. Asegúrate de configurar la variable de entorno GEMINI_API_KEY con tu clave de API de Google AI.
425
- 2. Inicia sesión en tu cuenta de Hugging Face utilizando el botón de abajo.
426
- 3. Haz clic en 'Ejecutar evaluación y enviar todas las respuestas' para obtener preguntas, ejecutar el sistema multiagente y ver los resultados.
427
  ---
428
- **Notas:**
429
- - Este sistema utiliza LangGraph como framework de agentes y Gemini 2.5 Flash como LLM.
430
- - El proceso puede tardar varios minutos dependiendo de la complejidad de las preguntas.
431
  """
432
  )
433
 
434
  gr.LoginButton()
435
 
436
- run_button = gr.Button("Ejecutar evaluación y enviar todas las respuestas")
437
 
438
- status_output = gr.Textbox(label="Estado de ejecución / Resultado del envío", lines=5, interactive=False)
439
- results_table = gr.DataFrame(label="Preguntas y respuestas del agente", wrap=True)
 
440
 
441
  run_button.click(
442
  fn=run_and_submit_all,
@@ -444,25 +170,25 @@ with gr.Blocks() as demo:
444
  )
445
 
446
  if __name__ == "__main__":
447
- print("\n" + "-"*30 + " Iniciando aplicación " + "-"*30)
448
- # Comprobar SPACE_HOST y SPACE_ID al inicio para información
449
  space_host_startup = os.getenv("SPACE_HOST")
450
- space_id_startup = os.getenv("SPACE_ID") # Obtener SPACE_ID al inicio
451
 
452
  if space_host_startup:
453
- print(f"✅ SPACE_HOST encontrado: {space_host_startup}")
454
- print(f" La URL de ejecución debería ser: https://{space_host_startup}.hf.space")
455
  else:
456
- print("ℹ️ Variable de entorno SPACE_HOST no encontrada (¿ejecutando localmente?).")
457
 
458
- if space_id_startup: # Imprimir URLs del repositorio si se encuentra SPACE_ID
459
- print(f"✅ SPACE_ID encontrado: {space_id_startup}")
460
- print(f" URL del repositorio: https://huggingface.co/spaces/{space_id_startup}")
461
- print(f" URL del árbol del repositorio: https://huggingface.co/spaces/{space_id_startup}/tree/main")
462
  else:
463
- print("ℹ️ Variable de entorno SPACE_ID no encontrada (¿ejecutando localmente?). No se puede determinar la URL del repositorio.")
464
 
465
- print("-"*(60 + len(" Iniciando aplicación ")) + "\n")
466
 
467
- print("Lanzando interfaz Gradio para el Sistema Multiagente...")
468
  demo.launch(debug=True, share=False)
 
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.")
35
+ return "Please Login to Hugging Face with the button.", None
36
 
37
  api_url = DEFAULT_API_URL
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)
103
  response.raise_for_status()
104
  result_data = response.json()
105
  final_status = (
106
+ f"Submission Successful!\n"
107
+ f"User: {result_data.get('username')}\n"
108
+ f"Overall Score: {result_data.get('score', 'N/A')}% "
109
+ f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
110
+ f"Message: {result_data.get('message', 'No message received.')}"
111
  )
112
+ print("Submission successful.")
113
  results_df = pd.DataFrame(results_log)
114
  return final_status, results_df
115
  except requests.exceptions.HTTPError as e:
116
+ error_detail = f"Server responded with status {e.response.status_code}."
117
  try:
118
  error_json = e.response.json()
119
+ error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
120
  except requests.exceptions.JSONDecodeError:
121
+ error_detail += f" Response: {e.response.text[:500]}"
122
+ status_message = f"Submission Failed: {error_detail}"
123
  print(status_message)
124
  results_df = pd.DataFrame(results_log)
125
  return status_message, results_df
126
  except requests.exceptions.Timeout:
127
+ status_message = "Submission Failed: The request timed out."
128
  print(status_message)
129
  results_df = pd.DataFrame(results_log)
130
  return status_message, results_df
131
  except requests.exceptions.RequestException as e:
132
+ status_message = f"Submission Failed: Network error - {e}"
133
  print(status_message)
134
  results_df = pd.DataFrame(results_log)
135
  return status_message, results_df
136
  except Exception as e:
137
+ status_message = f"An unexpected error occurred during submission: {e}"
138
  print(status_message)
139
  results_df = pd.DataFrame(results_log)
140
  return status_message, results_df
141
 
142
+
143
+ # --- Build Gradio Interface using Blocks ---
144
  with gr.Blocks() as demo:
145
+ gr.Markdown("# Basic Agent Evaluation Runner")
146
  gr.Markdown(
147
  """
148
+ **Instructions:**
149
+ 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
150
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
151
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
152
  ---
153
+ **Disclaimers:**
154
+ 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).
155
+ 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.
156
  """
157
  )
158
 
159
  gr.LoginButton()
160
 
161
+ run_button = gr.Button("Run Evaluation & Submit All Answers")
162
 
163
+ status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
164
+ # Removed max_rows=10 from DataFrame constructor
165
+ results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
166
 
167
  run_button.click(
168
  fn=run_and_submit_all,
 
170
  )
171
 
172
  if __name__ == "__main__":
173
+ print("\n" + "-"*30 + " App Starting " + "-"*30)
174
+ # Check for SPACE_HOST and SPACE_ID at startup for information
175
  space_host_startup = os.getenv("SPACE_HOST")
176
+ space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
177
 
178
  if space_host_startup:
179
+ print(f"✅ SPACE_HOST found: {space_host_startup}")
180
+ print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
181
  else:
182
+ print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
183
 
184
+ if space_id_startup: # Print repo URLs if SPACE_ID is found
185
+ print(f"✅ SPACE_ID found: {space_id_startup}")
186
+ print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
187
+ print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
188
  else:
189
+ print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
190
 
191
+ print("-"*(60 + len(" App Starting ")) + "\n")
192
 
193
+ print("Launching Gradio Interface for Basic Agent Evaluation...")
194
  demo.launch(debug=True, share=False)