MartinHummel commited on
Commit
7bfec74
Β·
1 Parent(s): f5286d9
agent/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # tools/__init__.py
2
+
agent/gaia_agent.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from langchain.agents import initialize_agent, AgentType
3
+ from langchain.tools import Tool
4
+ from langchain.llms import OpenAI
5
+ from tools.wikipedia_tool import wiki_search
6
+ from tools.audio_transcriber import transcribe_audio
7
+ from tools.file_parser import parse_file_and_summarize
8
+ from tools.image_chess_solver import solve_chess_image
9
+ from tools.youtube_tool import extract_video_id, get_youtube_transcript
10
+
11
+
12
+ def create_langchain_agent():
13
+ tools = [
14
+ Tool(name="Wikipedia Search", func=wiki_search, description="Search Wikipedia for facts."),
15
+ Tool(name="Transcribe Audio", func=transcribe_audio, description="Transcribe MP3 recordings."),
16
+ Tool(name="Image Chess Solver", func=solve_chess_image, description="Solve chess images."),
17
+ Tool(name="File Parser", func=parse_file_and_summarize, description="Summarize files."),
18
+ Tool(name="Youtube Tool Extract", func=extract_video_id, description="Extract videos ids-"),
19
+ Tool(name="Youtube Tool Transscript", func=get_youtube_transcript, description="Transscript youtube videos-"),
20
+ ]
21
+
22
+ llm = OpenAI(temperature=0.3, model_name="gpt-4", openai_api_key=os.getenv("Openai")) # Must be set in your env) # Or use HuggingFaceHub/llama3
23
+ agent = initialize_agent(
24
+ tools=tools,
25
+ llm=llm,
26
+ agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
27
+ verbose=True
28
+ )
29
+ return agent
app.py CHANGED
@@ -3,48 +3,87 @@ import gradio as gr
3
  import requests
4
  import inspect
5
  import pandas as pd
6
- import random
7
- from huggingface_hub import notebook_login
8
- from transformers import Tool
9
- from tools.tool_math import SolveEquationTool, ExplainSolutionTool
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  # --- Constants ---
12
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
13
 
14
- # --- Math Solver Agent Definition ---
15
- class MathSolverAgent:
 
16
  def __init__(self):
17
- self.tools = [
18
- SolveEquationTool(),
19
- ExplainSolutionTool(),
20
- ]
21
- print("MathSolverAgent initialized with tools.")
22
 
23
  def __call__(self, question: str) -> str:
24
- print(f"Agent received question (first 50 chars): {question[:50]}...")
25
- for tool in self.tools:
26
- if tool.name in question.lower():
27
- return tool(question)
28
-
29
  try:
30
- if random.random() < 0.5:
31
- raise ValueError("Simulating incorrect or skipped answer.")
32
-
33
- solution = self.tools[0](question)
34
- if solution.startswith("Error"):
35
- return solution
36
-
37
- explanation = self.tools[1](question)
38
- return f"{solution}\nExplanation:\n{explanation}"
39
  except Exception as e:
40
- return "Sorry, I couldn't solve that one."
41
-
42
 
43
- def run_and_submit_all(profile: gr.OAuthProfile | None):
44
- space_id = os.getenv("SPACE_ID")
 
 
 
 
 
45
 
46
  if profile:
47
- username = f"{profile.username}"
48
  print(f"User logged in: {username}")
49
  else:
50
  print("User not logged in.")
@@ -54,28 +93,38 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
54
  questions_url = f"{api_url}/questions"
55
  submit_url = f"{api_url}/submit"
56
 
 
57
  try:
58
- agent = MathSolverAgent()
59
  except Exception as e:
60
  print(f"Error instantiating agent: {e}")
61
  return f"Error initializing agent: {e}", None
62
-
63
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
64
  print(agent_code)
65
 
 
66
  print(f"Fetching questions from: {questions_url}")
67
  try:
68
  response = requests.get(questions_url, timeout=15)
69
  response.raise_for_status()
70
  questions_data = response.json()
71
  if not questions_data:
72
- print("Fetched questions list is empty.")
73
- return "Fetched questions list is empty or invalid format.", None
74
  print(f"Fetched {len(questions_data)} questions.")
75
  except requests.exceptions.RequestException as e:
76
  print(f"Error fetching questions: {e}")
77
  return f"Error fetching questions: {e}", None
 
 
 
 
 
 
 
78
 
 
79
  results_log = []
80
  answers_payload = []
81
  print(f"Running agent on {len(questions_data)} questions...")
@@ -90,17 +139,19 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
90
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
91
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
92
  except Exception as e:
93
- print(f"Error running agent on task {task_id}: {e}")
94
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
95
 
96
  if not answers_payload:
97
  print("Agent did not produce any answers to submit.")
98
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
99
 
 
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
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
105
  try:
106
  response = requests.post(submit_url, json=submission_data, timeout=60)
@@ -116,46 +167,56 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
116
  print("Submission successful.")
117
  results_df = pd.DataFrame(results_log)
118
  return final_status, results_df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  except requests.exceptions.RequestException as e:
120
- status_message = f"Submission Failed: {e}"
 
 
 
 
 
121
  print(status_message)
122
  results_df = pd.DataFrame(results_log)
123
  return status_message, results_df
124
 
125
- # --- Gradio Interface ---
 
126
  with gr.Blocks() as demo:
127
- gr.Markdown("# Math Solver and Explainer Agent")
128
  gr.Markdown(
129
  """
130
  **Instructions:**
131
-
132
- 1. Modify this agent to use symbolic math tools and explanations.
133
- 2. Log in to your Hugging Face account.
134
- 3. Run the agent and submit all answers for scoring.
 
 
 
135
  """
136
  )
137
 
138
  gr.LoginButton()
139
-
140
- # manual input
141
- manual_input = gr.Textbox(label="Try the Agent Manually", placeholder="e.g., Solve for x: 2*x + 3 = 7")
142
- manual_output = gr.Textbox(label="Agent Response", lines=4, interactive=False)
143
- manual_test_button = gr.Button("Run Agent Locally")
144
-
145
- def run_manual_input(user_input):
146
- agent = MathSolverAgent()
147
- user_input = user_input.strip()
148
- print(f"Manual input received: {user_input}")
149
- return agent(user_input)
150
- #agent = MathSolverAgent()
151
- #return agent(user_input)
152
-
153
- manual_test_button.click(fn=run_manual_input, inputs=manual_input, outputs=manual_output)
154
-
155
 
156
  run_button = gr.Button("Run Evaluation & Submit All Answers")
157
 
158
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
159
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
160
 
161
  run_button.click(
@@ -165,8 +226,9 @@ with gr.Blocks() as demo:
165
 
166
  if __name__ == "__main__":
167
  print("\n" + "-"*30 + " App Starting " + "-"*30)
 
168
  space_host_startup = os.getenv("SPACE_HOST")
169
- space_id_startup = os.getenv("SPACE_ID")
170
 
171
  if space_host_startup:
172
  print(f"βœ… SPACE_HOST found: {space_host_startup}")
@@ -174,7 +236,7 @@ if __name__ == "__main__":
174
  else:
175
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
176
 
177
- if space_id_startup:
178
  print(f"βœ… SPACE_ID found: {space_id_startup}")
179
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
180
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
@@ -182,5 +244,6 @@ if __name__ == "__main__":
182
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
183
 
184
  print("-"*(60 + len(" App Starting ")) + "\n")
185
- print("Launching Gradio Interface for Math Solver Agent...")
186
- demo.launch(debug=True, share=False)
 
 
3
  import requests
4
  import inspect
5
  import pandas as pd
 
 
 
 
6
 
7
+ from langchain.agents import initialize_agent, AgentType
8
+ from langchain.llms import OpenAI
9
+ from langchain.tools import Tool
10
+ from agent.gaia_agent import create_langchain_agent
11
+
12
+ from tools.wikipedia_tool import wiki_search
13
+ from tools.youtube_tool import get_youtube_transcript
14
+ from tools.audio_transcriber import transcribe_audio
15
+ from tools.image_chess_solver import solve_chess_image
16
+ from tools.file_parser import parse_file_and_summarize
17
+
18
+ def create_langchain_agent():
19
+ tools = [
20
+ Tool(
21
+ name="Wikipedia Search",
22
+ func=wiki_search,
23
+ description="Use this tool to look up verified facts on Wikipedia. Input: search term."
24
+ ),
25
+ Tool(
26
+ name="YouTube Transcript",
27
+ func=get_youtube_transcript,
28
+ description="Extract speech from YouTube videos. Input: video URL."
29
+ ),
30
+ Tool(
31
+ name="Transcribe Audio",
32
+ func=transcribe_audio,
33
+ description="Transcribe audio from a local MP3/WAV file. Input: path to audio file."
34
+ ),
35
+ Tool(
36
+ name="Image Chess Solver",
37
+ func=solve_chess_image,
38
+ description="Solve a chess puzzle from an image. Input: path to image file."
39
+ ),
40
+ Tool(
41
+ name="File Parser",
42
+ func=parse_file_and_summarize,
43
+ description="Answer data questions from a spreadsheet. Input: path to CSV/XLSX file."
44
+ ),
45
+ ]
46
+
47
+ llm = OpenAI(temperature=0) # Or replace with Llama3 via HuggingFaceHub
48
+ agent = initialize_agent(
49
+ tools=tools,
50
+ llm=llm,
51
+ agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
52
+ verbose=True,
53
+ handle_parsing_errors=True
54
+ )
55
+ return agent
56
+
57
+
58
+ # (Keep Constants as is)
59
  # --- Constants ---
60
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
61
 
62
+ # --- Basic Agent Definition ---
63
+ # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
64
+ class BasicAgent:
65
  def __init__(self):
66
+ print("Initializing LangChain Agent...")
67
+ self.agent = create_langchain_agent()
 
 
 
68
 
69
  def __call__(self, question: str) -> str:
70
+
 
 
 
 
71
  try:
72
+ result = self.agent.run(question)
73
+ return result
 
 
 
 
 
 
 
74
  except Exception as e:
75
+ return f"Agent error: {e}"
 
76
 
77
+ def run_and_submit_all( profile: gr.OAuthProfile | None):
78
+ """
79
+ Fetches all questions, runs the BasicAgent on them, submits all answers,
80
+ and displays the results.
81
+ """
82
+ # --- Determine HF Space Runtime URL and Repo URL ---
83
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
84
 
85
  if profile:
86
+ username= f"{profile.username}"
87
  print(f"User logged in: {username}")
88
  else:
89
  print("User not logged in.")
 
93
  questions_url = f"{api_url}/questions"
94
  submit_url = f"{api_url}/submit"
95
 
96
+ # 1. Instantiate Agent ( modify this part to create your agent)
97
  try:
98
+ agent = BasicAgent()
99
  except Exception as e:
100
  print(f"Error instantiating agent: {e}")
101
  return f"Error initializing agent: {e}", None
102
+ # 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)
103
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
104
  print(agent_code)
105
 
106
+ # 2. Fetch Questions
107
  print(f"Fetching questions from: {questions_url}")
108
  try:
109
  response = requests.get(questions_url, timeout=15)
110
  response.raise_for_status()
111
  questions_data = response.json()
112
  if not questions_data:
113
+ print("Fetched questions list is empty.")
114
+ return "Fetched questions list is empty or invalid format.", None
115
  print(f"Fetched {len(questions_data)} questions.")
116
  except requests.exceptions.RequestException as e:
117
  print(f"Error fetching questions: {e}")
118
  return f"Error fetching questions: {e}", None
119
+ except requests.exceptions.JSONDecodeError as e:
120
+ print(f"Error decoding JSON response from questions endpoint: {e}")
121
+ print(f"Response text: {response.text[:500]}")
122
+ return f"Error decoding server response for questions: {e}", None
123
+ except Exception as e:
124
+ print(f"An unexpected error occurred fetching questions: {e}")
125
+ return f"An unexpected error occurred fetching questions: {e}", None
126
 
127
+ # 3. Run your Agent
128
  results_log = []
129
  answers_payload = []
130
  print(f"Running agent on {len(questions_data)} questions...")
 
139
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
140
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
141
  except Exception as e:
142
+ print(f"Error running agent on task {task_id}: {e}")
143
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
144
 
145
  if not answers_payload:
146
  print("Agent did not produce any answers to submit.")
147
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
148
 
149
+ # 4. Prepare Submission
150
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
151
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
152
  print(status_update)
153
 
154
+ # 5. Submit
155
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
156
  try:
157
  response = requests.post(submit_url, json=submission_data, timeout=60)
 
167
  print("Submission successful.")
168
  results_df = pd.DataFrame(results_log)
169
  return final_status, results_df
170
+ except requests.exceptions.HTTPError as e:
171
+ error_detail = f"Server responded with status {e.response.status_code}."
172
+ try:
173
+ error_json = e.response.json()
174
+ error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
175
+ except requests.exceptions.JSONDecodeError:
176
+ error_detail += f" Response: {e.response.text[:500]}"
177
+ status_message = f"Submission Failed: {error_detail}"
178
+ print(status_message)
179
+ results_df = pd.DataFrame(results_log)
180
+ return status_message, results_df
181
+ except requests.exceptions.Timeout:
182
+ status_message = "Submission Failed: The request timed out."
183
+ print(status_message)
184
+ results_df = pd.DataFrame(results_log)
185
+ return status_message, results_df
186
  except requests.exceptions.RequestException as e:
187
+ status_message = f"Submission Failed: Network error - {e}"
188
+ print(status_message)
189
+ results_df = pd.DataFrame(results_log)
190
+ return status_message, results_df
191
+ except Exception as e:
192
+ status_message = f"An unexpected error occurred during submission: {e}"
193
  print(status_message)
194
  results_df = pd.DataFrame(results_log)
195
  return status_message, results_df
196
 
197
+
198
+ # --- Build Gradio Interface using Blocks ---
199
  with gr.Blocks() as demo:
200
+ gr.Markdown("# Basic Agent Evaluation Runner")
201
  gr.Markdown(
202
  """
203
  **Instructions:**
204
+ 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
205
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
206
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
207
+ ---
208
+ **Disclaimers:**
209
+ 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).
210
+ 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.
211
  """
212
  )
213
 
214
  gr.LoginButton()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
 
216
  run_button = gr.Button("Run Evaluation & Submit All Answers")
217
 
218
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
219
+ # Removed max_rows=10 from DataFrame constructor
220
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
221
 
222
  run_button.click(
 
226
 
227
  if __name__ == "__main__":
228
  print("\n" + "-"*30 + " App Starting " + "-"*30)
229
+ # Check for SPACE_HOST and SPACE_ID at startup for information
230
  space_host_startup = os.getenv("SPACE_HOST")
231
+ space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
232
 
233
  if space_host_startup:
234
  print(f"βœ… SPACE_HOST found: {space_host_startup}")
 
236
  else:
237
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
238
 
239
+ if space_id_startup: # Print repo URLs if SPACE_ID is found
240
  print(f"βœ… SPACE_ID found: {space_id_startup}")
241
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
242
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
 
244
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
245
 
246
  print("-"*(60 + len(" App Starting ")) + "\n")
247
+
248
+ print("Launching Gradio Interface for Basic Agent Evaluation...")
249
+ demo.launch(debug=True, share=False)
app1.py DELETED
@@ -1,181 +0,0 @@
1
- import os
2
- import gradio as gr
3
- import requests
4
- import inspect
5
- import pandas as pd
6
- import random
7
- from huggingface_hub import notebook_login
8
- from transformers import Tool
9
- from tools.tool_math import SolveEquationTool, ExplainSolutionTool
10
-
11
- # --- Constants ---
12
- DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
13
-
14
- # --- Math Solver Agent Definition ---
15
- class MathSolverAgent:
16
- def __init__(self):
17
- from transformers import pipeline
18
- self.tools = [
19
- SolveEquationTool(),
20
- ExplainSolutionTool(),
21
- ]
22
- self.fallback = pipeline("text-generation", model="mistralai/Mistral-7B-Instruct-v0.1")
23
- print("MathSolverAgent initialized with tools and fallback.")
24
- print("MathSolverAgent initialized with tools.")
25
-
26
- def __call__(self, question: str) -> str:
27
- print(f"Agent received question (first 50 chars): {question[:50]}...")
28
- try:
29
- if random.random() < 0.5:
30
- raise ValueError("Simulating incorrect or skipped answer.")
31
- solution = self.tools[0](question)
32
- explanation = self.tools[1](question)
33
- return f"{solution}\nExplanation:\n{explanation}"
34
- except Exception as e:
35
- print(f"Math tools failed with error: {e}. Falling back to LLM.")
36
- try:
37
- fallback_result = self.fallback(question, max_new_tokens=100, do_sample=False)[0]['generated_text']
38
- return fallback_result.strip()
39
- except Exception as llm_error:
40
- return f"Sorry, I couldn't solve that one (LLM error: {llm_error})."
41
-
42
- def run_and_submit_all(profile: gr.OAuthProfile | None):
43
- space_id = os.getenv("SPACE_ID")
44
-
45
- if profile:
46
- username = f"{profile.username}"
47
- print(f"User logged in: {username}")
48
- else:
49
- print("User not logged in.")
50
- return "Please Login to Hugging Face with the button.", None
51
-
52
- api_url = DEFAULT_API_URL
53
- questions_url = f"{api_url}/questions"
54
- submit_url = f"{api_url}/submit"
55
-
56
- try:
57
- agent = MathSolverAgent()
58
- except Exception as e:
59
- print(f"Error instantiating agent: {e}")
60
- return f"Error initializing agent: {e}", None
61
-
62
- agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
63
- print(agent_code)
64
-
65
- print(f"Fetching questions from: {questions_url}")
66
- try:
67
- response = requests.get(questions_url, timeout=15)
68
- response.raise_for_status()
69
- questions_data = response.json()
70
- if not questions_data:
71
- print("Fetched questions list is empty.")
72
- return "Fetched questions list is empty or invalid format.", None
73
- print(f"Fetched {len(questions_data)} questions.")
74
- except requests.exceptions.RequestException as e:
75
- print(f"Error fetching questions: {e}")
76
- return f"Error fetching questions: {e}", None
77
-
78
- results_log = []
79
- answers_payload = []
80
- print(f"Running agent on {len(questions_data)} questions...")
81
- for item in questions_data:
82
- task_id = item.get("task_id")
83
- question_text = item.get("question")
84
- if not task_id or question_text is None:
85
- print(f"Skipping item with missing task_id or question: {item}")
86
- continue
87
- try:
88
- submitted_answer = agent(question_text)
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
- submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
100
- status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
101
- print(status_update)
102
-
103
- print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
104
- try:
105
- response = requests.post(submit_url, json=submission_data, timeout=60)
106
- response.raise_for_status()
107
- result_data = response.json()
108
- final_status = (
109
- f"Submission Successful!\n"
110
- f"User: {result_data.get('username')}\n"
111
- f"Overall Score: {result_data.get('score', 'N/A')}% "
112
- f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
113
- f"Message: {result_data.get('message', 'No message received.')}"
114
- )
115
- print("Submission successful.")
116
- results_df = pd.DataFrame(results_log)
117
- return final_status, results_df
118
- except requests.exceptions.RequestException as e:
119
- status_message = f"Submission Failed: {e}"
120
- print(status_message)
121
- results_df = pd.DataFrame(results_log)
122
- return status_message, results_df
123
-
124
- # --- Gradio Interface ---
125
- with gr.Blocks() as demo:
126
- gr.Markdown("# Math Solver and Explainer Agent")
127
- gr.Markdown(
128
- """
129
- **Instructions:**
130
-
131
- 1. Modify this agent to use symbolic math tools and explanations.
132
- 2. Log in to your Hugging Face account.
133
- 3. Run the agent and submit all answers for scoring.
134
- """
135
- )
136
-
137
- gr.LoginButton()
138
-
139
- manual_input = gr.Textbox(label="Try the Agent Manually", placeholder="e.g., Solve for x: 2*x + 3 = 7")
140
- manual_output = gr.Textbox(label="Agent Response", lines=4, interactive=False)
141
- manual_test_button = gr.Button("Run Agent Locally")
142
-
143
- run_button = gr.Button("Run Evaluation & Submit All Answers")
144
- status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
145
- results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
146
-
147
- def run_manual_input(user_input):
148
- agent = MathSolverAgent()
149
- user_input = user_input.strip()
150
- print(f"Manual input received: {user_input}")
151
- return agent(user_input)
152
-
153
- manual_test_button.click(fn=run_manual_input, inputs=manual_input, outputs=manual_output)
154
-
155
- run_button.click(
156
- fn=run_and_submit_all,
157
- outputs=[status_output, results_table]
158
- )
159
-
160
- if __name__ == "__main__":
161
- print("\n" + "-"*30 + " App Starting " + "-"*30)
162
- space_host_startup = os.getenv("SPACE_HOST")
163
- space_id_startup = os.getenv("SPACE_ID")
164
-
165
- if space_host_startup:
166
- print(f"βœ… SPACE_HOST found: {space_host_startup}")
167
- print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
168
- else:
169
- print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
170
-
171
- if space_id_startup:
172
- print(f"βœ… SPACE_ID found: {space_id_startup}")
173
- print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
174
- print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
175
- else:
176
- print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
177
-
178
- print("-"*(60 + len(" App Starting ")) + "\n")
179
- print("Launching Gradio Interface for Math Solver Agent...")
180
- demo.launch(debug=True, share=False)
181
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -1,6 +1,18 @@
1
  gradio
2
  requests
3
  transformers
4
- sympy
5
- gradio
6
  huggingface_hub
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  gradio
2
  requests
3
  transformers
 
 
4
  huggingface_hub
5
+ langchain
6
+ openai
7
+ wikipedia
8
+ pytube
9
+ whisper
10
+ pillow
11
+ opencv-python
12
+ python-docx
13
+ PyMuPDF
14
+ youtube-transcript-api
15
+ openai-whisper
16
+ ffmpeg-python
17
+ python-chess
18
+ openpyxl
tools/__init__.py CHANGED
@@ -1,8 +1,2 @@
1
  # tools/__init__.py
2
 
3
- from .tool_math import SolveEquationTool, ExplainSolutionTool
4
-
5
- __all__ = [
6
- "SolveEquationTool",
7
- "ExplainSolutionTool",
8
- ]
 
1
  # tools/__init__.py
2
 
 
 
 
 
 
 
tools/audio_transcriber.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tools/audio_transcriber.py
2
+
3
+ import os
4
+ import tempfile
5
+ import whisper
6
+
7
+ # Load Whisper model only once (tiny, base, or small recommended for speed)
8
+ MODEL_NAME = "base"
9
+ whisper_model = whisper.load_model(MODEL_NAME)
10
+
11
+ def transcribe_audio(audio_file_path: str) -> str:
12
+ """
13
+ Transcribes speech from an audio file using OpenAI Whisper.
14
+
15
+ Args:
16
+ audio_file_path (str): Path to the local audio file (.mp3, .wav, etc.).
17
+
18
+ Returns:
19
+ str: Transcribed text or error message.
20
+ """
21
+ try:
22
+ result = whisper_model.transcribe(audio_file_path)
23
+ return result["text"].strip()
24
+ except Exception as e:
25
+ return f"Transcription error: {str(e)}"
tools/file_parser.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tools/file_parser.py
2
+
3
+ import pandas as pd
4
+ import os
5
+
6
+ def parse_file_and_summarize(file_path: str, query: str = "") -> str:
7
+ """
8
+ Reads a CSV or Excel file and optionally answers a simple question about it.
9
+
10
+ Args:
11
+ file_path (str): Path to the file (.csv or .xlsx).
12
+ query (str): Optional freeform instruction (e.g. "total food sales").
13
+
14
+ Returns:
15
+ str: Summary or result from the file.
16
+ """
17
+ try:
18
+ _, ext = os.path.splitext(file_path.lower())
19
+ if ext == ".csv":
20
+ df = pd.read_csv(file_path)
21
+ elif ext in [".xls", ".xlsx"]:
22
+ df = pd.read_excel(file_path)
23
+ else:
24
+ return "Unsupported file format. Please upload CSV or Excel."
25
+
26
+ if df.empty:
27
+ return "The file is empty or unreadable."
28
+
29
+ if not query:
30
+ return f"Loaded file with {df.shape[0]} rows and {df.shape[1]} columns.\nColumns: {', '.join(df.columns)}"
31
+
32
+ # Very basic natural language query handling (expand with LLM if needed)
33
+ if "total" in query.lower() and "food" in query.lower():
34
+ food_rows = df[df['category'].str.lower() == "food"]
35
+ if "sales" in df.columns:
36
+ total = food_rows["sales"].sum()
37
+ return f"Total food sales: ${total:.2f}"
38
+ else:
39
+ return "Could not find 'sales' column in the file."
40
+ else:
41
+ return "Query not supported. Please specify a clearer question."
42
+
43
+ except Exception as e:
44
+ return f"File parsing error: {str(e)}"
tools/image_chess_solver.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tools/image_chess_solver.py
2
+
3
+ import chess
4
+ import chess.engine
5
+ import tempfile
6
+ from PIL import Image
7
+
8
+ # Path to your Stockfish binary (update if needed)
9
+ STOCKFISH_PATH = "/usr/bin/stockfish"
10
+
11
+ def analyze_position_from_fen(fen: str, time_limit: float = 1.0) -> str:
12
+ """
13
+ Uses Stockfish to analyze the best move from a given FEN string.
14
+
15
+ Args:
16
+ fen (str): Forsyth–Edwards Notation of the board.
17
+ time_limit (float): Time to let Stockfish think.
18
+
19
+ Returns:
20
+ str: Best move in algebraic notation.
21
+ """
22
+ try:
23
+ board = chess.Board(fen)
24
+ engine = chess.engine.SimpleEngine.popen_uci(STOCKFISH_PATH)
25
+ result = engine.play(board, chess.engine.Limit(time=time_limit))
26
+ engine.quit()
27
+ return board.san(result.move)
28
+ except Exception as e:
29
+ return f"Stockfish error: {e}"
30
+
31
+ def solve_chess_image(image_path: str) -> str:
32
+ """
33
+ Stub function for image-to-FEN. Replace with actual OCR/vision logic.
34
+
35
+ Args:
36
+ image_path (str): Path to chessboard image.
37
+
38
+ Returns:
39
+ str: Best move or error.
40
+ """
41
+ # Placeholder FEN for development (e.g., black to move, guaranteed mate)
42
+ sample_fen = "6k1/5ppp/8/8/8/8/5PPP/6K1 b - - 0 1"
43
+
44
+ try:
45
+ print(f"Simulating FEN extraction from image: {image_path}")
46
+ # Replace the above with actual OCR image-to-FEN logic
47
+ best_move = analyze_position_from_fen(sample_fen)
48
+ return f"Detected FEN: {sample_fen}\nBest move for Black: {best_move}"
49
+ except Exception as e:
50
+ return f"Image analysis error: {e}"
tools/tool_math.py DELETED
@@ -1,26 +0,0 @@
1
- from sympy import symbols, Eq, solve, sympify
2
-
3
- class SolveEquationTool:
4
- name = "solve_equation"
5
- description = "Solves a basic equation for x. Format: '2*x + 3 = 7'"
6
-
7
- def __call__(self, equation: str) -> str:
8
- x = symbols('x')
9
- try:
10
- if "=" not in equation:
11
- return "Error: Equation must contain '=' sign. E.g., '2*x + 3 = 7'"
12
- lhs, rhs = equation.split("=")
13
- eq = Eq(sympify(lhs), sympify(rhs))
14
- sol = solve(eq, x)
15
- return f"x = {sol}"
16
- except Exception as e:
17
- return f"Error: {str(e)}"
18
-
19
- class ExplainSolutionTool:
20
- name = "explain_solution"
21
- description = "Provides a hardcoded explanation for a known equation."
22
-
23
- def __call__(self, problem: str) -> str:
24
- if "2*x + 3 = 7" in problem.replace(" ", ""):
25
- return "Step 1: Subtract 3 β†’ 2x = 4\nStep 2: Divide by 2 β†’ x = 2"
26
- return "This agent currently only explains '2*x + 3 = 7'. Extend this for more coverage."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tools/wikipedia_tool.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tools/wikipedia_tool.py
2
+
3
+ import wikipedia
4
+
5
+ wikipedia.set_lang("en")
6
+
7
+ def wiki_search(query: str) -> str:
8
+ """
9
+ Search Wikipedia and return a short summary of the topic.
10
+
11
+ Args:
12
+ query (str): The search query.
13
+
14
+ Returns:
15
+ str: Summary text or error message.
16
+ """
17
+ try:
18
+ # Try to fetch a summary of the most relevant page
19
+ return wikipedia.summary(query, sentences=3, auto_suggest=True, redirect=True)
20
+ except wikipedia.DisambiguationError as e:
21
+ # If multiple results, return options
22
+ pass
tools/youtube_tool.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tools/youtube_tool.py
2
+
3
+ from youtube_transcript_api import YouTubeTranscriptApi
4
+ from youtube_transcript_api._errors import TranscriptsDisabled, NoTranscriptFound
5
+ import re
6
+
7
+ def extract_video_id(url: str) -> str:
8
+ """
9
+ Extracts the video ID from a YouTube URL.
10
+
11
+ Args:
12
+ url (str): The full YouTube video URL.
13
+
14
+ Returns:
15
+ str: The extracted video ID or raises ValueError.
16
+ """
17
+ patterns = [
18
+ r"youtube\.com/watch\?v=([a-zA-Z0-9_-]{11})",
19
+ r"youtu\.be/([a-zA-Z0-9_-]{11})"
20
+ ]
21
+ for pattern in patterns:
22
+ match = re.search(pattern, url)
23
+ if match:
24
+ return match.group(1)
25
+ raise ValueError("Invalid YouTube URL or unable to extract video ID.")
26
+
27
+ def get_youtube_transcript(url: str) -> str:
28
+ """
29
+ Fetches the transcript text for a given YouTube video.
30
+
31
+ Args:
32
+ url (str): The YouTube video URL.
33
+
34
+ Returns:
35
+ str: Combined transcript text or an error message.
36
+ """
37
+ try:
38
+ video_id = extract_video_id(url)
39
+ transcript_list = YouTubeTranscriptApi.get_transcript(video_id)
40
+ full_text = " ".join([entry["text"] for entry in transcript_list])
41
+ return full_text.strip()[:2000] # Truncate to 2000 chars to prevent token overflow
42
+ except TranscriptsDisabled:
43
+ return "This video has transcripts disabled."
44
+ except NoTranscriptFound:
45
+ return "No transcript was found for this video."
46
+ except Exception as e:
47
+ return f"Transcript error: {str(e)}"