路由:Agent能够根据条件动态决定工作流的下一步

我们实际做Agent开发的时候,并不是像之前那样提示词链进行顺序处理执行线性工作流。现实环境往往更复杂,我们有很多Agent子系统,需要动态决策,到底当前使用哪个Agent子系统,用哪个工具函数、工具或者子流程。这种动态决策是通过路由实现的。

文章目录

举例

一个设计用于客户查询的Agent,当配备路由功能时,可以首先对传入查询进行分类确定用户的意图。基于此分类,它可以将查询定向到专门的Agent进行直接回答、用于账户信息的数据库检索工具,或用于复杂问题的升级程序,而不是默认使用单一的预定响应路径。

因此,使用复杂的Agent可以:

  • 分析用户的查询
  • 基于其 意图 路由查询:
    • 如果意图是"检查订单状态",路由到与订单数据库交互的子Agent
    • 如果意图是"产品信息",路由到搜索产品目录的子Agent或链
    • 如果意图是"技术支持",路由到访问故障排除指南
    • 如果意图不清楚,路由到澄清子Agent或提示词链

实际应用

路由模式是自适应Agent系统设计中的关键控制机制。

在人机交互中,例如虚拟助手或AI驱动导师,路由用于解释用户意图。对自然语言查询的初始分析确定后续的操作,无论是调用特定信息检索工具、升级到人工操作员,还是根据用户表现选择课程中的上下模块。在涉及多个专门工具或Agent的复杂系统中,路由充当高级调度器。类似地,AI编码助手使用路由来识别编程语言和用户意图------调试、解释或翻译----然后将代码片段传递到正确的专门工具。

最终,路由提供了创建功能多样化和上下文感知系统所需的逻辑仲裁能力。他将Agent从预定义序列的静态执行器转变为在可变条件下就完成任务的最有效任务做出决策的动态系统。

python 复制代码
import os

from langchain_community.chat_models import ChatTongyi
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough, RunnableBranch
os.environ["DASHSCOPE_API_KEY"] = "sk-xxx"
###路由的案例
try:
    llm = ChatTongyi(model="qwen-turbo-2025-04-28")
    print(f"llm已经初始化:{llm}")
except Exception as e:
    print(f"初始化模型失败:{e}")
    llm = None


## --- 定义模拟子 Agent 处理程序(相当于 ADK 的 sub_agents)---
def booking_handler(request: str) -> str:
    """模拟预订 Agent 处理请求。"""
    print("\n--- 委托给预订处理程序 ---")
    return f"预订处理程序处理了请求:'{request}'。结果:模拟预订操作。"


def info_handler(request: str) -> str:
    """模拟信息 Agent 处理请求。"""
    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 的基于 sub_agents 的自动流)---
## 使用 RunnableBranch 根据路由链的输出进行路由。
## 为 RunnableBranch 定义分支
branches = {
    "booker": RunnablePassthrough.assign(
        output=lambda x: booking_handler(x["request"])
    ),
    "info": RunnablePassthrough.assign(
        output=lambda x: info_handler(x["request"])
    ),
    "unclear": RunnablePassthrough.assign(
        output=lambda x: unclear_handler(x["request"])
    ),
}


## 创建 RunnableBranch。它接受路由链的输出
## 并将原始输入('request')路由到相应的处理程序。
delegation_branch = RunnableBranch(
    (lambda x: x['decision'].strip() == 'booker', branches["booker"]),  # 添加了 .strip()
    (lambda x: x['decision'].strip() == 'info', branches["info"]),  # 添加了 .strip()
    branches["unclear"]  # 'unclear' 或任何其他输出的默认分支
)

## 将路由链和委托分支组合成单个可运行对象
## 路由链的输出('decision')与原始输入('request')一起传递
## 到 delegation_branch。
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()

代码提供了一个协调器,根据请求的意图(预定、信息、不清楚)将用户请求路由到不同模拟子Agent处理程序。系统使用语言模型对请求进行分类,然后将其委托给适当的处理函数,模拟多Agent架构中常用的基本委托模式。

路由模式的核心组件是执行评估并指导流程的机制,这种机制除了上面的语言模型进行分类,还可以通过如下方式:

  • 基于LLM路由
  • 基于嵌入的路由
  • 基于规则的路由
  • 基于机器学习模型的路由

核心

在这里我们会发现,LLM不是用来干活的,而是用来判断让谁干活的!

python 复制代码
coordinator_router_prompt = ChatPromptTemplate.from_messages([
    ("system", """分析用户的请求并确定哪个专家处理程序应处理它。
     ...
     只输出一个词:'booker'、'info' 或 'unclear'。"""),
    ("user", "{request}")
])

RunnableBranch = if / elif / else:

python 复制代码
if decision == "booker":
    用 booking_handler
elif decision == "info":
    用 info_handler
else:
    用 unclear_handler

LangChain 写法是:

复制代码
delegation_branch = RunnableBranch(
    (lambda x: x['decision'].strip() == 'booker', branches["booker"]),
    (lambda x: x['decision'].strip() == 'info', branches["info"]),
    branches["unclear"]
)

你可以暂时无视 RunnableBranch 的写法

把它当成一个"高级 if-else"

我们也可以用Google 推出的Google ADK来实现这个路由,这里就不具体展示了。

相关推荐
Felaim2 小时前
【自动驾驶基础】LDM(Latent Diffusion Model) 要点总结
人工智能·机器学习·自动驾驶
科技快报2 小时前
昇思人工智能框架峰会 | 昇思MindSpore MoE模型性能优化方案,提升训练性能15%+
人工智能·性能优化
式5162 小时前
量子力学基础(二)狄拉克符号与复数向量空间
人工智能·算法·机器学习
视觉&物联智能2 小时前
【杂谈】-人工智能:助力护士回归人文关怀,而非取而代之
人工智能·深度学习·ai·aigc·agi
Gavin在路上2 小时前
AI学习之稀疏 MoE+Transformer架构
人工智能·学习·transformer
chenmingwei0002 小时前
RT-1: ROBOTICS TRANSFORMERFOR REAL-WORLD CONTROL AT SCALE
人工智能
Carl_奕然3 小时前
人工智能的幻觉问题:机理、挑战与缓解策略
人工智能·语言模型
独自归家的兔3 小时前
通义千问3-VL-Plus - 界面交互(本地图片改进)
java·人工智能·交互
LitchiCheng3 小时前
Mujoco 使用 Pinocchio 进行逆动力学及阻抗力矩控制维持当前位置
人工智能·python