mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-05-03 18:50:43 +08:00
* fix: resolve issue #467 - message content validation and Tavily search error handling This commit implements a comprehensive fix for issue #467 where the application crashed with 'Field required: input.messages.3.content' error when generating reports. ## Root Cause Analysis The issue had multiple interconnected causes: 1. Tavily tool returned mixed types (lists/error strings) instead of consistent JSON 2. background_investigation_node didn't handle error cases properly, returning None 3. Missing message content validation before LLM calls 4. Insufficient error diagnostics for content-related errors ## Changes Made ### Part 1: Fix Tavily Search Tool (tavily_search_results_with_images.py) - Modified _run() and _arun() methods to return JSON strings instead of mixed types - Error responses now return JSON: {"error": repr(e)} - Successful responses return JSON string: json.dumps(cleaned_results) - Ensures tool results always have valid string content for ToolMessages ### Part 2: Fix background_investigation_node Error Handling (graph/nodes.py) - Initialize background_investigation_results to empty list instead of None - Added proper JSON parsing for string responses from Tavily tool - Handle error responses with explicit error logging - Always return valid JSON (empty list if error) instead of None ### Part 3: Add Message Content Validation (utils/context_manager.py) - New validate_message_content() function validates all messages before LLM calls - Ensures all messages have content attribute and valid string content - Converts complex types (lists, dicts) to JSON strings - Provides graceful fallback for messages with issues ### Part 4: Enhanced Error Diagnostics (_execute_agent_step in graph/nodes.py) - Call message validation before agent invocation - Add detailed logging for content-related errors - Log message types, content types, and lengths when validation fails - Helps with future debugging of similar issues ## Testing - All unit tests pass (395 tests) - Python syntax verified for all modified files - No breaking changes to existing functionality * test: update tests for issue #467 fixes Update test expectations to match the new implementation: - Tavily search tool now returns JSON strings instead of mixed types - background_investigation_node returns empty list [] for errors instead of None - All tests updated to verify the new behavior - All 391 tests pass successfully * Update src/graph/nodes.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -264,3 +264,54 @@ class ContextManager:
|
||||
"""
|
||||
# TODO: summary implementation
|
||||
pass
|
||||
|
||||
|
||||
def validate_message_content(messages: List[BaseMessage]) -> List[BaseMessage]:
|
||||
"""
|
||||
Validate and fix all messages to ensure they have valid content before sending to LLM.
|
||||
|
||||
This function ensures:
|
||||
1. All messages have a content field
|
||||
2. No message has None or empty string content (except for legitimate empty responses)
|
||||
3. Complex objects (lists, dicts) are converted to JSON strings
|
||||
|
||||
Args:
|
||||
messages: List of messages to validate
|
||||
|
||||
Returns:
|
||||
List of validated messages with fixed content
|
||||
"""
|
||||
validated = []
|
||||
for i, msg in enumerate(messages):
|
||||
try:
|
||||
# Check if message has content attribute
|
||||
if not hasattr(msg, 'content'):
|
||||
logger.warning(f"Message {i} ({type(msg).__name__}) has no content attribute")
|
||||
msg.content = ""
|
||||
|
||||
# Handle None content
|
||||
elif msg.content is None:
|
||||
logger.warning(f"Message {i} ({type(msg).__name__}) has None content, setting to empty string")
|
||||
msg.content = ""
|
||||
|
||||
# Handle complex content types (convert to JSON)
|
||||
elif isinstance(msg.content, (list, dict)):
|
||||
logger.debug(f"Message {i} ({type(msg).__name__}) has complex content type {type(msg.content).__name__}, converting to JSON")
|
||||
msg.content = json.dumps(msg.content, ensure_ascii=False)
|
||||
|
||||
# Handle other non-string types
|
||||
elif not isinstance(msg.content, str):
|
||||
logger.debug(f"Message {i} ({type(msg).__name__}) has non-string content type {type(msg.content).__name__}, converting to string")
|
||||
msg.content = str(msg.content)
|
||||
|
||||
validated.append(msg)
|
||||
except Exception as e:
|
||||
logger.error(f"Error validating message {i}: {e}")
|
||||
# Create a safe fallback message
|
||||
if isinstance(msg, ToolMessage):
|
||||
msg.content = json.dumps({"error": str(e)}, ensure_ascii=False)
|
||||
else:
|
||||
msg.content = f"[Error processing message: {str(e)}]"
|
||||
validated.append(msg)
|
||||
|
||||
return validated
|
||||
|
||||
Reference in New Issue
Block a user