kobaIK commited on
Commit
00e9531
·
verified ·
1 Parent(s): 88e8423

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +430 -40
app.py CHANGED
@@ -3,23 +3,390 @@ import gradio as gr
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.
@@ -28,7 +395,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
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,13 +405,13 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
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
 
@@ -54,6 +421,9 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
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
@@ -69,30 +439,44 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
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
 
@@ -139,31 +523,28 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
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
-
150
- 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
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
 
161
  gr.LoginButton()
162
-
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(
@@ -173,24 +554,33 @@ with gr.Blocks() as demo:
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}")
182
  print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
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)
 
3
  import requests
4
  import inspect
5
  import pandas as pd
6
+ from smolagents import (
7
+ CodeAgent,
8
+ LiteLLMModel,
9
+ DuckDuckGoSearchTool,
10
+ LogLevel,
11
+ load_tool,
12
+ PythonInterpreterTool
13
+ )
14
+ from dotenv import load_dotenv
15
+ from smolagents import Tool
16
+ import base64
17
+ import anthropic
18
+ from PIL import Image
19
+ import io
20
+
21
+ class SimpleExcelTool(Tool):
22
+ name = "SimpleExcelTool"
23
+ description = "Load a downloaded Excel file associated with a task ID and perform basic operations like reading data"
24
+ inputs = {
25
+ "task_id": {
26
+ "type": "string",
27
+ "description": "Task ID for which the Excel file has been downloaded"
28
+ },
29
+ "operation": {
30
+ "type": "string",
31
+ "description": "Operation to perform on the Excel file (currently only 'read' is supported)",
32
+ "nullable": True
33
+ }
34
+ }
35
+ output_type = "string"
36
+
37
+ def forward(self, task_id: str, operation: str = "read") -> str:
38
+ try:
39
+ filename = f"{task_id}_downloaded_file"
40
+ df = pd.read_excel(filename, engine="openpyxl")
41
+
42
+ if operation == "read":
43
+ return df.head().to_string()
44
+ else:
45
+ return f"Unsupported operation: {operation}"
46
+ except Exception as e:
47
+ return f"Error reading Excel file: {str(e)}"
48
+
49
+ class ImageAnalysisTool(Tool):
50
+ name = "ImageAnalysisTool"
51
+ description = "Analyze a downloaded image file associated with a task ID using Claude Vision. Provide a detailed description of what's in the image."
52
+ inputs = {
53
+ "task_id": {
54
+ "type": "string",
55
+ "description": "Task ID for which the image file has been downloaded"
56
+ },
57
+ "prompt": {
58
+ "type": "string",
59
+ "description": "Optional specific question or aspect to analyze about the image",
60
+ "nullable": True
61
+ }
62
+ }
63
+ output_type = "string"
64
+
65
+ def __init__(self):
66
+ super().__init__()
67
+ self.client = anthropic.Client(api_key="")
68
+
69
+ def forward(self, task_id: str, prompt: str = "Describe what you see in this image in detail.") -> str:
70
+ try:
71
+ filename = f"{task_id}_downloaded_file"
72
+
73
+ with open(filename, 'rb') as img_file:
74
+ img_bytes = img_file.read()
75
+
76
+ img = Image.open(io.BytesIO(img_bytes))
77
+ if img.mode != 'RGB':
78
+ img = img.convert('RGB')
79
+
80
+ img_byte_arr = io.BytesIO()
81
+ img.save(img_byte_arr, format='JPEG')
82
+ img_byte_arr = img_byte_arr.getvalue()
83
+
84
+ base64_image = base64.b64encode(img_byte_arr).decode('utf-8')
85
+
86
+ message = self.client.messages.create(
87
+ model="claude-3-7-sonnet-20250219",
88
+ max_tokens=1000,
89
+ messages=[{
90
+ "role": "user",
91
+ "content": [
92
+ {
93
+ "type": "image",
94
+ "source": {
95
+ "type": "base64",
96
+ "media_type": "image/jpeg",
97
+ "data": base64_image
98
+ }
99
+ },
100
+ {
101
+ "type": "text",
102
+ "text": prompt
103
+ }
104
+ ]
105
+ }]
106
+ )
107
+
108
+ return message.content[0].text
109
+
110
+ except Exception as e:
111
+ return f"Error analyzing image: {str(e)}"
112
+
113
+
114
+ # New: TaskFileDownloaderTool
115
+ class TaskFileDownloaderTool(Tool):
116
+ name = "TaskFileDownloaderTool"
117
+ description = "Download a specific file associated with a given task ID and save it locally"
118
+ inputs = {
119
+ "task_id": {
120
+ "type": "string",
121
+ "description": "Task ID for which to download the associated file"
122
+ }
123
+ }
124
+ output_type = "string"
125
+
126
+ def forward(self, task_id: str) -> str:
127
+ try:
128
+ download_url = f"{DEFAULT_API_URL}/files/{task_id}"
129
+ response = requests.get(download_url)
130
+ response.raise_for_status()
131
+
132
+ filename = f"{task_id}_downloaded_file"
133
+ with open(filename, "wb") as f:
134
+ f.write(response.content)
135
+
136
+ return f"File downloaded successfully and saved as: {filename}"
137
+ except Exception as e:
138
+ return f"Error downloading file: {str(e)}"
139
+
140
+ # New: FileOpenerTool
141
+ class FileOpenerTool(Tool):
142
+ name = "FileOpenerTool"
143
+ description = "Open a downloaded file associated with a task ID and read its contents as plain text."
144
+ inputs = {
145
+ "task_id": {
146
+ "type": "string",
147
+ "description": "Task ID for which the file has been downloaded"
148
+ },
149
+ "num_lines": {
150
+ "type": "integer",
151
+ "description": "Number of lines to read from the file",
152
+ "nullable": True
153
+ }
154
+ }
155
+ output_type = "string"
156
+
157
+ def forward(self, task_id: str, num_lines: int = 10) -> str:
158
+ try:
159
+ filename = f"{task_id}_downloaded_file"
160
+ if not os.path.exists(filename):
161
+ return f"Error: File {filename} does not exist."
162
+
163
+ with open(filename, "r", encoding="utf-8", errors="ignore") as file:
164
+ lines = []
165
+ for _ in range(num_lines):
166
+ line = file.readline()
167
+ if not line:
168
+ break
169
+ lines.append(line.strip())
170
+
171
+ return "\n".join(lines)
172
+ except Exception as e:
173
+ return f"Error reading file: {str(e)}"
174
+
175
+ # New: SpeechToTextTool
176
+ import mlx_whisper
177
+
178
+ class SpeechToTextTool(Tool):
179
+ name = "SpeechToTextTool"
180
+ description = "Transcribe a downloaded MP3 audio file associated with a task ID into text."
181
+ inputs = {
182
+ "task_id": {
183
+ "type": "string",
184
+ "description": "Task ID for which the MP3 audio file has been downloaded"
185
+ }
186
+ }
187
+ output_type = "string"
188
+
189
+ def __init__(self):
190
+ super().__init__()
191
+
192
+ def forward(self, task_id: str) -> str:
193
+ try:
194
+ filename = f"{task_id}_downloaded_file"
195
+ if not os.path.exists(filename):
196
+ return f"Error: Audio file {filename} does not exist."
197
+
198
+ result = mlx_whisper.transcribe(filename)
199
+ return result["text"]
200
+ except Exception as e:
201
+ return f"Error transcribing audio file: {str(e)}"
202
+
203
+
204
+
205
+ import wikipedia
206
+
207
+ class WikipediaSearchTool(Tool):
208
+ name = "WikipediaSearchTool"
209
+ description = "Search Wikipedia for a query and return a brief summary."
210
+ inputs = {
211
+ "query": {
212
+ "type": "string",
213
+ "description": "Query to search on Wikipedia"
214
+ }
215
+ }
216
+ output_type = "string"
217
+
218
+ def __init__(self):
219
+ super().__init__()
220
+ wikipedia.set_lang("en") # Ensure English Wikipedia
221
+
222
+ def forward(self, query: str) -> str:
223
+ try:
224
+ summary = wikipedia.summary(query, sentences=3000)
225
+ return summary
226
+ except wikipedia.exceptions.DisambiguationError as e:
227
+ return f"Disambiguation error. Possible options: {e.options[:5]}"
228
+ except wikipedia.exceptions.PageError:
229
+ return f"Page not found for query: {query}"
230
+ except Exception as e:
231
+ return f"Error searching Wikipedia: {str(e)}"
232
+
233
+
234
+ import os
235
+ from youtube_transcript_api import YouTubeTranscriptApi, TextFormatter
236
+ import yt_dlp
237
+ import mlx_whisper
238
+
239
+ class YouTubeTranscriptTool(Tool):
240
+ name = "YouTubeTranscriptTool"
241
+ description = "Fetches or transcribes the text from a YouTube video ID."
242
+ inputs = {
243
+ "video_id": {
244
+ "type": "string",
245
+ "description": "YouTube Video ID (the part after 'watch?v=')"
246
+ }
247
+ }
248
+ output_type = "string"
249
+
250
+ def __init__(self):
251
+ super().__init__()
252
+
253
+ def forward(self, video_id: str) -> str:
254
+ try:
255
+ transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
256
+
257
+ try:
258
+ # First try manually created transcript
259
+ transcript = transcript_list.find_manually_created_transcript(['en'])
260
+ except Exception:
261
+ # If not found, try auto-generated transcript
262
+ transcript = transcript_list.find_generated_transcript(['en'])
263
+
264
+ transcript_data = transcript.fetch()
265
+
266
+ # Format nicely
267
+ formatter = TextFormatter()
268
+ text = formatter.format_transcript(transcript_data)
269
+
270
+ return text
271
+
272
+ except Exception as e:
273
+ print(f"No direct transcript found: {e}")
274
+ print("Trying to download and transcribe audio with Whisper...")
275
+
276
+ # Step 1: Download audio using yt_dlp
277
+ audio_filename = f"{video_id}.mp3"
278
+ try:
279
+ ydl_opts = {
280
+ 'format': 'bestaudio/best',
281
+ 'outtmpl': audio_filename,
282
+ 'postprocessors': [{
283
+ 'key': 'FFmpegExtractAudio',
284
+ 'preferredcodec': 'mp3',
285
+ 'preferredquality': '192',
286
+ }],
287
+ 'quiet': True,
288
+ }
289
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
290
+ ydl.download([f"https://www.youtube.com/watch?v={video_id}"])
291
+
292
+ # Step 2: Transcribe audio using mlx_whisper
293
+ result = mlx_whisper.transcribe(audio_filename)
294
+ return result["text"]
295
+
296
+ except Exception as download_error:
297
+ return f"Error downloading or transcribing YouTube audio: {str(download_error)}"
298
+ finally:
299
+ if os.path.exists(audio_filename):
300
+ os.remove(audio_filename) # Clean up downloaded file
301
+
302
+ # Load environment variables
303
+ load_dotenv()
304
 
305
  # (Keep Constants as is)
306
  # --- Constants ---
307
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
308
 
309
  # --- Basic Agent Definition ---
 
310
  class BasicAgent:
311
  def __init__(self):
312
+ print("Initializing Agent with tools...")
313
+
314
+ # Initialize the model using Claude via LiteLLM
315
+ self.model = LiteLLMModel(
316
+ model="claude-3-7-sonnet-20250219",
317
+ api_key="",
318
+ temperature=0.7,
319
+ max_tokens=4096
320
+ )
321
+
322
+ # Initialize tools
323
+ youtube_transcript_tool = YouTubeTranscriptTool()
324
+ excel_tool = SimpleExcelTool()
325
+ image_analysis_tool = ImageAnalysisTool()
326
+ file_opener_tool = FileOpenerTool()
327
+ speech_to_text_tool = SpeechToTextTool()
328
+ task_file_downloader_tool = TaskFileDownloaderTool()
329
+ wikipedia_search_tool = WikipediaSearchTool()
330
+
331
+ self.tools = [
332
+ DuckDuckGoSearchTool(),
333
+ wikipedia_search_tool,
334
+ youtube_transcript_tool,
335
+ PythonInterpreterTool(),
336
+ excel_tool,
337
+ image_analysis_tool,
338
+ file_opener_tool,
339
+ speech_to_text_tool,
340
+ task_file_downloader_tool
341
+ ]
342
+
343
+ # Initialize the agent
344
+ self.agent = CodeAgent(
345
+ tools=self.tools,
346
+ model=self.model,
347
+ verbosity_level=LogLevel.INFO
348
+ )
349
+
350
+ print("Agent initialized successfully")
351
+
352
+ def __call__(self, question: str, task_id: str) -> str:
353
+ print(f"Agent received question: {question[:100]}...")
354
+ try:
355
+ # Step 1: Download the file associated with the task first
356
+ download_result = self.tools[-1](task_id=task_id) # TaskFileDownloaderTool is the last in self.tools
357
+ print(download_result)
358
+
359
+ # Step 2: Create a comprehensive prompt for the agent
360
+ prompt = f"""Please answer the following question. Use the available tools (web search)
361
+ to gather relevant information before providing a comprehensive answer.
362
+
363
+ Question: {question}
364
+ Task_id: {task_id}
365
+
366
+ Instructions:
367
+ 1. Search for relevant information using web search.
368
+ 2. Look for relevant YouTube content if applicable.
369
+ 3. If the task requires working with an Excel or image file:
370
+ - First, download the file associated with the task ID using the file download tool.
371
+ - Then, perform analysis on the downloaded file.
372
+ 4. Extract and analyze data from Excel files after downloading.
373
+ 5. Convert images to text after downloading the image file.
374
+ 6. Convert attached mp3 to text as seepch to text
375
+ 7. Make Wikipedia search on facts and for a query and return a brief summary
376
+ 78. Synthesize all gathered and analyzed information into a clear, well-structured final answer.
377
+ Answer:"""
378
+
379
+ # Step 3: Get response from the agent
380
+ response = self.agent.run(prompt)
381
+ print(f"Agent generated response: {response[:100]}...")
382
+ return response
383
+
384
+ except Exception as e:
385
+ error_msg = f"Error generating answer: {str(e)}"
386
+ print(error_msg)
387
+ return error_msg
388
+
389
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
390
  """
391
  Fetches all questions, runs the BasicAgent on them, submits all answers,
392
  and displays the results.
 
395
  space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
396
 
397
  if profile:
398
+ username = f"{profile.username}"
399
  print(f"User logged in: {username}")
400
  else:
401
  print("User not logged in.")
 
405
  questions_url = f"{api_url}/questions"
406
  submit_url = f"{api_url}/submit"
407
 
408
+ # 1. Instantiate Agent
409
  try:
410
  agent = BasicAgent()
411
  except Exception as e:
412
  print(f"Error instantiating agent: {e}")
413
  return f"Error initializing agent: {e}", None
414
+
415
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
416
  print(agent_code)
417
 
 
421
  response = requests.get(questions_url, timeout=15)
422
  response.raise_for_status()
423
  questions_data = response.json()
424
+
425
+ print(questions_data)
426
+
427
  if not questions_data:
428
  print("Fetched questions list is empty.")
429
  return "Fetched questions list is empty or invalid format.", None
 
439
  print(f"An unexpected error occurred fetching questions: {e}")
440
  return f"An unexpected error occurred fetching questions: {e}", None
441
 
442
+ # 3. Run Agent
443
  results_log = []
444
  answers_payload = []
445
  print(f"Running agent on {len(questions_data)} questions...")
446
+
447
  for item in questions_data:
448
  task_id = item.get("task_id")
449
  question_text = item.get("question")
450
  if not task_id or question_text is None:
451
  print(f"Skipping item with missing task_id or question: {item}")
452
  continue
453
+
454
  try:
455
+ submitted_answer = agent(question_text, task_id)
456
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
457
+ results_log.append({
458
+ "Task ID": task_id,
459
+ "Question": question_text,
460
+ "Submitted Answer": submitted_answer
461
+ })
462
  except Exception as e:
463
+ print(f"Error running agent on task {task_id}: {e}")
464
+ results_log.append({
465
+ "Task ID": task_id,
466
+ "Question": question_text,
467
+ "Submitted Answer": f"AGENT ERROR: {e}"
468
+ })
469
 
470
  if not answers_payload:
471
  print("Agent did not produce any answers to submit.")
472
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
473
 
474
+ # 4. Prepare Submission
475
+ submission_data = {
476
+ "username": username.strip(),
477
+ "agent_code": agent_code,
478
+ "answers": answers_payload
479
+ }
480
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
481
  print(status_update)
482
 
 
523
  results_df = pd.DataFrame(results_log)
524
  return status_message, results_df
525
 
 
526
  # --- Build Gradio Interface using Blocks ---
527
  with gr.Blocks() as demo:
528
+ gr.Markdown("# Advanced Agent Evaluation Runner")
529
  gr.Markdown(
530
  """
531
  **Instructions:**
532
+ 1. Make sure you have set up your environment variables:
533
+ - HF_TOKEN: Your Hugging Face API token
534
+ - YOUTUBE_API_KEY: Your YouTube API key (optional)
535
+ 2. Log in to your Hugging Face account using the button below
536
+ 3. Click 'Run Evaluation & Submit All Answers' to process all questions
537
+
538
+ The agent will use:
539
+ - Web search (DuckDuckGo)
540
+ - YouTube search (if API key provided)
541
+ - Mistral-7B-Instruct LLM
542
  """
543
  )
544
 
545
  gr.LoginButton()
 
546
  run_button = gr.Button("Run Evaluation & Submit All Answers")
 
547
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
548
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
549
 
550
  run_button.click(
 
554
 
555
  if __name__ == "__main__":
556
  print("\n" + "-"*30 + " App Starting " + "-"*30)
557
+
558
+ # Check for required environment variables
559
+ hf_token = os.getenv("HF_TOKEN")
560
+ if not hf_token:
561
+ print("⚠️ Warning: HF_TOKEN not found in environment variables")
562
+
563
+ youtube_api_key = os.getenv("YOUTUBE_API_KEY")
564
+ if not youtube_api_key:
565
+ print("ℹ️ Note: YOUTUBE_API_KEY not found. YouTube search will be disabled")
566
+
567
+ # Check for SPACE_HOST and SPACE_ID
568
  space_host_startup = os.getenv("SPACE_HOST")
569
+ space_id_startup = os.getenv("SPACE_ID")
570
 
571
  if space_host_startup:
572
  print(f"✅ SPACE_HOST found: {space_host_startup}")
573
  print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
574
  else:
575
+ print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
576
 
577
+ if space_id_startup:
578
  print(f"✅ SPACE_ID found: {space_id_startup}")
579
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
580
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
581
  else:
582
+ print("ℹ️ SPACE_ID environment variable not found (running locally?)")
583
 
584
  print("-"*(60 + len(" App Starting ")) + "\n")
585
+ print("Launching Gradio Interface for Advanced Agent Evaluation...")
 
586
  demo.launch(debug=True, share=False)