2024年12月20日,发明了 Claude 的 Anthropic 公司发表了一篇博文,对如何构建有效的 LLM Agent 提供了系统性阐述,并深入探讨了各种 Workflow 和 Agent 的实现模式及适用场景。
原始文章内容干货满满,本文就针对该篇博文进行翻译,强烈推荐各位读者查看原始文章——Building effective agents。
文章整体相当长,本文仅包含正文内容,附录相关内容将在下一篇文章列出。
TL;DR
-
Agent 定义与类型:
- Workflow: 预定义的代码路径协调 LLM 和工具。
- Agent: LLM 动态指导流程,自主控制任务完成方式。
-
何时使用 Agent:
- 优先选择简单方案,仅在需要时增加复杂性。
- Workflow 提供一致性,Agent 提供灵活性和决策能力。
-
常见 Workflow 模式:
- 提示链: 将任务分解为多个步骤,提高准确性。
- 路由: 分类输入并定向到不同子任务,提高任务适配性。
- 并行化: 将任务分解为并行子任务或多次尝试提升性能。
- 编排器-执行器: 动态分解任务,适合复杂、不可预测的情况。
- 评估器-优化器: 循环评估和改进,适合明确标准的任务。
-
Agent 的适用场景:
- 处理复杂开放问题,难以预测步骤。
- 提供自主性和扩展性,但需平衡成本和潜在错误。
-
核心原则:
- 简单性:从简单设计开始,逐步增加复杂性。
- 透明性:显式规划 Agent 的流程。
- 工具设计:完善的文档和接口确保可靠性。
正文翻译
在过去的一年中,我们与各行各业的数十个团队合作构建大型语言模型(LLM)Agent。 在所有的合作中,最成功的实现并没有使用复杂的框架或专门的库。 相反,他们使用简单、可组合的模式进行构建。
在这篇文章中,我们分享了我们从与客户合作和自己构建 Agent 中学到的经验,并为开发人员提供有关构建有效 Agent 的实用建议。
什么是 Agent?
“Agent” 可以用多种方式定义。 一些客户将 Agent 定义为完全自主的系统,可以在较长时间内独立运行,使用各种工具来完成复杂的任务。 其他人则使用该术语来描述遵循预定义 Workflow 的更规范的实现。 在 Anthropic,我们将所有这些变体都归类为 agentic 系统,但在 Workflow
和 Agent
之间进行了重要的架构区分:
-
Workflow 是通过预定义的代码路径协调 LLM 和工具的系统。
-
Agent 是指 LLM 动态指导其自身流程和工具使用,并保持对其完成任务方式控制的系统。
下面,我们将详细探讨这两种类型的 agentic 系统。 在附录 1(“实践中的 Agent”)中,我们将介绍客户发现使用这些类型的系统具有特殊价值的两个领域。
何时(以及何时不)使用 Agent
当使用 LLM 构建应用程序时,我们建议找到最简单的解决方案,并且仅在需要时才增加复杂性。 这可能意味着根本不需要构建 agentic 系统。 Agentic 系统通常会牺牲实时性和成本以获得更好的任务性能,您应该考虑这种权衡何时有意义。
当需要更高的复杂性时,Workflow 为明确定义的任务提供可预测性和一致性,而当需要在规模上实现灵活性和模型驱动的决策时,Agent 是更好的选择。 然而,对于许多应用程序来说,使用检索和上下文示例(in-context examples)来优化单个 LLM 的调用通常就足够了。
何时以及如何使用框架
有许多框架可以使 agentic 系统更容易实现,包括:
- LangChain 的 LangGraph;
- Amazon Bedrock 的 AI Agent 框架;
- Rivet,一个拖放式 GUI LLM Workflow 构建器;以及
- Vellum,另一个用于构建和测试复杂 Workflow 的 GUI 工具。
这些框架通过简化标准底层任务(如调用 LLM、定义和解析工具以及将调用链接在一起)使入门变得容易。 然而,它们通常会创建额外的抽象层,这些层会模糊底层的提示和响应,从而使调试更加困难。 它们也可能会让人在更简单的设置就足够的情况下,倾向于添加复杂性。
我们建议开发人员首先直接使用 LLM API:许多模式可以在几行代码中实现。 如果您确实使用框架,请确保您了解底层代码。 对底层代码做出不正确的假设是客户错误的常见来源。
请参阅我们的 cookbook,了解一些示例实现。
构建模块、 Workflow 和 Agent
在本节中,我们将探讨我们在生产中看到的 agentic 系统的常见模式。 我们将从我们的基础构建模块——增强的 LLM 开始,并逐步增加复杂性,从简单的组合 Workflow 到自主的 Agent。
构建模块:增强的 LLM
agentic 系统的基本模块是通过检索
、工具
和记忆(memory)
等增强功能增强的 LLM。 我们目前的模型可以主动使用这些功能:例如生成自己的搜索查询,选择合适的工具,并确定要保留的信息。
我们建议关注实现的两个关键方面:针对您的特定用例定制这些功能,并确保它们为您的 LLM 提供简单、文档完善的接口。 虽然有很多方法可以实现这些增强功能,但一种方法是通过我们最近发布的 模型上下文协议(Model Context Protocal),该协议允许开发人员通过简单的客户端实现 与不断增长的第三方工具生态系统集成。
在本文的其余部分,我们将假设每次 LLM 调用都可以访问这些增强功能。
Workflow
提示链(Prompt chaining)
提示链将任务分解为一系列步骤,其中每个 LLM 调用都会处理上一个调用的输出。 您可以在任何中间步骤中添加检查程序(请参阅下图中的“gate”)以确保该过程仍在进行中。
何时使用这类 Workflow:
这类 Workflow 非常适合可以简单地分解为简洁的固定子任务的情况。 这么做的主要目标是通过使每个 LLM 调用成为更简单的任务来牺牲响应时间以获得更高的准确性。
适用于提示链的示例:
-
生成营销文案,然后将其翻译成不同的语言。
-
编写文档大纲,检查大纲是否符合特定标准,然后根据大纲编写文档。
路由(Routing)
路由对输入进行分类并将其定向到专门的后续任务。 这类 Workflow 更关注于根据不同情况构造更专业的提示链。 如果没有这类 Workflow,那对一种输入进行的优化可能会降低对其他输入的性能。
何时使用这类 Workflow:
路由适用于复杂任务,同时复杂任务可以分解为单独处理的不同类别,并且可以通过 LLM 或更传统的分类模型/算法准确地处理分类的情况。
适用于路由的示例:
-
将不同类型的客户服务查询(一般问题、退款请求、技术支持)定向到不同的下游流程、提示和工具。
-
将简单/常见的问题路由到较小的模型(如 Claude 3.5 Haiku),将困难/不常见的问题路由到更强大的模型(如 Claude 3.5 Sonnet)以优化成本和速度。
并行化(Parallelization)
LLM 有时可以同时处理一个任务,并通过编程方式将输出聚合。 这类 Workflow(并行化)主要有两种形式:
-
分解:将任务分解为并行运行的独立子任务。
-
投票:多次运行同一任务以获得不同的输出。
何时使用这类 Workflow:
当分解的子任务可以并行执行来提升响应速度,或者当需要多个视角或尝试获得更高的置信度结果时,并行化是有效的。 对于有许多因素需要考虑的复杂任务,当每个因素由单独的 LLM 调用处理时,LLM 的性能通常会更好,因为每一个单独的 LLM 可以专注于每个特定方面。
并行化的示例:
-
分解:
-
实现安全性审查:其中一个模型处理用户查询,而另一个模型判断用户查询是否存在不适当的内容或请求。 这往往比让同一个 LLM 调用处理安全性审查和核心响应效果更好。
-
LLM 性能的自动化评估,其中每个 LLM 调用都会评估模型在给定提示下的不同性能。
-
-
投票:
-
审查一段代码是否存在漏洞,其中多个不同的提示词会审查并标记代码(如果发现问题)。
-
评估给定的内容是否不适当,其中多个提示词会评估不同的方面或需要不同的投票阈值,以平衡误报和漏报。
-
编排器-执行器(Orchestrator-workers)
在编排器-执行器类型的 Workflow 中,有一个处于中心的 LLM 动态分解任务,并将其分配给其他 LLM 进行执行,并对其结果进行合成。
何时使用这类 Workflow:
这类 Workflow 非常适合于那些无法预测所需子任务的复杂任务(例如,在编码中,需要更改的文件数量以及每个文件中更改的性质可能取决于任务)。 虽然编排器-执行器的流程图与上一节并行化的流程图看上去很相似,但这两个 workflow 的关键区别在于编排器-执行器 workflow 的灵活性——子任务不是预定义的,是动态的,具体是由编排器根据特定输入确定的。
编排-执行的示例:
-
每次都对多个文件进行复杂更改的编码产品。
-
涉及从多个来源收集和分析信息以获取可能相关信息的搜索任务。
评估器-优化器(Workflow: Evaluator-optimizer)
在评估器-优化器 Workflow 中,一个 LLM 生成响应,而另一个 LLM 在一个循环中提供评估和反馈。
何时使用这类 Workflow:
当我们有明确的评估标准,并且当迭代地进行改进可以提供可度量的收益时,这类 Workflow 特别有效。 良好拟合的两个标志是,首先,LLM 的响应可以通过人类的详细反馈进行明显改进;其次,LLM 可以提供这种反馈。 这类似于人类作者在制作精美文章时可能会经历的一遍又一遍的写作过程。
评估器-优化器的示例:
-
文学翻译,其中存在 LLM 在最初的翻译时可能无法捕捉到的细微差别,但评估器 LLM 可以提供有用的评论。
-
复杂的搜索任务,需要多轮搜索和分析才能收集全面的信息,其中评估器决定是否需要进一步搜索。
Agent
随着 LLM 在理解复杂输入、参与推理和规划、可靠地使用工具以及从错误中恢复等关键能力方面日趋成熟,Agent 正在生产环境中使用。 Agent 通常从人类的指令或交互开始参与。 一旦任务明确,Agent 将独立规划和执行,并可能将结果返回给人类以获取更多的信息或判断。 在执行期间,Agent 必须在每个步骤从环境中获得“基本事实”(例如,工具调用结果或代码执行)来评估其过程。 Agent 可以在检查点或遇到障碍时暂停以获取人工反馈。 任务中止通常有两种情况:任务完成或者满足了停止条件(例如,最大迭代次数)。
Agent 可以处理复杂的任务,但它们的实现通常很简单。 它们通常是在基于环境反馈的循环中具有工具调用能力的 LLM。 因此,清晰完备地设计工具集及其文档至关重要。 我们在附录 2(“提示工程你的工具”)中详细介绍了工具开发的最佳实践。
何时使用 Agent:
Agent 可用于开放性问题,在这种问题中,预测解决问题所需的步骤很难,并且不能给出一个固定路径。 LLM 可能会运行多个回合,您必须对它的决策有一定的信任。 Agent 的自主性使其成为在受信任环境中扩展任务的理想选择。
Agent 的自主性意味着更高的成本,以及更可能犯一些复合性的错误。 我们建议在沙盒环境中进行广泛的测试,并使用适当的安全机制。
Agent 的示例:
以下示例来自我们自己的实现:
-
编码 Agent,用于解决 SWE-bench 任务,这些任务涉及根据任务描述编辑多个文件;
-
我们的“计算机使用”参考实现,其中 Claude 使用计算机完成任务。
组合和定制这些模式
这些构建模块不是规范性的。 它们是开发人员可以构造和组合以适应不同用例的常见模式。 与任何 LLM 功能一样,评价性能并进行迭代是成功的关键。 重复一遍:只有在它能明显改善结果时,您才应该考虑添加复杂性。
总结
LLM 领域的成功不在于构建最复杂的系统,而在于构建适合您需求的 正确 系统。 从简单的提示词开始,使用全面的评估对其进行优化,并且仅在更简单的解决方案不能满足需求时再添加多步骤的 agentic 系统。
在实现 Agent 时,我们尝试遵循三个核心原则:
-
在 Agent 的设计中保持 简单性。
-
通过显式的、明确的 Agent 的规划步骤来提升 系统的透明度。
-
通过完备的 工具文档和测试 来精心设计您的 Agent-计算机接口(ACI)。
框架可以帮助您快速入门,但当您转向生产环境时,务必减少抽象层并使用基础组件进行构建。 通过遵循这些原则,您可以创建不仅强大而且可靠、可维护并获得用户信任的 Agent。
感谢阅读到这里,如果这篇文章对你有所帮助,欢迎关注【算法工程笔记】公众号!