Build Efficient Agents——Anthropic团队

在过去的一年里,Anthropic团队(后面简称“团队”)与来自各行各业的团队合作,开发了基于LLM的智能体。结果显示,最成功的实现方式并非依赖复杂的框架或专门的库,而是采用简单、可组合的模式进行构建。

团队将通过这篇文章分享从客户合作和自身智能体构建中获得的经验,并为开发者提供构建高效智能体的实用建议。

原文链接:Building effective agents  Anthropic

什么是智能体(Agent)?

“智能体”可以有多种定义。有些客户将智能体定义为完全自主的系统,这些系统能够在较长时间内独立运行,使用各种工具完成复杂任务。而另一些客户则将智能体描述为遵循预定义工作流的更具指导性的实现。

在Anthropic,团队将这些变体统称为[智能体系统],但在架构上,他们在工作流和智能体之间划分了一个重要的区别:

  • 工作流:是指通过预定义的代码路径对LLM和工具进行编排的系统。
  • 智能体:是指LLM动态指挥其自身的流程和工具使用的系统,并保持对任务完成方式的控制权。

在下面的部分中,本文将详细探讨这两种类型的智能体系统。在原文附录1(“实践中的智能体”)中将描述客户发现这些系统特别有价值的两个领域。

何时使用(或不使用)智能体

在使用LLM构建应用程序时,建议尽可能选择简单的解决方案,只有在必要时才增加复杂性。因此,某些情况下可能完全不需要构建智能体系统。

智能体系统通常需要在延迟和成本上做出妥协,以换取更高的任务性能。在决定使用智能体之前,需要仔细评估这种权衡是否值得。

任务复杂性较高时,工作流可以为明确的任务提供稳定性和一致性,而在需要灵活性以及大规模[模型驱动]决策的场景中,智能体则是更好的选择。

然而,对于多数应用场景,通过检索和上下文示例优化单次LLM调用通常已经足以满足需求。

何时以及如何使用框架

目前有多种框架可以简化智能体系统的实现,包括:

  • LangGraph([LangChain]提供的工具),
  • 亚马逊BedrockAI Agent框架
  • [Rivet],一个拖放式的[GUI]工具,用于构建LLM工作流,
  • [Vellum],另一款支持构建和测试复杂工作流的GUI工具。

这些框架通过处理底层的常规任务(如调用LLM、定义和解析工具、链式调用等),大大降低了开发难度。然而,它们也会增加额外的抽象层,可能掩盖提示词和响应的实际逻辑,从而增加调试难度。此外,这些框架可能让开发者倾向于引入不必要的复杂性,而简单的实现方式可能已经足够。

建议开发者优先直接使用LLM的[API],许多功能可以通过简单的几行代码实现。如果选择使用框架,务必确保理解底层的实现逻辑,因为对底层机制的错误假设往往是开发中的主要问题之一。

有关具体的实现示例,请参考[Anthropic的相关手册]。

构建模块、工作流与智能体

本章将介绍生产环境中智能体系统的常见[设计模式]。从基础构建模块——增强型LLM开始,逐步扩展至复杂度更高的组合工作流和完全自主的智能体。

构建模块:增强型LLM

智能体系统的核心构建模块是增强型LLM,它结合了检索(Retrieval)工具使用(Tools)以及记忆(Memory)等功能。目前的模型能够主动利用这些能力,例如生成搜索查询、选择适合的工具以及确定需要保存的重要信息。

img

图1:增强型LLM

在实际应用中,应重点关注两个方面:一是根据具体的业务场景对这些功能进行定制化;二是确保为LLM提供一个简洁且文档完善的接口。

实现这些增强功能的方法有多种,其中之一是利用最新发布的模型上下文协议(Model Context Protocol),通过这一协议,开发者可以使用简单的客户端集成到不断扩展的第三方工具生态系统中。

在后续内容中,将默认每次LLM调用都可访问上述增强功能。

工作流:提示词链式调用

提示词链式调用是一种将任务分解为一系列步骤的流程,其中每次LLM调用都会基于上一步的输出进行处理。在流程的任意中间步骤,可以加入程序化检查(如图2中的“门控”所示),以确保流程按照预期顺利推进。

img

图2:提示词链式调用的工作流

适用场景:这种工作流适合那些可以被清晰分解为固定子任务的场景。其核心目标是在延迟与更高的准确性之间找到平衡,通过简化每次LLM调用的复杂度来提升整体效果。

提示词链式调用的典型应用示例

  • 生成营销文案并将其翻译为其他语言。
  • 撰写文档的大纲,验证大纲是否符合特定标准,再基于大纲撰写完整文档。

工作流:路由

路由是一种将输入分类并引导到特定后续任务的工作流。这种方法能够有效地分离关注点,便于针对不同输入类型设计更专业的提示词。如果不使用路由,优化某一类型输入时可能会影响其他输入的性能。

img

图3:路由工作流

适用场景:路由适合处理复杂任务,尤其是当任务包含可分别处理的不同类别,并且可以通过LLM或传统[分类模型]/算法准确完成分类时。

路由的典型应用示例

  • 将不同类型的客户服务请求(如常规问题、退款申请、技术支持)分别引导至对应的下游流程、提示词或工具。
  • 将简单或常见问题分配给较小的模型(如[Claude] 3.5 Haiku),将复杂或罕见问题分配给更强大的模型(如Claude 3.5 Sonnet),从而平衡成本与响应速度。

工作流:并行化

并行化是一种让LLM同时处理任务并通过程序汇总输出的工作流。这种方式通常有两种实现形式:

  • 分块:将任务拆分为相互独立的子任务,并行执行。
  • 投票:对同一任务运行多次,以获得多样化的视角或结果。
img

图4:并行化工作流

适用场景:当任务能够被分解成独立子任务以提升速度,或者需要通过多次尝试来增强结果[置信度]时,并行化是一种高效的工作流。对于涉及多个考量的复杂任务,让LLM分别处理每个考量,可以更专注地关注各自的具体内容,从而提升整体性能。

并行化的典型应用示例

  • 分块
    • 实现防护机制:一个模型实例负责回答用户查询,另一个实例同时筛查不适当内容或请求。将防护和核心任务分离处理的效果通常优于单一调用。
    • 自动化性能评估:在评估LLM表现时,每次调用分别评估模型对特定提示词的不同性能维度。
  • 投票
    • 代码漏洞审查:利用多个提示词从不同角度审查代码是否存在漏洞,并标记出潜在问题。
    • 内容适当性评估:通过多个提示词从不同角度对内容进行评估,并设定投票机制,如不同的通过门槛,以平衡误报与漏报的风险。

工作流:协调器-工作者

协调器-工作者工作流由一个中心LLM负责,它根据任务动态分解子任务,分派给多个工作者LLM处理,并最终整合所有工作者的结果。

img

图5:协调器-工作者工作流

适用场景:这种工作流非常适合处理无法预先确定子任务的复杂场景。例如,在编程任务中,需修改的文件数量及其具体修改内容通常取决于任务的具体要求。与并行化工作流类似,协调器-工作者的区别在于灵活性:子任务不是事先规划好的,而是由协调器根据输入动态生成。

协调器-工作者的典型应用示例

  • 编程工具:支持对多个文件进行复杂修改的任务,动态调整每个文件的修改内容。
  • 搜索任务:从多个信息来源中动态收集、分析数据,并提取最相关的信息。

工作流:评估器-优化器

评估器-优化器工作流通过一个LLM生成响应,另一个LLM对其进行评估并提供反馈,形成一个迭代循环。

img

图6:评估器-优化器工作流

适用场景:当任务有明确的评估标准且迭代优化能够显著提高质量时,这种工作流效果尤为突出。两个关键特征是:第一,LLM生成的响应在获得明确反馈后能够显著改进;第二,LLM可以自动生成这样的反馈。这种流程类似于人类作家通过多次修改完善文档的过程。

评估器-优化器的典型应用示例

  • 文学翻译:在翻译复杂文学作品时,翻译LLM可能无法初步捕捉其中的细微差别,而评估器LLM可以提供精准的修改建议。
  • 复杂搜索任务:在需要多轮搜索和分析的场景下,评估器判断当前信息是否足够全面,并决定是否需要进一步搜索和优化。

智能体

随着LLM在理解复杂输入、推理与规划、工具使用的可靠性以及错误恢复能力方面不断进步,智能体在实际应用中逐渐普及。智能体的工作通常从用户指令或交互式讨论开始。在任务明确后,智能体独立规划并执行任务,并可能在执行过程中再次向用户寻求信息或判断支持。在运行过程中,智能体需要在每一步从环境中获取“真实情况”(如工具调用或代码执行的结果)来评估进展。在某些节点或遇到阻碍时,智能体可以暂停并等待用户的反馈。任务的终止条件可以是完成任务目标,也可以通过设置最大迭代次数等机制来确保运行受控。

尽管智能体能够处理复杂任务,其实现方式通常较为简单,主要通过LLM基于环境反馈循环调用工具。因此,清晰设计并精心文档化的工具集对于智能体的成功运行至关重要。有关工具开发的详细建议,请参阅附录2(“工具的提示词工程”)。

img

图7:自主智能体

适用场景:自主智能体适合处理开放式问题,尤其是那些难以预测所需步骤或无法通过硬编码预设路径的任务。在这些场景中,LLM可能需要经过多轮交互完成任务,因此需要对其决策能力有足够的信任。自主智能体非常适合在可信环境中扩展任务。

自主智能体的高自主性同时伴随着更高的运行成本以及累积错误的潜在风险。因此,在部署前应在[沙盒]环境中进行充分测试,并设置适当的防护机制。

典型应用示例

  • 编程智能体:处理SWE-bench任务,根据任务描述对多个文件进行复杂编辑。
  • “计算机使用”参考实现:智能体(如Claude)通过与计算机交互完成复杂任务,如数据处理或信息检索。
img

图8:编码智能体的High-Level工作流

结合与定制这些模式

这些构建模块并非固定流程,而是开发者可以根据具体需求灵活调整和组合的常见设计模式。成功的关键在于不断衡量系统性能,并迭代改进实现方案。

请记住,仅在复杂性能显著提升结果时才应考虑引入更复杂的设计

总结

在LLM应用中,成功的关键不在于打造最复杂的系统,而在于找到适合自身需求的最佳方案。从简单的提示词开始,通过全面评估优化其效果,仅当简单方法不足以满足需求时再考虑引入多步骤智能体系统。

在构建智能体时,应遵循以下三项核心原则:

  1. 保持简洁性:设计尽量简单,避免不必要的复杂化。
  2. 注重透明性:通过清晰展示智能体的规划步骤,增加系统的可理解性。
  3. 优化接口设计:通过完善的工具文档和全面测试,精心设计智能体与计算机的交互接口。

框架可以帮助快速实现初步功能,但在生产环境中,逐步减少抽象层并基于基础组件进行构建更为可靠。遵循这些原则,您将能够打造强大、可靠且易于维护的智能体系统,同时赢得用户的信任。


附录1:智能体的实际应用

通过与客户合作,团队发现智能体在两个领域中展现出显著的应用潜力,这些领域也清晰地体现了智能体模式的实际价值。这些应用表明,智能体特别适用于以下场景:需要兼顾对话与操作有明确的成功标准支持反馈机制,并能有效结合人类监督

A. 客户支持

客户支持结合了聊天机器人界面的直观性与工具集成后的增强能力,是开放式智能体的理想应用场景。原因包括:

  • 客户支持交互既需要自然的对话流程,也需要访问外部信息和完成任务;
  • 智能体可以集成工具,用于提取客户数据、查询订单记录、访问知识库内容;
  • 操作(如退款处理或工单更新)可以通过自动化程序高效完成;
  • 成功标准清晰,可通过客户问题的解决情况进行衡量。

一些公司已通过“基于成功解决的计费模式”验证了这一方法的可行性,这种模s式仅对成功完成问题的智能体任务收费,充分展现了对其可靠性的信心。

B. 编程智能体

在软件开发领域,LLM功能从代码补全演变为自主问题解决,为智能体提供了广阔的应用前景。智能体在此领域的优势包括:

  • 代码解决方案可以通过[自动化测试]直接验证其正确性;
  • 测试结果为智能体提供反馈,帮助其反复优化解决方案;
  • 编程问题通常具有清晰的定义和结构化特征;
  • 输出质量可以通过客观的标准(如测试通过率)进行评价。

在团队的实现中,智能体能够基于拉取请求描述,在[SWE-bench Verified]基准测试中解决实际的[GitHub]问题。然而,尽管自动化测试能够验证功能实现,确保解决方案与系统的整体需求一致仍需要人类审查的参与,以提升质量控制。

附录2:工具的提示词工程

在智能体系统的构建中,工具往往是关键组成部分之一。通过API定义的工具使Claude能够与外部服务交互。当Claude需要调用工具时,API响应中会包含一个特定的工具调用部分。因此,工具的定义与规范设计应像整体提示词工程一样受到重视。以下是提示词工程在工具设计中的一些要点。

通常,同一操作可以有多种定义方式。例如,文件编辑既可以通过编写差异来实现,也可以通过重写整个文件完成。而对于结构化输出,代码既可以嵌入markdown中,也可以用JSON格式返回。虽然这些在软件工程中属于可互相转换的格式,但对LLM而言,某些格式生成起来更加复杂。例如,编写差异需要在生成代码前准确计算变化的行数;而将代码嵌入JSON则需要对换行符和引号进行额外的转义。

以下是选择工具格式时的一些建议:

  • 留有余地:为模型提供足够的tokens,让其有“思考空间”,避免写入死胡同。
  • 贴近自然:选择与模型在互联网上常见的格式相似的形式。
  • 简化负担:避免让模型处理额外的格式复杂度,例如大规模行计数或代码转义。

智能体与计算机接口([ACI])的优化建议

与设计人机交互(HCI)同样重要,ACI的设计也需要足够的投入。以下是具体优化方法:

  1. 站在模型的角度思考 确保工具描述和参数定义清晰易懂。一个优秀的工具定义应包括使用示例、特殊情况说明、输入格式要求,以及与其他工具的明确界限。
  2. 优化参数设计 参数名称和描述应清晰直观,便于理解。可以将其视为为团队中的新手开发者撰写注释文档,尤其是在多个类似工具共存时,这一点尤为重要。
  3. 测试并迭代 使用工作台运行大量示例输入,观察模型的错误表现,并逐步优化工具设计,确保可靠性。
  4. 防错设计(Poka-yoke) 通过调整参数或设计限制,降低模型犯错的可能性。例如,将工具参数限制为绝对路径而非相对路径,可有效避免路径错误。

在为[SWE-bench]构建智能体时,团队发现优化工具的重要性甚至超过了整体提示词。例如,他们发现模型在使用相对路径的工具时容易出错,特别是智能体从[根目录]切换到其他目录后。通过调整工具以要求使用绝对路径,模型显著提高了任务完成的准确性。


Build Efficient Agents——Anthropic团队
https://linxkon.github.io/Build_Efficient_Agents-Anthropic.html
作者
linxkon
发布于
2024年12月21日
许可协议