mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-16 11:24:45 +08:00
fix: handle greetings without triggering research workflow (#755)
* fix: handle greetings without triggering research workflow (#733) * test: update tests for direct_response tool behavior * fix: address Copilot review comments for coordinator_node - Extract locale from direct_response tool_args - Fix import sorting (ruff I001) * fix: remove locale extraction from tool_args in direct_response Use locale from state instead of tool_args to avoid potential side effects. The locale is already properly passed from frontend via state. * fix: only fallback to planner when clarification is enabled In legacy mode (BRANCH 1), no tool calls should end the workflow gracefully instead of falling back to planner. This fixes the test_coordinator_node_no_tool_calls integration test. --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
@@ -5,7 +5,7 @@ import json
|
||||
import logging
|
||||
import os
|
||||
from functools import partial
|
||||
from typing import Any, Annotated, Literal
|
||||
from typing import Annotated, Any, Literal
|
||||
|
||||
from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
@@ -63,6 +63,15 @@ def handoff_after_clarification(
|
||||
return
|
||||
|
||||
|
||||
@tool
|
||||
def direct_response(
|
||||
message: Annotated[str, "The response message to send directly to user."],
|
||||
locale: Annotated[str, "The user's detected language locale (e.g., en-US, zh-CN)."],
|
||||
):
|
||||
"""Respond directly to user for greetings, small talk, or polite rejections. Do NOT use this for research questions - use handoff_to_planner instead."""
|
||||
return
|
||||
|
||||
|
||||
def needs_clarification(state: dict) -> bool:
|
||||
"""
|
||||
Check if clarification is needed based on current state.
|
||||
@@ -524,12 +533,12 @@ def coordinator_node(
|
||||
messages.append(
|
||||
{
|
||||
"role": "system",
|
||||
"content": "CRITICAL: Clarification is DISABLED. You MUST immediately call handoff_to_planner tool with the user's query as-is. Do NOT ask questions or mention needing more information.",
|
||||
"content": "Clarification is DISABLED. For research questions, use handoff_to_planner. For greetings or small talk, use direct_response. Do NOT ask clarifying questions.",
|
||||
}
|
||||
)
|
||||
|
||||
# Only bind handoff_to_planner tool
|
||||
tools = [handoff_to_planner]
|
||||
# Bind both handoff_to_planner and direct_response tools
|
||||
tools = [handoff_to_planner, direct_response]
|
||||
response = (
|
||||
get_llm_by_type(AGENT_LLM_MAP["coordinator"])
|
||||
.bind_tools(tools)
|
||||
@@ -556,11 +565,24 @@ def coordinator_node(
|
||||
if tool_args.get("research_topic"):
|
||||
research_topic = tool_args.get("research_topic")
|
||||
break
|
||||
elif tool_name == "direct_response":
|
||||
logger.info("Direct response to user (greeting/small talk)")
|
||||
goto = "__end__"
|
||||
# Append direct message to messages list instead of overwriting response
|
||||
if tool_args.get("message"):
|
||||
messages.append(AIMessage(content=tool_args.get("message"), name="coordinator"))
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing tool calls: {e}")
|
||||
goto = "planner"
|
||||
|
||||
# Do not return early - let code flow to unified return logic below
|
||||
# Set clarification variables for legacy mode
|
||||
clarification_rounds = 0
|
||||
clarification_history = []
|
||||
clarified_topic = research_topic
|
||||
|
||||
# ============================================================
|
||||
# BRANCH 2: Clarification ENABLED (New Feature)
|
||||
# ============================================================
|
||||
@@ -735,16 +757,19 @@ def coordinator_node(
|
||||
logger.error(f"Error processing tool calls: {e}")
|
||||
goto = "planner"
|
||||
else:
|
||||
# No tool calls detected - fallback to planner instead of ending
|
||||
logger.warning(
|
||||
"LLM didn't call any tools. This may indicate tool calling issues with the model. "
|
||||
"Falling back to planner to ensure research proceeds."
|
||||
)
|
||||
# Log full response for debugging
|
||||
logger.debug(f"Coordinator response content: {response.content}")
|
||||
logger.debug(f"Coordinator response object: {response}")
|
||||
# Fallback to planner to ensure workflow continues
|
||||
goto = "planner"
|
||||
# No tool calls detected
|
||||
if enable_clarification:
|
||||
# BRANCH 2: Fallback to planner to ensure research proceeds
|
||||
logger.warning(
|
||||
"LLM didn't call any tools. This may indicate tool calling issues with the model. "
|
||||
"Falling back to planner to ensure research proceeds."
|
||||
)
|
||||
logger.debug(f"Coordinator response content: {response.content}")
|
||||
logger.debug(f"Coordinator response object: {response}")
|
||||
goto = "planner"
|
||||
else:
|
||||
# BRANCH 1: No tool calls means end workflow gracefully (e.g., greeting handled)
|
||||
logger.info("No tool calls in legacy mode - ending workflow gracefully")
|
||||
|
||||
# Apply background_investigation routing if enabled (unified logic)
|
||||
if goto == "planner" and state.get("enable_background_investigation"):
|
||||
|
||||
Reference in New Issue
Block a user