Essi commited on
Commit
a09e159
·
1 Parent(s): cd58f1c

refactor: Enhance GAIAAgent to handle Excel file attachments and improve expression evaluation

Browse files
Files changed (1) hide show
  1. app.py +39 -15
app.py CHANGED
@@ -1,5 +1,6 @@
1
  import ast
2
  from functools import lru_cache
 
3
  import json
4
  import operator
5
  import os
@@ -110,7 +111,8 @@ def _summarize_results(results_json: str, max_hits: int = 3) -> str:
110
  # ------------------------------- AGENT STATE ----------------------------- #
111
  # --------------------------------------------------------------------------- #
112
  class AgentState(TypedDict):
113
- msg: Annotated[list[BaseMessage], add_messages]
 
114
  question: str
115
  answer: str
116
  search_results: str
@@ -180,17 +182,38 @@ class GAIAAgent:
180
 
181
  # 1️⃣ Calculator path
182
  if _needs_calc(q):
183
- expr = q.strip()
184
- expr = re.sub(r"\s+", "", expr) # remove spaces
185
- result = calculator.invoke({"expression": expr})
186
-
187
- state["answer"] = result
188
- state["tools_used"].append("calculator")
189
- state["reasoning_steps"].append("Calculate")
190
-
191
- return state
 
 
 
 
 
192
 
193
- # 2️⃣ Web search path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  query = _extract_search_terms(q)
195
  results_json = web_search.invoke({"query": query})
196
 
@@ -210,7 +233,7 @@ class GAIAAgent:
210
  # Summarize search results for the LLM
211
  summary = _summarize_results(state["search_results"])
212
  if not summary:
213
- summary = "No useful web context found. Rely on your prior knowledge."
214
 
215
  state["context"] = "summary"
216
  state["reasoning_steps"].append("Process")
@@ -253,20 +276,21 @@ class GAIAAgent:
253
  state["reasoning_steps"].append("Answer verification completed.")
254
  return state
255
 
256
- def __call__(self, question: str) -> str:
257
  """Main agent call method."""
258
 
259
  print(f"GAIA Agent processing question: '{question}'\n")
260
 
261
  try:
262
  initial_state: AgentState = {
 
263
  "messages": [],
264
  "question": question,
265
  "answer": "",
266
  "search_results": "",
267
  "context": "",
268
  "reasoning_steps": [],
269
- "tools_used": []
270
  }
271
 
272
  # Run the graph
@@ -346,7 +370,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
346
  print(f"Skipping item with missing task_id or question: {item}")
347
  continue
348
  try:
349
- submitted_answer = agent(question_text)
350
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
351
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
352
  except Exception as e:
 
1
  import ast
2
  from functools import lru_cache
3
+ from io import BytesIO
4
  import json
5
  import operator
6
  import os
 
111
  # ------------------------------- AGENT STATE ----------------------------- #
112
  # --------------------------------------------------------------------------- #
113
  class AgentState(TypedDict):
114
+ task_id: str
115
+ messages: Annotated[list[BaseMessage], add_messages]
116
  question: str
117
  answer: str
118
  search_results: str
 
182
 
183
  # 1️⃣ Calculator path
184
  if _needs_calc(q):
185
+ # 1) strip all whitespace
186
+ expr = re.sub(r"\s+", "", q)
187
+
188
+ # 2) remove ANY character that isn’t digit, dot, operator, or parenthesis
189
+ # (kills “USD”, “kg”, YouTube IDs, etc.)
190
+ expr = re.sub(r"[^\d\.\+\-\*/\(\)]", "", expr)
191
+
192
+ # 3) guard against empty string after cleaning
193
+ if expr:
194
+ result = calculator.invoke({"expression": expr})
195
+ state["answer"] = result
196
+ state["tools_used"].append("calculator")
197
+ state["reasoning_steps"].append(f"calc:{expr}")
198
+ return state
199
 
200
+ # 2️⃣ Attachment (Excel file)
201
+ if "attached" in q.lower() and ".xls" in q.lower():
202
+ try:
203
+ task_id = state.get("task_id")
204
+ file_url = f"{DEFAULT_API_URL}/files/{task_id}"
205
+ xls_bytes = requests.get(file_url, timeout=10).content
206
+ df = pd.read_excel(BytesIO(xls_bytes))
207
+
208
+ total = df["sales"].sum()
209
+ state["answer"] = f"{total:.2f}"
210
+ state["tools_used"].append("excel_sum")
211
+ state["reasoning_steps"].append("xlsx")
212
+ return state
213
+ except Exception as e:
214
+ state["reasoning_steps"].append(f"xlsx_error:{e}")
215
+
216
+ # 3️⃣ Web search path
217
  query = _extract_search_terms(q)
218
  results_json = web_search.invoke({"query": query})
219
 
 
233
  # Summarize search results for the LLM
234
  summary = _summarize_results(state["search_results"])
235
  if not summary:
236
+ summary = state['search_results'][:4000] # cap to 4k chars
237
 
238
  state["context"] = "summary"
239
  state["reasoning_steps"].append("Process")
 
276
  state["reasoning_steps"].append("Answer verification completed.")
277
  return state
278
 
279
+ def __call__(self, question: str, task_id: str) -> str:
280
  """Main agent call method."""
281
 
282
  print(f"GAIA Agent processing question: '{question}'\n")
283
 
284
  try:
285
  initial_state: AgentState = {
286
+ "task_id": task_id,
287
  "messages": [],
288
  "question": question,
289
  "answer": "",
290
  "search_results": "",
291
  "context": "",
292
  "reasoning_steps": [],
293
+ "tools_used": [],
294
  }
295
 
296
  # Run the graph
 
370
  print(f"Skipping item with missing task_id or question: {item}")
371
  continue
372
  try:
373
+ submitted_answer = agent(question=question_text, task_id=task_id)
374
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
375
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
376
  except Exception as e: