🧭 Multi-Agent 路由机制
在系统入口处智能分析用户请求,自动路由到最合适的专业代理, 实现高效的任务分类和请求分发,构建智能化的 Agent 调度系统。
📚 什么是 Router?
Router(路由机制)是 Multi-Agent 系统中的入口调度层。 在用户请求进入系统时,Router 分析请求特征并一次性决定将其路由到哪个专业代理处理, 无需后续的动态交接。
| 特性 | 说明 | 优势 |
|---|---|---|
| 初始分发 | 在流程开始时进行一次性路由 | 快速定位目标代理 |
| 智能分类 | 基于请求内容、意图、复杂度分类 | 精准匹配专业能力 |
| 专业化代理 | 每个代理专注特定领域 | 提高处理质量 |
| 效率优化 | 直接路由,避免不必要的交接 | 降低延迟和成本 |
| 可扩展性 | 轻松添加新的代理分支 | 系统易于扩展 |
我的订单在哪里?"] --> Router["🧭 Router
智能路由层"] Router -->|"分析请求内容"| Analysis["请求分析
关键词:订单
意图:查询
领域:电商"] Analysis --> Decision{"路由决策"} Decision -->|"订单相关"| OrderAgent["订单代理
处理订单查询"] Decision -->|"技术问题"| TechAgent["技术代理
解决技术问题"] Decision -->|"账单问题"| BillingAgent["账单代理
处理账单问题"] Decision -->|"一般咨询"| GeneralAgent["客服代理
处理一般问题"] OrderAgent --> Result1["订单信息返回"] TechAgent --> Result2["技术解决方案"] BillingAgent --> Result3["账单处理结果"] GeneralAgent --> Result4["咨询答复"] Result1 --> End["完成"] Result2 --> End Result3 --> End Result4 --> End style Router fill:#3b82f6,color:#fff style Analysis fill:#8b5cf6,color:#fff style Decision fill:#f59e0b,color:#fff style OrderAgent fill:#10b981,color:#fff style TechAgent fill:#ef4444,color:#fff style BillingAgent fill:#06b6d4,color:#fff style GeneralAgent fill:#a855f7,color:#fff
Router vs 其他协作模式
| 模式 | 决策时机 | 转移次数 | 适用场景 |
|---|---|---|---|
| Router | 流程开始时 | 一次性 | 请求分类、领域分流 |
| Subagents | 预定义流程 | 固定顺序 | 流水线、多步骤任务 |
| Handoffs | 运行时动态 | 按需多次 | 升级、专业化转移 |
| Skills | 工具级别 | 工具共享 | 能力复用、工具管理 |
🔧 路由策略
Router 的核心是路由决策逻辑,可以基于规则、LLM 或混合方式实现。
{intent, category}"] L3 --> L4{"分类结果"} L4 -->|"order"| L5["订单代理"] L4 -->|"billing"| L6["账单代理"] L4 -->|"technical"| L7["技术代理"] end subgraph Strategy3["策略 3:混合路由"] H1["用户请求"] --> H2["规则预筛选"] H2 --> H3{"快速匹配?"} H3 -->|"是"| H4["直接路由"] H3 -->|"否"| H5["LLM 分析"] H5 --> H6["路由决策"] end style R2 fill:#10b981,color:#fff style L2 fill:#f59e0b,color:#fff style H5 fill:#8b5cf6,color:#fff
策略 1:基于规则的路由
"""
基于规则的路由 - 使用关键词匹配
"""
from typing import TypedDict, Annotated, Literal
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain_core.messages import HumanMessage, AIMessage
# 定义状态
class RouterState(TypedDict):
messages: Annotated[list, add_messages]
route_to: str # 路由目标
# 路由函数:基于关键词
def rule_based_router(state: RouterState) -> str:
"""基于规则的路由器"""
last_message = state["messages"][-1].content.lower()
# 规则定义
order_keywords = ["订单", "物流", "快递", "配送", "发货"]
billing_keywords = ["退款", "支付", "账单", "扣费", "价格"]
technical_keywords = ["bug", "崩溃", "卡顿", "登录不了", "打不开"]
# 关键词匹配
if any(kw in last_message for kw in order_keywords):
return "order_agent"
elif any(kw in last_message for kw in billing_keywords):
return "billing_agent"
elif any(kw in last_message for kw in technical_keywords):
return "technical_agent"
else:
return "general_agent"
# 专业代理
def order_agent(state: RouterState):
"""订单代理"""
return {
"messages": [AIMessage(content="订单代理:我来帮您查询订单信息")],
"route_to": "order_agent"
}
def billing_agent(state: RouterState):
"""账单代理"""
return {
"messages": [AIMessage(content="账单代理:我来处理您的账单问题")],
"route_to": "billing_agent"
}
def technical_agent(state: RouterState):
"""技术代理"""
return {
"messages": [AIMessage(content="技术代理:我来解决您的技术问题")],
"route_to": "technical_agent"
}
def general_agent(state: RouterState):
"""通用代理"""
return {
"messages": [AIMessage(content="客服代理:我来帮您解决问题")],
"route_to": "general_agent"
}
# 构建路由图
workflow = StateGraph(RouterState)
# 添加代理节点
workflow.add_node("order_agent", order_agent)
workflow.add_node("billing_agent", billing_agent)
workflow.add_node("technical_agent", technical_agent)
workflow.add_node("general_agent", general_agent)
# 从 START 条件路由到不同代理
workflow.add_conditional_edges(
START,
rule_based_router,
{
"order_agent": "order_agent",
"billing_agent": "billing_agent",
"technical_agent": "technical_agent",
"general_agent": "general_agent"
}
)
# 所有代理结束后到 END
workflow.add_edge("order_agent", END)
workflow.add_edge("billing_agent", END)
workflow.add_edge("technical_agent", END)
workflow.add_edge("general_agent", END)
app = workflow.compile()
# 测试
test_cases = [
"我的订单什么时候发货?",
"我要申请退款",
"应用一直崩溃",
"你们的营业时间?"
]
for test in test_cases:
result = app.invoke({"messages": [HumanMessage(content=test)]})
print(f"请求: {test}")
print(f"路由到: {result['route_to']}\n")
# 优势:
# - 快速(无需调用 LLM)
# - 成本低(纯规则匹配)
# - 可解释性强
# - 适合明确的分类场景
# 劣势:
# - 需要维护关键词列表
# - 难以处理复杂或模糊请求
# - 无法理解上下文和语义
策略 2:基于 LLM 的路由
"""
基于 LLM 的路由 - 使用结构化输出
"""
from typing import TypedDict, Annotated, Literal
from pydantic import BaseModel, Field
from langgraph.graph import StateGraph, START, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
# 定义路由决策结构
class RouteDecision(BaseModel):
"""路由决策结构"""
category: Literal["order", "billing", "technical", "general"] = Field(
description="请求类别:order(订单), billing(账单), technical(技术), general(一般)"
)
confidence: float = Field(
description="分类置信度 (0-1)",
ge=0,
le=1
)
reason: str = Field(
description="分类理由"
)
# 定义状态
class LLMRouterState(TypedDict):
messages: Annotated[list, add_messages]
route_decision: RouteDecision
route_to: str
# LLM 路由器
def llm_router(state: LLMRouterState):
"""使用 LLM 进行智能路由"""
llm = ChatOpenAI(model="gpt-4o")
llm_with_structure = llm.with_structured_output(RouteDecision)
prompt = f"""分析以下用户请求,并分类到最合适的类别:
用户请求:{state['messages'][-1].content}
分类规则:
- order: 订单查询、物流追踪、发货问题
- billing: 退款、支付、账单、价格
- technical: 技术故障、bug、登录问题
- general: 其他一般性咨询
返回分类结果、置信度和理由。
"""
decision = llm_with_structure.invoke(prompt)
return {
"route_decision": decision,
"route_to": f"{decision.category}_agent"
}
# 路由决策函数
def route_by_llm(state: LLMRouterState) -> str:
"""根据 LLM 决策路由"""
# 如果还没有决策,先调用 router 节点
if "route_decision" not in state:
return "router"
# 根据决策路由
return state["route_to"]
# 专业代理(简化版)
def order_agent(state: LLMRouterState):
llm = ChatOpenAI(model="gpt-4o")
response = llm.invoke("你是订单专员,帮用户查询订单信息")
return {"messages": [response]}
def billing_agent(state: LLMRouterState):
llm = ChatOpenAI(model="gpt-4o")
response = llm.invoke("你是账单专员,帮用户处理账单问题")
return {"messages": [response]}
def technical_agent(state: LLMRouterState):
llm = ChatOpenAI(model="claude-sonnet-4-5")
response = llm.invoke("你是技术支持,帮用户解决技术问题")
return {"messages": [response]}
def general_agent(state: LLMRouterState):
llm = ChatOpenAI(model="gpt-4o")
response = llm.invoke("你是客服,帮用户解决一般问题")
return {"messages": [response]}
# 构建 LLM 路由图
workflow = StateGraph(LLMRouterState)
# 添加 router 节点
workflow.add_node("router", llm_router)
# 添加代理节点
workflow.add_node("order_agent", order_agent)
workflow.add_node("billing_agent", billing_agent)
workflow.add_node("technical_agent", technical_agent)
workflow.add_node("general_agent", general_agent)
# START → router(先进行路由分析)
workflow.add_edge(START, "router")
# router → 条件路由到不同代理
workflow.add_conditional_edges(
"router",
lambda state: state["route_to"],
{
"order_agent": "order_agent",
"billing_agent": "billing_agent",
"technical_agent": "technical_agent",
"general_agent": "general_agent"
}
)
# 所有代理 → END
workflow.add_edge("order_agent", END)
workflow.add_edge("billing_agent", END)
workflow.add_edge("technical_agent", END)
workflow.add_edge("general_agent", END)
app = workflow.compile()
# 测试
result = app.invoke({
"messages": [HumanMessage(content="我的包裹怎么还没到?")]
})
print(f"路由决策:{result['route_decision']}")
print(f"类别:{result['route_decision'].category}")
print(f"置信度:{result['route_decision'].confidence}")
print(f"理由:{result['route_decision'].reason}")
# 优势:
# - 语义理解能力强
# - 可处理复杂和模糊请求
# - 无需维护规则列表
# - 可提供分类理由(可解释性)
# 劣势:
# - 调用 LLM,增加延迟
# - 成本相对较高
# - 需要处理 LLM 不确定性
策略 3:混合路由(推荐)
"""
混合路由 - 规则预筛选 + LLM 精准分类
"""
from typing import TypedDict, Annotated, Literal
from langgraph.graph import StateGraph, START, END
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
class HybridRouterState(TypedDict):
messages: Annotated[list, add_messages]
quick_match: bool # 是否快速匹配成功
route_to: str
confidence: float
# 第一层:快速规则匹配
def quick_rule_filter(state: HybridRouterState):
"""快速规则过滤器"""
last_message = state["messages"][-1].content.lower()
# 高置信度规则(明确关键词)
high_confidence_rules = {
"order_agent": ["订单号", "物流单号", "快递编号"],
"billing_agent": ["退款申请", "发票", "账单明细"],
"technical_agent": ["错误代码", "崩溃日志", "bug报告"]
}
# 检查高置信度匹配
for agent, keywords in high_confidence_rules.items():
if any(kw in last_message for kw in keywords):
return {
"quick_match": True,
"route_to": agent,
"confidence": 0.95
}
# 没有高置信度匹配,需要 LLM 分析
return {
"quick_match": False,
"confidence": 0.0
}
# 第二层:LLM 精准分类
class DetailedRouteDecision(BaseModel):
category: Literal["order", "billing", "technical", "general"]
confidence: float = Field(ge=0, le=1)
reason: str
keywords_found: list[str]
def llm_precise_classifier(state: HybridRouterState):
"""LLM 精准分类器"""
llm = ChatOpenAI(model="gpt-4o")
llm_with_structure = llm.with_structured_output(DetailedRouteDecision)
prompt = f"""深度分析用户请求,进行精准分类:
用户请求:{state['messages'][-1].content}
分析要求:
1. 仔细理解用户意图和上下文
2. 考虑隐含的需求和情绪
3. 识别关键词和问题类型
4. 给出高置信度的分类
返回详细的分类结果。
"""
decision = llm_with_structure.invoke(prompt)
return {
"route_to": f"{decision.category}_agent",
"confidence": decision.confidence
}
# 路由决策函数
def route_decision(state: HybridRouterState) -> Literal["quick_route", "llm_route"]:
"""决定使用快速路由还是 LLM 路由"""
if state.get("quick_match", False):
return "quick_route"
else:
return "llm_route"
def final_route(state: HybridRouterState) -> str:
"""最终路由"""
return state["route_to"]
# 代理节点(简化)
def order_agent(state: HybridRouterState):
return {"messages": [AIMessage(content="订单代理处理中...")]}
def billing_agent(state: HybridRouterState):
return {"messages": [AIMessage(content="账单代理处理中...")]}
def technical_agent(state: HybridRouterState):
return {"messages": [AIMessage(content="技术代理处理中...")]}
def general_agent(state: HybridRouterState):
return {"messages": [AIMessage(content="客服代理处理中...")]}
# 构建混合路由图
workflow = StateGraph(HybridRouterState)
# 第一层:快速过滤
workflow.add_node("quick_filter", quick_rule_filter)
# 第二层:LLM 分类
workflow.add_node("llm_classifier", llm_precise_classifier)
# 代理节点
workflow.add_node("order_agent", order_agent)
workflow.add_node("billing_agent", billing_agent)
workflow.add_node("technical_agent", technical_agent)
workflow.add_node("general_agent", general_agent)
# START → quick_filter(快速过滤)
workflow.add_edge(START, "quick_filter")
# quick_filter → 条件路由
workflow.add_conditional_edges(
"quick_filter",
route_decision,
{
"quick_route": "order_agent", # 快速匹配直接路由
"llm_route": "llm_classifier" # 需要 LLM 分析
}
)
# llm_classifier → 最终路由
workflow.add_conditional_edges(
"llm_classifier",
final_route,
{
"order_agent": "order_agent",
"billing_agent": "billing_agent",
"technical_agent": "technical_agent",
"general_agent": "general_agent"
}
)
# 所有代理 → END
workflow.add_edge("order_agent", END)
workflow.add_edge("billing_agent", END)
workflow.add_edge("technical_agent", END)
workflow.add_edge("general_agent", END)
app = workflow.compile()
# 测试不同场景
test_cases = [
("我的订单号是 123456,帮我查一下", "快速匹配"),
("东西还没到,有点着急", "LLM 分析"),
("我要退款申请,发票怎么开", "快速匹配"),
("我想了解一下你们的服务", "LLM 分析")
]
for test, expected_type in test_cases:
result = app.invoke({"messages": [HumanMessage(content=test)]})
print(f"请求: {test}")
print(f"快速匹配: {result.get('quick_match', False)}")
print(f"路由到: {result['route_to']}")
print(f"置信度: {result.get('confidence', 0)}")
print(f"预期类型: {expected_type}\n")
# 优势:
# - 平衡速度和准确性
# - 降低 LLM 调用成本(80%+ 请求快速匹配)
# - 对明确请求快速响应
# - 对复杂请求精准分类
# 适用场景:
# - 生产环境推荐方案
# - 高并发场景
# - 成本敏感的系统
🎯 完整实战示例
构建一个智能客服路由系统,支持多领域分流、优先级判断、 智能降级和完整的路由追踪。
"""
完整实战示例 - 智能客服路由系统
"""
import uuid
from typing import TypedDict, Annotated, Literal
from enum import Enum
from pydantic import BaseModel, Field
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage, AIMessage
# ========== 1. 定义枚举和数据结构 ==========
class AgentCategory(str, Enum):
"""代理类别"""
ORDER = "order"
BILLING = "billing"
TECHNICAL = "technical"
GENERAL = "general"
VIP = "vip"
class Priority(str, Enum):
"""优先级"""
LOW = "low"
NORMAL = "normal"
HIGH = "high"
URGENT = "urgent"
class RouteAnalysis(BaseModel):
"""路由分析结果"""
category: AgentCategory = Field(description="请求类别")
priority: Priority = Field(description="优先级")
confidence: float = Field(description="置信度", ge=0, le=1)
keywords: list[str] = Field(description="识别的关键词")
sentiment: str = Field(description="情绪(positive, neutral, negative)")
reason: str = Field(description="分类理由")
# ========== 2. 定义状态 ==========
class SmartRouterState(TypedDict):
messages: Annotated[list, add_messages]
user_id: str
session_id: str
# 路由信息
route_analysis: RouteAnalysis
route_to: str
route_method: str # "quick" or "llm"
# 用户信息
is_vip: bool
user_history: list[str]
# 追踪信息
route_timestamp: str
routing_time_ms: float
# ========== 3. 规则引擎 ==========
class RuleEngine:
"""规则引擎:快速匹配"""
# 高置信度规则
HIGH_CONFIDENCE_RULES = {
AgentCategory.ORDER: [
"订单号", "物流单号", "快递编号", "发货时间",
"配送时间", "订单状态", "在哪里"
],
AgentCategory.BILLING: [
"退款申请", "发票", "账单明细", "扣费",
"支付失败", "余额", "价格错误"
],
AgentCategory.TECHNICAL: [
"错误代码", "崩溃日志", "bug", "无法登录",
"打不开", "卡顿", "闪退"
]
}
# 优先级关键词
PRIORITY_KEYWORDS = {
Priority.URGENT: ["紧急", "立即", "马上", "投诉", "严重"],
Priority.HIGH: ["尽快", "着急", "重要", "损失"],
Priority.NORMAL: [] # 默认
}
# 负面情绪关键词
NEGATIVE_KEYWORDS = [
"不满", "失望", "生气", "愤怒", "差评",
"投诉", "垃圾", "骗子", "退货"
]
@classmethod
def quick_match(cls, message: str) -> dict | None:
"""快速匹配"""
message_lower = message.lower()
# 检查高置信度规则
for category, keywords in cls.HIGH_CONFIDENCE_RULES.items():
matched = [kw for kw in keywords if kw in message_lower]
if matched:
# 判断优先级
priority = Priority.NORMAL
for pri, pri_kws in cls.PRIORITY_KEYWORDS.items():
if any(kw in message_lower for kw in pri_kws):
priority = pri
break
# 判断情绪
sentiment = "negative" if any(
kw in message_lower for kw in cls.NEGATIVE_KEYWORDS
) else "neutral"
return {
"category": category,
"priority": priority,
"confidence": 0.9,
"keywords": matched,
"sentiment": sentiment,
"reason": f"关键词匹配:{', '.join(matched)}"
}
return None
# ========== 4. 路由节点 ==========
def quick_router(state: SmartRouterState):
"""快速路由器"""
import time
start_time = time.time()
message = state["messages"][-1].content
# 尝试快速匹配
quick_result = RuleEngine.quick_match(message)
if quick_result:
# 快速匹配成功
route_analysis = RouteAnalysis(**quick_result)
# VIP 用户直接升级到 VIP 代理
if state.get("is_vip", False):
route_to = "vip_agent"
else:
route_to = f"{route_analysis.category.value}_agent"
routing_time = (time.time() - start_time) * 1000
return {
"route_analysis": route_analysis,
"route_to": route_to,
"route_method": "quick",
"routing_time_ms": routing_time
}
# 快速匹配失败,需要 LLM
return {
"route_method": "need_llm"
}
def llm_router(state: SmartRouterState):
"""LLM 智能路由器"""
import time
start_time = time.time()
llm = ChatOpenAI(model="gpt-4o")
llm_with_structure = llm.with_structured_output(RouteAnalysis)
message = state["messages"][-1].content
user_history = state.get("user_history", [])
prompt = f"""深度分析客服请求并分类:
用户请求:{message}
用户历史:{user_history[-3:] if user_history else "无"}
分析要求:
1. 理解用户意图和情绪
2. 考虑用户历史上下文
3. 判断问题类别和优先级
4. 识别关键词
5. 评估用户情绪
类别说明:
- order: 订单查询、物流追踪
- billing: 退款、支付、账单
- technical: 技术问题、bug
- general: 一般咨询
优先级说明:
- urgent: 严重问题、用户投诉
- high: 影响使用、需尽快处理
- normal: 一般问题
- low: 简单咨询
返回完整的路由分析。
"""
route_analysis = llm_with_structure.invoke(prompt)
# VIP 用户特殊处理
if state.get("is_vip", False):
route_to = "vip_agent"
else:
route_to = f"{route_analysis.category.value}_agent"
routing_time = (time.time() - start_time) * 1000
return {
"route_analysis": route_analysis,
"route_to": route_to,
"route_method": "llm",
"routing_time_ms": routing_time
}
# ========== 5. 专业代理 ==========
def order_agent(state: SmartRouterState):
"""订单代理"""
llm = ChatOpenAI(model="gpt-4o")
priority = state["route_analysis"].priority
prompt_prefix = "【高优先级】" if priority in [Priority.HIGH, Priority.URGENT] else ""
prompt = f"""{prompt_prefix}你是订单专员。
用户请求:{state['messages'][-1].content}
路由分析:{state['route_analysis'].reason}
任务:帮助用户查询订单信息、解决物流问题。
"""
response = llm.invoke(prompt)
return {
"messages": [AIMessage(content=f"订单代理:{response.content}")]
}
def billing_agent(state: SmartRouterState):
"""账单代理"""
llm = ChatOpenAI(model="gpt-4o")
prompt = f"""你是账单专员。
用户请求:{state['messages'][-1].content}
情绪:{state['route_analysis'].sentiment}
任务:处理退款、支付、账单问题。注意用户情绪,友好沟通。
"""
response = llm.invoke(prompt)
return {
"messages": [AIMessage(content=f"账单代理:{response.content}")]
}
def technical_agent(state: SmartRouterState):
"""技术代理"""
llm = ChatAnthropic(model="claude-sonnet-4-5")
prompt = f"""你是技术支持工程师。
用户请求:{state['messages'][-1].content}
关键词:{', '.join(state['route_analysis'].keywords)}
任务:诊断并解决技术问题,提供清晰的解决方案。
"""
response = llm.invoke(prompt)
return {
"messages": [AIMessage(content=f"技术代理:{response.content}")]
}
def general_agent(state: SmartRouterState):
"""通用代理"""
llm = ChatOpenAI(model="gpt-4o")
response = llm.invoke("你是客服,处理一般性咨询")
return {
"messages": [AIMessage(content=f"客服代理:{response.content}")]
}
def vip_agent(state: SmartRouterState):
"""VIP 代理"""
llm = ChatAnthropic(model="claude-sonnet-4-5")
prompt = f"""你是 VIP 专属客服。
用户请求:{state['messages'][-1].content}
用户类型:VIP 会员
优先级:{state['route_analysis'].priority.value}
任务:提供高质量、个性化的服务,优先处理 VIP 用户问题。
"""
response = llm.invoke(prompt)
return {
"messages": [AIMessage(content=f"VIP 代理:{response.content}")]
}
# ========== 6. 路由决策 ==========
def should_use_llm(state: SmartRouterState) -> Literal["quick_done", "need_llm"]:
"""决定是否需要 LLM"""
return state.get("route_method", "need_llm")
def final_route(state: SmartRouterState) -> str:
"""最终路由"""
return state["route_to"]
# ========== 7. 构建工作流 ==========
workflow = StateGraph(SmartRouterState)
# 添加路由节点
workflow.add_node("quick_router", quick_router)
workflow.add_node("llm_router", llm_router)
# 添加代理节点
workflow.add_node("order_agent", order_agent)
workflow.add_node("billing_agent", billing_agent)
workflow.add_node("technical_agent", technical_agent)
workflow.add_node("general_agent", general_agent)
workflow.add_node("vip_agent", vip_agent)
# START → quick_router
workflow.add_edge(START, "quick_router")
# quick_router → 条件判断
workflow.add_conditional_edges(
"quick_router",
should_use_llm,
{
"quick_done": "order_agent", # 占位,会被 final_route 覆盖
"need_llm": "llm_router"
}
)
# 为快速路由添加最终路由
workflow.add_conditional_edges(
"quick_router",
final_route,
{
"order_agent": "order_agent",
"billing_agent": "billing_agent",
"technical_agent": "technical_agent",
"general_agent": "general_agent",
"vip_agent": "vip_agent"
}
)
# llm_router → 最终路由
workflow.add_conditional_edges(
"llm_router",
final_route,
{
"order_agent": "order_agent",
"billing_agent": "billing_agent",
"technical_agent": "technical_agent",
"general_agent": "general_agent",
"vip_agent": "vip_agent"
}
)
# 所有代理 → END
workflow.add_edge("order_agent", END)
workflow.add_edge("billing_agent", END)
workflow.add_edge("technical_agent", END)
workflow.add_edge("general_agent", END)
workflow.add_edge("vip_agent", END)
# 编译
app = workflow.compile()
# ========== 8. 测试系统 ==========
test_scenarios = [
{
"name": "订单查询(快速匹配)",
"message": "我的订单号是 123456,什么时候发货?",
"is_vip": False
},
{
"name": "复杂咨询(LLM 分析)",
"message": "东西还没到,有点着急,能帮我催一下吗?",
"is_vip": False
},
{
"name": "VIP 用户(优先处理)",
"message": "我要申请退款",
"is_vip": True
},
{
"name": "技术问题(负面情绪)",
"message": "这个破软件总是崩溃,太垃圾了!",
"is_vip": False
}
]
for scenario in test_scenarios:
print(f"\n{'='*60}")
print(f"场景:{scenario['name']}")
print(f"{'='*60}")
result = app.invoke({
"messages": [HumanMessage(content=scenario['message'])],
"user_id": f"user_{uuid.uuid4().hex[:8]}",
"session_id": f"session_{uuid.uuid4().hex[:8]}",
"is_vip": scenario["is_vip"],
"user_history": []
})
print(f"用户请求:{scenario['message']}")
print(f"\n路由分析:")
print(f" - 类别:{result['route_analysis'].category.value}")
print(f" - 优先级:{result['route_analysis'].priority.value}")
print(f" - 置信度:{result['route_analysis'].confidence}")
print(f" - 情绪:{result['route_analysis'].sentiment}")
print(f" - 理由:{result['route_analysis'].reason}")
print(f"\n路由决策:")
print(f" - 路由到:{result['route_to']}")
print(f" - 路由方法:{result['route_method']}")
print(f" - 路由耗时:{result['routing_time_ms']:.2f} ms")
# 优势:
# - 快速路由(80%+ 请求 < 10ms)
# - 精准分类(LLM 支持复杂场景)
# - VIP 优先处理
# - 情绪感知和优先级判断
# - 完整的路由追踪
# - 生产级错误处理
✨ Router 最佳实践
1. 路由策略选择
| 场景 | 推荐策略 | 原因 |
|---|---|---|
| 明确的分类场景 | 基于规则 | 快速、成本低、可解释 |
| 复杂语义理解 | 基于 LLM | 准确、灵活、无需维护规则 |
| 生产环境 | 混合路由 | 平衡速度、成本和准确性 |
| 高并发系统 | 规则 + 缓存 | 降低 LLM 调用频率 |
2. 路由器设计原则
- 快速决策:路由决策应尽可能快(目标 < 100ms)
- 高准确性:错误路由会导致用户体验差和浪费资源
- 可降级:LLM 失败时自动降级到规则路由
- 可追踪:记录路由决策、耗时、置信度
- 可扩展:易于添加新的代理分支
- 用户感知:考虑用户优先级、情绪、历史
3. 代理分类策略
- 按领域分类:订单、账单、技术、一般(最常见)
- 按能力分类:初级、中级、高级(按复杂度)
- 按用户分类:VIP、普通、新用户(按重要性)
- 按紧急度分类:紧急、高优先级、普通(按时效)
- 混合分类:领域 + 优先级的组合
4. 性能优化
# 优化策略
# 1. 缓存 LLM 路由结果
from functools import lru_cache
@lru_cache(maxsize=1000)
def cached_llm_route(message_hash: str):
"""缓存相似请求的路由结果"""
# 对相似请求返回缓存的路由决策
pass
# 2. 批量路由(适用于批处理场景)
def batch_route(messages: list[str]):
"""批量路由多个请求"""
# 使用 LLM 的 batch API 降低成本
pass
# 3. 异步路由
import asyncio
async def async_router(state):
"""异步路由器"""
# 使用异步 LLM 调用提高并发
pass
# 4. 规则优先级排序
# 将最常匹配的规则放在前面
PRIORITY_RULES = [
(most_common_keywords, "most_common_agent"),
(less_common_keywords, "less_common_agent"),
]
# 5. 监控和优化
def log_routing_metrics(state):
"""记录路由指标"""
metrics = {
"route_method": state["route_method"],
"routing_time_ms": state["routing_time_ms"],
"confidence": state["route_analysis"].confidence,
"category": state["route_analysis"].category
}
# 发送到监控系统
# 定期分析优化
5. 错误处理和降级
# 错误处理策略
def robust_llm_router(state):
"""带降级的 LLM 路由器"""
try:
# 尝试 LLM 路由
return llm_router(state)
except Exception as e:
logger.error(f"LLM 路由失败: {e}")
# 降级到规则路由
fallback_result = rule_based_router(state)
return {
"route_to": fallback_result,
"route_method": "fallback",
"error": str(e)
}
# 默认路由
def default_router(state):
"""默认路由到通用代理"""
return {
"route_to": "general_agent",
"route_method": "default",
"confidence": 0.5
}
❓ 常见问题
Q1: Router 和 Handoffs 有什么区别?
关键区别:
- 时机不同:
- Router:在流程开始时一次性决定路由
- Handoffs:在流程执行过程中动态转移
- 决策依据不同:
- Router:基于用户请求内容分类
- Handoffs:基于当前代理的处理结果判断
- 使用场景不同:
- Router:初始分流(客服系统、任务调度)
- Handoffs:升级转移(L1 → L2 → L3)
Q2: 如何提高路由准确性?
提升策略:
- 丰富规则库:持续积累和更新关键词规则
- 使用高质量 LLM:GPT-4o 或 Claude Sonnet 4.5
- 结构化输出:使用 Pydantic 约束 LLM 输出格式
- 上下文增强:利用用户历史、会话上下文
- 多轮确认:置信度低时询问用户确认
- 持续学习:收集错误路由案例,优化规则
Q3: Router 如何处理模糊请求?
处理策略:
# 处理模糊请求
def handle_ambiguous_request(state):
"""处理模糊请求"""
analysis = state["route_analysis"]
# 策略 1:置信度阈值
if analysis.confidence < 0.7:
# 询问用户明确意图
return {
"messages": [AIMessage(content="请问您是想咨询订单、账单还是技术问题?")],
"route_to": "clarification_agent"
}
# 策略 2:多标签路由
if len(analysis.keywords) == 0:
# 路由到通用代理
return {"route_to": "general_agent"}
# 策略 3:智能猜测 + 确认
return {
"messages": [AIMessage(content=f"我理解您是想咨询{analysis.category}相关问题,对吗?")],
"route_to": f"{analysis.category}_agent"
}
Q4: 如何监控 Router 性能?
关键指标:
- 路由准确率:正确路由的请求占比(目标 > 95%)
- 路由延迟:路由决策的平均耗时(目标 < 100ms)
- 快速匹配率:规则直接匹配的比例(目标 > 80%)
- LLM 调用率:需要 LLM 分析的比例(降低成本)
- 用户满意度:路由后的问题解决率
- 错误路由率:需要重新路由的比例
Q5: 如何实现动态路由规则更新?
动态更新方案:
# 动态规则管理
class DynamicRuleEngine:
"""动态规则引擎"""
def __init__(self):
self._rules = self._load_rules_from_db()
self._last_update = time.time()
def _load_rules_from_db(self):
"""从数据库加载规则"""
# 从配置中心或数据库加载最新规则
return {}
def refresh_rules(self):
"""刷新规则(定期调用)"""
if time.time() - self._last_update > 300: # 5 分钟
self._rules = self._load_rules_from_db()
self._last_update = time.time()
def add_rule(self, category: str, keywords: list[str]):
"""动态添加规则"""
self._rules.setdefault(category, []).extend(keywords)
# 同步到数据库
def match(self, message: str):
"""使用最新规则匹配"""
self.refresh_rules()
# 执行匹配逻辑
# 使用
engine = DynamicRuleEngine()
# 运营人员可以通过管理界面添加新规则
# 无需重启服务,实时生效
Q6: Router 如何支持多语言?
多语言支持策略:
- LLM 天然支持:使用 LLM 路由自动支持多语言
- 语言检测:先检测语言,然后使用对应语言的规则
- 翻译路由:将请求翻译为统一语言后再路由
- 多语言规则:为每种语言维护独立的关键词库
- 多语言代理:每种语言配置专门的代理