Masrkai commited on
Commit
9599b16
·
1 Parent(s): 152b50d
Files changed (1) hide show
  1. app.py +38 -246
app.py CHANGED
@@ -3,220 +3,32 @@ import gradio as gr
3
  import requests
4
  import inspect
5
  import pandas as pd
6
- import json
7
- import re
8
- from typing import Dict, Any, Optional
9
- import time
10
 
 
11
  # --- Constants ---
12
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
13
 
14
- class EnhancedAgent:
15
- """
16
- An enhanced AI agent that can handle various types of questions using web search,
17
- mathematical reasoning, and structured problem-solving approaches.
18
- """
19
-
20
  def __init__(self):
21
- print("EnhancedAgent initialized.")
22
- # You can add API keys or other initialization here
23
- self.search_timeout = 10
24
- self.max_retries = 3
25
-
26
- def search_web(self, query: str, max_results: int = 5) -> list:
27
- """
28
- Perform web search using a search API (you'll need to implement this with your preferred service)
29
- For now, this is a placeholder - you should integrate with Google Custom Search, Bing, or similar
30
- """
31
- try:
32
- # Placeholder for web search - replace with actual API call
33
- # Example with requests to a search service:
34
- # response = requests.get(f"https://your-search-api.com/search?q={query}")
35
- # return response.json()['results']
36
-
37
- # For demonstration, returning empty results
38
- print(f"Web search query: {query}")
39
- return []
40
- except Exception as e:
41
- print(f"Web search error: {e}")
42
- return []
43
-
44
- def extract_numbers(self, text: str) -> list:
45
- """Extract numbers from text"""
46
- return re.findall(r'-?\d+\.?\d*', text)
47
-
48
- def is_math_question(self, question: str) -> bool:
49
- """Determine if question requires mathematical computation"""
50
- math_keywords = ['calculate', 'compute', 'sum', 'multiply', 'divide', 'subtract',
51
- 'percentage', 'average', 'total', 'how many', 'how much']
52
- return any(keyword in question.lower() for keyword in math_keywords)
53
-
54
- def is_factual_question(self, question: str) -> bool:
55
- """Determine if question requires factual lookup"""
56
- factual_keywords = ['who is', 'what is', 'when did', 'where is', 'which country',
57
- 'capital of', 'president of', 'founded in', 'born in']
58
- return any(keyword in question.lower() for keyword in factual_keywords)
59
-
60
- def solve_math_question(self, question: str) -> str:
61
- """Handle mathematical questions"""
62
- try:
63
- # Extract numbers from the question
64
- numbers = self.extract_numbers(question)
65
-
66
- # Simple mathematical operations based on keywords
67
- if 'sum' in question.lower() or 'add' in question.lower():
68
- if len(numbers) >= 2:
69
- result = sum(float(n) for n in numbers)
70
- return str(result)
71
-
72
- elif 'multiply' in question.lower() or 'product' in question.lower():
73
- if len(numbers) >= 2:
74
- result = 1
75
- for n in numbers:
76
- result *= float(n)
77
- return str(result)
78
-
79
- elif 'subtract' in question.lower():
80
- if len(numbers) >= 2:
81
- result = float(numbers[0]) - float(numbers[1])
82
- return str(result)
83
-
84
- elif 'divide' in question.lower():
85
- if len(numbers) >= 2 and float(numbers[1]) != 0:
86
- result = float(numbers[0]) / float(numbers[1])
87
- return str(result)
88
-
89
- elif 'percentage' in question.lower() or '%' in question:
90
- if len(numbers) >= 2:
91
- result = (float(numbers[0]) / float(numbers[1])) * 100
92
- return f"{result}%"
93
-
94
- # If no specific operation found, return the first number found
95
- if numbers:
96
- return numbers[0]
97
-
98
- except Exception as e:
99
- print(f"Math solving error: {e}")
100
-
101
- return "Unable to solve mathematical question"
102
-
103
- def handle_factual_question(self, question: str) -> str:
104
- """Handle factual questions that might need web search"""
105
- # First try to answer with common knowledge
106
- question_lower = question.lower()
107
-
108
- # Common factual answers (you can expand this)
109
- if 'capital of france' in question_lower:
110
- return "Paris"
111
- elif 'capital of germany' in question_lower:
112
- return "Berlin"
113
- elif 'capital of japan' in question_lower:
114
- return "Tokyo"
115
- elif 'president of united states' in question_lower or 'us president' in question_lower:
116
- return "Joe Biden" # Update based on current information
117
-
118
- # If no direct match, try web search
119
- search_results = self.search_web(question)
120
- if search_results:
121
- # Process search results to extract answer
122
- # This is a simplified approach - in practice, you'd want more sophisticated extraction
123
- for result in search_results[:3]:
124
- if 'snippet' in result:
125
- return result['snippet'][:200] # Return first snippet
126
-
127
- return "Information not available"
128
-
129
- def analyze_question_type(self, question: str) -> str:
130
- """Analyze what type of question this is"""
131
- if self.is_math_question(question):
132
- return "mathematical"
133
- elif self.is_factual_question(question):
134
- return "factual"
135
- elif any(word in question.lower() for word in ['file', 'document', 'image', 'data']):
136
- return "file_based"
137
- else:
138
- return "general"
139
-
140
  def __call__(self, question: str) -> str:
141
- """
142
- Main agent function that processes questions and returns answers
143
- """
144
- print(f"Agent received question (first 100 chars): {question[:100]}...")
145
-
146
- try:
147
- # Clean the question
148
- question = question.strip()
149
-
150
- # Analyze question type
151
- question_type = self.analyze_question_type(question)
152
- print(f"Question type identified: {question_type}")
153
-
154
- # Route to appropriate handler
155
- if question_type == "mathematical":
156
- answer = self.solve_math_question(question)
157
- elif question_type == "factual":
158
- answer = self.handle_factual_question(question)
159
- elif question_type == "file_based":
160
- # For file-based questions, we'd need to access the files via the API
161
- # This would require additional implementation
162
- answer = "File-based question processing not yet implemented"
163
- else:
164
- # General reasoning approach
165
- answer = self.general_reasoning(question)
166
-
167
- print(f"Agent returning answer: {answer}")
168
- return answer
169
-
170
- except Exception as e:
171
- print(f"Error in agent processing: {e}")
172
- return "Error processing question"
173
-
174
- def general_reasoning(self, question: str) -> str:
175
- """Handle general questions with basic reasoning"""
176
- try:
177
- # Simple pattern matching for common question types
178
- question_lower = question.lower()
179
-
180
- if 'yes' in question_lower and 'no' in question_lower:
181
- # Yes/No question - make a reasonable guess
182
- if any(word in question_lower for word in ['is', 'are', 'can', 'will', 'should']):
183
- return "Yes"
184
- else:
185
- return "No"
186
-
187
- elif 'how many' in question_lower:
188
- # Try to extract numbers from context
189
- numbers = self.extract_numbers(question)
190
- if numbers:
191
- return numbers[-1] # Return the last number found
192
- else:
193
- return "1" # Default guess
194
-
195
- elif 'which' in question_lower or 'what' in question_lower:
196
- # Try to find the most likely answer from the question context
197
- words = question.split()
198
- # Look for capitalized words (potential proper nouns)
199
- proper_nouns = [word for word in words if word[0].isupper() and len(word) > 1]
200
- if proper_nouns:
201
- return proper_nouns[0]
202
-
203
- # Default response for unhandled cases
204
- return "Unable to determine answer"
205
-
206
- except Exception as e:
207
- print(f"General reasoning error: {e}")
208
- return "Error in reasoning"
209
 
210
- def run_and_submit_all(profile: gr.OAuthProfile | None):
211
  """
212
- Fetches all questions, runs the EnhancedAgent on them, submits all answers,
213
  and displays the results.
214
  """
215
  # --- Determine HF Space Runtime URL and Repo URL ---
216
- space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
217
 
218
  if profile:
219
- username = f"{profile.username}"
220
  print(f"User logged in: {username}")
221
  else:
222
  print("User not logged in.")
@@ -226,14 +38,13 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
226
  questions_url = f"{api_url}/questions"
227
  submit_url = f"{api_url}/submit"
228
 
229
- # 1. Instantiate Agent
230
  try:
231
- agent = EnhancedAgent() # Using our enhanced agent
232
  except Exception as e:
233
  print(f"Error instantiating agent: {e}")
234
  return f"Error initializing agent: {e}", None
235
-
236
- # Agent code URL
237
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
238
  print(agent_code)
239
 
@@ -244,16 +55,16 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
244
  response.raise_for_status()
245
  questions_data = response.json()
246
  if not questions_data:
247
- print("Fetched questions list is empty.")
248
- return "Fetched questions list is empty or invalid format.", None
249
  print(f"Fetched {len(questions_data)} questions.")
250
  except requests.exceptions.RequestException as e:
251
  print(f"Error fetching questions: {e}")
252
  return f"Error fetching questions: {e}", None
253
  except requests.exceptions.JSONDecodeError as e:
254
- print(f"Error decoding JSON response from questions endpoint: {e}")
255
- print(f"Response text: {response.text[:500]}")
256
- return f"Error decoding server response for questions: {e}", None
257
  except Exception as e:
258
  print(f"An unexpected error occurred fetching questions: {e}")
259
  return f"An unexpected error occurred fetching questions: {e}", None
@@ -262,34 +73,19 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
262
  results_log = []
263
  answers_payload = []
264
  print(f"Running agent on {len(questions_data)} questions...")
265
-
266
- for i, item in enumerate(questions_data):
267
  task_id = item.get("task_id")
268
  question_text = item.get("question")
269
  if not task_id or question_text is None:
270
  print(f"Skipping item with missing task_id or question: {item}")
271
  continue
272
-
273
  try:
274
- print(f"Processing question {i+1}/{len(questions_data)}: {task_id}")
275
  submitted_answer = agent(question_text)
276
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
277
- results_log.append({
278
- "Task ID": task_id,
279
- "Question": question_text[:100] + "..." if len(question_text) > 100 else question_text,
280
- "Submitted Answer": submitted_answer
281
- })
282
-
283
- # Small delay to avoid overwhelming the system
284
- time.sleep(0.1)
285
-
286
  except Exception as e:
287
- print(f"Error running agent on task {task_id}: {e}")
288
- results_log.append({
289
- "Task ID": task_id,
290
- "Question": question_text[:100] + "..." if len(question_text) > 100 else question_text,
291
- "Submitted Answer": f"AGENT ERROR: {e}"
292
- })
293
 
294
  if not answers_payload:
295
  print("Agent did not produce any answers to submit.")
@@ -346,24 +142,19 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
346
 
347
  # --- Build Gradio Interface using Blocks ---
348
  with gr.Blocks() as demo:
349
- gr.Markdown("# Enhanced AI Agent Evaluation Runner")
350
  gr.Markdown(
351
  """
352
  **Instructions:**
353
 
354
- 1. This enhanced agent can handle various types of questions including mathematical, factual, and general reasoning questions.
355
- 2. Log in to your Hugging Face account using the button below.
356
- 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
357
-
358
- **Agent Features:**
359
- - Mathematical question solving
360
- - Factual question handling with web search capability
361
- - General reasoning for complex questions
362
- - Question type classification
363
- - Error handling and retry mechanisms
364
 
365
  ---
366
- **Note:** This may take several minutes to process all questions.
 
 
367
  """
368
  )
369
 
@@ -372,6 +163,7 @@ with gr.Blocks() as demo:
372
  run_button = gr.Button("Run Evaluation & Submit All Answers")
373
 
374
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
375
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
376
 
377
  run_button.click(
@@ -380,10 +172,10 @@ with gr.Blocks() as demo:
380
  )
381
 
382
  if __name__ == "__main__":
383
- print("\n" + "-"*30 + " Enhanced Agent App Starting " + "-"*30)
384
  # Check for SPACE_HOST and SPACE_ID at startup for information
385
  space_host_startup = os.getenv("SPACE_HOST")
386
- space_id_startup = os.getenv("SPACE_ID")
387
 
388
  if space_host_startup:
389
  print(f"✅ SPACE_HOST found: {space_host_startup}")
@@ -391,14 +183,14 @@ if __name__ == "__main__":
391
  else:
392
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
393
 
394
- if space_id_startup:
395
  print(f"✅ SPACE_ID found: {space_id_startup}")
396
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
397
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
398
  else:
399
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
400
 
401
- print("-"*(60 + len(" Enhanced Agent App Starting ")) + "\n")
402
 
403
- print("Launching Gradio Interface for Enhanced Agent Evaluation...")
404
  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.")
 
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
 
 
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
 
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.")
 
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
 
150
+ 1. Please clone this space, then modify the code to define your agent's logic within the `BasicAgent` class or outside if necessary.
151
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
152
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
 
 
 
 
 
 
 
153
 
154
  ---
155
+ **Disclaimers:**
156
+ Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
157
+ This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a seperate action or even to answer the questions in async.
158
  """
159
  )
160
 
 
163
  run_button = gr.Button("Run Evaluation & Submit All Answers")
164
 
165
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
166
+ # Removed max_rows=10 from DataFrame constructor
167
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
168
 
169
  run_button.click(
 
172
  )
173
 
174
  if __name__ == "__main__":
175
+ print("\n" + "-"*30 + " App Starting " + "-"*30)
176
  # Check for SPACE_HOST and SPACE_ID at startup for information
177
  space_host_startup = os.getenv("SPACE_HOST")
178
+ space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
179
 
180
  if space_host_startup:
181
  print(f"✅ SPACE_HOST found: {space_host_startup}")
 
183
  else:
184
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
185
 
186
+ if space_id_startup: # Print repo URLs if SPACE_ID is found
187
  print(f"✅ SPACE_ID found: {space_id_startup}")
188
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
189
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
190
  else:
191
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
192
 
193
+ print("-"*(60 + len(" App Starting ")) + "\n")
194
 
195
+ print("Launching Gradio Interface for Basic Agent Evaluation...")
196
  demo.launch(debug=True, share=False)