路由模式(Routing)
相比提示链模式的固定线性流程,路由模式能根据输入动态选择不同的处理路径。它通过一个路由器对输入进行分类或评估,然后将其导向最合适的专用处理器,使系统从固定执行路径转变为动态决策系统。
这种动态决策能力------即根据特定条件将控制流导向不同的专用函数、工具或子流程------就是通过"路由"机制实现的。路由为智能体的操作框架引入了条件逻辑,使其从固定执行路径转变为动态决策系统。这种机制使智能体能够根据输入数据的特征、上下文信息或外部环境的变化,选择最合适的工具或子流程来处理任务。
核心思想:条件分发 ------ 先判断"这是什么类型的请求",再决定"交给谁处理"。
例如,一个用于客户咨询的智能体,在具备路由功能后,可以对用户查询进行分类以判断意图。根据分类结果,查询可以被导向专门的问答智能体、用于账户信息检索的数据库工具,或者用于复杂问题升级的流程。
与提示链的关系
| 对比 | 提示链模式 | 路由模式 |
|---|---|---|
| 流程 | 固定线性:A → B → C | 动态分支:A → B₁ / B₂ / B₃ |
| 决策 | 无决策,按顺序执行 | 有分类/判断步骤 |
| 适用 | 步骤确定的流水线任务 | 输入类型多样、需要不同处理方式的任务 |
路由模式的核心组件
路由模式的核心组件是执行评估并引导流程的机制,其实现方式包括以下五种:
1. 基于 LLM 的路由
通过提示语言模型分析输入,并输出指示下一步或目标标识符或指令。
示例 Prompt:"分析用户查询,仅输出类别:'订单状态'、'产品信息'、'技术支持'或'其他'。"
智能体系统读取输出并据此引导工作流。
优点 :灵活,能处理复杂和新颖的输入
缺点:有延迟和成本,结果可能不稳定
2. 基于嵌入的路由
利用嵌入向量(RAG)来表示输入数据,并通过计算与不同工具或子流程的嵌入向量之间的相似度来决定路由。例如,智能体可以将用户查询转换为嵌入向量,并计算与预定义工具或子流程的嵌入向量之间的相似度,以确定最相关的工具或子流程来处理查询。
优点 :语义理解能力强,适合模糊匹配
缺点:需要预先计算各路径的嵌入表示
3. 基于规则的路由
通过预定义的规则或条件(如 if-else、switch-case)来指导路由决策,根据关键词或者结构化数据进行路由。
优点 :比 LLM 路由更快、更确定,无 LLM 调用成本
缺点:处理复杂或新颖输入的灵活性较低
4. 基于机器学习模型的路由
采用如分类器等判别模型,在小规模标注数据集上专门训练以实现路由任务。与嵌入方法类似,但其特点是监督微调过程,路由逻辑编码在模型权重中。与 LLM 路由不同,决策组件是一个独立的判别模型,而非提示引导的语言模型输出。LLM 可用于生成合成训练数据,但不参与实时路由决策。
优点 :快速且准确,适合高频场景
缺点:需要标注数据和训练过程
5. 混合路由
结合上述多种方法以实现更鲁棒的路由机制。例如,系统可以首先使用基于规则的路由进行快速分类,如果输入不符合任何规则,则退回到基于 LLM 的路由进行更深入的分析。
流程示意
┌→ [处理器 A] → 结果 A
输入 → [路由器] ──→├→ [处理器 B] → 结果 B
└→ [处理器 C] → 结果 C
路由机制可以在智能体操作周期的多个阶段实现:既可用于分配初始任务分类,也可在处理链中间决定后续动作,或在子流程中选择最合适的工具。
适用场景
路由模式是设计自适应智能体系统的关键控制机制,使其能够根据输入和内部状态动态调整执行路径,广泛应用于多个领域:
| 场景 | 路由示例 |
|---|---|
| 客服系统 | 分类意图 → 订单查询 / 技术支持 / 投诉处理 |
| 文档处理 | 识别格式 → JSON 解析 / CSV 转换 / 纯文本提取 |
| AI 编程助手 | 识别语言和意图 → 调试 / 解释 / 代码翻译 |
| 研究系统 | 判断任务类型 → 检索 / 摘要 / 深度分析 |
人机交互场景
在虚拟助手、AI 教师等场景中,路由用于解析用户意图。系统对自然语言查询进行初步分析,决定后续动作,如调用信息检索工具、升级到人工、或根据用户表现选择下一个课程模块,从而实现超越线性对话流的上下文响应。
自动化数据与文档处理
路由承担分类与分发功能。系统根据内容、元数据或格式分析(如邮件、工单、API 数据),并将其导向相应工作流,如销售线索导入、针对 JSON/CSV 的数据转换、或紧急问题升级。
多工具/多智能体协作系统
路由充当高级调度器。例如,研究系统由检索、摘要、分析等智能体组成,路由器根据当前目标分配任务。同样,AI 编程助手会先识别编程语言和用户意图(调试、解释、翻译),再将代码片段交给对应工具处理。
总之,路由为系统提供了逻辑仲裁能力,是构建功能多样、具备上下文感知系统的基础。它将智能体从静态执行者转变为能根据变化条件做出决策的动态系统。
代码示例
示例 1:LangChain 实现(
python
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableBranch
load_dotenv()
# --- 配置 ---
# 确保环境变量已设置 OPENAI_API_KEY
try:
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
print(f"语言模型初始化成功:{llm.model_name}")
except Exception as e:
print(f"语言模型初始化失败:{e}")
llm = None
# --- 定义模拟子智能体处理器(等同于 ADK sub_agents)---
def booking_handler(request: str) -> str:
"""模拟预订智能体处理请求。"""
print("\n--- 委托给预订处理器 ---")
return f"预订处理器已处理请求:'{request}'。结果:模拟预订动作。"
def info_handler(request: str) -> str:
"""模拟信息智能体处理请求。"""
print("\n--- 委托给信息处理器 ---")
return f"信息处理器已处理请求:'{request}'。结果:模拟信息检索。"
def unclear_handler(request: str) -> str:
"""处理无法委托的请求。"""
print("\n--- 处理不明确请求 ---")
return f"协调者无法委托请求:'{request}'。请补充说明。"
# --- 定义协调者路由链(等同于 ADK 协调者指令)---
coordinator_router_prompt = ChatPromptTemplate.from_messages([
("system", """分析用户请求,判断应由哪个专属处理器处理。
- 若请求涉及预订机票或酒店,输出 'booker'。
- 其他一般信息问题,输出 'info'。
- 若请求不明确或不属于上述类别,输出 'unclear'。
只输出一个词:'booker'、'info' 或 'unclear'。"""),
("user", "{request}")
])
if llm:
coordinator_router_chain = coordinator_router_prompt | llm | StrOutputParser()
# --- 定义委托逻辑(等同于 ADK 的 Auto-Flow)---
branches = {
"booker": RunnablePassthrough.assign(
output=lambda x: booking_handler(x['request']['request'])
),
"info": RunnablePassthrough.assign(
output=lambda x: info_handler(x['request']['request'])
),
"unclear": RunnablePassthrough.assign(
output=lambda x: unclear_handler(x['request']['request'])
),
}
delegation_branch = RunnableBranch(
(lambda x: x['decision'].strip() == 'booker', branches["booker"]),
(lambda x: x['decision'].strip() == 'info', branches["info"]),
branches["unclear"] # 默认分支
)
coordinator_agent = (
{
"decision": coordinator_router_chain,
"request": RunnablePassthrough()
}
| delegation_branch
| (lambda x: x['output'])
)
# --- 示例用法 ---
def main():
if not llm:
print("\n因 LLM 初始化失败,跳过执行。")
return
print("--- 预订请求示例 ---")
request_a = "帮我预订飞往伦敦的机票。"
result_a = coordinator_agent.invoke({"request": request_a})
print(f"最终结果 A: {result_a}")
print("\n--- 信息请求示例 ---")
request_b = "意大利的首都是哪里?"
result_b = coordinator_agent.invoke({"request": request_b})
print(f"最终结果 B: {result_b}")
print("\n--- 不明确请求示例 ---")
request_c = "讲讲量子物理。"
result_c = coordinator_agent.invoke({"request": request_c})
print(f"最终结果 C: {result_c}")
if __name__ == "__main__":
main()
使用 LangChain + OpenAI GPT 构建路由系统:
-
协调者 (coordinator):通过 LLM 将请求分类为
booker/info/unclear -
子处理器:三个模拟函数分别处理预订、信息查询、不明确请求
-
路由机制 :
RunnableBranch根据分类结果将请求委托给对应处理器用户请求 → [LLM 分类] → booker / info / unclear → [对应处理器] → 结果
代码利用 LangChain 和 GPT 构建了一个简单智能体系统。定义了 booking_handler、info_handler、unclear_handler 三个模拟子智能体处理器,分别处理不同类型请求。核心组件 coordinator_router_chain 通过 ChatPromptTemplate 指示语言模型将用户请求分类为 booker、info 或 unclear。RunnableBranch 根据分类结果将原始请求委托给对应处理函数。coordinator_agent 组合上述组件,先路由请求,再交由选定处理器,最终输出处理结果。
示例 2:Google ADK 实现
python
import uuid
from typing import Dict, Any, Optional
from dotenv import load_dotenv
from google.adk.agents import Agent
from google.adk.runners import InMemoryRunner
from google.adk.tools import FunctionTool
from google.genai import types
from google.adk.events import Event
load_dotenv()
# --- 定义工具函数 ---
def booking_handler(request: str) -> str:
"""
处理机票和酒店预订请求。
Args:
request: 用户的预订请求。
Returns:
预订处理确认信息。
"""
print("-------------------------- 预订处理器已调用 ----------------------------")
return f"已模拟处理预订请求:'{request}'。"
def info_handler(request: str) -> str:
"""
处理一般信息请求。
Args:
request: 用户问题。
Returns:
信息检索处理结果。
"""
print("-------------------------- 信息处理器已调用 ----------------------------")
return f"信息请求:'{request}'。结果:模拟信息检索。"
def unclear_handler(request: str) -> str:
"""处理无法委托的请求。"""
return f"协调者无法委托请求:'{request}'。请补充说明。"
# --- 创建工具 ---
booking_tool = FunctionTool(booking_handler)
info_tool = FunctionTool(info_handler)
# 定义配备工具的专用子智能体
booking_agent = Agent(
name="Booker",
model="gemini-2.0-flash",
description="专门处理机票和酒店预订请求,通过 booking tool 实现。",
tools=[booking_tool]
)
info_agent = Agent(
name="Info",
model="gemini-2.0-flash",
description="专门提供一般信息和答疑,通过 info tool 实现。",
tools=[info_tool]
)
# 定义父智能体(协调者),包含委托指令
coordinator = Agent(
name="Coordinator",
model="gemini-2.0-flash",
instruction=(
"你是主协调者,只负责分析用户请求并委托给合适的专用智能体。"
"不要直接回答用户。\n"
"- 任何涉及机票或酒店预订的请求,委托给 'Booker' 智能体。\n"
"- 其他一般信息问题,委托给 'Info' 智能体。"
),
description="负责将用户请求路由到正确专用智能体的协调者。",
sub_agents=[booking_agent, info_agent]
)
# --- 执行逻辑 ---
async def run_coordinator(runner: InMemoryRunner, request: str):
"""用给定请求运行协调者智能体并委托。"""
print(f"\n--- 协调者运行请求:'{request}' ---")
final_result = ""
try:
user_id = "user_123"
session_id = str(uuid.uuid4())
await runner.session_service.create_session(
app_name=runner.app_name, user_id=user_id, session_id=session_id
)
for event in runner.run(
user_id=user_id,
session_id=session_id,
new_message=types.Content(
role='user',
parts=[types.Part(text=request)]
),
):
if event.is_final_response() and event.content:
if hasattr(event.content, 'text') and event.content.text:
final_result = event.content.text
elif event.content.parts:
text_parts = [part.text for part in event.content.parts if part.text]
final_result = "".join(text_parts)
break
print(f"协调者最终响应:{final_result}")
return final_result
except Exception as e:
print(f"处理请求时发生错误:{e}")
return f"处理请求时发生错误:{e}"
async def main():
"""主函数,运行 ADK 示例。"""
print("--- Google ADK 路由示例(ADK Auto-Flow 风格)---")
print("注意:需安装并认证 Google ADK。")
runner = InMemoryRunner(coordinator)
result_a = await run_coordinator(runner, "帮我预订巴黎的酒店。")
print(f"最终输出 A: {result_a}")
result_b = await run_coordinator(runner, "世界最高的山峰是什么?")
print(f"最终输出 B: {result_b}")
result_c = await run_coordinator(runner, "说一个随机的事实。")
print(f"最终输出 C: {result_c}")
result_d = await run_coordinator(runner, "查找下个月飞往东京的航班。")
print(f"最终输出 D: {result_d}")
if __name__ == "__main__":
import nest_asyncio
import asyncio
nest_asyncio.apply()
asyncio.run(main())
Agent Development Kit(ADK)是用于工程化智能体系统的框架,提供结构化环境定义智能体能力与行为。与显式计算图架构不同,ADK 路由通常通过定义一组代表智能体功能的"工具"实现。用户查询由底层模型匹配到合适工具,框架内部自动完成路由。
使用 Google ADK 构建多智能体路由系统:
- 协调者智能体(Coordinator):分析请求并自动委托
- 子智能体 :Booker(预订)和 Info(信息),各自配备
FunctionTool - 路由机制 :ADK 的 Auto-Flow 根据
sub_agents的描述自动完成委托,无需显式编写分支逻辑
脚本包含一个主协调者智能体和两个专用子智能体。每个子智能体配备 FunctionTool,分别模拟预订和信息检索。协调者智能体的主要职责是分析用户消息并自动委托给 Booker 或 Info,ADK 的 Auto-Flow 机制会根据 sub_agents 自动完成委托。run_coordinator 函数设置 InMemoryRunner,创建用户和会话 ID,通过 runner 处理请求并提取最终响应文本。
两种实现的核心区别
LangChain 需要显式编写路由分支逻辑(RunnableBranch),而 ADK 通过智能体描述 + Auto-Flow 自动路由。
局限性
- 分类错误:路由器判断失误会导致请求进入错误的处理路径
- 维护成本:路径增多时,路由规则和处理器的维护复杂度上升
- 单层限制:简单路由只做一次分发,复杂场景可能需要多层路由或与其他模式结合
