你的 AI 为什么总在同一个坑里栽跟头?一文讲透 Reflexion:让大模型学会「记仇」的魔法
你有没有过这种崩溃时刻:
让 AI 写段代码,它报错了;你原样重试一遍,它犯了完全一模一样的错。或者你让它去办件事,它走错一步,你让它再试一次,它又从同一个错误开头。
这不是你 prompt 写得不好。这是大模型出厂时就带的一个「天性缺陷」:
它是一个极强的「一次性」推理器,却是个「从不记仇」的推理器。
第一次答错,第二次它照样踩同一个坑,不会从自己的失败里学半点东西。
2023 年,一篇 NeurIPS 论文(Shinn 等,Reflexion)给出了一个特别反直觉也特别实用的解法——不重新训练模型,只是让它在失败后写一张「错题笔记」,下次带着笔记重来。
今天我用一个贯穿全篇的真实例子,把这套「让 AI 开窍」的机制一次讲透。所有数据均来自原始论文,可核对。
〇、一个让 AI 当场露怯的题
让一个机器人去「拿一个苹果」。
环境设定:屋里有 3 个房间——卧室(抽屉、衣柜)、厨房(冰箱、橱柜)、客厅。苹果其实在厨房的冰箱里。判定器很简单:机器人最后手里有没有苹果?
这是论文真实 benchmark(AlfWorld:在屋里找/搬物体)的翻版。接下来你看它怎么翻车。
一、先记住一个大前提:模型只是子程序,框架才是大脑
很多人以为,Reflexion 是模型「自己在反思、自己变聪明了」。
错。模型从头到尾只干一件事:接到一段提示词,吐出一段文字。至于「失败之后要不要总结、总结完要不要重来」,全是你写的外部代码在管。
最朴素的样子就是 ReAct(目前几乎所有 Agent 的内核):你看到模型「思考 → 行动 → 观察」一步一步走,以为它在想;其实「走完这步看结果、不对就换下一步」这个循环,是你写的一个 while 循环在驱动。模型只是被反复调用的子程序。
一句话定调:模型是子程序,框架才是大脑。 Reflexion 的全部魔法,都是在这颗大脑外面套的那层循环里发生的——模型权重一次都没更新过。
二、ReAct 的死穴:多跑几轮也没用
还是「拿苹果」。机器人脑子里跑的是 ReAct 那套「思考→行动→观察」:
思考:苹果应该在卧室里,先去卧室。
行动:走到卧室,打开抽屉。 观察:袜子,没有。
思考:那看看衣柜。
行动:打开衣柜。 观察:衣服,没有。
思考:卧室没有,再去客厅看看。
行动:走到客厅,翻茶几。 观察:遥控器,没有。
→ 步数用完了,手里还是空空。
判定:FAIL(手里没有苹果)。
到这里,ReAct 把这次经历全丢了。你要是再启动一次 ReAct,它还会先去卧室翻抽屉——因为「白跑一趟」的教训它根本没存下来。
这就是 ReAct 的命门:跑完一轮就结案,这次犯的错,下一轮照样犯。
很多人下意识觉得:「让 ReAct 多跑几轮不就行了?」不行。ReAct 的「多步」是在同一次尝试内部纠错,跑完这一轮,教训随之消失。下一轮是全新独立的一次,照样踩坑。你多跑几轮 ReAct ≠ Reflexion,除非你手动加「失败→写笔记→回灌下轮」——那你已经自己重写了一遍 Reflexion。
Reflexion 要补的,就是这个洞。
三、Reflexion 怎么补洞:Trial 1 失败,写一张笔记
还是「拿苹果」。Reflexion 分两轮(论文里叫 trial)。
Trial 1(和 ReAct 一模一样地失败)
机器人照旧:翻卧室抽屉(没有)→ 翻衣柜(没有)→ 去客厅翻茶几(没有)→ 步数用完,空手。判定:FAIL。
失败后,Reflexion 多做了一步:写反思
它把整段失败经历想一遍,生成一段可复用的教训:
「我先在卧室翻抽屉、衣柜,又去客厅,全白费。苹果从来不在卧室/客厅的家具里——它通常在厨房的冰箱里。下次别乱翻,直接去厨房开冰箱。」
这段教训被塞进一个列表 M(这就是它的「记忆」)。此时 M = [ 这条教训 ]。
关键点:机器人的「脑子」一点没变(权重冻结),它只是把这句话写进了 M。所谓「学习」,不过是 M.append(教训) 这一行。
Trial 2(带着笔记重来,成功)
这次拼给机器人的提示词里,自动附上了 M 的内容:
(系统自动附上教训)你之前发现:苹果在厨房冰箱,别去卧室客厅乱翻。
思考:直接去厨房开冰箱。
行动:走到厨房,打开冰箱。 观察:冰箱里有苹果!
行动:拿起苹果,交给用户。
→ 任务完成。
判定:SUCCESS(手里有苹果),结束。
整个过程只用了 2 轮,没有微调、没有 GPU。看一眼「记忆」长什么样:
Trial 1 后: M = []
Trial 2 前: M = [ "苹果在厨房冰箱,别去卧室客厅乱翻" ]
Trial 2 后: 成功,M 不再增长
如果 Trial 2 还失败(比如冰箱也空了),就会再 append 一条新教训,下一轮提示词里同时带着两条——这就是「越试越准」的来源。
一句话:Reflexion 干的事,就是让机器人在 Trial 1 白跑一圈后,自动写一张「苹果在厨房、别去卧室乱翻」的便签塞进记忆,Trial 2 带着便签直接去厨房就成功了——而传统 ReAct 重试会再白跑一遍卧室。
四、它的「记忆」到底记在哪?
很多人以为记忆「存在模型里」。错。Reflexion 的权重从头到尾冻结,没有任何 model.update()。那张「便签」最朴素地活在你程序运行时的一个文本列表里:
M = [ "苹果在厨房冰箱,别去卧室客厅乱翻" ]
它真正「生效」的地方,是每一轮被原样拼进发给 LLM 的提示词(上下文窗口)。模型能「记住」教训,是因为这次输入里就有这句话,不是它自己记住的。
三个实现真相:
- 不是存在模型权重:模型冻结,没有参数更新。
- 活在程序内存 + 上下文窗口:最朴素就是个 Python 列表,每轮拼进 prompt。
- 默认不持久化:程序退出
M就清空;上下文撑爆了,实战会搬进向量库只召回相关几条。
论文还明确:记忆条数有上限 Ω(通常 1–3),防 prompt 太长。这埋下一个隐患——下面会说。
一个被网文讲错的点:有人说记忆分「短期/长期/情景三层」。论文其实只定义 2 类——短期记忆 = 本轮轨迹,长期记忆 = 反思文本;episodic(情景记忆)只是长期记忆缓冲区的别称,不是第三类。别被误导。
五、它是怎么「判定成败」的?
Reflexion 不规定你用什么评估器,只要求有个「成功/失败」信号。论文里给了三类(都基于真实实验):
- 确定性判定(最稳):比如代码能编译吗、单测过没过、到没到目标状态。拿苹果例子里就是「手里有没有苹果」。
- 标量奖励:游戏得分、环境回报。
- LLM 当裁判(最弱):没有现成验证器时,让另一个 LLM 读轨迹判成败——开放任务才用,但裁判本身可能误判。
论文还明确支持「内部模拟」反馈:没有真实环境/验证器时,让 LLM 自己模拟环境反馈当奖励信号。这让它能在「没有编译器/单测」的任务里也跑,但更依赖模型不自欺。
因果链:整个循环质量的上限,由评估器决定。验证器准,反思就有准绳;验证器烂,反思就跟着跑偏。这也正好框定了它的适用边界——必须有便宜可靠的自动验证器,反思循环才有「咬点」。
六、它底层到底怎么跑?一张执行时序图
整个流程就是一个外层 Trial 循环包着一个内层 ReAct 循环,加上两次 LLM 调用。CPU 一行一行执行:
第 0 步 · 启动
M = [] # 情景记忆清空
t = 1 # 第几轮尝试
第 1 步 · 进入 Trial 1
内层清空:τ = []
内层循环(ReAct 式):用 ctx = 任务 + M + τ 拼 prompt → 调 LLM → 出一步
环境执行 → 返回观察 → 重复直到完成或步数到顶
第 2 步 · 评估(不调权重) score = Evaluator(τ) → 失败
第 3 步 · 失败分支(关键) r = reflect_llm(任务, τ, 反馈) → 生成「教训」
M.append(r) → 记忆里现在有 1 条
第 4 步 · 回到第 1 步,但 t=2 这次拼 prompt 时带上 M(含教训)
第 5 步 · 再评估 成功→结束;又失败→再生成教训,t=3……直到成功或撞上限
三个关键特征:
- 内层先完整跑完,外层才判断:不会「走一步失败就反思」,而是整轮跑完、统一评估。
- 每次 Trial 都是「从头重跑」:失败不会在半路续跑,而是带着记忆从任务起点再来一遍。
- 权重全程冻结:你能在执行流里找遍,也找不到任何一处梯度更新。
七、它解决了什么痛点?
| 痛点 | 没有 Reflexion | 有 Reflexion |
|---|---|---|
| 首错率高但「给个提示就对」 | 模型卡在第一次的错误里,只能靠人重问 | 自动生成「我哪步错了」的提示,下一轮带着走 |
| 用了 API 模型、不能微调 | 想提升只能换更贵的模型或做 SFT 训练管线 | 权重冻结,纯靠上下文里的反思文本提效 |
| 跨尝试没有记忆 | 每轮都从零开始,重复踩坑 | 情景记忆保留失败经验,越试越准 |
| 失败不可解释 | 只知道「不对」,不知道「为什么」 | 反思是可读文本,能审计、能调试、能定位到具体步骤 |
传统强化学习(RL)的痛点在于:微调大模型要海量样本 + 昂贵的梯度训练,对 GPT-4 这种体量的模型基本不现实;而且一个 20 步任务只给一个 0/1 奖励,模型不知道哪一步错了(信用分配难题)。Reflexion 用一段文字反馈直接指向错误步骤(论文称之为「语义梯度」),信息密度远高于标量奖励。
八、它既是「范式」也是「框架」
这点很多人搞混层级,说清楚:
- 学习范式层:Verbal Reinforcement Learning(语言式强化学习)——用自然语言反馈当「梯度」,替代传统基于梯度的 RL。
- 架构设计模式层:Andrew Ng 将其列为 4 大 Agent 设计模式之一「Reflection」;Reflexion 是该模式最经典、最早的系统性实现。
- 具体框架层:落到工程,就是 Actor + Evaluator + Self-Reflection + 情景记忆 的可运行闭环。
一句话:Reflexion = 「语言式强化」这套学习范式 + 「Reflection」这个设计模式 + 第一个把这套思想落地的具体框架。值得提一句,它和 ReAct 是同一批作者(最后一位作者 Shunyu Yao 也是 ReAct 作者)——理解这点,才懂为什么它的内层直接复用 ReAct。
九、论文实测:它到底有多能打
数据来自原始论文(NeurIPS 2023),可核对:
| 任务 | 结果 |
|---|---|
| HumanEval 代码生成 | 91% pass@1,超过当时 GPT-4 的 80% |
| AlfWorld 决策(屋里找/搬物体) | 比 baseline 高 22%(12 步内) |
| HotPotQA 多跳问答 | 高 20% |
论文的 baseline 就是 plain ReAct——也就是说,它亲自验证过「光靠 ReAct 多跑几轮不够,必须加那层反思+记忆才拿到增益」。
十、它的坑:什么时候别用
诚实的边界,必须讲:
- 局部最优 / 记忆中毒:一条错误反思会被存进
M(上限仅 1–3 条),反而锁死错误路径。记忆小,留一条错的比留十条对的更致命。 - 上下文会膨胀:反思越攒越多,prompt 变长变贵,需摘要 / 向量检索 / 裁剪。
- 强模型才有用:自我反思是强模型涌现能力,小模型连自己错哪都看不准,用了反而更差。
- 记忆默认任务内易失:换任务
M清空,不会自动跨任务积累成「技能库」。 - 比原地调试贵:每次 Trial = 整轮重跑 + 一次额外反思调用;必须设
max_trials护栏。
决策口诀:「有自动判定 ✕ 首错率高 ✕ 模型够强 ✕ 不微调」四个 yes 才上;没有验证器、要固化权重、要实时——都别用。
十一、它和谁长得像?别再认错
- ≠ ReAct:ReAct 是单次内的「思考→行动→观察」循环,跑完即忘;Reflexion 在 ReAct 外层加 Trial 循环 + 记忆。Reflexion 的内层就是 ReAct。
- ≠ Self-Refine:Self-Refine 是生成→自己给反馈→在同一份输出上原地改稿;Reflexion 是整轮失败→从头重跑→教训存记忆喂下轮。一个是「改稿」,一个是「重做 + 记笔记」。很多人把他俩当一回事,机制其实不同。
最后:一张速查表
Reflexion 是什么 不调权重,用自然语言反思(错题笔记)强化 Agent
内层循环 = ReAct(思考→行动→观察)
外层循环 = Trial 循环:评估→反思→记笔记→带笔记重跑
记忆住哪 程序内存的文本列表 M + 拼进 prompt;2 类(短期轨迹/长期反思)
评估器 确定性 / 标量 / LLM裁判;需「成败信号」
最大卖点 无训练、即时生效,把可校验难任务的准确率拉起来
致命前提 必须有便宜可靠的自动验证器
别用场景 无验证器 / 要固化权重 / 实时 / 弱模型
实测 HumanEval 91% / AlfWorld +22% / HotPotQA +20%(baseline=纯ReAct)
Reflexion 不是换个提示词就能触发的魔法。它需要你写一段外部控制器代码:反复调模型、跑评估器、失败就生成反思、把反思塞进记忆、带着记忆重来。
它的共同敌人,也不是模型「不够聪明」,而是同一个:模型不会从自己的失败里学。
ReAct 给了它「走一步看一步」的循环;Reflexion 让它「记仇」——失败了写张便签,下次别再栽同一个跟头。
如果你身边还有人用「重试一遍」硬刚同一个错误,把这篇转给他——他差的不是更好的模型,而是一个会记仇的推理脚手架。
更多推荐
所有评论(0)