139 lines
4.9 KiB
Python
139 lines
4.9 KiB
Python
"""
|
||
路由与初始化模块
|
||
包含状态初始化节点和条件路由函数
|
||
|
||
三层统一循环防护:
|
||
1. 全局步数硬上限(reasoning_step > max_steps)
|
||
2. 路由模式检测(A→B→A→B 交替循环)
|
||
3. 状态停滞检测(连续相同动作)
|
||
"""
|
||
|
||
from datetime import datetime
|
||
|
||
from ...core.intent import get_route_by_reasoning, ReasoningAction
|
||
from ...main_graph.state import MainGraphState
|
||
from ...logger import info
|
||
|
||
|
||
# ========== 初始化状态节点 ==========
|
||
def init_state_node(state: MainGraphState) -> MainGraphState:
|
||
"""初始化状态节点:在流程开始时设置初始值"""
|
||
state.current_phase = "initializing"
|
||
state.reasoning_step = 0
|
||
state.start_time = datetime.now().isoformat()
|
||
|
||
if not state.user_query and state.messages:
|
||
last_msg = state.messages[-1]
|
||
state.user_query = getattr(last_msg, "content", str(last_msg))
|
||
|
||
return state
|
||
|
||
|
||
# ========== 条件路由函数 ==========
|
||
def route_by_reasoning(state: MainGraphState) -> str:
|
||
"""
|
||
根据推理结果决定下一步路由,带三层统一循环防护
|
||
|
||
核心逻辑:
|
||
1. DIRECT_RESPONSE → 直接返回 llm_call
|
||
2. 子图完成/已有结果 → 直接返回 llm_call
|
||
3. 步数超限 → 直接返回 llm_call
|
||
4. 其他 → 正常路由
|
||
"""
|
||
# 获取历史动作
|
||
previous_actions = [h.get("action") for h in state.reasoning_history]
|
||
|
||
info(f"[条件路由] step={state.reasoning_step}, phase={state.current_phase}, history={previous_actions}")
|
||
|
||
# ========== 获取推理结果 ==========
|
||
reasoning_result = state.debug_info.get("reasoning_result")
|
||
latest_action = reasoning_result.action.name if reasoning_result else None
|
||
|
||
# ========== 核心检查:DIRECT_RESPONSE 优先 ==========
|
||
# 从 reasoning_result 检查(最新)
|
||
if latest_action == "DIRECT_RESPONSE":
|
||
info(f"[条件路由] 推理结果为 DIRECT_RESPONSE,直接去 llm_call")
|
||
return "llm_call"
|
||
|
||
# 备用:从历史记录检查
|
||
if previous_actions and previous_actions[-1] == "DIRECT_RESPONSE":
|
||
info(f"[条件路由] 历史记录最新动作为 DIRECT_RESPONSE,直接去 llm_call")
|
||
return "llm_call"
|
||
|
||
# ========== 子图完成/已有结果 ==========
|
||
if "subgraph_completed" in previous_actions or state.final_result:
|
||
info("[条件路由] 子图已完成或已有结果,直接终止")
|
||
return "llm_call"
|
||
|
||
# ========== 步数超限 ==========
|
||
if state.reasoning_step > state.max_steps:
|
||
info(f"[条件路由] 步数超限 ({state.reasoning_step}/{state.max_steps}),强制终止")
|
||
return "llm_call"
|
||
|
||
# ========== 特殊阶段快速通道 ==========
|
||
if state.current_phase in ("max_steps_exceeded", "finalizing", "done"):
|
||
return "llm_call"
|
||
if state.current_phase == "error_handling" or state.current_error:
|
||
return "handle_error"
|
||
|
||
# ========== 无推理结果,默认终止 ==========
|
||
if not reasoning_result:
|
||
info("[条件路由] 无推理结果,默认去 llm_call")
|
||
return "llm_call"
|
||
|
||
# ========== 计算目标路由 ==========
|
||
route = get_route_by_reasoning(reasoning_result)
|
||
|
||
route_mapping = {
|
||
"direct_response": "llm_call",
|
||
"retrieve_rag": "rag_retrieve",
|
||
"re_retrieve_rag": "rag_retrieve",
|
||
"web_search": "web_search",
|
||
"clarify": "llm_call",
|
||
"call_tool": "llm_call",
|
||
"contact": "contact_subgraph",
|
||
"dictionary": "dictionary_subgraph",
|
||
"news_analysis": "news_analysis_subgraph",
|
||
}
|
||
target = route_mapping.get(route, "llm_call")
|
||
|
||
# ========== 循环防护检测 ==========
|
||
# 1. 路由模式检测(A→B→A→B 交替)
|
||
if len(previous_actions) >= 4:
|
||
if (previous_actions[-4] == previous_actions[-2]
|
||
and previous_actions[-3] == previous_actions[-1]
|
||
and previous_actions[-2] != previous_actions[-1]):
|
||
info(f"[条件路由] 检测到路由循环: {previous_actions[-4:]},强制终止")
|
||
return "llm_call"
|
||
|
||
# 2. 状态停滞检测(连续相同动作)
|
||
if len(previous_actions) >= 2 and previous_actions[-1] == previous_actions[-2]:
|
||
info(f"[条件路由] 连续相同动作 '{previous_actions[-1]}',强制终止")
|
||
return "llm_call"
|
||
|
||
# ========== 智能优化 ==========
|
||
if target == "rag_retrieve" and (state.rag_docs or state.rag_context):
|
||
info("[条件路由] RAG 结果已存在,跳过检索")
|
||
return "llm_call"
|
||
|
||
info(f"[条件路由] 动作={latest_action}, 目标={target}")
|
||
return target
|
||
|
||
|
||
# ========== 完成阶段条件路由函数 ==========
|
||
|
||
def should_summarize(state: MainGraphState) -> str:
|
||
"""
|
||
检查是否需要总结对话(对话足够长时)
|
||
|
||
Args:
|
||
state: 当前图状态
|
||
|
||
Returns:
|
||
"summarize" 或 "finalize"
|
||
"""
|
||
if state.turns_since_last_summary >= 5: # 每5轮对话总结一次
|
||
return "summarize"
|
||
else:
|
||
return "finalize"
|