构建高效的 AI 代理系统

题记:本文改编自 Anthropic 公司的研究报告《Building effective agents》。原文发表于 2024 年 12 月 20 日, 由 Erik Schluntz 和 Barry Zhang 撰写。本文对原文进行了翻译、整理和补充, 旨在为中文读者提供关于构建高效 AI 代理系统的实用指南。

过去一年里, Anthropic 与数十个团队合作, 帮助他们在各行各业中构建基于大语言模型 (LLM) 的 AI 代理系统。有趣的是, 最成功的实现往往并不依赖复杂的框架或专门的库, 而是采用简单、可组合的模式来构建。

这篇文章将分享 Anthropic 与客户合作以及自身构建代理系统的经验, 为开发者提供一些实用建议, 帮助他们构建高效的 AI 代理。

什么是 AI 代理?

“代理” 这个词可以有多种定义。有些客户将代理定义为完全自主的系统, 能够长期独立运行, 利用各种工具完成复杂任务。另一些则用这个词来描述更具规定性的实现, 遵循预定义的工作流程。Anthropic 将所有这些变体都归类为 “代理系统”, 但在架构上区分了 “工作流” 和 “代理”:

  • 工作流 是通过预定义的代码路径来编排 LLM 和工具的系统。
  • 代理 则是 LLM 能够动态指导自身流程和工具使用的系统, 自主控制如何完成任务。

接下来, 我们将详细探讨这两种类型的代理系统。在附录 1(“实践中的代理”) 中, 还描述了两个客户发现代理系统特别有价值的领域。

何时 (以及何时不) 使用代理

在构建基于 LLM 的应用时, 建议先寻找最简单的解决方案, 只有在必要时才增加复杂性。这可能意味着根本不需要构建代理系统。代理系统通常会牺牲延迟和成本来换取更好的任务表现, 开发者需要考虑这种权衡是否合理。

当确实需要更复杂的系统时, 工作流为定义明确的任务提供了可预测性和一致性, 而代理则更适合需要灵活性和模型驱动决策的大规模场景。不过, 对于许多应用来说, 仅仅通过检索和上下文示例来优化单个 LLM 调用通常就足够了。

何时以及如何使用框架

市面上有许多框架可以简化代理系统的实现, 包括:

  • LangChain 的 LangGraph;
  • 亚马逊 Bedrock 的 AI Agent 框架;
  • Rivet, 一个拖放式 GUI LLM 工作流构建器;
  • Vellum, 另一个用于构建和测试复杂工作流的 GUI 工具。

这些框架通过简化调用 LLM、定义和解析工具、链接调用等标准低级任务, 使入门变得容易。然而, 它们往往会创建额外的抽象层, 掩盖底层的提示和响应, 使调试变得更加困难。它们还可能诱使开发者在简单设置就足够的情况下增加不必要的复杂性。

建议开发者从直接使用 LLM API 开始: 许多模式只需几行代码就能实现。如果确实使用了框架, 请确保理解底层代码。对底层实现的错误假设是客户常见的错误来源。

可以参考 Anthropic 的 cookbook 获取一些示例实现。

构建模块、工作流和代理

在这一部分, 我们将探讨在生产环境中常见的代理系统模式。我们将从基础构建模块——增强型 LLM 开始, 逐步增加复杂性, 从简单的组合工作流到自主代理。

构建模块: 增强型 LLM

代理系统的基本构建模块是经过增强的 LLM, 具备检索、工具使用和记忆等能力。当前的模型可以主动使用这些能力——生成自己的搜索查询、选择适当的工具, 并决定保留哪些信息。

img

增强型 LLM

建议重点关注实现的两个关键方面: 根据具体用例定制这些能力, 并确保它们为 LLM 提供易用、文档完善的接口。虽然有多种方式可以实现这些增强功能, 但一种方法是通过 Anthropic 最近发布的 模型上下文协议(MCP), 它允许开发者通过简单的 客户端实现 与不断增长的第三方工具生态系统集成。

在本文的其余部分, 我们将假设每个 LLM 调用都能访问这些增强功能。

提示链工作流

提示链将任务分解为一系列步骤, 每个 LLM 调用处理前一个调用的输出。可以在任何中间步骤添加程序化检查 (见下图中的 “门控”), 以确保流程仍在正轨上。

img

提示链工作流

何时使用此工作流: 当任务可以轻松、清晰地分解为固定的子任务时, 这种工作流最为理想。主要目标是通过牺牲延迟来换取更高的准确性, 因为每个 LLM 调用都变成了一个更简单的任务。

提示链有用的例子:

  • 生成营销文案, 然后将其翻译成不同语言。
  • 写一份文档大纲, 检查大纲是否符合某些标准, 然后基于大纲撰写文档。

路由工作流

路由对输入进行分类, 并将其导向专门的后续任务。这种工作流允许关注点分离, 并构建更专门化的提示。如果没有这种工作流, 为一种输入优化可能会损害其他输入的性能。

img

路由工作流

何时使用此工作流: 当复杂任务有明显的不同类别需要分别处理, 并且分类可以由 LLM 或更传统的分类模型 / 算法准确处理时, 路由工作得很好。

路由有用的例子:

  • 将不同类型的客户服务查询 (一般问题、退款请求、技术支持) 导向不同的下游流程、提示和工具。
  • 将简单 / 常见问题路由到较小的模型 (如 Claude 3.5 Haiku), 将困难 / 不寻常的问题路由到更强大的模型 (如 Claude 3.5 Sonnet), 以优化成本和速度。

并行化工作流

LLM 有时可以同时处理一个任务, 然后以编程方式汇总它们的输出。这种工作流, 即并行化, 主要有两种变体:

  • 分段: 将任务分解为并行运行的独立子任务。
  • 投票: 多次运行相同的任务以获得多样化的输出。

img

并行化工作流

何时使用此工作流: 当分割的子任务可以并行化以提高速度, 或者需要多个视角或尝试来获得更高置信度的结果时, 并行化是有效的。对于涉及多个考虑因素的复杂任务, LLM 通常在每个考虑因素由单独的 LLM 调用处理时表现更好, 允许对每个特定方面进行集中注意。

并行化有用的例子:

  • 分段:
    • 实现防护措施, 其中一个模型实例处理用户查询, 而另一个筛选不当内容或请求。这往往比让同一个 LLM 调用同时处理防护措施和核心响应表现更好。
    • 自动化评估 LLM 性能的评估, 其中每个 LLM 调用评估模型在给定提示上的不同方面的表现。
  • 投票:
    • 审查代码中的漏洞, 多个不同的提示审查代码并在发现问题时标记。
    • 评估给定内容是否不当, 多个提示评估不同方面或要求不同的投票阈值来平衡假阳性和假阴性。

编排器 - 工作者工作流

在编排器 - 工作者工作流中, 一个中央 LLM 动态分解任务, 将它们委派给工作者 LLM, 并综合他们的结果。

img

编排器 - 工作者工作流

何时使用此工作流: 这种工作流非常适合无法预测所需子任务的复杂任务 (例如, 在编码中, 需要更改的文件数量和每个文件中更改的性质可能取决于具体任务)。虽然在拓扑结构上与并行化相似, 但关键区别在于其灵活性——子任务不是预定义的, 而是由编排器根据具体输入确定的。

编排器 - 工作者有用的例子:

  • 每次都需要对多个文件进行复杂更改的编码产品。
  • 涉及从多个来源收集和分析信息以寻找可能相关信息的搜索任务。

评估器 - 优化器工作流

在评估器 - 优化器工作流中, 一个 LLM 调用生成响应, 而另一个在循环中提供评估和反馈。

img

评估器 - 优化器工作流

何时使用此工作流: 当我们有明确的评估标准, 并且迭代改进能提供可衡量的价值时, 这种工作流特别有效。适合使用的两个标志是: 首先, 当人类表达反馈时, LLM 的响应可以明显改进; 其次, LLM 能够提供这样的反馈。这类似于人类作者在产生精炼文档时可能经历的迭代写作过程。

评估器 - 优化器有用的例子:

  • 文学翻译, 其中有一些翻译 LLM 最初可能无法捕捉的细微差别, 但评估器 LLM 可以提供有用的批评。
  • 复杂的搜索任务, 需要多轮搜索和分析来收集全面信息, 评估器决定是否需要进一步搜索。

代理

随着 LLM 在关键能力上的成熟(如理解复杂输入、进行推理和规划、可靠使用工具以及从错误中恢复等),代理正在生产环境中崭露头角。代理通过与人类用户的命令或交互讨论开始工作。一旦任务明确, 代理就会独立规划和操作, 必要时可能会回到人类那里寻求进一步信息或判断。在执行过程中, 代理必须在每一步从环境中获得 “基本事实”(如工具调用结果或代码执行) 以评估其进展。然后, 代理可以在检查点或遇到障碍时暂停以获取人类反馈。任务通常在完成时终止, 但也常常包括停止条件 (如最大迭代次数) 以保持控制。

代理可以处理复杂的任务, 但它们的实现往往很简单。它们通常只是基于环境反馈在循环中使用工具的 LLM。因此, 清晰、周到地设计工具集及其文档至关重要。我们在附录 2(“工具的提示工程”) 中详细阐述了工具开发的最佳实践。

img

自主代理

何时使用代理: 代理可用于难以或无法预测所需步骤数量的开放性问题, 以及无法硬编码固定路径的情况。LLM 可能会运行多个回合, 你必须对其决策有一定程度的信任。代理的自主性使其非常适合在受信任环境中扩展任务。

代理的自主性意味着更高的成本, 以及潜在的累积错误。建议在沙盒环境中进行广泛测试, 并配备适当的防护措施。

代理有用的例子:

以下是 Anthropic 实现的一些例子:

img

编码代理的高级流程

组合和定制这些模式

这些构建模块并非强制性的。它们是开发者可以塑造和组合以适应不同用例的常见模式。与任何 LLM 功能一样, 成功的关键在于衡量性能并迭代实现。再次强调: 只有在明确改善结果时, 才应该考虑增加复杂性。

总结

在 LLM 领域取得成功并不在于构建最复杂的系统, 而在于为你的需求构建 “正确” 的系统。从简单的提示开始, 通过全面评估来优化它们, 只有当更简单的解决方案不足以满足需求时, 才添加多步骤的代理系统。

在实现代理时, 尽量遵循三个核心原则:

  1. 保持代理设计的 简单性
  2. 通过明确展示代理的规划步骤来优先考虑 透明度
  3. 通过彻底的工具文档编写和测试, 仔细设计你的代理 - 计算机接口 (ACI)。

框架可以帮助你快速入门, 但在转向生产环境时, 不要犹豫减少抽象层并使用基本组件构建。遵循这些原则, 你可以创建不仅强大, 而且可靠、可维护、并能赢得用户信任的代理。

附录 1: 实践中的代理

Anthropic 与客户的合作揭示了两个特别有前景的 AI 代理应用, 展示了上述模式的实际价值。这两个应用都说明了代理如何为既需要对话又需要行动、有明确成功标准、能够实现反馈循环, 并整合有意义的人类监督的任务增加最大价值。

A. 客户支持

客户支持将熟悉的聊天机器人界面与通过工具集成增强的能力相结合。这非常适合更开放式的代理, 因为:

  • 支持互动自然遵循对话流程, 同时需要访问外部信息和执行操作;
  • 可以集成工具来获取客户数据、订单历史和知识库文章;
  • 可以通过程序化方式处理发放退款或更新工单等操作;
  • 可以通过用户定义的解决方案清晰地衡量成功。

几家公司通过基于使用的定价模型展示了这种方法的可行性, 他们只对成功解决的问题收费, 显示了对其代理效果的信心。

B. 编码代理

软件开发领域展现了 LLM 功能的巨大潜力, 能力从代码补全演变到自主问题解决。代理在这里特别有效, 因为:

  • 代码解决方案可以通过自动化测试进行验证;
  • 代理可以使用测试结果作为反馈来迭代解决方案;
  • 问题空间定义明确且结构化;
  • 输出质量可以客观衡量。

在 Anthropic 自己的实现中, 代理现在可以仅基于拉取请求描述解决 SWE-bench Verified 基准测试中的真实 GitHub 问题。然而, 尽管自动化测试有助于验证功能, 人工审查仍然对确保解决方案符合更广泛的系统要求至关重要。

附录 2: 工具使用的提示工程

无论你构建的是哪种代理系统, 工具很可能是你代理的重要组成部分。工具 使 Claude 能够通过在 Anthropic 的 API 中指定其确切结构和定义来与外部服务和 API 交互。当 Claude 响应时, 如果它计划调用工具, API 响应中将包含一个 工具使用块。工具定义和规范应该得到与整体提示一样多的提示工程关注。在这个简短的附录中, 我们描述了如何对你的工具进行提示工程。

通常有几种方法可以指定相同的操作。例如, 你可以通过编写差异或重写整个文件来指定文件编辑。对于结构化输出, 你可以在 markdown 或 JSON 内返回代码。在软件工程中, 这些差异是表面的, 可以无损地从一种转换为另一种。然而, 有些格式对 LLM 来说比其他格式更难写。编写差异需要在写新代码之前知道块头中有多少行在变化。在 JSON 中编写代码 (相比于 markdown) 需要额外转义换行符和引号。

对决定工具格式的建议如下:

  • 给模型足够的标记来 “思考”, 以免它将自己写入死角。
  • 保持格式接近模型在互联网上自然出现的文本。
  • 确保没有格式 “开销”, 比如必须保持对数千行代码的准确计数, 或对它写的任何代码进行字符串转义。

一个经验法则是考虑人机界面 (HCI) 需要投入多少努力, 并计划在创建良好的代理 - 计算机界面 (ACI) 上投入同样多的努力。以下是一些如何做到这一点的想法:

  • 站在模型的角度思考。基于描述和参数, 使用这个工具是否显而易见, 还是你需要仔细思考? 如果是后者, 那么对模型来说可能也是如此。一个好的工具定义通常包括使用示例、边缘情况、输入格式要求, 以及与其他工具的明确界限。
  • 你如何更改参数名称或描述以使事情更明显? 把这想象成为你团队中的初级开发人员写一个很棒的文档字符串。这在使用许多相似工具时尤其重要。
  • 测试模型如何使用你的工具: 在 Anthropic 的 工作台 中运行许多示例输入, 看看模型犯了什么错误, 然后迭代。
  • 对你的工具进行 防错 设计。更改参数, 使其更难犯错误。

在构建 SWE-bench 代理时, Anthropic 实际上花在优化工具上的时间比优化整体提示还多。例如, 他们发现当代理移出根目录后, 模型在使用相对文件路径的工具时会犯错误。为了解决这个问题, 他们更改了工具, 始终要求使用绝对文件路径——他们发现模型完美地使用了这种方法。

结语

构建高效的 AI 代理系统是一门艺术, 需要平衡简单性和功能性。从基本的增强型 LLM 开始, 逐步探索更复杂的工作流和自主代理, 每一步都应该基于实际需求和性能评估。记住, 最佳解决方案并不总是最复杂的那个, 而是最适合你特定用例的那个。

通过仔细设计工具、优化工作流程, 并在必要时引入自主代理, 你可以创建既强大又可靠的 AI 系统。无论是改善客户支持还是推动软件开发, AI 代理都展现了巨大的潜力。但关键在于始终保持批判性思考, 不断测试和迭代, 确保你的系统不仅智能, 而且值得信赖。

随着 AI 技术的不断发展, 我们期待看到更多创新的代理系统应用。希望这篇文章能为你在这个领域中的探索提供有价值的指导。记住, 在 AI 的世界里, 最好的系统往往是那些既能发挥技术优势, 又能与人类智慧无缝协作的系统。

comments powered by Disqus