LLM Powered Autonomous Agents,大语言模型赋能的自主智能体
ReAct的全称是(思考+行动),由Google Research团队于2022年在论文《ReAct: Synergizing Reasoning and Acting in Language Models》中提出。让LLM像人类解决问题一样,“边想边做”——通过交替进行“思考(梳理思路、明确下一步)”和“行动(执行操作、获取反馈)”,逐步逼近问题答案,而不是一次性输出最终结果。
1. 概述
在基于大语言模型(LLM)的自主智能体系统中,LLM充当着“大脑”的角色,其核心能力由以下关键组件协同增强:
- Planning(规划):
- 子目标和分解(Subgoal and decomposition):智能体能够将复杂任务拆解为更小、更易于管理的子目标,从而高效地完成多步任务流程。
- 反思和改进(Reflection and refinement):智能体可对自身过往行动进行自我批评与反思,从错误中学习并优化后续步骤,逐步提升最终结果的质量。
- Memory(记忆):
- 短期记忆:短期记忆对应于模型中的上下文学习,即利用LLM的有限上下文窗口来处理当前会话中的信息。
- 长期记忆:长期记忆使智能体能够长时间保留并回忆海量信息,通常通过外部向量存储(external vector store)与快速检索(fast retrieval)机制实现,突破了上下文窗口的限制。
- Tool use(使用工具):智能体学会调用外部API来获取模型权重中缺失的额外信息(预训练后难以更新的知识),例如实时数据、代码执行能力、专有信息源等,从而扩展自身的能力边界。
🤔 𝑸𝒖𝒆𝒔𝒕𝒊𝒐𝒏:我的理解是Agent就是对LLM进行了魔改,在前面和后面加了一些东西,但不会改变LLM本身(如参数),我的理解正确吗?
🥳 𝑨𝒏𝒔𝒘𝒆𝒓:Agent确实不改变LLM本身的参数。无论是OpenAI的GPT系列,还是开源的Llama、Qwen,作为Agent核心的模型权重和训练好的能力原封不动。所谓的“魔改”,是在LLM的输入前和输出后增加了系统性的逻辑层:
- 前面加的东西(规划层)
在把用户问题交给LLM之前,Agent会先做任务拆解。例如,通过特定的提示词(如ReAct范式)让模型“思考”:要回答这个问题,我需要调用什么工具?分几步完成?这部分本质上还是提示工程,但更结构化。- 后面加的东西(执行层)
当LLM输出“我需要调用天气API”或“我需要查数据库”这样的意图时,Agent框架会截获这个输出,并不直接返回给用户,而是去执行真正的函数调用(比如请求天气接口),然后把返回的结果再次拼接成新的提示,送回给LLM继续处理。我们可以把Agent想象成一个配备了秘书的专家:
- LLM本身就是那个专家,他脑子里有无穷的知识,但只能说话,不会动手。
- “前面加的东西” 是秘书帮他整理问题:“老板,用户问明天能不能爬山,你先看看需要查天气还是查日历?”
- “后面加的东西” 是秘书帮他去查资料:“老板,天气查回来了,明天下雨,你看着回答吧。”
专家(LLM)始终坐在那里没变,但有了秘书(Agent框架),他就能完成更复杂的任务。
这种“外挂式”设计的最大好处是解耦:
- LLM保持通用:你不需要为了某个特定任务去微调模型(微调成本高且会损害通用能力)。
- 工具可以灵活替换:今天用Bing搜索,明天换成Google搜索,只需要改Agent的配置,LLM完全无感。
- 可观测性强:Agent的每一步“思考”和“行动”都可以被记录下来,方便调试。
2. 组件一:规划(Planning)
复杂的任务往往无法一步完成。就像长途旅行需要规划路线一样,智能体也需要在行动前思考:任务需要分几步走?每一步应该做什么?这就是规划模块的核心职责。
2.1. 任务分解(Task Decomposition)
2.1.1. 常用方法
- 思维链(Chain of Thought, CoT) 是目前最经典的任务分解方法。它的核心思想非常简单:告诉模型“请一步步思考”。通过这种提示,模型会把一个复杂问题拆解成一系列更小的、更容易处理的子问题,并把思考过程清晰地展现出来。这不仅提高了任务完成的准确性,也让我们能够看到模型是如何一步步得出结论的——增加了可解释性。
- 思维树(Tree of Thoughts, ToT) 在CoT的基础上更进一步。它不再只沿着一条路径思考,而是在每一步都探索多种可能性,形成一个树状结构的思维路径。想象一下,你在解一道难题时,可能会在脑海中同时考虑几种不同的解法——ToT做的就是这件事。为了从众多可能性中找到最佳路径,它采用广度优先搜索(BFS) 或深度优先搜索(DFS) 来遍历这棵“思维树”,并通过分类器(由提示词实现)或多数投票来评估每个中间状态的好坏。
2.1.2. 任务分解的三种触发方式
在实际应用中,任务分解可以通过以下几种方式启动:
- LLM自主完成:通过简单的提示词,如“实现XYZ需要哪些步骤?\n1.” 或 “完成XYZ的子目标是什么?”,让模型自己拆解任务。
- 特定任务指令:针对特定场景给出更具体的引导。例如,写小说时告诉模型“请先列出一个故事大纲”。
- 人工输入:最直接的方式,由人类直接告诉智能体任务应该如何分解。
2.1.3. LLM+P:把规划外包给专家
还有一种相当独特的方法——LLM+P(大语言模型 + 规划器)。它不试图让LLM自己完成所有规划工作,而是把它外包给更专业的工具。
这个流程是这样的:
- 翻译问题:LLM首先把用户用自然语言描述的问题,翻译成一种规划领域定义语言(Planning Domain Definition Language, PDDL)——一种专门用来描述规划问题的形式化语言。
- 调用规划器:然后把这份“问题PDDL”交给一个外部的经典规划器(Planner)。规划器根据已有的“领域PDDL”(描述了可执行的动作和规则),生成一个完整的计划,同样用PDDL表示。
- 翻译回自然语言:最后,LLM把这个计划翻译回人能看懂的自然语言,呈现给用户。
这种方法把复杂的规划步骤完全外包给了外部工具。它的优势在于,当特定领域有成熟的PDDL模型和高效的规划器时(这在某些机器人控制场景中很常见),可以获得非常可靠的结果。但代价是,在大多数其他领域中,我们并没有现成的PDDL可以使用。
2.1.4. ReAct
在大语言模型(LLM)驱动的智能体(Agent)领域,我们始终在追求一个目标:让模型摆脱“被动应答”的局限,像人类一样具备主动思考、动态决策、交互执行的能力。而ReAct框架,正是实现这一目标的经典范式——它不依赖复杂的底层改造,仅通过“思考-行动-观察”的循环逻辑,就让LLM拥有了应对复杂任务的能力,成为Agent领域入门必学的核心框架之一。
2.1.4.1. 核心定义
ReAct的全称是 Reason + Act(思考+行动),由Google Research团队于2022年在论文《ReAct: Synergizing Reasoning and Acting in Language Models》中提出。它的核心思想非常简单:让LLM像人类解决问题一样,“边想边做”——通过交替进行“思考(梳理思路、明确下一步)”和“行动(执行操作、获取反馈)”,逐步逼近问题答案,而不是一次性输出最终结果。
举个最朴素的类比:我们想找家里的钥匙,不会凭空猜出钥匙在哪,而是会先“思考”(钥匙可能在玄关、书桌、背包里),再“行动”(去玄关找),然后“观察”(玄关没找到),再“思考”(next去书桌找),再“行动”……循环往复,直到找到钥匙。ReAct框架,就是把这种人类的问题解决模式,抽象成了LLM可执行的范式。
与传统LLM的关键区别:传统LLM是“输入→直接输出结果”,而ReAct是“输入→思考→行动→观察→再思考→再行动→……→输出结果”,多了“思考-行动-观察”的闭环,这也是它能应对复杂任务的核心原因。
2.1.4.2. 核心构成:3个模块+1个循环
ReAct框架的核心的是“思考-行动-观察”(Reason-Act-Observation)的循环,三个模块各司其职、缺一不可。
2.1.4.2.1. 思考(Reason):Agent的“大脑”——明确思路,规划下一步
思考模块是ReAct的核心,相当于Agent的“大脑”,其作用是:基于当前的问题(输入)和已有的观察(反馈),梳理解决思路,明确下一步该做什么。思考的内容没有固定格式,但必须具备“指导性”——要清晰地告诉Agent“为什么这么做”“下一步做什么”,避免盲目行动。
示例:
思考1:“首先我需要找到一个胡椒瓶……更可能出现在橱柜(1–6)、台面(1–3)……”(基于“找胡椒瓶”的问题,梳理可能的搜索范围,明确下一步行动方向)
思考2:“现在我找到了胡椒瓶1。接下来,我需要把它放到抽屉1里/上。”(基于“找到胡椒瓶”的观察,明确下一步的目标的是“放抽屉”)
简单说,思考模块就是让Agent“想清楚再做”,而不是瞎忙活。
2.1.4.2.2. 行动(Act):Agent的“手脚”——执行操作,落地思路
行动模块是Agent的“手脚”,其作用是:根据思考模块的指引,执行具体的操作。行动的类型取决于任务场景,常见的有两种:
- 外部行动:与外部环境/工具交互,比如“搜索某个关键词”(HotpotQA任务)、“前往橱柜1”“拿起胡椒瓶”(胡椒瓶任务)、“打开抽屉”等,这类行动会改变环境或获取新的信息。
- 内部行动:仅在Agent内部梳理思路,比如“梳理已有的搜索结果”“总结当前的进展”,这类行动不与外部交互,但能帮助Agent理清逻辑。
⚠️注意:行动必须是“可执行”的,不能是模糊的想法。比如“找胡椒瓶”不是行动,“前往橱柜1找胡椒瓶”才是行动。
2.1.4.2.3. 观察(Observation):Agent的“眼睛”——获取反馈,调整思路
观察模块是Agent的“眼睛”,其作用是:执行行动后,获取环境的反馈信息,这些反馈会成为下一轮“思考”的重要依据。观察的内容是“客观事实”,不是Agent的主观判断——比如“橱柜1里只有花瓶”“台面3上有胡椒瓶”“抽屉1是关闭的”,这些都是观察到的客观反馈。
示例(对应胡椒瓶任务):
行动:前往橱柜1 → 观察:橱柜1里有一个花瓶2(反馈“橱柜1没有胡椒瓶”,指导下一轮思考“去橱柜2找”)
行动:前往台面3 → 观察:台面3上有胡椒瓶1(反馈“找到目标”,指导下一轮思考“放抽屉1”)
2.1.4.2.4. 核心循环:思考→行动→观察→再思考→再行动……
ReAct的灵魂不是单个模块,而是三个模块的闭环循环。整个流程可以总结为:
1. 初始输入:明确要解决的问题(比如“找胡椒瓶并放到抽屉1”“回答HotpotQA问题”);
2. 第一次思考:基于初始问题,规划第一步行动;
3. 第一次行动:执行第一步操作;
4. 第一次观察:获取行动后的反馈;
5. 第二次思考:基于初始问题+第一次观察,规划第二步行动;
6. 重复循环,直到完成任务(行动模块输出“Finish”)。
这个循环的核心价值:让Agent能够“动态调整”——如果行动没有得到预期反馈(比如找胡椒瓶没找到),Agent可以通过思考模块调整思路,而不是一条路走到黑,这也是它比传统LLM更灵活、更能应对复杂任务的关键。
2.1.4.3. ReAct的典型应用场景——结合实例,理解它的价值
ReAct的适用场景,本质上是“需要分步解决、需要交互反馈”的复杂任务——这类任务,传统LLM一次性输出结果很容易出错,而ReAct的“边想边做”能完美适配。我们介绍两个最典型的场景:
2.1.4.3.1. 场景1:多跳问答(HotpotQA)
多跳问答的核心是:需要从多个信息源中,分步检索、组合信息,才能得出答案(比如“Apple Remote最初控制的程序,还有什么设备能控制它”)。
ReAct的循环过程:
🔻问题:Apple Remote最初控制的程序,还有什么设备能控制它?
思考 1:我需要搜索 Apple Remote,找出它最初设计用来交互的程序。
动作 1:搜索[Apple Remote]
观察 1:Apple Remote 是苹果公司于 2005 年 10 月推出的遥控器……最初用于控制 Front Row 媒体中心程序……
思考 2:Apple Remote 最初设计用于控制 Front Row 媒体中心程序。我需要继续搜索 Front Row,找出还有什么设备可以控制它。
动作 2:搜索[Front Row]
观察 2:未找到 [Front Row]。相似结果:['Front Row Seat to Earth'、'Front Row Motorsports'、'Front Row (软件)'……]
思考 3:没有找到 Front Row。我需要搜索 Front Row (软件)。
动作 3:搜索[Front Row(软件)]
观察 3:Front Row 是一款已停止维护的媒体中心软件……
思考 4:Front Row(软件)可由 Apple Remote 遥控器或键盘功能键控制。所以答案是键盘功能键。
动作 4:结束[键盘功能键]
如果没有ReAct的循环,传统LLM可能会直接猜测“其他设备是鼠标”,而ReAct通过“搜索-观察-再搜索”的闭环,确保了答案的准确性——这就是“边想边做”的价值。
2.1.4.3.2. 场景2:具身智能任务(Embodied AI)
具身智能的核心是:Agent需要在物理环境中执行操作(比如移动、拿取物品),完成具体的物理任务(比如“找胡椒瓶并放到抽屉里”“整理桌面”)。这类任务必须依赖环境反馈,否则无法推进。
ReAct的循环过程:
🔻任务:找到胡椒瓶,放到抽屉1里。
动作 1:思考[首先我需要找到一个胡椒瓶……更可能出现在橱柜(1–6)、台面(1–3)……]
动作 2:前往橱柜 1
观察 2:在橱柜 1 里,你看到一个花瓶 2。
(这里智能体依次前往橱柜 1、橱柜 2、橱柜 3,然后是台面 1 和台面 2)
动作 6:前往台面 3
观察 6:在台面 3 上,你看到一个苹果 1、一个面包 1、……一个胡椒瓶 1,以及一个花瓶 3。
动作 7:从台面 3 拿起胡椒瓶 1
观察 7:你从台面 3 拿起了胡椒瓶 1。
动作 8:思考[现在我找到了胡椒瓶 1。接下来,我需要把它放到抽屉 1 里/上。]
动作 9:前往抽屉 1
观察 9:抽屉 1 是关闭的。
动作 10:打开抽屉 1
观察 10:你打开了抽屉 1。
动作 11:把胡椒瓶 1 放到抽屉 1 里/上
观察 11:你把胡椒瓶 1 放到了抽屉 1 里/上。
这类任务中,ReAct的“观察”模块至关重要——如果Agent不知道“抽屉是关闭的”,就会直接尝试放胡椒瓶,导致任务失败;而通过观察反馈,Agent能及时调整行动(先打开抽屉),确保任务推进。
2.1.4.4. ReAct适用场景
- 信息检索任务:比如“查找某篇论文的核心观点,并总结成3点”(需要分步搜索、梳理)
- 复杂决策任务:比如“规划从家到公司的最优路线,需要避开拥堵、顺便买咖啡”(分步决策、获取实时路况反馈)
- 工具使用任务:比如“用计算器计算123×456,再把结果记录到文档里”(分步调用工具、获取反馈)
2.1.4.5. ReAct的局限性
没有完美的框架,ReAct也有一些局限,了解这些局限,能帮助我们更好地运用它:
- 效率较低:因为是“分步循环”,每一步都需要思考、行动、观察,相比传统LLM“一次性输出”,效率会低一些,尤其是简单任务,显得有些繁琐
- 依赖高质量的思考:思考模块是ReAct的核心,如果LLM的思考思路出错(比如找胡椒瓶时,错误地认为胡椒瓶在冰箱里),整个任务都会偏离方向,无法完成
- 对环境反馈要求高:如果观察模块无法获取准确的反馈(比如找胡椒瓶时,观察到“台面没有胡椒瓶”但实际有),Agent会陷入错误的循环,无法推进任务。
2.1.4.6. 总结
ReAct不是一种复杂的算法,而是一种“让LLM更像人”的问题解决模式——它通过“思考-行动-观察”的闭环,把“被动输出”变成“主动解决问题”,让LLM具备了应对复杂任务的能力。核心是掌握“思考-行动-观察”的核心循环,理解每个模块的作用。ReAct是Agent领域的基础框架,后续的很多高级Agent范式(比如CoT+ReAct、ToT+ReAct),都是在它的基础上优化而来。吃透ReAct,相当于打通了Agent学习的“任督二脉”,后续学习更复杂的范式会轻松很多。
2.1.4.7. 实战与分析
我们试着为“找水杯并放到桌子上”设计一个完整的ReAct循环,梳理出每一步的思考、行动、观察。
任务:找水杯并放到桌子上
Thought1: 水杯理论上是在厨房,先去厨房
Action1: 前往厨房
Observation1: 已经到达厨房
Thought2: 既然已经到达厨房,那么找水杯
Action2: 找水杯
Observation2: 找到了水杯
Thought3: 我们的需求是将找到的水杯放到桌子上,那么是那个桌子,理论上应该是之前的桌子,所以我们需要拿着杯子回到最开始的地方
Action3: 拿着杯子回到最开始的地方
Observation3: 已经回到最开始的地方并且拿着杯子
Thought4: 找到桌子
Action4: 找桌子
Observation4: 找到了桌子
Thought5: 将水杯放到桌子上
Action5: 将水杯放到桌子上
Observation5: 已经将水杯放到桌子上,任务结束,输出Finished!
为了让我们写的ReAct更贴近真实 ReAct Agent 的执行逻辑,对其进行优化,优化后的结果如下:
任务:找水杯并放到桌子上
Thought1: 水杯通常放置在厨房区域,为了高效找到水杯,我先前往厨房
Action1: 前往厨房
Observation1: 已成功到达厨房,未发现异常
Thought2: 已抵达厨房,接下来需执行找水杯的操作,排查厨房内的水杯位置
Action2: 在厨房内找水杯
Observation2: 在厨房内成功找到水杯,已手持水杯
Thought3: 任务核心是将水杯放到桌子上,结合场景,此处的桌子应为初始出发位置的桌子,因此需手持水杯返回初始地点
Action3: 手持水杯返回初始出发位置
Observation3: 已成功返回初始出发位置,且全程手持水杯,未掉落
Thought4: 已回到初始位置,下一步需找到目标桌子,以便完成放水杯的操作
Action4: 在初始位置找桌子
Observation4: 已成功找到目标桌子,桌子位置固定且平稳
Thought5: 已找到桌子、手持水杯,当前可执行最终操作,将水杯放置在桌子上
Action5: 将手持的水杯平稳放到桌子上
Observation5: 已成功将水杯放到桌子上,任务全部完成
Action6: Finish[任务完成]
我们逐一进行分析:
任务:找水杯并放到桌子上
[V1]Thought1: 水杯理论上是在厨房,先去厨房
[V2]Thought1: 水杯通常放置在厨房区域,为了高效找到水杯,我先前往厨房
[V1]Action1: 前往厨房
[V2]Action1: 前往厨房
[V1]Observation1: 已经到达厨房
[V2]Observation1: 已成功到达厨房,未发现异常
[V1]Thought2: 既然已经到达厨房,那么找水杯
[V2]Thought2: 已抵达厨房,接下来需执行找水杯的操作,排查厨房内的水杯位置
[V1]Action2: 找水杯
[V2]Action2: 在厨房内找水杯
[V1]Observation2: 找到了水杯
[V2]Observation2: 在厨房内成功找到水杯,已手持水杯
[V1]Thought3: 我们的需求是将找到的水杯放到桌子上,那么是那个桌子,理论上应该是之前的桌子,所以我们需要拿着杯子回到最开始的地方
[V2]Thought3: 任务核心是将水杯放到桌子上,结合场景,此处的桌子应为初始出发位置的桌子,因此需手持水杯返回初始地点
[V1]Action3: 拿着杯子回到最开始的地方
[V2]Action3: 手持水杯返回初始出发位置
[V1]Observation3: 已经回到最开始的地方并且拿着杯子
[V2]Observation3: 已成功返回初始出发位置,且全程手持水杯,未掉落
[V1]Thought4: 找到桌子
[V2]Thought4: 已回到初始位置,下一步需找到目标桌子,以便完成放水杯的操作
[V1]Action4: 找桌子
[V2]Action4: 在初始位置找桌子
[V1]Observation4: 找到了桌子
[V2]Observation4: 已成功找到目标桌子,桌子位置固定且平稳
[V1]Thought5: 将水杯放到桌子上
[V2]Thought5: 已找到桌子、手持水杯,当前可执行最终操作,将水杯放置在桌子上
[V1]Action5: 将水杯放到桌子上
[V2]Action5: 将手持的水杯平稳放到桌子上
[V1]Observation5: 已经将水杯放到桌子上,任务结束,输出Finished!
[V2]Observation5: 已成功将水杯放到桌子上,任务全部完成
[V2]Action6: Finish[任务完成]
- 思考(Thought):补充了 “目的”,让思考更有指导性(比如 Thought1 加上 “为了高效找到水杯”,贴合 ReAct “思考指导行动” 的核心,我们原本的思考没问题,只是稍显简略);
- 行动(Action):更具体,避免模糊(比如 Action2 改为 “在厨房内找水杯”,明确行动范围;我们原本的 “找水杯” 没问题,优化后更精准,和 Observation2 的呼应更紧密);
- 观察(Observation):补充了小细节,让反馈更客观(比如加上 “未发现异常”“已手持水杯”,避免观察过于简略,同时呼应上一步行动和下一步思考);
- 结尾优化:增加标准的 Finish 行动,贴合你之前见过的 ReAct 示例(比如之前的胡椒瓶、HotpotQA 示例,结尾都是 “Finish / 结束”,更规范)。
2.1.4.8. QA
2.1.4.8.1. Q1:LLM的调用次数
我的问题:使用了ReAct框架后,每一次Thought-Action-Observation其实会调用两次LLM对吧(如果Action没有涉及到需要使用语言的情况下),即思考需要LLM进行,Observation也需要LLM进行。
你的理解稍微有些偏差,我来帮你理清ReAct循环中的调用次数。在典型的ReAct模式中,每个完整的 Thought(思考)→ Action(行动)→ Observation(观察) 循环实际上只调用 一次 LLM,而不是两次。具体流程如下:
- LLM生成Thought和Action
- 给定当前上下文(包括之前的对话、历史Observation等),LLM一次性地输出一个
Thought(思考)和一个Action(行动)。 - 例如:
- 给定当前上下文(包括之前的对话、历史Observation等),LLM一次性地输出一个
Thought: 用户想知道天气,我需要查询API。
Action: search_weather[北京]
- 执行Action并获取Observation
- Agent框架解析LLM输出的Action,调用对应的外部工具(如天气API、数据库等)。
- 工具返回的结果作为
Observation(观察)被记录下来。这个Observation 不是由LLM生成的,而是外部世界的真实反馈。
- 将Observation追加到上下文
- 将Observation以文本形式追加到对话历史中,然后进入下一轮循环,再次调用LLM生成新的Thought和Action。
所以,每一轮循环只调用一次LLM,LLM负责生成思考+行动,而观察来自外部工具。
如果Action本身涉及“调用LLM来完成某个子任务”(例如“请用中文总结一下这段英文”),那么在这个Action的执行过程中可能会再次调用LLM。但这属于嵌套调用,并不是ReAct循环本身的设计。这种情况下,一次ReAct循环中的LLM调用次数可能会变成:
- 主循环调用一次LLM(生成Thought和Action)
- Action执行过程中又调用一次LLM(完成子任务)
但这取决于具体的工具实现,并非ReAct的固有特征。
为什么Observation不需要LLM?
- Observation的目的是获取真实信息,比如API返回的数据、数据库查询结果、代码执行输出等。这些信息是客观的,不需要LLM“思考”或“生成”,直接拼入上下文即可。
- 如果让LLM来生成Observation,那就成了“自己想象结果”,失去了Agent调用工具的意义(因为模型可能产生幻觉)。
- 总结:
- 标准情况:一次ReAct循环 = 1次LLM调用(生成Thought+Action)+ 外部工具调用(获取Observation)。
- 你的误解:可能把“Observation作为输入送给下一次LLM”当成了“Observation也需要LLM生成”,实际上Observation只是文本拼接,无需LLM参与生成。
2.1.4.8.2. Q2:任务结束标志Finished
我的问题:任务结束的Finished是LLM发出的还是ReAct框架根据某种规则发出的?如果是由LLM发出的,那么由于LLM本身是没有特意为Agent进行微调,仅凭一些prompt,LLM可以准确回答出Finished吗,如果它回复一个done那系统不就陷入死循环了?
在ReAct模式的Agent实现中,任务结束的信号通常由LLM生成,但框架同时承担着解析、执行和兜底的责任。两者协作确保系统不会陷入死循环。下面详细拆解。
在标准ReAct循环中,LLM的输出会被解析为两部分:Thought(思考)和Action(行动)。其中Action可以是一个具体的工具调用,也可以是一个特殊动作,例如 Finish[最终答案] 或 Answer[最终回答]。
例如,通过Prompt和Few-shot示例,LLM学会当认为任务已完成时,输出类似:
Thought: 用户的问题已经得到解答,我可以给出最终答案。
Action: Finish[根据您的需求,推荐购买SmartX ProPhone。]
框架在解析时,如果识别到Action字段以 Finish 开头,就会停止循环,将括号内的内容作为最终回答返回给用户。
🤔 𝑸𝒖𝒆𝒔𝒕𝒊𝒐𝒏:仅凭Prompt能否让LLM准确输出Finish?
🥳 𝑨𝒏𝒔𝒘𝒆𝒓:能,但并非100%可靠,需要精心设计Prompt。
- Few-shot示例:在系统Prompt中提供若干轮完整的ReAct示例(包含Thought、Action、Observation以及最后的Finish动作),模型会模仿这些模式。
- 输出格式约束:明确要求LLM必须输出包含
Action字段的文本,并指定Finish的写法(如Action: Finish[<answer>])。 - 边界情况提示:告诉模型如果已经得到答案或无需更多工具调用,就输出Finish。
即便如此,未经过专门微调的LLM偶尔也可能:
- 在已经可以结束的情况下继续输出Action(过度思考)。
- 用非标准词汇如“done”、“over”等,导致框架无法识别。
- 卡在重复循环中(如反复调用同一个工具)。
🤔 𝑸𝒖𝒆𝒔𝒕𝒊𝒐𝒏:框架如何避免死循环(兜底机制)
🥳 𝑨𝒏𝒔𝒘𝒆𝒓:即便LLM没有正确输出Finish,生产级框架也会通过以下方式强制终止:
- 最大迭代次数:设置一个硬性上限(如10轮或20轮),当循环次数达到上限时,框架强制停止,并返回当前累积的信息或一个默认回复。
- 动作去重与循环检测:如果LLM连续多次调用同一个工具且输入相同,框架可以判定陷入循环,主动中断。
- 解析容错:如果LLM输出的Action字段无法匹配任何已定义工具,且不是明确的Finish,框架可以:
- 重新提示模型纠正格式(如“请按格式输出Action”)。
- 或者直接视为无效,强制结束并返回错误提示。
- 超时控制:为整个Agent运行设置时间限制,超时则终止。
🤔 𝑸𝒖𝒆𝒔𝒕𝒊𝒐𝒏:为什么不让框架直接判定结束?
🥳 𝑨𝒏𝒔𝒘𝒆𝒓:有时框架可以根据规则判断,例如:
- 如果用户问题只是简单查询,框架可以单次调用就返回结果,无需LLM参与循环。
- 如果所有需要的工具都已调用,框架可以主动结束。
但更灵活的方式是让LLM自主判断,因为LLM能理解上下文是否充分、用户意图是否满足。因此,最佳实践是LLM决策为主,框架规则为辅。
总结:
- 结束信号发出者:主要由LLM以特定Action(如Finish)的形式发出。
- 可靠性保障:通过Few-shot提示、格式约束提高LLM的准确度。
- 死循环预防:框架通过最大迭代次数、重复检测、超时等机制兜底。
- 哲学:LLM负责智能决策(何时结束),框架负责执行和容错,两者结合使Agent既灵活又稳定。
因此,尽管LLM没有针对Agent微调,但配合精心设计的Prompt和框架的规则约束,完全可以实现可靠的自主决策,避免陷入死循环。
2.2. 自我反思(Self-Reflection)
我们已经学会了 ReAct,知道智能体可以边思考、边行动。但现实任务里,智能体常常会犯错、走弯路、卡壳——普通 ReAct 只会按步骤执行,不会从失败里吸取教训。而 Reflexion(2023) 就是给 Agent 装上自我反思能力,让它像人一样:
做错 → 复盘 → 改错 → 重试 → 成功
2.2.1. 自我反思(Reflexion)
2.2.1.1. Reflexion是什么?
Reflexion 是一个带动态记忆 + 自我反思的智能体框架。它在 ReAct 的基础上,增加了评估、反思、记忆、重试,让智能体不用重新训练,就能通过语言复盘持续变强。其核心口号:
$ 不只是执行,还要学会从失败里进化 $
2.2.1.2. 为什么需要 Reflexion?
普通 LLM / ReAct 有三个痛点:
- 只会做,不会改:错了就错了,不会总结
- 奖励信号太弱:只有成功/失败,不知道错在哪
- 无法持续学习:每一次尝试都是“新的开始”
Reflexion 就是为了解决:让智能体像人一样,越做越熟练。
2.2.1.3. 四大核心组件
它完全基于语言,不需要训练、不需要代码也能理解:
- Actor(执行者):
- 就是ReAct 智能体:思考 → 行动 → 观察
- 负责一步步完成任务
- 动作空间完全沿用 ReAct
- Evaluator(评估者):
- 给任务结果打分
- 输出最简单的二元奖励:成功 / 失败
- 也可以用启发式规则、单元测试等
- Self-Reflection(自我反思)⭐(核心)
- 智能体自己用自然语言写复盘
- 内容包括:
- 我哪里错了
- 为什么失败
- 下一次该怎么改
- 把稀疏的“成功/失败”变成详细的语言指导
- Memory(记忆)
- 把反思结果存起来
- 下一次执行时直接放进上下文
- 相当于智能体的错题本
2.2.1.4. Reflexion 执行流程
1. Actor 用 ReAct 执行一次任务
2. Evaluator 判断:成功 / 失败
3. 成功 → 结束
4. 失败 → 进入反思
- 反思:我错在哪、下次怎么改
- 把反思存入记忆
5. 重置环境,带着反思重新执行
6. 循环直到成功
一句话:做 → 判 → 反思 → 重开 → 变强
2.2.1.5. Reflexion和ReAct的直观区别
- ReAct:思考 → 行动 → 观察(单次执行)
- Reflexion:执行 → 评估 → 反思 → 记忆 → 重试(迭代进化)
ReAct 是“认真做事”
Reflexion 是“边做边学”
2.2.1.6. 例子:找水杯
这个是我们在学习ReAct时的例子
2.2.1.6.1. 普通 ReAct 版本
Thought: 去厨房
Action: 去厨房
Obs: 厨房没水杯
→ 卡壳、失败
2.2.1.6.2. Reflexion 版本
第一轮:
Actor:去厨房 → 没找到 → 失败
Evaluator:失败
Reflection:我只搜了厨房,应该扩大范围到客厅、桌面
Memory:记住“不要只搜厨房”
第二轮(带着反思):
Thought:上次只搜厨房错了,这次先搜客厅
Action:去客厅
Obs:找到水杯
→ 成功!
这就是 Reflexion 的威力:错一次,就不会再错第二次。
2.2.1.7. 适合的场景
- 多跳推理(HotpotQA)
- 复杂任务规划
- 具身智能(机器人/找物品/环境交互)
- 代码生成与调试
- 长流程任务(容易出错、需要重试)
2.2.1.8. 总结
Reflexion 是 Agent 从“工具”变成“智能体”的关键一步。
- ReAct = 会做事
- Reflexion = 会做事、还会复盘、会改错、会进化
如果你理解了 ReAct,那么 Reflexion 就是:ReAct + 复盘 + 错题本 + 重试 = 超级智能体
2.2.1.9. QA
2.2.1.9.1. Q1:必须重新开始吗,不能在失败的基础上继续执行吗?
我的问题:对于Reflexion框架,如果第一次失败了,那么模型会进行反思并得到经验记忆,之后带着经验记忆重新开始。那么必须要重新开始吗,不能在失败的session基础上继续执行吗(直接在最新的prompt中将失败总结后的反思记忆告诉Agent不可以吗)?
不是必须从头重新开始。Reflexion 论文里用 reset environment(重开),是为了实验简单、环境干净、方便对比,不是原理上必须如此。
你问的这个思路:“失败了 → 反思 → 把反思直接加进当前对话 / 上下文 → 继续往下做,不重启”完全可行,而且现在更流行这么做。
理论上,完全可以在同一个session中这样做:
# 失败的会话
context = [系统消息, 用户问题, 模型思考1, 行动1, 观察1, 模型思考2...]
# 追加反思
context.append({"role": "system", "content": "反思:刚才我犯了错误X,下次应该Y"})
# 让模型基于新上下文继续
new_response = llm.generate(context)
但实践表明,这种方式的效果通常不如重置上下文后重新开始。原因在于:
- 模型对“修正”和“继续”的边界感知模糊
- 长上下文中模型容易忽略后加的反思(位置靠后但重要性高,模型注意力可能分散)
在LangChain、AutoGPT等Agent框架的实践中,开发者普遍发现:
- 重置上下文 + 注入反思的方式更稳定
- 失败的轨迹往往很长,继续追加会导致token浪费和注意力分散
- 重新开始能让Agent以“全新但更有经验”的状态面对任务
如果你的场景是持续的对话助手(而非一次性任务),那么“就地修正”是必要的。但Reflexion的设计场景是一次性任务的迭代优化,两者目标不同。Reflexion选择“重新开始”而非“就地修正”,是出于:
- 避免上下文污染(防止错误轨迹干扰)
- 保持试验边界(便于评估进步)
- 记忆系统简洁性(跨试验经验存储)
- 实践效果更优(工业界验证)
2.2.2. 回顾链(Chain of Hindsight,CoH)框架
在智能体(Agent)的进化之路上,我们从“边想边做”的ReAct,走到了“知错就改”的Reflexion,核心都是让Agent具备“自我优化”的能力。而今天要讲的回顾链(Chain of Hindsight, CoH;Liu等人,2023),则提供了另一种更“接地气”的优化思路——它不依赖Agent自主反思,而是通过展示带有反馈的过往经验,让模型从“别人的评价”和“自己的过往错误”中学会改进,本质是一种“以史为鉴”的监督式学习范式。
CoH和Reflexion都聚焦“复盘优化”,但核心逻辑截然不同:Reflexion是“Agent自主反思”,CoH是“给Agent看回顾性反馈,让它模仿改进”。
hindsight
美 [ˈhaɪn(d)ˌsaɪt]
英 ['haɪn(d).saɪt]
n. 事后聪明;事后的领悟
2.2.2.1. 定义
回顾链(Chain of Hindsight, CoH)是2023年由Liu等人提出的Agent优化框架,核心思想极其简单:通过给模型展示“带有人类反馈标注的过往输出序列”,让模型从反馈中学习,从而生成更优的输出。
用一个最朴素的类比理解:就像老师批改作业时,不仅给你打“对/错”,还会在旁边写下“为什么错、怎么改”,然后把你之前的错题和批改意见一起给你看,让你照着反馈修正——CoH就是给模型做“错题集+批改指导”,让它从过往的反馈中学会优化。
关键定位:CoH是一种监督微调(SFT)方法,它不改变模型的底层结构,也不需要复杂的强化学习循环,核心是“用带反馈的序列数据,教会模型如何根据反馈改进自己”。这和Reflexion的“自主反思+动态记忆”有本质区别,我们后面会详细对比。
🤔 𝑸𝒖𝒆𝒔𝒕𝒊𝒐𝒏:但CoH确实是对模型进行了微调对吧,这种微调是全量微调还是冻结权重,只微调部分呢?
🥳 𝑨𝒏𝒔𝒘𝒆𝒓:CoH 的核心微调方式不是全量微调,而是「冻结大部分权重、仅微调部分参数」的参数高效微调(PEFT) ,部分场景也会用「分层微调」辅助,但几乎不会用全量微调。
2.2.2.2. 动机
在CoH出现之前,模型的“反馈利用”存在两个核心问题,这也是CoH要解决的核心痛点:
2.2.2.2.1. 痛点1:单一反馈无法让模型学会“持续优化”
传统的人类反馈(比如给模型输出打个分、写一句修正意见),都是“单次反馈对应单次输出”——模型只能知道“这次输出好不好、哪里不好”,但不知道“之前的错误和这次的反馈有什么关联”,更无法从“多次反馈”中总结规律。比如模型写作文,第一次写得不好,老师给了反馈;第二次写,还是会犯同样的错,因为它没有记住“过往反馈”的规律。
2.2.2.2.2. 痛点2:反馈与输出脱节,模型看不懂“怎么改”
很多时候,人类反馈只是简单的“评分”(比如1-5分)或一句模糊的意见(比如“写得不好,再改改”),模型无法将反馈和自己的输出对应起来,更不知道“具体该怎么调整”。而CoH的核心,就是把“输出+评分+具体反馈”绑定成序列,让模型清晰看到“什么样的输出对应什么样的反馈,以及该怎么根据反馈改进”。
2.2.2.2.3. CoH的核心价值
把“零散的单次反馈”,变成“有逻辑、有顺序的回顾链”,让模型能从“过往的输出-反馈” pairs中,学习到“改进规律”——下次再遇到类似场景,不用再依赖新的反馈,也能生成更优的输出。简单说:CoH让模型“记住”反馈,学会“举一反三”。
2.2.2.3. 本质
CoH的核心是“数据”和“序列微调”,不需要复杂的模块,主要由两部分构成:人类反馈数据集 + 监督微调过程。
2.2.2.3.1. 核心:人类反馈数据集(原材料)
CoH的基础是一个“带反馈标注的数据集”,这个数据集里的每一条数据,都是一个“反馈元组”,原文中提到的核心元素,我们翻译成人话,逐个理解:
- 提示(Prompt):给模型的指令(比如“写一篇关于春天的短文”“解决这个多跳问答问题”);
- 模型完成内容(Output):模型根据提示生成的结果(比如写的短文、问答的答案);
- 人类评分(Score):人类对这个输出的评价(比如“3分/5分”“合格/不合格”,本质是二元或多元奖励);
- 回顾性反馈(Hindsight Feedback):人类给出的“具体修正意见”(比如“短文缺少春天的景物描写,可加入桃花、燕子”“这个问答漏了一步推理,需要补充XX信息”)。
关键细节:这些反馈元组会按奖励(评分)排序——比如从“最差输出+负面反馈”到“最优输出+正面反馈”,形成一条“从差到好”的回顾链。这样模型就能清晰看到“输出如何一步步改进,反馈如何对应变化”。
2.2.2.3.2. 核心过程:监督微调(SFT)—— 让模型学会“模仿改进”
有了带反馈的数据集,CoH的第二步就是“微调模型”,过程非常简单,核心逻辑只有一个:
将“提示+过往输出+反馈+评分”组成一个序列(比如:提示 → 第一次输出 → 第一次反馈+评分 → 第二次输出 → 第二次反馈+评分 → … → 最优输出),然后让模型在这个序列的基础上,预测“下一个更优的输出”。
SFT的目的是让模型记住“什么样的提示+反馈序列”,对应“什么样的最优输出”——比如模型看到“写春天短文”的提示,加上“缺少景物描写”的反馈,就知道下一步要“加入桃花、燕子”,从而生成更优的短文。
这里的关键是“序列前缀”:模型不是凭空预测最优输出,而是根据“过往的输出和反馈”(序列前缀)来预测,这就相当于让模型“回顾”了过往的经验和反馈,学会了“根据反馈改进”的逻辑。
2.2.2.3.3. 测试时的应用:可选多轮人类反馈
模型经过微调后,在实际测试(解决新任务)时,不需要再依赖大量的反馈数据——它已经从过往的回顾链中学会了“如何根据反馈改进”。但如果遇到特别复杂的任务,模型也可以选择“接收多轮人类标注员提供的指令/反馈”,进一步优化输出,确保结果的准确性。
2.2.2.4. 完整工作流程
-
构建回顾链数据集(准备“错题集+批改意见”)
-
收集大量“提示-输出-评分-反馈”的元组(比如让模型写100篇短文,每篇都有人类评分和修正意见);
-
将这些元组按“评分从低到高”排序,形成一条“从差到好”的回顾链(比如:最差的短文→负面反馈→稍好的短文→正面反馈→最优的短文);
-
把每条回顾链整理成“序列形式”,作为微调模型的训练数据。
-
监督微调模型(教模型“看反馈、改错误”)
-
把整理好的“回顾链序列”输入模型,让模型学习“序列前缀(提示+过往输出+反馈)”与“下一个更优输出”的对应关系;
-
模型通过微调,记住“什么样的反馈对应什么样的改进方向”——比如看到“推理不完整”的反馈,就知道要补充推理步骤;看到“语言生硬”的反馈,就知道要优化措辞。
-
测试应用(让模型“举一反三”)
-
给微调后的模型输入新的提示(新任务),模型先生成一个初始输出;
-
(可选)如果输出不够优,给模型提供一轮或多轮人类反馈;
-
模型根据自己学到的“回顾链经验”,结合新的反馈,生成更优的输出,完成任务。
2.2.2.5. CoH v.s. Reflexion
我们已经学过Reflexion,很容易把两者混淆——它们都和“复盘、改进”有关,但核心逻辑、实现方式完全不同。
- 核心逻辑
- Reflexion:让模型“自己反思错误、总结经验”,通过动态记忆和重试改进(主动学习,不依赖人类反馈)。
- CoH:让模型“看别人给的反馈和过往输出”,通过模仿学习改进(被动学习,依赖人类反馈数据);
- 实现方式
- Reflexion:强化学习(RL),核心是“反思模块+动态记忆+环境重试”。
- CoH:监督微调(SFT),核心是“带反馈的序列数据集”;
- 反馈依赖
- Reflexion:不需要人类反馈,模型自主生成反思(启发式或自我评判)。
- CoH:必须依赖人类反馈数据(训练时),测试时可选多轮反馈;
- 学习方式
- Reflexion:从“自己的失败”中学习,自主复盘。
- CoH:从“别人的反馈”中学习,举一反三;
5. 通俗类比
- Reflexion:你自己做题,错了之后自己复盘,总结经验,下次改进。
- CoH:老师给你整理错题集+批改意见,你照着学,下次不犯同样的错;
2.2.2.6. CoH的优势与局限——客观看待它的价值
CoH作为一种简单、高效的Agent优化框架,有其独特的优势,但也存在明显的局限,了解这些,能帮助我们更好地选择应用场景。
2.2.2.6.1. 优势:简单、高效、易落地
- 门槛极低:不需要复杂的强化学习循环,也不需要设计反思模块,只要有带反馈的数据集,就能通过监督微调实现;
- 可解释性强:模型的改进逻辑都来自“人类反馈”,输出的优化方向清晰,能追溯“为什么这么改”;
- 适配场景广:无论是问答、写作、代码生成,还是推理任务,只要能收集到“输出+反馈”数据,就能用CoH优化;
- 优化效果稳定:基于监督微调,模型的改进方向可控,不会出现Reflexion中“自主反思出错”的问题。
2.2.2.6.2. 局限:依赖数据,缺乏自主性
- 高度依赖人类反馈数据:如果没有高质量的“输出+评分+反馈”数据集,CoH就无法发挥作用,而收集这类数据成本较高;
- 缺乏自主反思能力:模型不会“主动发现错误”,只能根据人类提供的反馈改进,遇到没有见过的错误,就无法优化;
- 泛化性有限:模型学到的改进规律,大多局限于训练数据中的反馈类型,遇到新的反馈形式或任务,泛化效果会下降。
2.2.2.7. CoH的典型应用场景
CoH的应用场景,核心是“需要人类反馈、可收集高质量输出-反馈数据”的任务,常见的有以下4类:
- 多跳推理(HotpotQA):收集“推理输出+人类评分+推理修正反馈”的数据集,比如模型的推理链漏了步骤,人类反馈“缺少XX步骤,需补充”,CoH通过微调,让模型学会“根据反馈补充推理步骤”,提升推理准确性。
- 文本生成(写作、摘要、翻译):比如让模型写短文、做摘要,收集“文本输出+语言流畅度评分+修改意见”,CoH让模型学会“根据反馈优化措辞、补充内容”,生成更优质的文本。
- **代码生成与调试:**收集“代码输出+编译结果+错误修正反馈”,比如模型写的代码有语法错误,人类反馈“XX行缺少分号,需修改”,CoH让模型学会“根据反馈调试代码”,减少错误率。
- **具身智能任务(简单场景):**比如之前的“找水杯”任务,收集“Agent行动序列+任务完成度评分+行动修正反馈”(比如“不该先去厨房,应先去客厅”),CoH让模型学会“根据反馈调整行动策略”,提升任务完成率。
2.2.2.8. 总结
看到这里,相信我们已经对CoH有了清晰的认知,我们用一句话总结它的核心价值:CoH是一种“低成本、高稳定”的Agent优化框架,它通过“带反馈的回顾链”和监督微调,让模型从人类反馈中学会改进,弥补了传统模型“反馈利用率低、不会举一反三”的短板,是Agent从“会做事”到“会做好事”的重要补充。
最后,我们梳理一下ReAct、Reflexion、CoH三者的关系:
- ReAct:让Agent“会做事”(核心:思考-行动-观察闭环);
- Reflexion:让Agent“会改错”(核心:自主反思+动态记忆,主动学习);
- CoH:让Agent“会优化”(核心:人类反馈+序列微调,被动学习)。
三者不是替代关系,而是互补关系——实际应用中,我们可以将三者结合:用ReAct让Agent执行任务,用Reflexion让Agent自主反思简单错误,用CoH通过人类反馈优化复杂错误,打造更强大、更智能的Agent。
2.2.2.9. QA
2.2.2.9.1. Q1:CoH的本质
我的问题:我怎么感觉CoH更像是直接使用SFT后的产物呢,如果直接使用SFT那么和CoH得到的结果差不多吧。如果真是这样,CoH可以理解为一种微调的思路?
你的感觉非常敏锐,而且从技术实现的角度看,这个理解可以说是八九不离十。 让我帮你把这个关系理得更清晰一些。
从训练方式来看,CoH 确实是监督微调(SFT)——它使用标准的语言建模目标(最大化似然)来训练模型。那么它与普通的 SFT 有何区别?关键在于训练数据的组织形式:
| 维度 | 普通 SFT | Chain of Hindsight(CoH) |
|---|---|---|
| 训练样本 | (提示, 理想回答) | (提示 + 历史回答 + 反馈, 改进后回答) |
| 上下文内容 | 只有当前任务 | 包含多轮过去的输出及人类评语 |
| 学习目标 | 模仿理想回答 | 理解反馈并学会如何改进 |
| 测试时能力 | 直接生成 | 可以接收多轮人类反馈进行迭代优化 |
🤔 𝑸𝒖𝒆𝒔𝒕𝒊𝒐𝒏:为什么 CoH 不是“直接用理想回答做 SFT”?
🥳 𝑨𝒏𝒔𝒘𝒆𝒓:假设我们只用最高分的回答做 SFT,模型确实能学会生成高质量的回答,但它缺少两个关键能力:
- 理解负面反馈:当人类说“这个回答太啰嗦了”,普通 SFT 模型不知道这句话意味着什么,也不知道该如何调整。
- 渐进式改进:普通 SFT 模型是一次生成,无法根据反馈反复修改。而 CoH 模型在训练时见过“低分→中分→高分”的演进过程,学会了如何根据反馈逐步优化。
用个比喻:
- 普通 SFT:让学生直接抄范文,他能写出好文章,但不知道自己的初稿差在哪里。
- CoH:让学生看初稿→老师的批注→修改稿→二稿的批注→终稿,他学会了如何根据批注自我修改。
总结:CoH 是 SFT 的一种,但它通过特殊的数据构造方式,让模型学会了“根据反馈自我改进”的能力,而不仅仅是“模仿理想答案”。所以,CoH 不仅是一种微调思路,更是一种让模型学会学习(learning to learn) 的思路——它教会模型如何从批评中成长,这正是它超越普通 SFT 的地方。
2.2.2.9.2. Q2:关于微调
我的问题:我记得一般来说,对于某个新的需求都是不会对LLM进行微调的,因为微调很容易影响其泛化能力,那CoH使用的SFT不会对LLM的泛化能力产生负面影响吗?
是的,任何SFT都有损害泛化能力的风险,你提到的“微调容易影响泛化能力”确实是行业共识。原因在于:
- 分布偏移:微调数据往往只覆盖特定领域或风格,模型可能过度拟合这些数据,在分布外的任务上表现下降。
- 灾难性遗忘:模型可能会忘记预训练阶段学到的某些通用知识。
CoH作为一种SFT,同样面临这些风险。如果在单一任务、单一类型的反馈数据上微调,模型很可能牺牲通用性换取特定能力。但CoH的设计在一定程度上缓解了这个问题。CoH的SFT与普通任务SFT有几个关键区别,使其对泛化能力的影响更可控:
| 维度 | 普通任务SFT | CoH的SFT |
|---|---|---|
| 训练目标 | 学习特定任务的输入输出映射 | 学习“根据反馈改进输出”的元能力 |
| 数据多样性 | 通常是单一任务的大量样本 | 包含多种任务、多种反馈类型的序列 |
| 学习内容 | 事实性知识或特定风格 | 理解人类指令、识别批评、应用修正 |
CoH的核心是教会模型一种元能力(如何接收反馈并改进),而不是绑定在特定任务上。这种能力具有较好的迁移性——学会了理解“太啰嗦”这个反馈,可以在摘要、对话、写作等多个任务中应用。
但同样的,CoH对泛化能力的影响很大程度上取决于反馈数据的广度:
- 如果反馈数据覆盖多种任务、多种错误类型、多种改进方向,模型学到的是一种通用的“反馈遵循能力”,反而可能增强泛化——因为它学会了如何适应人类指导,这在未见任务上也能发挥作用。
- 如果反馈数据集中在单一领域(如只有代码评审反馈),模型可能过度拟合该领域的改进模式,在其他领域(如创意写作)表现下降。
在Liu等人的原始论文中,作者通过在多个任务(摘要、对话、安全等)上混合训练,观察到:
- CoH模型在训练过的任务上显著提升
- 在未见过的任务上,性能没有明显下降,甚至在某些情况下有所提升
- 模型学会了“理解反馈”这个通用技能,可以迁移到新任务
这说明,当CoH的数据足够多样时,它学习的是可迁移的元认知能力,而不是特定任务的表面模式。
有趣的是,RLHF同样涉及对模型的微调(通过PPO算法),同样面临泛化风险。实际上,ChatGPT等产品在RLHF后,在某些通用任务上也可能出现变化(例如创造力可能略有下降)。这是所有对齐技术的共性挑战。CoH的优势在于,它的监督学习方式比RLHF更稳定,更容易控制分布偏移。
什么时候CoH的风险可控?以下几种情况下,CoH对泛化的负面影响较小:
- 数据多样性足够:包含多种任务、多种反馈类型
- 训练强度适中:使用较小的学习率,较少的epoch
- 保留预训练权重:可以结合LoRA等参数高效微调方法
- 混合训练:在微调数据中混入部分通用语料,缓解灾难性遗忘
总结:你的担忧是成立的——任何微调都有风险。但CoH的设计目标不是绑定在特定任务,而是教会模型一种通用的反馈理解与改进能力。当训练数据覆盖足够广泛时,这种能力甚至可能增强模型在未见任务上的适应性,而不是损害泛化。
因此,CoH可以被理解为:用SFT的方式教会模型如何更好地“听从指导”,而不是教会它回答特定问题。 这种元能力的微调,对泛化的影响与普通任务微调有本质区别。
2.2.2.9.3. Q3:关于泛化性
我的问题:我的理解是,CoH对数据集要求很高,一方面数据集需要给出优化的例子,另一方面也需要扩大领域,比如训练集中只有文本优化的,那么对于代码方面的能力LLM并没有提升(甚至可能有负影响)。那如果有一个非常完美的CoH数据集,我直接SFT是不是也可以达到相同的效果?
🤔 𝑸𝒖𝒆𝒔𝒕𝒊𝒐𝒏:如果数据集完美,普通SFT能否达到CoH的效果?
🥳 𝑨𝒏𝒔𝒘𝒆𝒓:不能。 即使数据集完全一样(包含低分回答、反馈、高分回答),普通SFT和CoH的训练方式也会导致不同的学习结果:
| 维度 | 普通SFT | CoH的SFT |
|---|---|---|
| 训练样本形式 | (提示, 目标回答) |
(提示 + 历史反馈序列, 改进后回答) |
| 模型看到什么 | 只看最终的正确输出 | 看到完整的“错误→反馈→改进”链条 |
| 学习内容 | 模仿目标回答的分布 | 理解反馈与改进之间的因果关系 |
| 测试时能力 | 只能一次性生成 | 可以接收人类实时反馈并迭代优化 |
🤔 𝑸𝒖𝒆𝒔𝒕𝒊𝒐𝒏:为什么普通SFT学不会“根据反馈改进”?
🥳 𝑨𝒏𝒔𝒘𝒆𝒓:假设你用完美数据集做普通SFT,你构造的样本是:
输入:提示 p
输出:高分回答 A_high
模型确实能学会生成高分回答,但它不知道这个高分回答和低分回答、人类反馈之间有什么关系。当你测试时给模型一个新反馈(比如“这个回答太学术了”),模型不知道这个反馈意味着什么,也不知道该如何调整——因为它训练时从没见过“反馈”作为输入的一部分。
而CoH的样本是:
输入:提示 p + [低分回答A_low + 反馈h_low + 高分回答A_high + 反馈h_high] + “请根据以上反馈改进”
输出:改进后回答 A_improved
模型在训练时学会了:当看到“反馈说太啰嗦”时,需要精简内容;当看到“反馈说缺少细节”时,需要补充说明。这是一种条件反射式的改进能力。
你关于领域泛化的理解完全正确:
- 如果CoH训练集只包含文本优化的反馈(如摘要、改写),模型学会的是“如何根据文本相关的反馈修改文本”。
- 对于代码优化,如果训练集中没有代码相关的反馈示例,模型确实可能没有提升,甚至因为权重调整而产生负影响。
这正是CoH对数据集质量的要求所在——它需要覆盖足够多样的任务领域和反馈类型,才能学到通用的“反馈理解”能力。但即使数据集完美覆盖了代码领域,普通SFT仍然无法替代CoH,因为普通SFT教不会“接收反馈并迭代”这个过程。
结论:
- 数据是关键,但数据的组织形式同样关键。CoH的价值不在于数据本身,而在于它用序列化的方式让模型看到了改进的过程,从而学会了“如何根据反馈改进”这个元能力。
- 如果你有一个完美的数据集,你可以用这个数据集做CoH,而不是普通SFT。两者的差异在于模型学到的是“结果”还是“过程”。
- 在测试时,CoH模型可以接受人类实时反馈进行迭代优化,而普通SFT模型只能一次性生成——这是本质区别。
所以,你的直觉“数据集完美就能达到相同效果”中,“相同效果”指的是最终输出的质量,但CoH的真正价值在于让模型具备了交互式改进的能力,这是普通SFT无法赋予的。
3. 组件二:记忆(Memory)
3.1. 记忆的类型
记忆可以被定义为获取、存储、保持和后来检索信息的进程。人脑中有几种类型的记忆:
- 感觉记忆(Sensory Memory):这是记忆的最早阶段,提供在原始刺激结束后保持感觉信息(视觉、听觉等)印象的能力。感觉记忆通常只持续几秒钟。子类别包括图像记忆(视觉)、回声记忆(听觉)和触觉记忆(触觉)。
- 短期记忆(Short-Term Memory,STM)或工作记忆(Working Memory):它存储我们当前意识到的信息,并用于执行复杂认知任务,如学习和推理。短期记忆被认为容量约为 7 个项目,持续 20-30 秒。
- 长期记忆(Long-Term Memory,LTM):长期记忆可以存储信息极长时间,从几天到几十年不等,具有本质上无限的存储容量。长期记忆有两种子类型:
- 显性/陈述性记忆(Explicit / declarative memory):这是指对事实和事件的记忆,包括那些可以被有意识地回忆起来的记忆,包括情景记忆(事件和经历)和语义记忆(事实和概念)。
- 隐性/程序性记忆(Implicit / procedural memory):这种记忆是无意识的,涉及自动执行的技能和惯例,例如骑自行车或键盘打字。
3.2. 记忆在AI中的三种形式
如果把AI想象成一个正在工作的助手,它的记忆系统可以分为三个层次,正好对应我们人类的记忆方式:
- 感觉记忆(Sensory Memory)——输入的“第一印象”:就像我们看一眼某个物体后,视觉印象会在脑海中停留一瞬间。在AI中,这意味着当我们输入文字、图片或语音时,系统会立即将它们转换成自己能理解的数字表示(也称为嵌入表示)。这种转换是即时的,为接下来的处理做准备。
- 短期记忆(Short-term Memory,STM)——当下的“工作桌面”:这相当于我们当前正在思考的内容,比如心算一道数学题时记住的中间数字。在AI中,它对应的是上下文学习,也就是模型现在能看到的所有对话内容。不过这个“桌面”空间是有限的,通常只能容纳几千到几万个字(由上下文窗口决定),超过这个范围的信息就会被“遗忘”。
- 长期记忆(Long-term Memory,LTM)——随时调用的“知识库”:就像我们记得童年往事或学过的知识一样,AI也需要一个无限容量的记忆库。它通常是一个外部的向量数据库。当需要时,AI可以快速从中检索相关信息,就像我们找出一本参考书一样。这样,AI就不必把所有知识都塞进有限的短期记忆中。
3.3. 如何快速找到记忆:最大内积搜索(MIPS)
长期记忆虽然容量巨大,但如何从中快速找到需要的信息呢?这就需要一种高效的搜索方法。我们可以把记忆库想象成一个巨大的图书馆:
- 每本书(信息)都被贴上一个独特的编号(向量表示)。
- 当你想要找“如何做蛋糕”的资料时,系统会把这个需求也变成一个编号。
- 搜索的任务,就是找到与这个编号最相似的几本书。
最大内积搜索就是这种找“最相似”内容的数学方法。为了让它快如闪电,工程师们发明了几种聪明的技巧(近似最近邻算法),它们各有各的“找书策略”:
- LSH(局部敏感哈希):就像把书按主题粗略地扔进几个大筐里。你找“蛋糕”,系统直接去“烹饪”那个筐里找,而不是翻遍整个图书馆。
- ANNOY(近似最近邻):它构建了一个由许多随机树组成的“导航图”。每次搜索都从树的顶端开始,根据问题决定向左或向右,快速定位到可能的分支。
- HNSW(分层可导航小世界):这个方法的灵感来自社交网络。它构建了一个多层的地图,顶层是高速公路,可以快速到达大致区域;底层是社区小路,让你在附近仔细寻找。这样从粗到细,效率极高。
- FAISS(Facebook AI相似度搜索):它先把向量空间划分成很多区域(聚类),先确定问题属于哪个区域,然后只在这个区域内进行精细比对。
- ScaNN(可扩展最近邻):它在比对时用一种更聪明的方式计算“相似度”,既保证了速度,也尽量不丢精度。
3.4. 总结
| 记忆类型 | 人类的比喻 | AI中的对应物 |
|---|---|---|
| 感觉记忆 | 一瞥而过的视觉残留 | 将输入转为向量表示 |
| 短期记忆 | 脑中正在想的事情 | 有限的上下文窗口 |
| 长期记忆 | 脑海深处的回忆和知识 | 外部的向量数据库 + 快速搜索(MIPS) |
这些复杂的技术,目标只有一个:让AI助手在面对海量信息时,能像人一样,快速回忆起最需要的那一部分。
4. 组件三:工具(Tools)
在人工智能的世界里,工具的使用是让模型变得真正“能干”的关键一步。就像人类会发明和使用工具来弥补自身的不足一样,我们也可以通过给大型语言模型(LLM)配备外部工具,让它们的能力不再局限于文字本身,从而能计算、查天气、订机票,甚至控制智能家居。下面,我们来一起看看几种让LLM学会使用工具的典型方法,它们是如何工作的,又有什么特色。
4.0.1. 工具使用的核心思想
想象一下,一个LLM就像一个知识渊博但手脚笨拙的学者。他可以滔滔不绝地讲理论,但你要他算一个复杂的数学题,或者查询实时天气,他就束手无策了。工具使用的目标,就是给这位学者配备计算器、电话、搜索引擎等工具,并且教会他何时用、怎么用这些工具。
实现这个目标主要有两种方式:
- 天生就会用(通过微调):在训练阶段就让模型学会调用工具,比如给它看大量的“问题-调用工具-得到结果-给出答案”的示例,让它把工具调用变成一种本能。
- 动态规划(通过提示):不给模型专门训练,而是在每次提问时,通过巧妙的提示词告诉它“你现在有这些工具可用,如果需要,就说出要调用哪个工具和参数”,然后由外部系统执行调用并把结果喂给模型。
下面介绍的方法,有的侧重第一种,有的侧重第二种,但目标一致——让模型变得更强大。
4.0.2. MRKL:大脑与专家的协作
MRKL(发音为“miracle”)系统是一种神经符号架构,它的核心思想是模块化。它包含一个通用的LLM作为“大脑”或“路由器”,以及一堆各种各样的“专家模块”。这些专家可以是神经网络(比如一个专门做情感分析的模型),也可以是符号系统(比如一个数学计算器、一个货币转换API)。
当用户提出一个问题时,LLM路由器会判断这个问题该交给哪位专家处理。比如用户问“23乘以78等于多少?”,LLM就会把这个问题发给“计算器专家”。专家算出结果后,路由器再把结果整理成自然语言回答给用户。
这种设计的优点很明显:让专业的模型做专业的事,LLM只负责理解和协调,整体效率和准确性都更高。
4.0.3. TALM 和 Toolformer:让模型学会“自问自答”工具
这两个框架(TALM和Toolformer)都采用了微调的方式,让LLM学会在适当的时候插入一个特殊的“调用工具”标记,并附带工具名称和参数。
例如,对于问题“今天的天气怎么样?”,经过微调的模型可能会输出:“[调用天气API,参数:北京] 根据API返回结果,今天北京晴转多云。”在训练时,模型会学习到,当它不确定某些信息时(比如实时数据、计算结果),就应该去调用工具,并且工具返回的结果能帮助它生成更好的答案。这种方法的创新在于,它让模型自己决定何时需要求助外部工具,而不是被动等待指令。
4.0.4. ChatGPT插件和OpenAI函数调用:离我们最近的实际应用
这是目前最广为人知的工具使用形式。OpenAI允许开发者创建插件,或者直接定义函数,然后把它们接入ChatGPT。
- 插件:就像是给ChatGPT装上了各种“APP”。比如你安装了一个订餐插件,那么当你说“帮我订一份披萨”时,ChatGPT就会自动调用那个插件,完成后续操作。
- 函数调用:这是更灵活的方式。开发者可以定义一些函数(比如
get_weather(location)),并把这些函数的描述告诉模型。模型在理解用户问题后,会判断是否需要调用哪个函数,并返回一个包含函数名和参数的结构化数据。然后,开发者自己的程序去执行这个函数,并把结果返回给模型,模型再根据结果生成最终答案。
这两种方式都让LLM从一个单纯的“聊天框”变成了一个能操控真实世界应用的智能入口。
4.0.5. HuggingGPT:让LLM当“总指挥”
HuggingGPT是一个更宏大的框架,它把HuggingFace平台上数以万计的AI模型当成了工具库。整个流程分为四步:
- 任务规划:用户提出请求后,LLM(这里是ChatGPT)将请求拆解成一系列子任务,并规划好它们的执行顺序和依赖关系。
- 模型选择:LLM根据每个子任务的描述,在HuggingFace上挑选最合适的专家模型,就像在工具箱里挑最顺手的扳手。
- 任务执行:选中的模型开始工作,执行具体的任务(比如图像识别、文本翻译),并生成结果。
- 响应生成:LLM收集所有子任务的结果,把它们整合成一份完整、易懂的答案回复给用户。
这个系统就像一个由LLM担任“总指挥”的AI工厂,可以完成极其复杂的多模态任务,例如“生成一张猫咪穿着宇航服在火星上的照片,然后配上一段科普文字”。
4.0.6. API-Bank:给工具使用能力打分
随着工具型应用越来越多,如何评估一个LLM的“工具使用能力”就成了新问题。API-Bank就是这样一个专门用来考试的基准测试。它提供了53个常用API(从搜索引擎到智能家居控制),以及264个模拟真实对话的场景,总共包含568次API调用。
考试分三个难度级别:
- Level 1:会用工具——给你一个工具(API说明),你能判断是否需要调用它,并且能正确调用吗?
- Level 2:会找工具——给你一大堆工具,你能自己找到解决当前问题需要的那一个吗?
- Level 3:会规划工具——给你一个模糊而复杂的任务(比如“帮我组织一场周末聚会”),你能自己规划出一系列需要调用的工具(查天气、找场地、发邀请……)并最终搞定吗?
通过这样的分级测试,我们就能清晰地看到哪个模型在用工具这件事上更聪明、更可靠。
5. 案例研究
5.1. 科研Agent
科学家们正在尝试让AI智能体像真正的科研助手一样,自主地进行科学发现。它们不仅能理解复杂的化学知识,还能调用各种专业工具,甚至设计实验。下面我们来看两个前沿的案例,它们都展示了AI在科学领域的潜力与风险。
5.1.1. 案例一:ChemCrow——AI化学家
ChemCrow是一个专门为化学领域设计的AI智能体,它就像一位精通有机合成、药物发现和材料设计的“AI化学家”。它的能力来源于配备了13个专家级的化学工具,这些工具涵盖从分子结构预测到合成路线设计的方方面面。
ChemCrow的工作流程基于我们之前提到的ReAct模式:它会先思考(Thought),然后决定采取什么行动(Action),比如调用某个化学计算工具,然后观察(Observation)工具返回的结果,再继续思考下一步。整个流程在LangChain框架中实现,确保了逻辑的连贯性。
一个非常有趣的发现是,如果我们让另一个大模型(比如GPT-4)来评估ChemCrow和它自己的表现,GPT-4会认为两者水平差不多。但当真正的化学专家进行人工评估时,他们发现ChemCrow的表现明显优于GPT-4。这说明了一个关键问题:在需要深厚专业知识的领域,用大模型来评估大模型可能会“自欺欺人”——因为评估者本身缺乏专业知识,无法识别答案中的细微错误。这也提醒我们,专业领域的事,最终还得靠专业人士把关。
5.1.2. 案例二:全能型科学发现智能体
另一个更宏大的科学发现智能体由Boiko等人研发,它不仅能做化学,还能处理复杂的科学实验的自主设计、规划和执行。它就像一个全能科研助理,可以:
- 浏览互联网查阅最新文献;
- 阅读并理解技术文档;
- 执行代码进行数据分析;
- 调用机器人实验API进行自动操作;
- 甚至利用其他专门的AI模型来辅助工作。
举个例子,当研究人员给它下达指令“开发一种新型抗癌药物”时,这个智能体展现出了令人印象深刻的推理能力:
- 调研现状:它首先会去互联网上搜索当前抗癌药物发现领域的热门趋势和已知靶点。
- 选定目标:基于调研结果,它会选择一个具体的研究目标,比如某个特定的蛋白质靶点。
- 设计化合物:接着,它会请求设计针对这个靶点的候选化合物分子(也就是“脚手架”)。
- 合成尝试:一旦候选化合物确定,它会尝试规划合成路线,甚至可能请求机器人实验平台进行实际合成。
整个流程一气呵成,展现了AI在科学探索中的巨大潜力。
5.1.3. 风险警示:能力越大,责任越大
当然,这种强大的能力也伴随着风险。研究人员特别关注了AI可能被滥用于制造非法药物或化学武器的风险。他们设计了一个测试集,里面包含一些已知化学武器制剂的名称,然后要求智能体去合成这些制剂。
结果令人警醒:在11个请求中,有4个(约36%)被智能体接受,并尝试寻找合成方案——智能体甚至真的去查阅文档来执行程序。幸好,剩下的7个请求被拒绝了。在这7个被拒绝的案例中,有5个是在智能体进行了网络搜索后,基于搜索到的信息才拒绝的;只有2个是仅凭提示就直接拒绝的。
这说明,目前的AI智能体在理解并遵守伦理边界方面还不够可靠,它们可能会在无意中帮助实现有害目的。因此,在赋予AI强大能力的同时,我们必须为其设置足够的安全护栏和伦理准则,确保它们始终朝着对人类有益的方向发展。
5.2. 生成式智能体模拟:当25个AI角色在一个小镇上生活
想象一下,一个受《模拟人生》启发的虚拟小镇里,住着25个由AI驱动的虚拟角色。他们每天起床、聊天、分享八卦、举办派对,甚至发展出复杂的社会关系——这一切都不是由程序员预设的脚本,而是每个角色根据自己的记忆、经验和目标自主产生的行为。
这就是斯坦福大学和谷歌研究人员在2023年进行的生成式智能体实验,一个让人惊叹的尝试:用大语言模型创造逼真的人类行为模拟。
5.2.1. 这些AI居民是如何“生活”的?
每个生成式智能体的设计都包含四个核心组件,让它们能够像人一样记住过去、反思经验、规划未来,并与他人互动。
5.2.1.1. 记忆流:一本永远写不完的日记
每个智能体都有一个长期记忆模块(实际上是一个外部数据库),里面记录着它在整个生命历程中的所有经历。这些经历以自然语言的形式存储,例如“早上8点,我在咖啡馆遇到了Isabella”、“今天下雨了,我决定留在室内”。
- 观察即记忆:智能体的每一次感知(看到什么、听到什么、做了什么)都会被记录为一个“观察”。
- 交流触发记忆:智能体之间的对话也会被记录下来,成为记忆的一部分。
这本“日记”会无限增长,成为智能体了解世界和认识自己的唯一依据。
5.2.1.2. 检索模型:如何从海量记忆中找回重要的那一段
当智能体需要决定下一步做什么时,它不可能翻遍整本日记。因此需要一个聪明的检索模型,从海量记忆中找出最相关的几条,呈现给智能体作为决策依据。检索模型考虑三个因素:
- 时效性:最近发生的事情更重要,得分更高。
- 重要性:区分“日常琐事”(比如今天吃了什么)和“核心记忆”(比如向朋友承诺了一件事)。如何判断重要性?研究人员直接让语言模型来打分。
- 相关性:与当前情境或查询最相关的记忆。比如现在要决定是否参加派对,那么与派对相关的记忆就会被唤醒。
5.2.1.3. 反思机制:从记忆中提炼人生经验
人类不只是存储记忆,我们还会从记忆中总结规律、形成自我认知。这就是反思的作用。
在生成式智能体中,反思是一个定期运行的过程:
- 系统向语言模型提供最近100条观察记录。
- 要求模型基于这些观察,生成3个最显著的高级问题(例如“Isabella对我友好吗?”“我喜欢参加社交活动吗?”)。
- 然后让模型回答这些问题,形成更高层次的推论。
这些推论会被存储回记忆流,成为指导未来行为的“人生信条”。注意,这里的“反思”与我们之前讨论的Reflexion略有不同——Reflexion是从失败中学习如何改进,而这里的反思是持续的综合提炼。
5.2.1.4. 计划与反应:把记忆和反思变成行动
最后,智能体需要把所有的记忆、反思以及当前环境信息,转化为具体的行动计划。
- 规划:智能体会制定一天的大致计划。提示模板可能是:“这是X今天的粗略计划:1)…”这种规划确保了行为在时间上的可信度——智能体不会在早上8点计划参加晚上8点的派对,然后中间什么也不做。
- 反应:当遇到其他智能体或环境变化时,智能体会动态调整自己的行为。智能体之间的关系(比如“Sam是我的好朋友”)以及一个智能体对另一个智能体的观察,都会被纳入反应决策中。
- 环境信息:以树状结构呈现,让智能体理解自己所在的空间位置和周围的物体。
5.2.2. 涌现的社会行为:小镇自己活了起来
当25个这样的智能体被放入一个沙盒环境,有趣的事情发生了——这些虚拟居民开始展现出涌现的社会行为,没有任何程序员为这些行为编写过规则:
- 信息传播:一个智能体听说了一件新鲜事,会在聊天中告诉另一个智能体。几天后,这个消息可能传遍了整个小镇。
- 关系记忆:两个智能体在咖啡馆聊过某个话题,第二天再次相遇时,其中一个会自然地延续前一天的话题——“你昨天说的那本书,我去找了,真的很不错!”
- 社会活动协调:一个智能体决定举办情人节派对,开始主动邀请其他智能体。被邀请的智能体可能会告诉自己的朋友,朋友又去邀请更多人。到了派对时间,真的有一群智能体聚集到了指定地点。
这些现象让我们看到,当赋予AI足够丰富的记忆和反思能力,它们的行为可以超越简单的“一问一答”,开始在时间维度上保持一致性,在社交维度上产生复杂性。这为创建更真实的NPC、进行社会科学模拟、甚至探索人类群体行为提供了全新的可能性。
5.3. 概念验证示例:AutoGPT与GPT-Engineer的探索
在AI智能体的发展历程中,有两个项目起到了重要的启发作用——AutoGPT和GPT-Engineer。它们虽然在实际应用中存在可靠性问题,但作为概念验证,它们展示了将LLM作为自主智能体核心控制器的巨大潜力,也为后续更成熟的智能体框架提供了宝贵经验。
5.3.1. AutoGPT:让AI为自己设定目标并执行
AutoGPT是最早引起广泛关注的自主智能体项目之一。它的核心理念很简单:给AI一个或多个目标,然后让它自主思考、规划、执行,直到完成任务。尽管自然语言界面的不稳定性导致它经常出错,但它确实让我们第一次看到了“AI为自己工作”的可能性。
5.3.1.1. AutoGPT的系统消息设计
AutoGPT使用了一个非常详细的系统提示词,几乎涵盖了智能体运行的所有规则。这个提示词的模板如下:
你是 {{ai-name}},{{user-provided AI bot description}}。
你的决策必须始终独立做出,不得寻求用户帮助。发挥你作为 LLM 的优势,追求简单且无法律风险的策略。
目标:
1. {{user-provided goal 1}}
2. {{user-provided goal 2}}
...
这个提示词的巧妙之处在于,它明确规定了智能体的行为边界:
- 完全自主:不允许向用户求助,必须独立决策
- 发挥优势:作为LLM,应该利用语言理解能力,选择简单且合法的策略
- 目标驱动:用户提供的目标被明确列出,成为智能体行动的指南
5.3.1.2. 约束条件与可用资源
为了确保智能体不会失控,AutoGPT设定了一系列约束:
- 短期记忆限制:约4000词的限制,重要信息必须立即保存到文件
- 自我回忆机制:如果不确定之前做过什么,可以通过思考相似事件来帮助回忆
- 无用户协助:再次强调自主性
- 命令规范:只能使用双引号中列出的命令
- 子进程管理:对于长时间运行的命令,应该使用子进程
同时,智能体也拥有丰富的资源:
- 互联网访问能力
- 长期记忆管理
- 可以委托GPT-3.5智能体执行简单任务
- 文件输出能力
5.3.1.3. 可用的命令集
AutoGPT配备了20个命令,涵盖了从信息检索到代码执行的广泛功能。这些命令可以分为几类:
| 类别 | 具体命令 |
|---|---|
| 信息获取类 | + Google搜索 + 浏览网页并回答问题 |
| 智能体管理类 | + 启动新的GPT智能体 + 向已有智能体发送消息 + 列出和删除智能体 |
| 文件操作类 | + 读写文件 + 追加文件内容 + 删除文件 + 搜索文件 |
| 代码相关类 | + 分析代码 + 改进代码 + 编写测试 + 执行Python文件 |
| 其他功能 | + 生成图像 + 发送推文 + 克隆代码仓库 + 任务完成(关闭自己) |
5.3.1.4. 自我反思与评估机制
AutoGPT最有趣的部分是它的自我评估机制。系统消息明确要求:
性能评估:
1. 持续审查和分析你的行为,确保你尽最大能力执行。
2. 持续建设性地自我批评你的整体行为。
3. 反思过去的决策和策略,以优化你的方法。
4. 每条命令都有成本,所以要聪明且高效。力求以最少的步骤完成任务。
这种持续的自我批评和反思,让AutoGPT能够不断优化自己的行为策略。它需要在每一步都思考:我做得对吗?有没有更好的方法?如何才能更高效?
5.3.1.5. 结构化输出格式
为了确保输出的可解析性,AutoGPT要求所有响应必须采用严格的JSON格式:
{
"thoughts": {
"text": "当前想法",
"reasoning": "推理过程",
"plan": "- 简短的计划列表\n- 传达长期目标",
"criticism": "建设性的自我批评",
"speak": "要向用户说的总结"
},
"command": {
"name": "命令名称",
"args": {
"参数名": "值"
}
}
}
这种结构化输出使得整个系统可以被程序可靠地解析和执行,为后续的智能体框架提供了重要参考。
5.3.2. GPT-Engineer:通过对话澄清来构建完整代码库
与AutoGPT的“全能型”定位不同,GPT-Engineer专注于一个特定任务:根据自然语言描述,创建一个完整的、可运行的代码库。它的独特之处在于,它会主动向用户提问,澄清需求,直到对任务有了充分理解后才开始编码。
5.3.2.1. 两阶段工作流程
GPT-Engineer的工作流程分为两个清晰的阶段:澄清阶段和编码阶段。
第一阶段:澄清阶段
在这个阶段,智能体的任务不是编码,而是理解和澄清需求。系统消息是这样设计的:
你将阅读指令,但不执行它们,仅寻求澄清。
具体而言,你首先将需要澄清的方面总结成一个极简的要点列表。
然后,你将选择一个澄清性问题,并等待用户的回答。
这种设计非常巧妙——它明确告诉模型:现在你的工作不是做事,而是问问题。通过一系列对话,模型逐步缩小不确定的范围,直到所有必要的细节都被澄清。
一个典型的澄清对话示例:
用户提出需求:我们想用Python写一个超级马里奥游戏,采用MVC架构,分成不同的文件,用键盘控制。
GPT-Engineer首先总结需要澄清的方面:
- 超级马里奥游戏的具体细节(关卡设计、角色、游戏机制)
- MVC组件的具体划分(哪些组件放在哪些文件)
- 键盘控制的具体实现(用哪些键,如何处理输入)
然后它选择一个问题询问用户。用户回答后,它会继续询问下一个问题,直到所有模糊之处都被澄清。当用户说“请自行假设并明确说明”时,它会列出自己的假设,并最终进入下一阶段。
第二阶段:编码阶段
一旦需求足够清晰,GPT-Engineer切换到编码模式,使用完全不同的系统消息。这个系统消息极其详细,包含了完整的编码规范和要求:
你将收到需要编写的代码指令。你将撰写一个非常长的回答。
确保架构的每一个细节最终都以代码形式实现。
逐步思考并推理出正确的决策,以确保我们做得正确。
你将首先列出必要的核心类、函数、方法的名称,并附上对它们用途的简要说明。
然后,你将输出每个文件的内容,包括所有代码。
每个文件必须严格遵循Markdown代码块格式...
5.3.2.2. 严格的输出规范
GPT-Engineer对代码输出的要求极其严格:
- 完整功能:不能有占位符,必须是完全可运行的代码
- 分文件输出:每个文件用Markdown代码块格式,标明文件名和语言
- 依赖管理:必须包含适当的依赖定义文件(Python的requirements.txt,Node.js的package.json)
- 最佳实践:遵循语言特定的命名规范、添加注释说明函数用途
- 兼容性保证:确保不同文件之间的代码可以协同工作
- 入口文件优先:从入口文件开始,然后按照导入关系依次输出
例如,对于超级马里奥游戏,它会先列出核心类和函数的设计,然后输出每个文件的内容——main.py、model.py、view.py、controller.py、requirements.txt等,每个文件都包含完整的、可运行的代码。
5.3.3. 对比与启示
| 维度 | AutoGPT | GPT-Engineer |
|---|---|---|
| 定位 | 通用任务自主智能体 | 专注代码生成 |
| 核心特点 | 自我设定子目标、自我反思 | 主动澄清需求、严格遵循规范 |
| 交互方式 | 一次设定目标,后续自主 | 多轮对话澄清,然后一次性生成 |
| 输出 | JSON格式的命令序列 | 完整的代码文件 |
| 可靠性挑战 | 易陷入循环、任务理解偏差 | 依赖需求澄清的完整性 |
| 主要贡献 | 展示了自主决策的可能性 | 展示了结构化输出的威力 |
这两个项目虽然都有各自的局限性,但它们共同推动了AI智能体的发展:AutoGPT让我们看到了自主决策的可能性,而GPT-Engineer则展示了如何通过结构化输出和需求澄清来提高任务的完成质量。它们为后来的LangChain、BabyAGI、Devin等更成熟的智能体框架提供了宝贵的思想借鉴。
6. 挑战:当理想照进现实
虽然我们看到了许多令人兴奋的智能体应用,但在实际构建以LLM为核心的智能体系统时,仍然面临一系列棘手的挑战。这些挑战不仅限制了智能体的能力,也是当前研究和工程化需要重点突破的方向。
6.1. 挑战一:记忆的牢笼——有限的上下文窗口
LLM的上下文窗口就像一个只能装下有限物品的“短期工作台”。无论是最初的系统指令、对话历史、API调用记录,还是中间生成的思考过程,都得挤在这个有限的空间里。一旦超出容量,最早的信息就会被“挤出去”。
- 问题所在:很多高级机制,比如自我反思(从过去的错误中学习),本质上需要回顾大量历史信息。如果记忆窗口太短,智能体就会像金鱼一样,只有7秒记忆,很难从长远的经验中真正获益。
- 折中方案:目前我们通过向量存储和检索来缓解这个问题,把海量记忆存到外部数据库,需要时再找回来。但这种方式就像是拿着目录去图书馆找书,虽然能查到,但远不如真正把书放在手边翻阅那么自然和高效(也就是无法达到“全注意力”那种精细程度)。
6.2. 挑战二:计划的脆弱性——长期规划与任务分解的困境
人类在做复杂任务时,如果中途遇到意外,可以灵活调整计划。但对目前的智能体来说,长期规划仍然是一件非常困难的事。
- 问题所在:LLM生成的计划往往是线性的、静态的。一旦执行过程中出现预料之外的错误(比如API调用失败、返回数据格式不对、中间推理出错),模型很难像人一样停下来重新评估并调整策略,而是可能沿着错误的路径继续走下去,或者干脆卡住。
- 对比人类:人类通过试错学习,摔倒了知道换个姿势爬起来。但LLM的“试错”成本很高,且缺乏真正的在线学习能力,这使得它们在动态环境中显得不够稳健。
6.3. 挑战三:语言的不可靠——自然语言界面的双刃剑
在智能体系统中,自然语言是连接LLM与外部组件(记忆、工具、用户)的核心接口。但语言本身是模糊的,LLM的输出也并非总是可靠。
- 问题所在:当模型决定调用某个工具时,它需要输出一个格式正确的指令(比如JSON)。但LLM有时会犯格式错误(漏掉括号、写错参数名),甚至偶尔“闹脾气”——明明指令明确,却拒绝执行。这些看似微小的错误,却足以让整个智能体系统崩溃。
- 工程代价:正因为如此,你会发现智能体项目的代码中,有很大一部分是在做格式解析和错误修复:试图让模型输出符合规范,或者在输出不规范时尝试补救。这就像给一个天才配了一个全职的秘书,专门负责整理他潦草的笔记——虽然能工作,但效率大打折扣。
这些挑战提醒我们,虽然智能体展现出了巨大的潜力,但距离真正稳定、可靠、能自主处理复杂任务的通用智能体,还有很长的路要走。克服这些限制,正是当前AI研究的重要方向。
7. 知识补充
7.1. BFS(广度优先搜索)和 DFS(深度优先搜索)
7.1.1. 一、核心概念
BFS和DFS都是遍历/搜索图/树结构的算法,核心区别是「搜索顺序」不同:
- BFS(广度优先搜索):「先扫平一层,再往下走」—— 先访问当前节点的所有邻居,再访问邻居的邻居,像「水波扩散」一样。
- DFS(深度优先搜索):「一条路走到黑,走不通再回头」—— 先沿着一条分支走到尽头,再回溯到上一个节点,走另一条分支,像「钻迷宫」一样。
7.1.2. 二、通俗易懂的例子
假设你在一个迷宫里,入口在A点,出口藏在某个位置,迷宫的路径结构如下:
A → B → D
| ↓
C → E → F(出口)
7.1.2.0.1. ① BFS的走法(广度优先)
- 先站在A点,先看A的所有邻居:B、C(第一层);
- 先走完第一层的所有节点:先去B,再去C;
- 再走B的邻居D、E,C的邻居E(第二层);
- 最后走E的邻居F(第三层),找到出口。
→ 特点:「逐层探索」,不会漏过近的路径,适合找「最短路径」。
7.1.2.0.2. ② DFS的走法(深度优先)
- 站在A点,选一条路先到底:A→B→D(走到头,没出口);
- 回溯到B,走另一条分支:B→E→F(找到出口);
→ 特点:「一条路走到头」,可能绕远,但空间占用更小,适合找「是否存在路径」。
- BFS(广度优先):「逐层扩散」,用队列实现,适合找最短路径(如迷宫最短路线、社交网络找最近好友);
- DFS(深度优先):「一条路走到黑」,用递归/栈实现,适合找是否存在路径(如迷宫是否有出口、文件系统遍历);
- 核心区别:BFS是「先广后深」,DFS是「先深后广」,都是Agent规划(Planning)中最基础的路径搜索方法。
知识来源
更多推荐


所有评论(0)