代理系统设计模式

构建代理系统涉及协调 LLM 调用、数据检索和外部动作如何协同工作。 可以将代理系统的设计模式视为 复杂性和自主性的连续性:从 确定性链到可以做出动态决策的单代理系统(并可能涉及多个 LLM 调用的幕后),到协调多个专用 代理 的多 代理 体系结构。

工具调用

在深入了解设计模式之前,必须了解工具调用,这是一项基本功能,可在任何代理系统中使用,从简单到复杂。 工具调用是一种机制,允许代理系统与外部函数、数据源或服务进行交互。 这可以启用:

  • 实时数据查找,例如 SQL 查询、CRM 提取或矢量索引检索。
  • 执行发送电子邮件或更新记录等操作。
  • 通过 Python 函数或 API 进行任意逻辑或转换。

因此,工具调用提供了一种强大的机制,使 LLM“了解”外部数据或 API,无论选择哪种设计模式。

若要详细了解代理工具,请参阅 AI 代理工具

以下各节讨论了三种代理系统设计模式,每个模式都可以利用不同程度的工具调用。

比较第一代 AI 应用设计模式

第一代 AI 应用(代理)设计模式按复杂性顺序呈现。

设计模式 何时使用 优点 缺点
确定性链
  • 定义完善的任务
  • 静态管道,如基本 RAG
  • 无需进行实时决策
  • 非常简单
  • 易于审核
  • 死板
  • 需要更改代码才能适应
单代理系统
  • 处理同一领域中中等到复杂的查询
  • 在没有多个专用代理开销的情况下进行一些动态决策。
  • 灵活
  • 比多代理更简单
  • 良好的默认值
  • 可预测性较低
  • 注意防范重复或不正确的工具调用
多代理系统 大型或跨职能域;多个“专家”代理;不同的逻辑或聊天上下文;高级反射模式。
  • 高度模块化
  • 适用于大规模领域
  • 复杂的协调工作
  • 更难跟踪和调试

单代理系统

单代理系统具有一个协调的逻辑流(通常协调多个 LLM 调用)来处理传入请求。 代理可以:

  1. 接收请求,例如用户查询,以及任何相关的上下文信息,如对话历史记录。
  2. 分析如何做出最佳响应,并选择是否调用工具以获取外部数据或采取行动。
  3. 如果需要,请重复调用 LLM(和/或相同工具),直到达到目标或满足特定条件(例如接收有效数据或解决错误)。
  4. 将工具输出集成到对话中。
  5. 返回一个连贯的回应作为输出。

在许多用例中,一轮 LLM 推理(通常使用工具调用)就足够了。 但是,更高级的代理可以循环执行多个步骤,直到达到所需的结果。

即使只有“一个”代理,你仍然可以在后台进行多个 LLM 和工具调用(用于规划、生成、验证等),所有这些调用都由此单一统一流管理。

示例:技术支持助理

  • 如果用户提出一个简单的问题(“我们的返回策略是什么?”),代理可能会直接从 LLM 的知识做出响应。
  • 如果用户想要其订单状态,代理将调用函数 lookup_order(customer_id, order_id)。 如果该工具以“无效订单号”进行响应,代理可能会重试或提示用户输入正确的 ID,继续,直到提供最终答案。

何时使用

  • 你期望多样化的用户查询,但仍在一个统一的领域或产品范畴内。
  • 某些查询或条件可能保证工具的使用,例如决定何时提取客户数据。
  • 需要比确定性链更具灵活性,但不需要针对不同的任务使用单独的专用代理。

优点:

  • 代理可以通过选择要调用的工具(如果有)来适应新的或意外的查询。
  • 代理可以循环遍历重复的 LLM 调用或工具调用来优化结果 - 无需完全多代理设置。
  • 这种设计模式通常是企业用例的甜蜜点-比多代理设置更容易调试,同时仍允许动态逻辑和有限自治。

注意事项:

  • 与硬编码链相比,你必须防范重复或无效的工具调用。 (无限循环可能发生在任何工具调用方案中,因此设置迭代限制或超时。
  • 如果应用程序跨越了完全不同的子域(财务、devops、marketing 等),单个代理可能会变得笨拙或功能要求过载。
  • 你仍然需要精心设计的提示和约束来使代理保持专注和相关。

确定性链(硬编码步骤)

在此模式中,开发人员定义以何种顺序和参数调用哪些组件。 没有关于调用哪些工具或以何种顺序的动态决策。 系统遵循所有请求的预定义工作流,使其高度可预测。

通常称为“链”,流本质上是一个固定的步骤链,例如:

  1. 始终检索用户的请求,并从相关上下文的向量索引中检索。
  2. 将该上下文与用户的请求合并到最终 LLM 提示符。
  3. 调用 LLM 并返回响应。

示例:基本 RAG 链

基本 RAG 链的示意图。

确定性 RAG 链可能总是这样:

  1. 使用用户传入的请求,从向量索引中检索前k个结果。
  2. 将检索的区块格式化为提示模板(扩充)。
  3. 将扩充式提示传递给 LLM(生成)。
  4. 返回 LLM 的响应。

何时使用

  • 这适用于具有可预测工作流的明确定义任务。
  • 当一致性和审核是首要任务时。
  • 如果想要通过避免多次 LLM 调用以做出编排决策来最大程度地减少延迟。

优点:

  • 最高可预测性和可审核性。
  • 通常具有较低延迟(LLM 调用用于编排的次数更少)。
  • 更易于测试和验证。

注意事项:

  • 处理各种或意外请求的灵活性有限。
  • 随着逻辑分支的增长,可能会变得复杂且难以维护。
  • 可能需要进行重大重构才能适应新功能。

多代理系统

多代理系统涉及两个或多个专用代理,这些代理交换消息和/或协作处理任务。 每个代理都有自己的域或任务专业知识、上下文和可能不同的工具集。 单独的“协调器”(可能是另一个 LLM 或基于规则的路由器)将请求定向到相应的代理,或决定何时将请求从一个代理移交到另一个代理。

示例:具有专用代理的企业助手

  • 客户支持代理: 处理 CRM 查找、返回和发货。
  • 分析代理: 重点介绍 SQL 查询和数据汇总。
  • 监督器/路由器: 选择哪个代理最适合给定的用户查询,或何时切换。

每个子代理都可以在其自己的域中(例如 lookup_customer_accountrun_sql_query)内执行工具调用,这通常需要唯一的提示或对话历史记录。

何时使用

  • 你有不同的问题领域或技能集,如编码代理或财务代理。
  • 每个代理都需要访问会话历史记录或特定于域的提示。
  • 你有这么多工具,将它们全部拟合到一个代理的架构是不切实际的;每个代理都可以拥有子集。
  • 你想要在专门的智能体之间实现反思、评论或来回协作。

优点:

  • 这种模块化方法意味着每个代理都可以由单独的团队开发或维护,专门处理窄域。
  • 可以处理单个代理难以一致管理的大型复杂企业工作流。
  • 促进高级多步骤或多透视推理 - 例如,一个生成答案的代理,另一个代理验证答案。

注意事项:

  • 需要一种策略来在代理之间进行路由,并处理跨多个终结点的日志记录、跟踪和调试的开销。
  • 如果你有许多子代理和工具,则确定哪个代理有权访问哪些数据或 API 可能会变得复杂。
  • 如果未仔细约束,代理可以无限期地在相互之间推卸任务,而不解决任务。
    • 单代理工具调用中也存在无限循环风险,但多代理设置增加了另一层调试复杂性。

实用建议

无论选择哪种设计模式,请考虑以下用于开发稳定且可维护的代理系统的最佳做法。

  1. 简单开始: 如果只需要简单的链条,确定性链可以快速构建。
  2. 逐渐添加复杂性: 由于需要更多动态查询或灵活的数据源,请使用工具调用迁移到单代理系统。
  3. 转到多代理: 仅当您有明确区分的域或任务、多个对话上下文,或出于工具集过于庞大无法由单个代理提示的情况。

如果用例从小型开始(如简单的 RAG 链)以硬编码链开头。 随着需求的发展,可以为动态决策添加工具调用逻辑,甚至将任务细分为多个专用代理。 在实践中,许多实际代理系统将模式组合在一起。 例如,使用最确定性的链,但如果需要,LLM 可在单个步骤中动态调用某些 API。

马赛克 AI 代理框架 与你选择的任何模式无关,因此随着应用程序的发展,可以轻松改进设计模式。

开发指南

  • 提示
    • 保持提示清晰和最少,以避免矛盾的说明,分散信息,减少幻觉。
    • 仅提供代理所需的工具和上下文,而不是一组未绑定的 API 或大型无关上下文。
  • 日志记录和可观测性
    • 为每个用户请求、代理计划和工具调用实现详细的日志记录。 MLflow 跟踪等工具可以帮助捕获结构化日志进行调试。
    • 安全地存储日志,并注意对话数据中的个人身份信息(PII)。
  • 模型更新和版本锁定
    • 当提供程序在后台更新模型时,LLM 行为可能会改变。 使用版本固定和频繁的回归测试来确保代理逻辑保持可靠且稳定。
    • MLflow马赛克 AI 代理评估 相结合提供了一种简化的版本控制代理的方式,并定期评估质量和性能。

测试和迭代指南

  • 错误处理和回退逻辑
    • 规划应对工具或 LLM 故障。 超时、格式不正确的响应或空结果可能会中断工作流。 在高级功能失败时,包括重试策略、回退逻辑或更简单的回退链。
  • 迭代提示设计
    • 预期会随着时间的推移优化提示和链逻辑。 使用 Git 和 MLflow 对每次更改进行版本化控制,从而可以回滚或比较不同版本的性能。
    • 考虑 DSPy 等框架以编程方式优化代理系统中的提示和其他组件。

生产指南

  • 延迟与成本优化
    • 每增加一个额外的 LLM 或工具调用都会增加令牌消耗和响应时间。 尽可能合并步骤或缓存重复查询,以保持性能和成本可管理。
  • 安全和沙盒技术
    • 如果代理可以更新记录或运行代码,请对这些操作进行沙盒处理,或在必要时强制实施人工审批。 这在企业或受监管的环境中至关重要,以避免意外的伤害。
    • Databricks 建议使用 Unity Catalog 工具进行沙盒化执行。 请参阅 Unity 目录函数工具与代理代码工具。 Unity 目录可实现任意代码执行的隔离,并防止恶意执行者欺骗代理生成和运行干扰或窃听其他请求的代码。

通过遵循这些准则,可以缓解许多最常见的故障模式,例如工具错误调用、偏移 LLM 性能或意外成本峰值,以及构建更可靠、可缩放的代理系统。