Spaces:
Configuration error
Configuration error
Update error handling
Browse files
agent.py
CHANGED
|
@@ -187,19 +187,49 @@ def build_agent_graph(provider: str = "groq"):
|
|
| 187 |
# Assistant: reasoning step that plans next action
|
| 188 |
def assistant_node(state: MessagesState) -> dict:
|
| 189 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
messages = state["messages"]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
response = llm_with_tools.invoke(messages)
|
|
|
|
|
|
|
| 192 |
|
| 193 |
# Validate response format
|
| 194 |
-
if not response
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
|
| 199 |
return {"messages": response}
|
| 200 |
except Exception as e:
|
| 201 |
error_msg = f"Error in assistant node: {str(e)}"
|
| 202 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
|
| 204 |
# Stubbed retriever node for future integration
|
| 205 |
def retriever_node(state: MessagesState):
|
|
|
|
| 187 |
# Assistant: reasoning step that plans next action
|
| 188 |
def assistant_node(state: MessagesState) -> dict:
|
| 189 |
try:
|
| 190 |
+
# Validate input state
|
| 191 |
+
if not isinstance(state, dict) or "messages" not in state:
|
| 192 |
+
raise ValueError("Invalid state format")
|
| 193 |
+
|
| 194 |
messages = state["messages"]
|
| 195 |
+
if not messages:
|
| 196 |
+
raise ValueError("Empty message list")
|
| 197 |
+
|
| 198 |
+
# Invoke LLM
|
| 199 |
response = llm_with_tools.invoke(messages)
|
| 200 |
+
if response is None:
|
| 201 |
+
raise ValueError("LLM returned None response")
|
| 202 |
|
| 203 |
# Validate response format
|
| 204 |
+
if not isinstance(response, (AIMessage, HumanMessage, SystemMessage)):
|
| 205 |
+
raise ValueError(f"Invalid response type from LLM: {type(response)}")
|
| 206 |
+
|
| 207 |
+
# Validate response content
|
| 208 |
+
if not hasattr(response, "content") or response.content is None:
|
| 209 |
+
raise ValueError("Response missing content")
|
| 210 |
+
|
| 211 |
+
if not isinstance(response.content, str):
|
| 212 |
+
raise ValueError(f"Invalid content type: {type(response.content)}")
|
| 213 |
+
|
| 214 |
+
# Ensure response has content
|
| 215 |
+
if not response.content.strip():
|
| 216 |
+
raise ValueError("Empty response content")
|
| 217 |
+
|
| 218 |
+
# Add FINAL ANSWER prefix if missing
|
| 219 |
+
content = response.content
|
| 220 |
+
if "FINAL ANSWER:" not in content:
|
| 221 |
+
content = f"FINAL ANSWER: {content}"
|
| 222 |
+
response = AIMessage(content=content)
|
| 223 |
|
| 224 |
return {"messages": response}
|
| 225 |
except Exception as e:
|
| 226 |
error_msg = f"Error in assistant node: {str(e)}"
|
| 227 |
+
print(f"Assistant node error: {error_msg}") # Log error for debugging
|
| 228 |
+
return {
|
| 229 |
+
"messages": AIMessage(
|
| 230 |
+
content="FINAL ANSWER: Error occurred while processing request. Please try again."
|
| 231 |
+
)
|
| 232 |
+
}
|
| 233 |
|
| 234 |
# Stubbed retriever node for future integration
|
| 235 |
def retriever_node(state: MessagesState):
|
app.py
CHANGED
|
@@ -25,53 +25,54 @@ class BasicAgent:
|
|
| 25 |
def __call__(self, question: str) -> str:
|
| 26 |
print(f"Agent received question (first 50 chars): {question[:50]}...")
|
| 27 |
try:
|
|
|
|
|
|
|
|
|
|
| 28 |
# Create properly typed messages
|
| 29 |
-
system_msg = SystemMessage(
|
| 30 |
-
content="""You are a helpful AI assistant. Format your final answer as:
|
| 31 |
-
FINAL ANSWER: [your answer here]"""
|
| 32 |
-
)
|
| 33 |
human_msg = HumanMessage(content=question)
|
| 34 |
-
msgs: List[AnyMessage] = [
|
| 35 |
|
| 36 |
# Create and cast the state
|
| 37 |
input_state = cast(MessagesState, {"messages": msgs})
|
| 38 |
|
| 39 |
-
# Invoke the graph
|
| 40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
-
# Validate response
|
| 43 |
-
if not isinstance(result, dict)
|
| 44 |
-
|
| 45 |
|
| 46 |
-
if not result["messages"]:
|
| 47 |
-
|
| 48 |
|
| 49 |
-
# Get the last message
|
| 50 |
last_msg = result["messages"][-1]
|
| 51 |
if not isinstance(last_msg, (AIMessage, HumanMessage, SystemMessage)):
|
| 52 |
-
|
| 53 |
|
|
|
|
| 54 |
answer = last_msg.content
|
| 55 |
if not isinstance(answer, str):
|
| 56 |
-
|
| 57 |
|
| 58 |
-
# Ensure proper formatting
|
| 59 |
if not answer.strip():
|
| 60 |
return "Error: Empty response from agent"
|
| 61 |
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
final_answer = answer.split("FINAL ANSWER:", 1)[1].strip()
|
| 68 |
-
if not final_answer:
|
| 69 |
-
return "Error: Empty answer after FINAL ANSWER prefix"
|
| 70 |
|
| 71 |
-
return
|
|
|
|
| 72 |
|
| 73 |
except Exception as e:
|
| 74 |
-
error_msg = f"Error
|
| 75 |
print(error_msg)
|
| 76 |
return error_msg
|
| 77 |
|
|
|
|
| 25 |
def __call__(self, question: str) -> str:
|
| 26 |
print(f"Agent received question (first 50 chars): {question[:50]}...")
|
| 27 |
try:
|
| 28 |
+
# Import system prompt from agent module
|
| 29 |
+
from agent import system_prompt
|
| 30 |
+
|
| 31 |
# Create properly typed messages
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
human_msg = HumanMessage(content=question)
|
| 33 |
+
msgs: List[AnyMessage] = [system_prompt, human_msg]
|
| 34 |
|
| 35 |
# Create and cast the state
|
| 36 |
input_state = cast(MessagesState, {"messages": msgs})
|
| 37 |
|
| 38 |
+
# Invoke the graph with proper error handling
|
| 39 |
+
try:
|
| 40 |
+
result = self.graph.invoke(input_state)
|
| 41 |
+
except Exception as e:
|
| 42 |
+
print(f"Graph invocation error: {str(e)}")
|
| 43 |
+
return f"Error: Failed to process request - {str(e)}"
|
| 44 |
|
| 45 |
+
# Validate response structure
|
| 46 |
+
if not isinstance(result, dict):
|
| 47 |
+
return "Error: Invalid response format from agent"
|
| 48 |
|
| 49 |
+
if "messages" not in result or not result["messages"]:
|
| 50 |
+
return "Error: No response messages from agent"
|
| 51 |
|
| 52 |
+
# Get the last message
|
| 53 |
last_msg = result["messages"][-1]
|
| 54 |
if not isinstance(last_msg, (AIMessage, HumanMessage, SystemMessage)):
|
| 55 |
+
return f"Error: Invalid message type - {type(last_msg)}"
|
| 56 |
|
| 57 |
+
# Get and validate content
|
| 58 |
answer = last_msg.content
|
| 59 |
if not isinstance(answer, str):
|
| 60 |
+
return f"Error: Invalid answer type - {type(answer)}"
|
| 61 |
|
|
|
|
| 62 |
if not answer.strip():
|
| 63 |
return "Error: Empty response from agent"
|
| 64 |
|
| 65 |
+
# Handle FINAL ANSWER prefix
|
| 66 |
+
if "FINAL ANSWER:" in answer:
|
| 67 |
+
parts = answer.split("FINAL ANSWER:", 1)
|
| 68 |
+
if len(parts) == 2 and parts[1].strip():
|
| 69 |
+
return parts[1].strip()
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
+
# If no prefix or empty after prefix, return full answer
|
| 72 |
+
return answer.strip()
|
| 73 |
|
| 74 |
except Exception as e:
|
| 75 |
+
error_msg = f"Error processing request: {str(e)}"
|
| 76 |
print(error_msg)
|
| 77 |
return error_msg
|
| 78 |
|