mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-23 22:24:46 +08:00
feat: Add intelligent clarification feature in coordinate step for research queries (#613)
* fix: support local models by making thought field optional in Plan model - Make thought field optional in Plan model to fix Pydantic validation errors with local models - Add Ollama configuration example to conf.yaml.example - Update documentation to include local model support - Improve planner prompt with better JSON format requirements Fixes local model integration issues where models like qwen3:14b would fail due to missing thought field in JSON output. * feat: Add intelligent clarification feature for research queries - Add multi-turn clarification process to refine vague research questions - Implement three-dimension clarification standard (Tech/App, Focus, Scope) - Add clarification state management in coordinator node - Update coordinator prompt with detailed clarification guidelines - Add UI settings to enable/disable clarification feature (disabled by default) - Update workflow to handle clarification rounds recursively - Add comprehensive test coverage for clarification functionality - Update documentation with clarification feature usage guide Key components: - src/graph/nodes.py: Core clarification logic and state management - src/prompts/coordinator.md: Detailed clarification guidelines - src/workflow.py: Recursive clarification handling - web/: UI settings integration - tests/: Comprehensive test coverage - docs/: Updated configuration guide * fix: Improve clarification conversation continuity - Add comprehensive conversation history to clarification context - Include previous exchanges summary in system messages - Add explicit guidelines for continuing rounds in coordinator prompt - Prevent LLM from starting new topics during clarification - Ensure topic continuity across clarification rounds Fixes issue where LLM would restart clarification instead of building upon previous exchanges. * fix: Add conversation history to clarification context * fix: resolve clarification feature message to planer, prompt, test issues - Optimize coordinator.md prompt template for better clarification flow - Simplify final message sent to planner after clarification - Fix API key assertion issues in test_search.py * fix: Add configurable max_clarification_rounds and comprehensive tests - Add max_clarification_rounds parameter for external configuration - Add comprehensive test cases for clarification feature in test_app.py - Fixes issues found during interactive mode testing where: - Recursive call failed due to missing initial_state parameter - Clarification exited prematurely at max rounds - Incorrect logging of max rounds reached * Move clarification tests to test_nodes.py and add max_clarification_rounds to zh.json
This commit is contained in:
@@ -30,6 +30,9 @@ async def run_agent_workflow_async(
|
||||
max_plan_iterations: int = 1,
|
||||
max_step_num: int = 3,
|
||||
enable_background_investigation: bool = True,
|
||||
enable_clarification: bool | None = None,
|
||||
max_clarification_rounds: int | None = None,
|
||||
initial_state: dict | None = None,
|
||||
):
|
||||
"""Run the agent workflow asynchronously with the given user input.
|
||||
|
||||
@@ -39,6 +42,9 @@ async def run_agent_workflow_async(
|
||||
max_plan_iterations: Maximum number of plan iterations
|
||||
max_step_num: Maximum number of steps in a plan
|
||||
enable_background_investigation: If True, performs web search before planning to enhance context
|
||||
enable_clarification: If None, use default from State class (False); if True/False, override
|
||||
max_clarification_rounds: Maximum number of clarification rounds allowed
|
||||
initial_state: Initial state to use (for recursive calls during clarification)
|
||||
|
||||
Returns:
|
||||
The final state after the workflow completes
|
||||
@@ -50,12 +56,24 @@ async def run_agent_workflow_async(
|
||||
enable_debug_logging()
|
||||
|
||||
logger.info(f"Starting async workflow with user input: {user_input}")
|
||||
initial_state = {
|
||||
# Runtime Variables
|
||||
"messages": [{"role": "user", "content": user_input}],
|
||||
"auto_accepted_plan": True,
|
||||
"enable_background_investigation": enable_background_investigation,
|
||||
}
|
||||
|
||||
# Use provided initial_state or create a new one
|
||||
if initial_state is None:
|
||||
initial_state = {
|
||||
# Runtime Variables
|
||||
"messages": [{"role": "user", "content": user_input}],
|
||||
"auto_accepted_plan": True,
|
||||
"enable_background_investigation": enable_background_investigation,
|
||||
}
|
||||
|
||||
# Only set clarification parameter if explicitly provided
|
||||
# If None, State class default will be used (enable_clarification=False)
|
||||
if enable_clarification is not None:
|
||||
initial_state["enable_clarification"] = enable_clarification
|
||||
|
||||
if max_clarification_rounds is not None:
|
||||
initial_state["max_clarification_rounds"] = max_clarification_rounds
|
||||
|
||||
config = {
|
||||
"configurable": {
|
||||
"thread_id": "default",
|
||||
@@ -76,10 +94,12 @@ async def run_agent_workflow_async(
|
||||
"recursion_limit": get_recursion_limit(default=100),
|
||||
}
|
||||
last_message_cnt = 0
|
||||
final_state = None
|
||||
async for s in graph.astream(
|
||||
input=initial_state, config=config, stream_mode="values"
|
||||
):
|
||||
try:
|
||||
final_state = s
|
||||
if isinstance(s, dict) and "messages" in s:
|
||||
if len(s["messages"]) <= last_message_cnt:
|
||||
continue
|
||||
@@ -90,12 +110,44 @@ async def run_agent_workflow_async(
|
||||
else:
|
||||
message.pretty_print()
|
||||
else:
|
||||
# For any other output format
|
||||
print(f"Output: {s}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing stream output: {e}")
|
||||
print(f"Error processing output: {str(e)}")
|
||||
|
||||
# Check if clarification is needed using centralized logic
|
||||
if final_state and isinstance(final_state, dict):
|
||||
from src.graph.nodes import needs_clarification
|
||||
|
||||
if needs_clarification(final_state):
|
||||
# Wait for user input
|
||||
print()
|
||||
clarification_rounds = final_state.get("clarification_rounds", 0)
|
||||
max_clarification_rounds = final_state.get("max_clarification_rounds", 3)
|
||||
user_response = input(
|
||||
f"Your response ({clarification_rounds}/{max_clarification_rounds}): "
|
||||
).strip()
|
||||
|
||||
if not user_response:
|
||||
logger.warning("Empty response, ending clarification")
|
||||
return final_state
|
||||
|
||||
# Continue workflow with user response
|
||||
current_state = final_state.copy()
|
||||
current_state["messages"] = final_state["messages"] + [
|
||||
{"role": "user", "content": user_response}
|
||||
]
|
||||
# Recursive call for clarification continuation
|
||||
return await run_agent_workflow_async(
|
||||
user_input=user_response,
|
||||
max_plan_iterations=max_plan_iterations,
|
||||
max_step_num=max_step_num,
|
||||
enable_background_investigation=enable_background_investigation,
|
||||
enable_clarification=enable_clarification,
|
||||
max_clarification_rounds=max_clarification_rounds,
|
||||
initial_state=current_state,
|
||||
)
|
||||
|
||||
logger.info("Async workflow completed successfully")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user