likki1715 commited on
Commit
4df03d1
·
verified ·
1 Parent(s): 1f76542

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -61
app.py CHANGED
@@ -10,35 +10,76 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
10
 
11
  # --- Tool Implementations ---
12
 
13
- def download_task_file(task_id: str) -> str:
14
- """Checks the API for attached files and downloads them to the working directory."""
15
  url = f"{DEFAULT_API_URL}/files/{task_id}"
16
  try:
17
  response = requests.get(url, timeout=15)
18
- if response.status_code == 200:
19
- cd = response.headers.get('content-disposition')
20
- filename = f"file_{task_id[:8]}.tmp"
21
- if cd:
22
- match = re.search(r'filename="?([^"]+)"?', cd)
23
- if match:
24
- filename = match.group(1)
25
- with open(filename, 'wb') as f:
26
- f.write(response.content)
27
- return (
28
- f"\n[SYSTEM: File '{filename}' downloaded. "
29
- f"READ IT FIRST using PYTHON:\n```python\n"
30
- f"try:\n"
31
- f" with open('{filename}', 'r', encoding='utf-8') as f:\n"
32
- f" print(f.read())\n"
33
- f"except:\n"
34
- f" with open('{filename}', 'rb') as f:\n"
35
- f" print(repr(f.read()[:2000]))\n"
36
- f"```\n]\n"
37
- )
38
- return ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  except Exception as e:
40
- print(f"File download error for {task_id}: {e}")
41
- return ""
42
 
43
 
44
  def web_search(query: str) -> str:
@@ -50,7 +91,7 @@ def web_search(query: str) -> str:
50
  return "No results found."
51
  output = []
52
  for r in results:
53
- output.append(f"Title: {r.get('title','')}\nURL: {r.get('href','')}\nSnippet: {r.get('body','')[:200]}")
54
  return "\n---\n".join(output)
55
  except ImportError:
56
  try:
@@ -61,7 +102,7 @@ def web_search(query: str) -> str:
61
  return "No results found."
62
  output = []
63
  for r in results:
64
- output.append(f"Title: {r.get('title','')}\nURL: {r.get('href','')}\nSnippet: {r.get('body','')[:200]}")
65
  return "\n---\n".join(output)
66
  except Exception as e:
67
  return f"Search error: {e}"
@@ -70,7 +111,6 @@ def web_search(query: str) -> str:
70
 
71
 
72
  def web_fetch(url: str) -> str:
73
- """Fetches the text content of a web page."""
74
  try:
75
  headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
76
  response = requests.get(url, timeout=20, headers=headers)
@@ -140,7 +180,6 @@ class SmartAgent:
140
  print(f"SmartAgent initialized with Groq ({self.model})")
141
 
142
  def call_llm(self, prompt: str) -> str:
143
- # Hard cap prompt to avoid 413
144
  if len(prompt) > 8000:
145
  prompt = prompt[:3000] + "\n\n[...context trimmed...]\n\n" + prompt[-3000:]
146
 
@@ -175,35 +214,43 @@ class SmartAgent:
175
  def __call__(self, question: str, task_id: str) -> str:
176
  print(f"\nQuestion: {question[:100]}...")
177
 
178
- file_alert = download_task_file(task_id)
 
 
 
 
 
 
 
179
 
180
  system = """You are an expert AI solving benchmark questions. Think step by step.
181
 
182
  TOOLS AVAILABLE:
183
- - SEARCH: <query> (web search)
184
- - WIKIPEDIA: <query> (Wikipedia lookup)
185
- - FETCH: <url> (read a webpage)
186
- - PYTHON: ```python ... ``` (run code, always use print())
187
-
188
- ANSWER FORMAT: When done, output exactly:
189
- ANSWER: <your answer>
190
-
191
- RULES:
192
- - Read any downloaded file FIRST with PYTHON
193
- - Use FETCH to read URLs mentioned in questions
194
- - Be concise - one tool per step
195
- - Numbers: no units unless asked, no commas
196
- - Short phrases, no articles (a/the)
197
- - Comma-separated if multiple items needed"""
198
-
199
- # Keep a short rolling history instead of full conversation
 
 
200
  history = []
201
- initial_prompt = f"{system}\n\nQuestion: {question}{file_alert}"
202
 
203
- for iteration in range(6):
204
  time.sleep(15)
205
 
206
- # Build prompt from system + question + last 3 exchanges only
207
  if not history:
208
  prompt = initial_prompt
209
  else:
@@ -212,19 +259,22 @@ RULES:
212
  f"Step {i+1}:\nAction: {h['action']}\nResult: {h['result'][:400]}"
213
  for i, h in enumerate(recent)
214
  ])
215
- prompt = f"{system}\n\nQuestion: {question}{file_alert}\n\nPrevious steps:\n{exchanges}\n\nContinue:"
216
 
217
  response = self.call_llm(prompt)
218
  print(f" LLM [{iteration}]: {response[:200]}...")
219
 
220
- # Parse tool calls
221
  fetch_match = re.search(r'FETCH:\s*(https?://\S+)', response)
222
  search_match = re.search(r'SEARCH:\s*(.+?)(?:\n|$)', response)
223
  wiki_match = re.search(r'WIKIPEDIA:\s*(.+?)(?:\n|$)', response)
224
  python_match = re.search(r'PYTHON:\s*```(?:python)?\n?(.*?)```', response, re.DOTALL)
225
  answer_match = re.search(r'ANSWER:\s*(.+?)(?:\n|$)', response, re.IGNORECASE)
226
 
227
- if fetch_match:
 
 
 
 
228
  url = fetch_match.group(1).strip()
229
  print(f" Tool: FETCH({url[:80]})")
230
  result = web_fetch(url)
@@ -244,17 +294,18 @@ RULES:
244
  print(f" Tool: PYTHON({code[:60]}...)")
245
  result = run_python(code)
246
  history.append({"action": f"PYTHON: {code[:100]}", "result": result})
247
- elif answer_match:
248
- answer = answer_match.group(1).strip()
249
- print(f" Final Answer: {answer}")
250
- return answer
251
  else:
252
- history.append({"action": "none", "result": "No valid tool found. Use SEARCH, WIKIPEDIA, FETCH, PYTHON, or ANSWER."})
253
 
254
- # Fallback: force answer
255
  recent = history[-3:]
256
  exchanges = "\n\n".join([f"Action: {h['action']}\nResult: {h['result'][:300]}" for h in recent])
257
- fallback_prompt = f"{system}\n\nQuestion: {question}\n\nSteps taken:\n{exchanges}\n\nOut of steps. Give ONLY: ANSWER: <answer>"
 
 
 
 
 
258
  last = self.call_llm(fallback_prompt)
259
  answer_match = re.search(r'ANSWER:\s*(.+?)(?:\n|$)', last, re.IGNORECASE)
260
  if answer_match:
@@ -343,7 +394,7 @@ with gr.Blocks() as demo:
343
  gr.Markdown("# 🤖 Smart Agent — GAIA Benchmark Runner")
344
  gr.Markdown(
345
  """
346
- **Powered by Groq (Llama 3.1 8B Instant)**
347
  **Instructions:**
348
  1. Make sure `GROQ_API_KEY` is set in your Space secrets
349
  2. `requirements.txt` must include: `gradio`, `requests`, `pandas`, `openpyxl`, `ddgs`, `beautifulsoup4`
 
10
 
11
  # --- Tool Implementations ---
12
 
13
+ def download_and_read_task_file(task_id: str):
14
+ """Downloads file and immediately reads its content. Returns (filename, content_str)."""
15
  url = f"{DEFAULT_API_URL}/files/{task_id}"
16
  try:
17
  response = requests.get(url, timeout=15)
18
+ if response.status_code != 200:
19
+ return None, ""
20
+
21
+ cd = response.headers.get('content-disposition', '')
22
+ filename = f"file_{task_id[:8]}.tmp"
23
+ match = re.search(r'filename="?([^"]+)"?', cd)
24
+ if match:
25
+ filename = match.group(1)
26
+
27
+ with open(filename, 'wb') as f:
28
+ f.write(response.content)
29
+
30
+ print(f" [File downloaded: {filename}]")
31
+
32
+ # Try to read content immediately based on file type
33
+ ext = filename.lower().split('.')[-1]
34
+
35
+ if ext in ['xlsx', 'xls']:
36
+ try:
37
+ df = pd.read_excel(filename, sheet_name=None)
38
+ content = ""
39
+ for sheet, data in df.items():
40
+ content += f"Sheet: {sheet}\n{data.to_string()}\n\n"
41
+ return filename, content[:3000]
42
+ except Exception as e:
43
+ return filename, f"Excel read error: {e}"
44
+
45
+ elif ext == 'py':
46
+ try:
47
+ with open(filename, 'r', encoding='utf-8') as f:
48
+ return filename, f.read()
49
+ except Exception as e:
50
+ return filename, f"Python file read error: {e}"
51
+
52
+ elif ext in ['txt', 'csv', 'json', 'md']:
53
+ try:
54
+ with open(filename, 'r', encoding='utf-8') as f:
55
+ return filename, f.read()[:3000]
56
+ except Exception as e:
57
+ return filename, f"Text read error: {e}"
58
+
59
+ elif ext in ['mp3', 'wav', 'ogg', 'm4a']:
60
+ # Audio - try whisper if available, else note it
61
+ try:
62
+ import whisper
63
+ model = whisper.load_model("tiny")
64
+ result = model.transcribe(filename)
65
+ return filename, f"Audio transcript: {result['text']}"
66
+ except Exception:
67
+ return filename, f"Audio file '{filename}' downloaded but cannot be transcribed (no whisper). File size: {len(response.content)} bytes."
68
+
69
+ elif ext in ['png', 'jpg', 'jpeg', 'gif', 'webp']:
70
+ return filename, f"Image file '{filename}' downloaded. Size: {len(response.content)} bytes. Cannot read image content directly."
71
+
72
+ else:
73
+ # Try text first, fall back to binary
74
+ try:
75
+ with open(filename, 'r', encoding='utf-8') as f:
76
+ return filename, f.read()[:3000]
77
+ except Exception:
78
+ return filename, f"Binary file '{filename}' downloaded. Size: {len(response.content)} bytes."
79
+
80
  except Exception as e:
81
+ print(f" File download error for {task_id}: {e}")
82
+ return None, ""
83
 
84
 
85
  def web_search(query: str) -> str:
 
91
  return "No results found."
92
  output = []
93
  for r in results:
94
+ output.append(f"Title: {r.get('title','')}\nURL: {r.get('href','')}\nSnippet: {r.get('body','')[:300]}")
95
  return "\n---\n".join(output)
96
  except ImportError:
97
  try:
 
102
  return "No results found."
103
  output = []
104
  for r in results:
105
+ output.append(f"Title: {r.get('title','')}\nURL: {r.get('href','')}\nSnippet: {r.get('body','')[:300]}")
106
  return "\n---\n".join(output)
107
  except Exception as e:
108
  return f"Search error: {e}"
 
111
 
112
 
113
  def web_fetch(url: str) -> str:
 
114
  try:
115
  headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
116
  response = requests.get(url, timeout=20, headers=headers)
 
180
  print(f"SmartAgent initialized with Groq ({self.model})")
181
 
182
  def call_llm(self, prompt: str) -> str:
 
183
  if len(prompt) > 8000:
184
  prompt = prompt[:3000] + "\n\n[...context trimmed...]\n\n" + prompt[-3000:]
185
 
 
214
  def __call__(self, question: str, task_id: str) -> str:
215
  print(f"\nQuestion: {question[:100]}...")
216
 
217
+ # Download and immediately read any attached file
218
+ filename, file_content = download_and_read_task_file(task_id)
219
+
220
+ file_context = ""
221
+ if filename and file_content:
222
+ file_context = f"\n\n[ATTACHED FILE: '{filename}']\n{file_content}\n[END OF FILE]"
223
+ elif filename:
224
+ file_context = f"\n\n[ATTACHED FILE: '{filename}' - could not read content]"
225
 
226
  system = """You are an expert AI solving benchmark questions. Think step by step.
227
 
228
  TOOLS AVAILABLE:
229
+ - SEARCH: <query>
230
+ - WIKIPEDIA: <query>
231
+ - FETCH: <url>
232
+ - PYTHON: ```python ... ``` (always use print())
233
+
234
+ OUTPUT FORMAT:
235
+ THOUGHT: <reasoning>
236
+ SEARCH: <query>
237
+
238
+ Or when done:
239
+ ANSWER: <exact answer>
240
+
241
+ STRICT RULES:
242
+ - If file content is provided above, use it directly - DO NOT re-read it
243
+ - Answer must be exact: numbers only (no units unless asked), short phrases
244
+ - No articles (a/the), no commas in numbers
245
+ - Comma-separated list if multiple items needed
246
+ - Do NOT say "Unable to determine" - always give your best guess"""
247
+
248
  history = []
249
+ initial_prompt = f"{system}\n\nQuestion: {question}{file_context}"
250
 
251
+ for iteration in range(8):
252
  time.sleep(15)
253
 
 
254
  if not history:
255
  prompt = initial_prompt
256
  else:
 
259
  f"Step {i+1}:\nAction: {h['action']}\nResult: {h['result'][:400]}"
260
  for i, h in enumerate(recent)
261
  ])
262
+ prompt = f"{system}\n\nQuestion: {question}{file_context}\n\nPrevious steps:\n{exchanges}\n\nContinue:"
263
 
264
  response = self.call_llm(prompt)
265
  print(f" LLM [{iteration}]: {response[:200]}...")
266
 
 
267
  fetch_match = re.search(r'FETCH:\s*(https?://\S+)', response)
268
  search_match = re.search(r'SEARCH:\s*(.+?)(?:\n|$)', response)
269
  wiki_match = re.search(r'WIKIPEDIA:\s*(.+?)(?:\n|$)', response)
270
  python_match = re.search(r'PYTHON:\s*```(?:python)?\n?(.*?)```', response, re.DOTALL)
271
  answer_match = re.search(r'ANSWER:\s*(.+?)(?:\n|$)', response, re.IGNORECASE)
272
 
273
+ if answer_match:
274
+ answer = answer_match.group(1).strip()
275
+ print(f" Final Answer: {answer}")
276
+ return answer
277
+ elif fetch_match:
278
  url = fetch_match.group(1).strip()
279
  print(f" Tool: FETCH({url[:80]})")
280
  result = web_fetch(url)
 
294
  print(f" Tool: PYTHON({code[:60]}...)")
295
  result = run_python(code)
296
  history.append({"action": f"PYTHON: {code[:100]}", "result": result})
 
 
 
 
297
  else:
298
+ history.append({"action": "none", "result": "No valid tool. Use SEARCH, WIKIPEDIA, FETCH, PYTHON, or ANSWER."})
299
 
300
+ # Fallback: force a best-guess answer
301
  recent = history[-3:]
302
  exchanges = "\n\n".join([f"Action: {h['action']}\nResult: {h['result'][:300]}" for h in recent])
303
+ fallback_prompt = (
304
+ f"{system}\n\nQuestion: {question}{file_context}\n\n"
305
+ f"Steps taken:\n{exchanges}\n\n"
306
+ f"You MUST give a final answer now. Do not say 'unable to determine'. "
307
+ f"Use your best judgment. Output ONLY: ANSWER: <answer>"
308
+ )
309
  last = self.call_llm(fallback_prompt)
310
  answer_match = re.search(r'ANSWER:\s*(.+?)(?:\n|$)', last, re.IGNORECASE)
311
  if answer_match:
 
394
  gr.Markdown("# 🤖 Smart Agent — GAIA Benchmark Runner")
395
  gr.Markdown(
396
  """
397
+ **Powered by Groq (Llama 3.3 70B)**
398
  **Instructions:**
399
  1. Make sure `GROQ_API_KEY` is set in your Space secrets
400
  2. `requirements.txt` must include: `gradio`, `requests`, `pandas`, `openpyxl`, `ddgs`, `beautifulsoup4`