Update app.py
Browse files
app.py
CHANGED
@@ -182,17 +182,12 @@ def discover_attachment(task_id: str, api_url: str) -> Optional[str]:
|
|
182 |
# -------------------------
|
183 |
|
184 |
class AgentState(TypedDict):
|
185 |
-
question: str
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
task_id: str
|
192 |
-
logs: Dict[str, Any]
|
193 |
-
file_url: str
|
194 |
-
code_blocks: List[Dict[str, str]]
|
195 |
-
next_step: str
|
196 |
|
197 |
# -------------------------
|
198 |
# BasicAgent implementation
|
@@ -246,18 +241,14 @@ class BasicAgent:
|
|
246 |
if not file_url:
|
247 |
file_url = discover_attachment(task_id, self.api_url) or ""
|
248 |
|
|
|
249 |
state: AgentState = {
|
250 |
"question": question,
|
251 |
-
"current_step": "route",
|
252 |
"answer": "",
|
253 |
-
"
|
254 |
-
"
|
255 |
-
"search_query": "",
|
256 |
-
"task_id": task_id,
|
257 |
-
"logs": {},
|
258 |
"file_url": file_url,
|
259 |
-
"
|
260 |
-
"next_step": ""
|
261 |
}
|
262 |
|
263 |
print(f"\nProcessing task {task_id}")
|
@@ -265,10 +256,15 @@ class BasicAgent:
|
|
265 |
print(f"File URL: {state['file_url']}")
|
266 |
|
267 |
try:
|
268 |
-
|
|
|
|
|
|
|
269 |
if "answer" not in final_state:
|
270 |
-
raise ValueError(f"No 'answer' in state
|
|
|
271 |
return final_state["answer"]
|
|
|
272 |
except Exception as e:
|
273 |
print(f"Error in workflow execution: {str(e)}")
|
274 |
return f"Error processing question: {str(e)}"
|
@@ -331,17 +327,13 @@ class BasicAgent:
|
|
331 |
print(f"Generated answer: {answer}")
|
332 |
return {
|
333 |
"answer": answer,
|
334 |
-
"
|
335 |
-
"next_step": "done",
|
336 |
-
"history": state["history"] + [{"role": "assistant", "content": answer}]
|
337 |
}
|
338 |
except Exception as e:
|
339 |
print(f"\nError processing image {state['file_url']}: {str(e)}")
|
340 |
return {
|
341 |
"answer": f"Error processing image: {str(e)}",
|
342 |
-
"
|
343 |
-
"next_step": "done",
|
344 |
-
"history": state["history"] + [{"role": "assistant", "content": f"Error: {str(e)}"}]
|
345 |
}
|
346 |
|
347 |
def _process_video(self, state: AgentState) -> Dict[str, Any]:
|
@@ -359,17 +351,13 @@ class BasicAgent:
|
|
359 |
print(f"Generated answer: {answer}")
|
360 |
return {
|
361 |
"answer": answer,
|
362 |
-
"
|
363 |
-
"next_step": "done",
|
364 |
-
"history": state["history"] + [{"role": "assistant", "content": answer}]
|
365 |
}
|
366 |
except Exception as e:
|
367 |
print(f"\nError processing video {state['file_url']}: {str(e)}")
|
368 |
return {
|
369 |
"answer": f"Error processing video: {str(e)}",
|
370 |
-
"
|
371 |
-
"next_step": "done",
|
372 |
-
"history": state["history"] + [{"role": "assistant", "content": f"Error: {str(e)}"}]
|
373 |
}
|
374 |
|
375 |
def _process_spreadsheet(self, state: AgentState) -> Dict[str, Any]:
|
@@ -387,17 +375,13 @@ class BasicAgent:
|
|
387 |
print(f"Generated answer: {answer}")
|
388 |
return {
|
389 |
"answer": answer,
|
390 |
-
"
|
391 |
-
"next_step": "done",
|
392 |
-
"history": state["history"] + [{"role": "assistant", "content": answer}]
|
393 |
}
|
394 |
except Exception as e:
|
395 |
print(f"\nError processing spreadsheet {state['file_url']}: {str(e)}")
|
396 |
return {
|
397 |
"answer": f"Error processing spreadsheet: {str(e)}",
|
398 |
-
"
|
399 |
-
"next_step": "done",
|
400 |
-
"history": state["history"] + [{"role": "assistant", "content": f"Error: {str(e)}"}]
|
401 |
}
|
402 |
|
403 |
def _process_python(self, state: AgentState) -> Dict[str, Any]:
|
@@ -415,17 +399,13 @@ class BasicAgent:
|
|
415 |
print(f"Generated answer: {answer}")
|
416 |
return {
|
417 |
"answer": answer,
|
418 |
-
"
|
419 |
-
"next_step": "done",
|
420 |
-
"history": state["history"] + [{"role": "assistant", "content": answer}]
|
421 |
}
|
422 |
except Exception as e:
|
423 |
print(f"\nError processing Python file {state['file_url']}: {str(e)}")
|
424 |
return {
|
425 |
"answer": f"Error processing Python file: {str(e)}",
|
426 |
-
"
|
427 |
-
"next_step": "done",
|
428 |
-
"history": state["history"] + [{"role": "assistant", "content": f"Error: {str(e)}"}]
|
429 |
}
|
430 |
|
431 |
def _process_text(self, state: AgentState) -> Dict[str, Any]:
|
@@ -445,17 +425,13 @@ QUESTION:
|
|
445 |
print(f"Generated answer: {answer}")
|
446 |
return {
|
447 |
"answer": answer,
|
448 |
-
"
|
449 |
-
"next_step": "done",
|
450 |
-
"history": state["history"] + [{"role": "assistant", "content": answer}]
|
451 |
}
|
452 |
except Exception as e:
|
453 |
print(f"\nLLM Error in answer generation: {str(e)}")
|
454 |
return {
|
455 |
"answer": "I encountered an error while generating the answer.",
|
456 |
-
"
|
457 |
-
"next_step": "done",
|
458 |
-
"history": state["history"] + [{"role": "assistant", "content": "Error generating answer"}]
|
459 |
}
|
460 |
|
461 |
def _build_workflow(self) -> Graph:
|
@@ -473,7 +449,7 @@ QUESTION:
|
|
473 |
# Set entry point
|
474 |
sg.set_entry_point("route")
|
475 |
|
476 |
-
# Add conditional edges
|
477 |
sg.add_conditional_edges(
|
478 |
"route",
|
479 |
{
|
@@ -487,7 +463,7 @@ QUESTION:
|
|
487 |
|
488 |
# Add edges from each processing node to END
|
489 |
for node in ["process_image", "process_video", "process_spreadsheet", "process_python", "process_text"]:
|
490 |
-
sg.add_edge(node, END)
|
491 |
|
492 |
return sg.compile()
|
493 |
|
|
|
182 |
# -------------------------
|
183 |
|
184 |
class AgentState(TypedDict):
|
185 |
+
question: str # Input question
|
186 |
+
answer: str # Output answer (required by Gradio)
|
187 |
+
current_step: str # Current processing step
|
188 |
+
next_step: str # Next step in workflow
|
189 |
+
file_url: str # URL of attached file if any
|
190 |
+
history: List[Dict[str, str]] # Conversation history
|
|
|
|
|
|
|
|
|
|
|
191 |
|
192 |
# -------------------------
|
193 |
# BasicAgent implementation
|
|
|
241 |
if not file_url:
|
242 |
file_url = discover_attachment(task_id, self.api_url) or ""
|
243 |
|
244 |
+
# Initialize state with just the question
|
245 |
state: AgentState = {
|
246 |
"question": question,
|
|
|
247 |
"answer": "",
|
248 |
+
"current_step": "route",
|
249 |
+
"next_step": "",
|
|
|
|
|
|
|
250 |
"file_url": file_url,
|
251 |
+
"history": []
|
|
|
252 |
}
|
253 |
|
254 |
print(f"\nProcessing task {task_id}")
|
|
|
256 |
print(f"File URL: {state['file_url']}")
|
257 |
|
258 |
try:
|
259 |
+
# Invoke the workflow with just the question
|
260 |
+
final_state = self.workflow.invoke({"question": question})
|
261 |
+
|
262 |
+
# Debug guard to check for answer key
|
263 |
if "answer" not in final_state:
|
264 |
+
raise ValueError(f"☠ No 'answer' key in state; keys = {list(final_state.keys())}")
|
265 |
+
|
266 |
return final_state["answer"]
|
267 |
+
|
268 |
except Exception as e:
|
269 |
print(f"Error in workflow execution: {str(e)}")
|
270 |
return f"Error processing question: {str(e)}"
|
|
|
327 |
print(f"Generated answer: {answer}")
|
328 |
return {
|
329 |
"answer": answer,
|
330 |
+
"next_step": END
|
|
|
|
|
331 |
}
|
332 |
except Exception as e:
|
333 |
print(f"\nError processing image {state['file_url']}: {str(e)}")
|
334 |
return {
|
335 |
"answer": f"Error processing image: {str(e)}",
|
336 |
+
"next_step": END
|
|
|
|
|
337 |
}
|
338 |
|
339 |
def _process_video(self, state: AgentState) -> Dict[str, Any]:
|
|
|
351 |
print(f"Generated answer: {answer}")
|
352 |
return {
|
353 |
"answer": answer,
|
354 |
+
"next_step": END
|
|
|
|
|
355 |
}
|
356 |
except Exception as e:
|
357 |
print(f"\nError processing video {state['file_url']}: {str(e)}")
|
358 |
return {
|
359 |
"answer": f"Error processing video: {str(e)}",
|
360 |
+
"next_step": END
|
|
|
|
|
361 |
}
|
362 |
|
363 |
def _process_spreadsheet(self, state: AgentState) -> Dict[str, Any]:
|
|
|
375 |
print(f"Generated answer: {answer}")
|
376 |
return {
|
377 |
"answer": answer,
|
378 |
+
"next_step": END
|
|
|
|
|
379 |
}
|
380 |
except Exception as e:
|
381 |
print(f"\nError processing spreadsheet {state['file_url']}: {str(e)}")
|
382 |
return {
|
383 |
"answer": f"Error processing spreadsheet: {str(e)}",
|
384 |
+
"next_step": END
|
|
|
|
|
385 |
}
|
386 |
|
387 |
def _process_python(self, state: AgentState) -> Dict[str, Any]:
|
|
|
399 |
print(f"Generated answer: {answer}")
|
400 |
return {
|
401 |
"answer": answer,
|
402 |
+
"next_step": END
|
|
|
|
|
403 |
}
|
404 |
except Exception as e:
|
405 |
print(f"\nError processing Python file {state['file_url']}: {str(e)}")
|
406 |
return {
|
407 |
"answer": f"Error processing Python file: {str(e)}",
|
408 |
+
"next_step": END
|
|
|
|
|
409 |
}
|
410 |
|
411 |
def _process_text(self, state: AgentState) -> Dict[str, Any]:
|
|
|
425 |
print(f"Generated answer: {answer}")
|
426 |
return {
|
427 |
"answer": answer,
|
428 |
+
"next_step": END
|
|
|
|
|
429 |
}
|
430 |
except Exception as e:
|
431 |
print(f"\nLLM Error in answer generation: {str(e)}")
|
432 |
return {
|
433 |
"answer": "I encountered an error while generating the answer.",
|
434 |
+
"next_step": END
|
|
|
|
|
435 |
}
|
436 |
|
437 |
def _build_workflow(self) -> Graph:
|
|
|
449 |
# Set entry point
|
450 |
sg.set_entry_point("route")
|
451 |
|
452 |
+
# Add conditional edges from route to processing nodes
|
453 |
sg.add_conditional_edges(
|
454 |
"route",
|
455 |
{
|
|
|
463 |
|
464 |
# Add edges from each processing node to END
|
465 |
for node in ["process_image", "process_video", "process_spreadsheet", "process_python", "process_text"]:
|
466 |
+
sg.add_edge(node, END) # Critical: ensure each processing node terminates at END
|
467 |
|
468 |
return sg.compile()
|
469 |
|