周刊第17期: 如何构建智能体(Agent)

—— 学习四篇博客: 大模型驱动的自主智能体(Lilian Weng)/构建高效的智能体(Anthropic)/构建智能体实践指南(OpenAI)/智能体的上下文工程(Manus)

本文为周刊第17期,前期的周刊参见:周刊系列

TL;DR 本期周刊通过几篇博客文章来讲如何构建智能体(Agent): 1) 《大模型驱动的自主智能体》: 关于智能体最经典的一篇文章,介绍大模型驱动的智能体的核心架构,其中主要三个核心部分(规划、记忆、工具使用)的职能分别是什么?以及参考案例。 2) 《构建高效的智能体》(by Anthropic): Anthropic发布的智能体构建指南,阐述什么是智能体以及智能体系统?何时构建智能体?有哪些类型的智能体系统?智能体和工作流的区别?以及如何构建它们? 3) 《构建智能体实践指南》(by OpenAI): OpenAI发布的智能体构建指南,阐述他们对智能体的定义,以及何时构建智能体?智能体的设计原则有哪些?如何做好安全防护? 4) 《智能体的上下文工程》: Manus首席科学家从Manus项目经验中分享构建Agent的实践教训,以及具体在上下文工程中应该怎么做。

如无特殊说明,本文中的Agent或智能体指的都是大模型驱动的智能体(LLM powered agents).

Lilian Weng:大模型驱动的自主智能体

原文:LLM Powered Autonomous Agents

Lilian Weng (翁荔)是前OpenAI安全系统团队负责人,后离职与前OpenAI CTO Mira Murati 一起创业,成为 Thinking Machines Lab 的联合创始人。她的这篇文章发表于2023年6月。可以说,Lilian Weng 是最早意识到 Agent(大模型驱动的智能体)重要性的人,而很多Agent开发者也把她的这篇博客当成了教科书级的存在。

lilian-weng

文章一开头,作者就说到:利用大语言模型(LLM)作为核心驱动来构建Agent是一个极富创意的想法(cool concept)。LLM就像Agent的大脑,驱动Agent解决各种问题。在Agent系统中,主要有规划(Planning)、记忆(Memory)、工具使用(Tool use)几个核心部分。

agent-overview

一、规划 Planning

在规划部分,Agent完成两项任务:

  1. 细分目标与拆解任务:Agent将庞大的任务拆成小块,每一块都是一个小目标,这样可以把复杂任务简单化。在任务拆解中,典型的方法有思维链(CoT, Chain of Thought)和思维树(Tree of Thoughts)。思维链是将复杂的问题转换为“分布思考”,通过一步一步的思维链来拆解复杂任务。而思维树则是思维链的进一步拓展,在每个思考阶段还可以进行多重推理探索,每一步都可以产生多个想法,形成一个树状的结构,并使用BFS(广度优先搜索)或DFS(深度优先搜索)来探索并评估各想法。还有一种方法是LLM+P, 这种方法会将任务分解规划外包给一个外部的工具,即”P”,LLM则使用该工具返回的结果。
  2. 反思与优化:Agent会反思自己过去的行为,学习并改成错误,以提高解决问题的效果。典型的方法如 ReAct、Reflexion、CoH、AD。ReAct 通过提示词模板”Thought: … / Action: … / Observation: …” 强制Agent显示记录思考过程,通过自然语言生成推理轨迹,再执行具体行动,并观察结果以调整后续步骤。而 Reflextion 则是在ReAct 的基础上增加奖励模型来判断行为是否低效或包含幻觉,来决定是否调整策略。CoH (Chain of Hindsight, 回顾链)通过SFT(监督微调)让大模型从历史反馈中改进。AD(Algorithm Distillation, 算法蒸馏)则是通过强化学习让Agent模仿自身过去的改进轨迹来强化整个“学习过程”。

二、记忆 Memory

类比人类大脑的记忆存储及获取,一般有如下三种记忆:

  1. 感知记忆(Sensory Memory): 这是记忆的第一步,在感官接受刺激后短暂保留的信息,比如看到一幅图片后的视觉记忆,或听到一段音乐后的听觉记忆等。对于大模型而言则是原始输入的token向量化表示。
  2. 短期记忆(Short-Term Memory, STM): 也被称为工作记忆(Working Memory)。 当我们意识到需要某些信息用来学习或推理等复杂认知任务时,就会将这些信息存储在短期记忆中。而在大模型任务处理时,大模型就依赖于上下文窗口来存储短期记忆信息。
  3. 长期记忆(Long-Term Memory, LTM): 这些是记录在我们大脑皮层长期存在的记忆,一般而言容量几乎无限。一种是需要有意识的回忆,比如特定的事件,称为显性记忆;另一种是无意识的记忆,比如骑车技能,称为隐性记忆。对于大模型而言,长期记忆依赖于外部工具,如向量数据库,信息的获取效率依赖检索算法,一般标准的做法是通过最大内积搜索(MIPS)检索数据,使用一种叫近似最近邻(ANN)的算法。常用的ANN算法有:LSH(局部敏感哈希)、ANNOY、HNSW、FAISS、ScaNN 等,这些算法在数据检索的速度、维度、精度上各有侧重,实际应用过程中需根据场景选择。

三、工具使用 Tool use

Agent通过调用外部工具API,可以获取那些不在大模型权重的信息,也拥有了执行任务的能力。比如调用搜索引擎查询信息,调用数据库查询最新数据,甚至编译或执行代码等。

一般的Agent框架都提供了类似框架能力,作者重点介绍了HuggingGPT这一框架,它运用ChatGPT作为指挥中心,从HuggingFace平台上挑选合适的模型来执行任务。整个系统分为四步:1) 任务规划:将用户请求分解为多个小任务;2) 选择模型:将任务分配给不同的专家模型执行;3) 执行任务:专家模型将针对特定任务进行操作,并记录结果; 4) 响应生成:大模型接收执行结果,向用户总结输出。

hugging-gpt

最后,作者总结了几点挑战,到现在仍是Agent领域所研究的课题:1) 有限的上下文长度,影响反思和规划。2) 规划和任务分解能力方面,大模型在动态调整规划时不如人类灵活。3) 自然语言不够精确,大模型通过自然语言与外部工具交互,可能因为格式生成错误而导致命令不能够被执行。


Anthropic: 构建高效的智能体

原文:Building effective agents

这是 Anthropic 团队在2024年12月发表的博客,在博客中 Anthropic 总结了过去一年跟其他行业团队合作构建智能体的经验。

什么是Agent ?

关于Agent的定义没有明确标准。有人把能够自主运行、使用各种工具完成复杂任务的自主执行系统称为Agent,也有把遵循预先定义的工作流、按指令执行的系统称为Agent。在Anthropic看来,各种变体都可以归类为 Agentic System(智能体系统),而用 Workflow(工作流)和 Agent(智能体) 来区分:

  • Workflow: 通过预定义代码路径来协调大模型(LLM)和工具的系统;
  • Agent: 由大模型动态指导自身流程和工具使用,并对完成任务保持控制的系统。

何时构建Agent ?

通常,构建 Agentic System 具有较高的成本和延迟,因此,只有必要的时候才构建。也就是说,如果是简单场景,那优先考虑提示词工程(Prompt engineering)等低成本方案。当确实需要更复杂的解决方案时,面对 Workflow 和 Agent 也有考量标准:对于定义明确的任务,Workflow 能提供可预测性和一致性;而需要更灵活的大模型决策场景时,则考虑Agent.

何时及如何使用框架 ?

很多框架可以用来构建Agentic System, 比如 LangChain 的 LangGraph, Amazon Bedrock, Rivet, Vellum 等。使用框架上手容易,但副作用是框架的抽象层会掩盖底层的提示和响应,使得调试困难,而且也会增加应用的复杂度。作者建议开发者优先选择使用大模型API,直接编码实现,如果一定要使用框架,得确保理解框架底层代码。

构建 Workflow 和 Agent

作者从基本单元(Block)到 Workflow 再到 Agent 逐步介绍其构建方式。

构建基本单元(Block)

首先从构建Agentic System 的最基本单元(Block)开始:对大模型进行增强,比如检索、调用工具、记忆(读写外部存储)等。一个建议的做法是,通过MCP(Mode Context Protocol)协议来与三方工具集成交互。

block-augmented-llm

构建不同类型的 Workflow

下面作者介绍了几种典型的 Workflow 及其构建方式。

1、Prompt chaining (提示词链)

Prompt chaining 是将一个任务分解为一系列步骤,其中前一次大模型调用输出将会处理成为下一次大模型调用的输入提示词,这样每一次大模型的调用都是处理简单的任务,用调用时长的代价来换取更高的准确性。常见的案例有:生成营销文案并翻译成其他语言,先编写文档大纲再根据文档大纲编写文档。

prompt-chaining-workflow

2、Routing (路由)

Routing 工作流通过大模型对输入进行分类,并将其定向转到专门的后续任务。常见的案例有:根据用户咨询问题类别导向不同的下游流程,将简单的问题路由到小模型而将困难的问题路由到更大的模型以优化成本和速度。

routing-workflow

3、Parallelization(并行化)

并行化工作流是让大模型将同一任务分给多个下游流程,或者将一个大任务分解成多个子任务给下游流程,然后通过程序聚合它们的输出。前一种作者称为Sectioning(分段), 将一个任务分段为独立的子任务并运行,我觉得有点像 MapReduce, 如:让一个模型处理用户查询,让另一个模型对其不当内容或请求进行筛查。后一种作者称为 Voting(投票),多个实例运行相同的任务以获得不同的输出,如:审查同一段代码的漏洞,多个提示词进行不同方面的审查,如果发现问题则标记出来。

parallelization-workflow

4、Orchestrator-workers (协调者-工作者模式)

在协调者-工作者模式的工作流中,协调者是一个中央控制的大模型单元,它分解任务并将其委派给其他大模型工作者,并综合输出结果。

orchestrator-workers-workflow

5、Evaluator-optimizer(评估者-优化者模式)

在评估者-优化者模式的工作流中,一个大模型调用生成,而另一个大模型调用(评估者)在循环中提供评估和反馈。这种工作流适合通过迭代来改进大模型生成效果的场景,如文档翻译,一个大模型负责翻译和优化,另一个大模型负责评估和反馈。

evaluator-optimizer-workflow

构建 Agent

自主Agent可以处理复杂任务,但实现起来往往很简单,它通常是大模型在一个循环中根据环境反馈使用工具。在执行过程中,Agent从用户或环境中获得反馈,自主规划并操作。而Agent的自主性也意味着更高的成本,以及潜在的错误累积。作者举了他们尝试过的Agent,如一个用于解决 SWE-bench 测试集任务的编码Agent; 调用 Claude 来操作电脑完成任务。

autonomous-agent

上述的 Workflow 和 Agent 的模式也是可以组合和定制使用的。

最后,作者总结了他们在实现Agent中的三点核心原则:

  1. 保持Agent设计的简洁性。
  2. 通过展示Agent规划步骤以确保透明性优先。
  3. 通过工具文档和测试,精心设计Agent和计算机间的接口。

OpenAI: 构建智能体实践指南

原文(文档下载链接):A practical guide to building agents

今年5月,OpenAI也发布了一篇构建Agent的指导文档。

什么是Agent?

与Anthropic 的博客文章观点不同,OpenAI很明确的指出了Agent是能够代表用户独立完成任务的系统。那些尽管继承了大模型但是没有使用它来控制工作流程执行的应用都不是Agent,比如简单的聊天机器人、预先编排工作流程的大模型应用等。也就是说,OpenAI认为,Workflow不是Agent,它也没有使用Anthropic提的比较泛化的词:Agentic System.

何时构建Agent?

在这个问题上,OpenAI 的观点近似 Anthropic, 认为 Agent 适合处理复杂问题,适用于那些传统确定性和基于规则的方法难以处理的工作流程。比如:复杂决策场景,难以维护的规则,或严重依赖非结构化数据的场景。

Agent 设计基础

从最基本的形式看,Agent由三个核心组件构成:

  • 模型:为Agent的推理和决策提供支持的大语言模型
  • 工具:Agent可采取行动的外部功能或API
  • 指令:定义Agent行为的明确指导和安全防护(guardrails)

选择模型

不同的模型在任务复杂度、推理时长(latency)和成本方面各有优劣,并不是每项任务都需要性能最强的模型,因为性能更强往往也意味着推理时长更慢、成本更高。

OpenAI给出的建议是:先采用能力最强的模型构建Agent原型,以建立性能基准。在此基础上,尝试替换为更小的模型,以检验其性能,同时权衡推理时长和成本。这样避免过早的限制Agent的能力。

定义工具

通过使用系统和应用的API,工具可以扩展Agent的能力。而对于那些没有API的遗留系统,Agent则依赖与网页或UI直接交互。

每个工具应该有标准化的定义,以便实现灵活的工具与Agent之间的多对多关系。OpenAI这里提到的标准化定义的工具(tools)类似于Anthropic所提到的符合 MCP 协议的工具,以及Google所提出的符合A2A协议的Agent.

Agent通常需要三类工具:

  1. 数据类:帮助Agent获取执行工作流所需的上下文信息,如查询数据库、读取计算机文档、搜索网络等。
  2. 动作类:使Agent能采取行动,如写入数据、更新记录、发送邮件、转客服工单等。
  3. 编排类:Agent本身也可以成为其他Agent的工具,如研究Agent、写作Agent、翻译Agent等。

配置指令

高质量的指令对Agent来说至关重要,清晰的指令能减少歧义,提高决策准确性,让工作流执行更流畅、错误更少。写好Agent指令需要注意以下几点:利用现有文档、引导Agent拆解任务、定义明确的动作、以及覆盖边界情况。

编排Agent

在模型、工具、指令三大核心组件具备后,接下来就需要考虑编排模式,让Agent有效执行工作流。

一般编排模式分类两类:

  1. 单Agent系统:由一个配备合适工具和指令的模型,在循环中执行工作流。
  2. 多Agent系统:将工作流的执行分配给多个协作的Agent.

单Agent系统

单Agent系统可以通过不断增加工具来处理更多任务,这种模式可控性更强,评估和维护也更简单。

在单Agent系统模式下,Agent的作业运行通常由循环来实现,让Agent一直执行,直到满足退出条件为止。

openai-single-agent-system

一般来说,单Agent系统可以满足大多数场景,当场景逻辑复杂到难以维护、或添加了太多工具导致过载时,就要考虑多Agent系统了。

多Agent系统

多Agent系统有很多种设计方法,最常用的是以下两种模式:

1、管理者模式(Manager pattern): 一个中心管理者Agent通过工具调用来协调多个专用Agent(agents as tools), 每个Agent处理特定任务。

openai-multi-agent-manager-pattern

2、去中心化模式(Decentralized pattern): 多个Agent以平等的方式去中心化协作,基于各自专长互相交接任务(agents handing off to agents)。

openai-multi-agent-decentralized-pattern

Guardrails (安全防护)

Guardrails 可以帮助开发者管理数据隐私风险,并确保大模型不被滥用。

Guardrails 需要通过分层防御机制来建立,单一的防护很难做到足够安全。

Guardrails 的类型包括:

  • 相关性分类器(Relevance Classifier):确保Agent回复保持在预期范围内,标记离题的询问。
  • 安全分类器(Safety Classifier):检测危险输入,防止利用系统漏洞。
  • 个人身份信息过滤器(PII Filter):防止模型输出不必要的个人身份信息(Personally Identifiable Information).
  • 内容审核(Moderation):标记有害或不当内容,确保交互安全。
  • 工具安全评估(Tool Safeguards):为每个工具评估风险等级,调用高风险工具触发人工审核。
  • 基于规则的防护(Rules-based protections):包括blocklist、正则表达式过滤等措施,防止已知威胁,如敏感词或SQL注入等。
  • 输出验证(Output validation):通过提示词工程和内容检查,对输出内容进行检查。

季逸超: 智能体的上下文工程

原文:Context Engineering for AI Agents

季逸超(Yichao ‘Peak’ Ji)是Manus的联合创始人兼首席科学家,最近他在Manus官网发布了一篇名为 Context Engineering for AI Agents: Lessons from Building Manus 的博客,从技术角度总结了构建Manus过程中的一些经验。

作者回顾了Manus立项初期面临的抉择:是使用开源模型来训练一个端到端的智能体模型(agentic model),还是基于前沿模型的上下文学习能力构建一个Agent. Manus团队之前有过创业的经验教训:当他们从头训练了一个模型,GPT-3一经推出,耗费大量成本训练的模型变得无关紧要。因此,在Manus上,团队选择了上下文工程。作者比喻说:“如果模型进步是上涨的潮水,我们希望Manus成为那条船,而不是固定在海床上的柱子。”总结上下文工程经验如下。

围绕 KV 缓存进行设计

作者认为 “KV 缓存命中率”是Agent生产阶段最重要的单一指标,因为它直接影响延迟和成本。这也令我想到计算机领域的一句著名的话:“计算机科学中只有两个难题:缓存失效和命名。”

一个典型的Agent处理任务过程是:在接收用户输入后,Agent通过一系列工具调用链来完成任务。在每次迭代中,模型根据上下文选择一个预定义动作并执行,然后观察结果。动作和观察结果被附加到上下文中,形成下一次迭代的输入。这个循环会持续进行,直到任务完成。这个过程中,上下文会不断增长,根据Manus的数据统计,平均输入和输出token的比例约为100:1.

具有相同前缀的上下文可以利用Transformer架构的KV缓存机制,这将大大减少了首token的生成时间和推理成本。根据Manus团队的计算,使用Claude Sonnet时,存储的输入token成本为0.3美元/百万token,而未缓存的成本为3美元/百万token,相差十倍。

因此,提升KV缓存命中率的关键实践有:1) 保持提示词前缀稳定;2) 使得上下文只在尾部增加;3) 在需要时明确标记缓存断点,这是为了手工告诉大模型哪些可以被缓存复用。

manus-design-around-kv-cache

在调整使用工具时,采用掩码方式,而非增删

通过使用工具让Agent能力更强,但如果任由用户自定义工具,也会造成不可预测的结果。Manus团队的做法是:避免在Agent执行迭代过程中动态添加或删除工具。一部分原因也是工具定义在上下文的前部,会导致KV缓存失效。采取的替代做法是使用上下文感知的状态机来管理工具的可用性,以遮蔽掩码的方式来允许或阻止某些工具调用动作。

manus-mask-not-remove

使用文件系统作为上下文

虽然当前业界前沿大模型都提供128K甚至更多的上下文窗口,但实际场景中这还远远不够,不仅因为过程中的观察结果往往包含了大量非结构化数据及文件,导致很容易超出上下文限制,而且长上下文也会导致模型性能下降、成本提升等问题。

Manus则将文件系统作为上下文,大小不受限制,持久化,而且Agent可以直接操作。不仅将文件系统用作存储,还用作非结构化的长期外部记忆。

manus-use-file-system-as-context

通过复述操控注意力

Manus在执行任务中,会生成一个todo.md的文件,用来记录任务列表,并在执行过程中更新它。这是一种操控注意力的机制。Manus平均完成一个任务需要大约50次工具调用,而过程中依赖大模型进行决策,这个作业链条太长,以至于大模型很容易偏离主题或忘记早期目标。因此,Manus通过不断重写代办事项列表,并将其目标复述到上下文的末尾,进而将代办推进模型的近期注意力范围内,避免了上述问题。

manus-attention-through-recitation

保留错误内容

大模型会产生幻觉,环境会返回错误,工具会出现异常行为,这些都会导致Agent犯错。在发现错误后清理痕迹继续重试并不是推荐的做法,因为清楚错误信息会移除证据,这会让大模型在下一步理解时缺失信息。因此,最有效的方法是将错误保留在上下文中,让模型看到错误的行动及其观察结果,以降低重复错误的可能性。

manus-keep-wrong-stuff-in

不要迷信少样本提示

少样本提示(Few-Shot Prompting)是大模型提示词工程中常用的方法之一,通过在提示词中增加少量样本示例让模型来模仿其样例,以提高输出的准确性。但在Agent中,这种方法也可能适得其反,模型遵循样本模式,重复类似行动,导致过度泛化,甚至产生幻觉。因此,推荐的做法是增加多样性,在模板中增加顺序或格式上的微小噪音,在控制中增加随机性。

manus-not-few-shotted

以上是作者在构建Manus过程中总结的实践经验。


Agent = LLM + memory + planning skills + tool use

This is probably just a start of a new era :)

– Lilian Weng, 2023-6-27, on x

知识共享许可协议 本文采用「CC BY-SA 4.0」知识共享许可协议,如果还喜欢其他文章, 欢迎订阅“胡涂说”博客
公众号
微信公众号同步更新,欢迎关注😊
对我博客最大的鼓励来自于你的评论,欢迎选择 来回复, 也可以在 GitHub discussion 留言。