Tesvia commited on
Commit
790cac2
·
verified ·
1 Parent(s): 9623335

Upload 3 files

Browse files
Files changed (3) hide show
  1. agent.py +28 -6
  2. app.py +41 -39
  3. tools.py +25 -1
agent.py CHANGED
@@ -6,7 +6,9 @@ from __future__ import annotations
6
 
7
  import asyncio
8
  import os
9
- from typing import Any, Sequence, Callable, List
 
 
10
 
11
  from dotenv import load_dotenv
12
  from agents import Agent, Runner, FunctionTool, Tool
@@ -21,6 +23,12 @@ from tools import (
21
  duckduckgo_search,
22
  )
23
 
 
 
 
 
 
 
24
  # ---------------------------------------------------------------------------
25
  # Load the added system prompt
26
  # ---------------------------------------------------------------------------
@@ -82,18 +90,32 @@ class GAIAAgent:
82
 
83
  def __init__(self, *, extra_tools: Sequence[FunctionTool] | None = None):
84
  self._agent = _build_agent(extra_tools=extra_tools)
 
 
85
 
86
- async def _arun(self, question: str) -> str:
87
- result = await Runner.run(self._agent, question)
 
 
 
 
 
 
 
 
 
 
 
 
88
  return str(result.final_output).strip()
89
 
90
- def __call__(self, question: str, **kwargs: Any) -> str:
91
  try:
92
  loop = asyncio.get_running_loop()
93
  except RuntimeError:
94
- return asyncio.run(self._arun(question))
95
  else:
96
- return loop.run_until_complete(self._arun(question))
97
 
98
 
99
  def gaia_agent(*, extra_tools: Sequence[FunctionTool] | None = None) -> GAIAAgent:
 
6
 
7
  import asyncio
8
  import os
9
+ import time
10
+ import datetime
11
+ from typing import Any, Sequence, Callable, List, Optional
12
 
13
  from dotenv import load_dotenv
14
  from agents import Agent, Runner, FunctionTool, Tool
 
23
  duckduckgo_search,
24
  )
25
 
26
+ # ---------------------------------------------------------------------------
27
+ # Logging Utility
28
+ # ---------------------------------------------------------------------------
29
+ def log(msg):
30
+ print(f"[{datetime.datetime.now():%Y-%m-%d %H:%M:%S}] {msg}")
31
+
32
  # ---------------------------------------------------------------------------
33
  # Load the added system prompt
34
  # ---------------------------------------------------------------------------
 
90
 
91
  def __init__(self, *, extra_tools: Sequence[FunctionTool] | None = None):
92
  self._agent = _build_agent(extra_tools=extra_tools)
93
+ # Store the model id for logging
94
+ self.model_id = _select_model()
95
 
96
+ async def _arun(self, question: str, q_index: Optional[int] = None) -> str:
97
+ q_num = q_index + 1 if q_index is not None else "?"
98
+ log(f"Answering question {q_num}:")
99
+ log(f" Question: {question!r}")
100
+ log(f" Model: {self.model_id}")
101
+
102
+ t0 = time.time()
103
+ try:
104
+ result = await Runner.run(self._agent, question)
105
+ duration = time.time() - t0
106
+ log(f" Total duration: {duration:.2f} seconds.")
107
+ except Exception as e:
108
+ log(f" Error during answer: {e}")
109
+ raise
110
  return str(result.final_output).strip()
111
 
112
+ def __call__(self, question: str, q_index: Optional[int] = None, **kwargs: Any) -> str:
113
  try:
114
  loop = asyncio.get_running_loop()
115
  except RuntimeError:
116
+ return asyncio.run(self._arun(question, q_index=q_index))
117
  else:
118
+ return loop.run_until_complete(self._arun(question, q_index=q_index))
119
 
120
 
121
  def gaia_agent(*, extra_tools: Sequence[FunctionTool] | None = None) -> GAIAAgent:
app.py CHANGED
@@ -2,30 +2,34 @@ import os
2
  import gradio as gr
3
  import requests
4
  import pandas as pd
 
5
 
6
  # --- Our Agent ---
7
  from agent import gaia_agent
8
 
 
 
 
 
9
  # Debugging level. If DEBUG=0 then DEBUG will be False. If DEBUG=1 then DEBUG will be True.
10
  DEBUG = os.getenv("DEBUG", "0") == "1"
11
 
12
- # (Keep Constants as is)
13
  # --- Constants ---
14
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
15
 
16
- def run_and_submit_all( profile: gr.OAuthProfile | None):
17
  """
18
  Fetches all questions, runs the BasicAgent on them, submits all answers,
19
  and displays the results.
20
  """
21
  # --- Determine HF Space Runtime URL and Repo URL ---
22
- space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
23
 
24
  if profile:
25
- username= f"{profile.username}"
26
- print(f"User logged in: {username}")
27
  else:
28
- print("User not logged in.")
29
  return "Please Login to Hugging Face with the button.", None
30
 
31
  api_url = DEFAULT_API_URL
@@ -35,16 +39,16 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
35
  # 1. Instantiate Agent (now using OpenAI Agents SDK)
36
  try:
37
  agent = gaia_agent()
38
- print("OpenAI Agent instantiated successfully.")
39
  except Exception as e:
40
- print(f"Error instantiating agent: {e}")
41
  return f"Error initializing agent: {e}", None
42
- # In the case of an app running as a hugging Face space, this link points toward your codebase ( useful for others so please keep it public)
43
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
44
- print(agent_code)
45
 
46
  # 2. Fetch Questions
47
- print(f"Fetching questions from: {questions_url}")
48
  import json
49
 
50
  try:
@@ -52,57 +56,55 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
52
  response.raise_for_status()
53
  questions_data = response.json()
54
  if not questions_data:
55
- print("Fetched questions list is empty.")
56
  return "Fetched questions list is empty or invalid format.", None
57
- print(f"Fetched {len(questions_data)} questions.")
58
  except json.JSONDecodeError as e:
59
- print(f"Error decoding JSON response from questions endpoint: {e}")
60
- print(f"Response text: {response.text[:500]}")
61
  return f"Error decoding server response for questions: {e}", None
62
  except requests.exceptions.RequestException as e:
63
- print(f"Error fetching questions: {e}")
64
  return f"Error fetching questions: {e}", None
65
  except Exception as e:
66
- print(f"An unexpected error occurred fetching questions: {e}")
67
  return f"An unexpected error occurred fetching questions: {e}", None
68
 
69
  # 3. Run the Agent
70
  results_log = []
71
  answers_payload = []
72
- print(f"Running agent on {len(questions_data)} questions...")
73
- for item in questions_data:
74
  task_id = item.get("task_id")
75
  question_text = item.get("question")
76
  if not task_id or question_text is None:
77
- print(f"Skipping item with missing task_id or question: {item}")
78
  continue
79
  try:
80
- submitted_answer = agent(question_text)
81
- # --- DEBUG LOGGING ---
82
  if DEBUG:
83
- print(f"[DEBUG] Task {task_id}: Answer type: {type(submitted_answer)}, Value: {repr(submitted_answer)}")
84
  else:
85
- print(f"[{task_id}] {question_text[:50]}... → {submitted_answer[:40]}")
86
 
87
- # Force string type here just in case (defensive)
88
  submitted_answer = str(submitted_answer).strip()
89
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
90
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
91
  except Exception as e:
92
- print(f"Error running agent on task {task_id}: {e}")
93
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
94
 
95
  if not answers_payload:
96
- print("Agent did not produce any answers to submit.")
97
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
98
 
99
- # 4. Prepare Submission
100
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
101
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
102
- print(status_update)
103
 
104
  # 5. Submit
105
- print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
106
  try:
107
  response = requests.post(submit_url, json=submission_data, timeout=60)
108
  response.raise_for_status()
@@ -114,7 +116,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
114
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
115
  f"Message: {result_data.get('message', 'No message received.')}"
116
  )
117
- print("Submission successful.")
118
  results_df = pd.DataFrame(results_log)
119
  return final_status, results_df
120
  except requests.exceptions.HTTPError as e:
@@ -125,22 +127,22 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
125
  except requests.exceptions.JSONDecodeError:
126
  error_detail += f" Response: {e.response.text[:500]}"
127
  status_message = f"Submission Failed: {error_detail}"
128
- print(status_message)
129
  results_df = pd.DataFrame(results_log)
130
  return status_message, results_df
131
  except requests.exceptions.Timeout:
132
  status_message = "Submission Failed: The request timed out."
133
- print(status_message)
134
  results_df = pd.DataFrame(results_log)
135
  return status_message, results_df
136
  except requests.exceptions.RequestException as e:
137
  status_message = f"Submission Failed: Network error - {e}"
138
- print(status_message)
139
  results_df = pd.DataFrame(results_log)
140
  return status_message, results_df
141
  except Exception as e:
142
  status_message = f"An unexpected error occurred during submission: {e}"
143
- print(status_message)
144
  results_df = pd.DataFrame(results_log)
145
  return status_message, results_df
146
 
@@ -178,7 +180,7 @@ with gr.Blocks() as demo:
178
  if __name__ == "__main__":
179
  print("\n" + "-"*30 + " App Starting " + "-"*30)
180
  space_host_startup = os.getenv("SPACE_HOST")
181
- space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
182
 
183
  if space_host_startup:
184
  print(f"✅ SPACE_HOST found: {space_host_startup}")
@@ -186,14 +188,14 @@ if __name__ == "__main__":
186
  else:
187
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
188
 
189
- if space_id_startup: # Print repo URLs if SPACE_ID is found
190
  print(f"✅ SPACE_ID found: {space_id_startup}")
191
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
192
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
193
  else:
194
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
195
 
196
- print("-"*(60 + len(" App Starting ")) + "\n")
197
 
198
  print("Launching Gradio Interface for Agent Evaluation…")
199
  demo.launch(debug=True, share=False)
 
2
  import gradio as gr
3
  import requests
4
  import pandas as pd
5
+ import datetime
6
 
7
  # --- Our Agent ---
8
  from agent import gaia_agent
9
 
10
+ # Logging utility
11
+ def log(msg):
12
+ print(f"[{datetime.datetime.now():%Y-%m-%d %H:%M:%S}] {msg}")
13
+
14
  # Debugging level. If DEBUG=0 then DEBUG will be False. If DEBUG=1 then DEBUG will be True.
15
  DEBUG = os.getenv("DEBUG", "0") == "1"
16
 
 
17
  # --- Constants ---
18
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
19
 
20
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
21
  """
22
  Fetches all questions, runs the BasicAgent on them, submits all answers,
23
  and displays the results.
24
  """
25
  # --- Determine HF Space Runtime URL and Repo URL ---
26
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
27
 
28
  if profile:
29
+ username = f"{profile.username}"
30
+ log(f"User logged in: {username}")
31
  else:
32
+ log("User not logged in.")
33
  return "Please Login to Hugging Face with the button.", None
34
 
35
  api_url = DEFAULT_API_URL
 
39
  # 1. Instantiate Agent (now using OpenAI Agents SDK)
40
  try:
41
  agent = gaia_agent()
42
+ log("OpenAI Agent instantiated successfully.")
43
  except Exception as e:
44
+ log(f"Error instantiating agent: {e}")
45
  return f"Error initializing agent: {e}", None
46
+
47
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
48
+ log(agent_code)
49
 
50
  # 2. Fetch Questions
51
+ log(f"Fetching questions from: {questions_url}")
52
  import json
53
 
54
  try:
 
56
  response.raise_for_status()
57
  questions_data = response.json()
58
  if not questions_data:
59
+ log("Fetched questions list is empty.")
60
  return "Fetched questions list is empty or invalid format.", None
61
+ log(f"Fetched {len(questions_data)} GAIA questions.")
62
  except json.JSONDecodeError as e:
63
+ log(f"Error decoding JSON response from questions endpoint: {e}")
64
+ log(f"Response text: {response.text[:500]}")
65
  return f"Error decoding server response for questions: {e}", None
66
  except requests.exceptions.RequestException as e:
67
+ log(f"Error fetching questions: {e}")
68
  return f"Error fetching questions: {e}", None
69
  except Exception as e:
70
+ log(f"An unexpected error occurred fetching questions: {e}")
71
  return f"An unexpected error occurred fetching questions: {e}", None
72
 
73
  # 3. Run the Agent
74
  results_log = []
75
  answers_payload = []
76
+ log(f"Running agent on {len(questions_data)} questions...")
77
+ for idx, item in enumerate(questions_data):
78
  task_id = item.get("task_id")
79
  question_text = item.get("question")
80
  if not task_id or question_text is None:
81
+ log(f"Skipping item with missing task_id or question: {item}")
82
  continue
83
  try:
84
+ submitted_answer = agent(question_text, q_index=idx)
 
85
  if DEBUG:
86
+ log(f"[DEBUG] Task {task_id}: Answer type: {type(submitted_answer)}, Value: {repr(submitted_answer)}")
87
  else:
88
+ log(f"[{task_id}] {question_text[:50]}... → {submitted_answer[:40]}")
89
 
 
90
  submitted_answer = str(submitted_answer).strip()
91
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
92
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
93
  except Exception as e:
94
+ log(f"Error running agent on task {task_id}: {e}")
95
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
96
 
97
  if not answers_payload:
98
+ log("Agent did not produce any answers to submit.")
99
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
100
 
101
+ # 4. Prepare Submission
102
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
103
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
104
+ log(status_update)
105
 
106
  # 5. Submit
107
+ log(f"Submitting {len(answers_payload)} answers to: {submit_url}")
108
  try:
109
  response = requests.post(submit_url, json=submission_data, timeout=60)
110
  response.raise_for_status()
 
116
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
117
  f"Message: {result_data.get('message', 'No message received.')}"
118
  )
119
+ log("Submission successful.")
120
  results_df = pd.DataFrame(results_log)
121
  return final_status, results_df
122
  except requests.exceptions.HTTPError as e:
 
127
  except requests.exceptions.JSONDecodeError:
128
  error_detail += f" Response: {e.response.text[:500]}"
129
  status_message = f"Submission Failed: {error_detail}"
130
+ log(status_message)
131
  results_df = pd.DataFrame(results_log)
132
  return status_message, results_df
133
  except requests.exceptions.Timeout:
134
  status_message = "Submission Failed: The request timed out."
135
+ log(status_message)
136
  results_df = pd.DataFrame(results_log)
137
  return status_message, results_df
138
  except requests.exceptions.RequestException as e:
139
  status_message = f"Submission Failed: Network error - {e}"
140
+ log(status_message)
141
  results_df = pd.DataFrame(results_log)
142
  return status_message, results_df
143
  except Exception as e:
144
  status_message = f"An unexpected error occurred during submission: {e}"
145
+ log(status_message)
146
  results_df = pd.DataFrame(results_log)
147
  return status_message, results_df
148
 
 
180
  if __name__ == "__main__":
181
  print("\n" + "-"*30 + " App Starting " + "-"*30)
182
  space_host_startup = os.getenv("SPACE_HOST")
183
+ space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
184
 
185
  if space_host_startup:
186
  print(f"✅ SPACE_HOST found: {space_host_startup}")
 
188
  else:
189
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
190
 
191
+ if space_id_startup: # Print repo URLs if SPACE_ID is found
192
  print(f"✅ SPACE_ID found: {space_id_startup}")
193
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
194
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
195
  else:
196
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
197
 
198
+ print("-" * (60 + len(" App Starting ")) + "\n")
199
 
200
  print("Launching Gradio Interface for Agent Evaluation…")
201
  demo.launch(debug=True, share=False)
tools.py CHANGED
@@ -7,12 +7,31 @@ from __future__ import annotations
7
  import contextlib
8
  import io
9
  import os
 
 
10
  from typing import List, Dict
11
 
12
  from agents import function_tool
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  # 1. --------------------------------------------------------------------
15
  @function_tool
 
16
  def python_run(code: str) -> str:
17
  """Execute trusted Python code and return the captured stdout together with
18
  the repr() of the last expression (or `_result` variable if set).
@@ -36,6 +55,7 @@ def python_run(code: str) -> str:
36
 
37
  # 2. --------------------------------------------------------------------
38
  @function_tool
 
39
  def load_spreadsheet(path: str, sheet: str | int | None = None) -> list[Dict[str, str]]:
40
  """Read .csv, .xls or .xlsx from disk and return rows as list of dictionaries.
41
 
@@ -65,6 +85,7 @@ def load_spreadsheet(path: str, sheet: str | int | None = None) -> list[Dict[str
65
 
66
  # 3. --------------------------------------------------------------------
67
  @function_tool
 
68
  def youtube_transcript(url: str, lang: str = "en") -> str:
69
  """Fetch the subtitles of a YouTube video.
70
 
@@ -84,6 +105,7 @@ def youtube_transcript(url: str, lang: str = "en") -> str:
84
 
85
  # 4. --------------------------------------------------------------------
86
  @function_tool
 
87
  def transcribe_audio(path: str, model: str = "whisper-1") -> str:
88
  """Transcribe an audio file using OpenAI Whisper.
89
 
@@ -104,6 +126,7 @@ def transcribe_audio(path: str, model: str = "whisper-1") -> str:
104
 
105
  # 5. --------------------------------------------------------------------
106
  @function_tool
 
107
  def image_ocr(path: str) -> str:
108
  """Perform OCR on an image using Tesseract.
109
 
@@ -120,6 +143,7 @@ def image_ocr(path: str) -> str:
120
 
121
  # 6. --------------------------------------------------------------------
122
  @function_tool
 
123
  def duckduckgo_search(query: str, max_results: int = 5) -> List[Dict[str, str]]:
124
  """Search DuckDuckGo and return a list of result dicts with title, href and body.
125
 
@@ -139,4 +163,4 @@ def duckduckgo_search(query: str, max_results: int = 5) -> List[Dict[str, str]]:
139
  "body": r.get("body", ""),
140
  }
141
  )
142
- return results
 
7
  import contextlib
8
  import io
9
  import os
10
+ import time
11
+ import datetime
12
  from typing import List, Dict
13
 
14
  from agents import function_tool
15
 
16
+ def log(msg):
17
+ print(f"[{datetime.datetime.now():%Y-%m-%d %H:%M:%S}] {msg}")
18
+
19
+ def log_tool_call(func):
20
+ def wrapper(*args, **kwargs):
21
+ t0 = time.time()
22
+ log(f"Step: {func.__name__} started.")
23
+ try:
24
+ result = func(*args, **kwargs)
25
+ log(f"Step: {func.__name__} completed in {time.time() - t0:.2f}s.")
26
+ return result
27
+ except Exception as e:
28
+ log(f"Step: {func.__name__} error: {e}")
29
+ raise
30
+ return wrapper
31
+
32
  # 1. --------------------------------------------------------------------
33
  @function_tool
34
+ @log_tool_call
35
  def python_run(code: str) -> str:
36
  """Execute trusted Python code and return the captured stdout together with
37
  the repr() of the last expression (or `_result` variable if set).
 
55
 
56
  # 2. --------------------------------------------------------------------
57
  @function_tool
58
+ @log_tool_call
59
  def load_spreadsheet(path: str, sheet: str | int | None = None) -> list[Dict[str, str]]:
60
  """Read .csv, .xls or .xlsx from disk and return rows as list of dictionaries.
61
 
 
85
 
86
  # 3. --------------------------------------------------------------------
87
  @function_tool
88
+ @log_tool_call
89
  def youtube_transcript(url: str, lang: str = "en") -> str:
90
  """Fetch the subtitles of a YouTube video.
91
 
 
105
 
106
  # 4. --------------------------------------------------------------------
107
  @function_tool
108
+ @log_tool_call
109
  def transcribe_audio(path: str, model: str = "whisper-1") -> str:
110
  """Transcribe an audio file using OpenAI Whisper.
111
 
 
126
 
127
  # 5. --------------------------------------------------------------------
128
  @function_tool
129
+ @log_tool_call
130
  def image_ocr(path: str) -> str:
131
  """Perform OCR on an image using Tesseract.
132
 
 
143
 
144
  # 6. --------------------------------------------------------------------
145
  @function_tool
146
+ @log_tool_call
147
  def duckduckgo_search(query: str, max_results: int = 5) -> List[Dict[str, str]]:
148
  """Search DuckDuckGo and return a list of result dicts with title, href and body.
149
 
 
163
  "body": r.get("body", ""),
164
  }
165
  )
166
+ return results