mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-20 21:04:45 +08:00
fix: the exception of plan validation (#714)
* fix: Missing Required Fields in Plan Validation * fix: the exception of plan validation * Fixed the test errors * Addressed the comments of the PR reviews
This commit is contained in:
@@ -146,24 +146,29 @@ def validate_and_fix_plan(plan: dict, enforce_web_search: bool = False) -> dict:
|
||||
# SECTION 2: Enforce web search requirements
|
||||
# ============================================================
|
||||
if enforce_web_search:
|
||||
# Check if any step has need_search=true
|
||||
has_search_step = any(step.get("need_search", False) for step in steps)
|
||||
# Check if any step has need_search=true (only check dict steps)
|
||||
has_search_step = any(
|
||||
step.get("need_search", False)
|
||||
for step in steps
|
||||
if isinstance(step, dict)
|
||||
)
|
||||
|
||||
if not has_search_step and steps:
|
||||
# Ensure first research step has web search enabled
|
||||
for idx, step in enumerate(steps):
|
||||
if step.get("step_type") == "research":
|
||||
if isinstance(step, dict) and step.get("step_type") == "research":
|
||||
step["need_search"] = True
|
||||
logger.info(f"Enforced web search on research step at index {idx}")
|
||||
break
|
||||
else:
|
||||
# Fallback: If no research step exists, convert the first step to a research step with web search enabled.
|
||||
# This ensures that at least one step will perform a web search as required.
|
||||
steps[0]["step_type"] = "research"
|
||||
steps[0]["need_search"] = True
|
||||
logger.info(
|
||||
"Converted first step to research with web search enforcement"
|
||||
)
|
||||
if isinstance(steps[0], dict):
|
||||
steps[0]["step_type"] = "research"
|
||||
steps[0]["need_search"] = True
|
||||
logger.info(
|
||||
"Converted first step to research with web search enforcement"
|
||||
)
|
||||
elif not has_search_step and not steps:
|
||||
# Add a default research step if no steps exist
|
||||
logger.warning("Plan has no steps. Adding default research step.")
|
||||
@@ -176,6 +181,29 @@ def validate_and_fix_plan(plan: dict, enforce_web_search: bool = False) -> dict:
|
||||
}
|
||||
]
|
||||
|
||||
# ============================================================
|
||||
# SECTION 3: Ensure required Plan fields are present (Issue #710 fix)
|
||||
# ============================================================
|
||||
# Set locale from state if not present
|
||||
if "locale" not in plan or not plan.get("locale"):
|
||||
plan["locale"] = "en-US" # Default locale
|
||||
logger.info("Added missing locale field with default value 'en-US'")
|
||||
|
||||
# Ensure has_enough_context is present
|
||||
if "has_enough_context" not in plan:
|
||||
plan["has_enough_context"] = False # Default value
|
||||
logger.info("Added missing has_enough_context field with default value 'False'")
|
||||
|
||||
# Ensure title is present
|
||||
if "title" not in plan or not plan.get("title"):
|
||||
# Try to infer title from steps or use a default
|
||||
if steps and isinstance(steps[0], dict) and "title" in steps[0]:
|
||||
plan["title"] = steps[0]["title"]
|
||||
logger.info(f"Inferred missing title from first step: {plan['title']}")
|
||||
else:
|
||||
plan["title"] = "Research Plan" # Default title
|
||||
logger.info("Added missing title field with default value 'Research Plan'")
|
||||
|
||||
return plan
|
||||
|
||||
|
||||
@@ -381,8 +409,20 @@ def extract_plan_content(plan_data: str | dict | Any) -> str:
|
||||
return plan_data.content
|
||||
elif isinstance(plan_data, dict):
|
||||
# If it's already a dictionary, convert to JSON string
|
||||
logger.debug("Converting plan dictionary to JSON string")
|
||||
return json.dumps(plan_data)
|
||||
# Need to check if it's dict with content field (AIMessage-like)
|
||||
if "content" in plan_data:
|
||||
if isinstance(plan_data["content"], str):
|
||||
logger.debug("Extracting plan content from dict with content field")
|
||||
return plan_data["content"]
|
||||
if isinstance(plan_data["content"], dict):
|
||||
logger.debug("Converting content field dict to JSON string")
|
||||
return json.dumps(plan_data["content"], ensure_ascii=False)
|
||||
else:
|
||||
logger.warning(f"Unexpected type for 'content' field in plan_data dict: {type(plan_data['content']).__name__}, converting to string")
|
||||
return str(plan_data["content"])
|
||||
else:
|
||||
logger.debug("Converting plan dictionary to JSON string")
|
||||
return json.dumps(plan_data)
|
||||
else:
|
||||
# For any other type, try to convert to string
|
||||
logger.warning(f"Unexpected plan data type {type(plan_data).__name__}, attempting to convert to string")
|
||||
|
||||
Reference in New Issue
Block a user