Spaces:
Sleeping
Sleeping
Essi
commited on
Commit
·
a09e159
1
Parent(s):
cd58f1c
refactor: Enhance GAIAAgent to handle Excel file attachments and improve expression evaluation
Browse files
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 |
-
|
|
|
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 |
-
|
184 |
-
expr = re.sub(r"\s+", "",
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
|
|
|
|
|
|
|
|
|
|
192 |
|
193 |
-
# 2️⃣
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 =
|
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:
|