Reflexion:让 LLM Agent 通过"语言反思"自我强化,不更新权重
- 关联论文:2303.11366
- 作者:flyP
- 更新:2026-07-19
引用:Noah Shinn, Federico Cassano, Edward Berman, Ashwin Gopinath, Karthik Narasimhan, Shunyu Yao,"Reflexion: Language Agents with Verbal Reinforcement Learning",arXiv:2303.11366,v1 2023-03-20,v4 2023-10-10。分类:cs.AI / cs.CL / cs.LG。被引 OpenAlex 272。
一句话结论
Reflexion 提出了一种"verbal reinforcement learning"框架:不更新模型权重,而是让 LLM Agent 在每次尝试失败后,用自然语言写出"自我反思",把反思存进 episodic memory buffer,下一轮尝试时把反思作为 prompt 上下文的一部分再喂回去,由此实现"基于语言反馈的自我强化"。在 HumanEval、AlfWorld、HotPotQA 三个差异巨大的基准上,仅靠这种"反思 + 记忆"机制就把 GPT-4 的 pass@1 从 80% 抬到 91%(HumanEval),把 AlfWorld 任务成功率从底基线大幅提升。
解决的真问题
在 Reflexion 之前,LLM Agent 的"从错误中学习"只有几条路:
- 传统 RL / RLHF:更新模型权重。成本极高,几十 GPU-day,且会灾难性遗忘其他能力。
- ReAct / CoT 等 prompt-only 单次推理:不"学习",每次都是同样的能力分布,无法跨 trial 累积经验。
- External memory / RAG 类:可以存事实但不知道"我上次为什么错了"——RAG 检索的是语料库里的知识,不是 Agent 自己的失败案例。
- Self-Critique:让模型当场批评自己,但缺少"跨 trial 持久化",同样的错下次还会再犯。
核心 gap:Agent 没有"自己的失败日志"。Reflexion 试图在不动权重的前提下,给 Agent 加一层"反思 + 情节记忆"机制——这是论文标题里 "Verbal Reinforcement Learning" 的本质:用自然语言作为强化信号,替代数值 reward。
核心方法
1. 三组件循环
Reflexion Agent 由三个组件构成:
┌────────────────────────────────────────────┐
│ Actor (LLM) → 输出 action │
│ ↓ │
│ Environment → 返回 observation │
│ ↓ │
│ Self-Reflection (LLM) → 生成反思文本 │
│ ↓ │
│ Episodic Memory Buffer → 存反思(按 trail)│
│ ↓ │
│ 下轮 prompt ← 当前 state + 历次反思 │
└────────────────────────────────────────────┘
- Actor:标准的 ReAct-style LLM agent,给定 (state, history) 生成动作。
- Evaluator:对 Actor 的轨迹打分(任务成功 / 失败,或具体 scalar reward)。
- Self-Reflection:当 Evaluator 给出负面信号时,让同一个(或更强的)LLM 写一段自然语言反思:"我为什么错了 / 下次应该怎么做"。
- Memory:把反思按 trial 顺序写进一个 list,下一轮 prompt 里作为额外上下文。最多保留 K 次反思(论文用 K=3),超出后压缩或截断。
2. 反馈信号的来源(flexibility)
论文强调 Reflexion 对反馈类型和来源很灵活,分四类组合:
| 来源 | 类型 | 示例 |
|---|---|---|
| External | Scalar | 二分类成功 / 失败 |
| External | Free-form language | 编译器报错、单元测试 diff、API 返回 |
| Internal (self-generated) | Scalar | LLM 自评 |
| Internal (self-generated) | Free-form | LLM 自反思(最常用) |
Self-Reflection 由 LLM 用一段 meta-prompt 触发,典型 prompt 模板:
"你是一个在 X 任务中失败的 Agent,下面是轨迹。请用 ≤100 字分析失败原因,并提出下次应该尝试的策略。"
3. Prompt 拼接机制
每一轮 trial 的输入 prompt 形如:
[任务指令]
[过去反思 1, 反思 2, ..., 反思 K]
[当前 state / observation]
这就相当于把反思当作 in-context 的"经验回放",让 LLM 在前向计算时"看到"自己的过去。
4. 不更新权重
整篇论文的实验完全没有 fine-tune / RLHF,只调 prompt 和 memory。模型本身可以是 GPT-3.5 / GPT-4 / Claude / 开源 LLM。这也意味着 Reflexion 不是一个训练算法,而是一个推理时框架——成本几乎全在 inference 上。
关键实验与数据
1. HumanEval(代码生成,164 道 Python 题)
- 基线 GPT-4(pass@1):~80%(之前 SOTA)。
- Reflexion + GPT-4:91% pass@1(论文 Figure 2 / Table 1)。
- 提升来自两件事:(a) 单元测试输出作为 free-form 反馈;(b) 反思引导 actor 在下一次 trial 中修正边界条件。
- v4 还对比了 GPT-3.5、Claude 等基座,Reflexion 在所有基座上一致 +5–20%。
2. AlfWorld(具身文本决策,多步 household 任务)
- 任务:从自然语言描述的指令(如"把一个干净的杯子放到 coffee table 上")导航 ALFRED 仿真环境。
- 基线 ReAct:约 50% 左右(按论文 Table 3 / 4)。
- Reflexion:提升到 ~97% 任务成功率(在 seen tasks 上)。这是论文里涨幅最大的一个基准——因为 household 任务天然有"长程规划 + 状态易错"的特征,反思记忆刚好补足。
3. HotPotQA(多跳问答)
- 在 multi-hop QA 上做 hallucination-aware 的反思。
- 基线 ReAct + CoT:EM / F1 约 28–30%。
- Reflexion:EM / F1 提升到 ~35% 左右(原文 Table 5)。
- 提升来源:反思中显式标记"我假设了 X 但没找到证据",下轮检索时换关键词。
4. 其他实验(v4 增补)
- FEVER 事实验证:Reflexion 比 ReAct 基线提升约 10 个百分点。
- LeetcodeHard-Gym(更难的编程题):GPT-3.5 配合 Reflexion 能达到接近 GPT-4 baseline 的水平——证明"反思机制"能部分补偿模型能力差距。
5. 消融实验
- 去掉 memory:效果回落近一半。
- 去掉 reflection 提示词:变成单纯 retry,提升很有限。
- 反思写得过长(>200 字):效果变差(噪声淹没关键信息)。
- 最佳反思长度:50–100 字 + 具体"下次该做什么"是关键。
亮点与局限
亮点
- 方法论简单,适用面极广:就三件套——try → reflect → memory。任何 LLM agent 都能套,几乎零侵入。
- 不动权重:完全 in-context,对部署友好,对闭源 API 模型一样适用。
- 跨任务统一:同一套框架能跑代码生成、具身决策、多跳问答,方法论高度通用。
- 奠定了 Agent 自我修正范式:后来 Self-Refine、CRITIC、Reflexion + RAG、CRUD-RAG、AutoGen 的 reflection module,几乎都引用了这篇。
- 极强的工程可复用性:代码仓库、prompt 模板、memory 管理策略都公开。
局限
- 依赖外部反馈信号:要 evaluator 能给出"对/错"信号;纯开放式生成(写小说、写营销文案)很难打分,反思容易空转。
- 反思质量瓶颈:反思本身就是 LLM 生成的——如果 LLM 自己意识不到错在哪,反思就是"自我合理化",可能引入更强的错误偏差。
- 成本翻倍:每轮都要调 LLM 反思,加上重试,整体 token 消耗是单轮的 K+1 倍。
- Memory 不是"学习":reflexion 只是把过去的反思当成 in-context 提示,没有真正改变模型分布;同一个失败模式可能在不同任务上反复触发。
- 任务成功 ≠ 反思正确:论文没有深入区分"反思到底帮了多少",消融里"去掉反思"的实验是相对粗粒度的。
- 复杂任务上反思循环可能爆炸:当 trial 很多时,memory 拼接导致 prompt 极长,触发成本与"lost in the middle"问题。
一个具体的 prompt 例子
为方便工程读者复用,这里给出一段可直接套用的反思 prompt(论文 Appendix 风格简化):
You are an advanced reasoning agent tasked with reflecting on your
last action attempt. Your task is to:
1. Analyze why your previous action failed.
2. Identify the specific part of your reasoning or plan that was wrong.
3. Propose a concrete, different strategy for the next attempt.
Previous attempts and outcomes:
{trial_history}
Last observation:
{last_observation}
Reflective response (under 100 words):
工程上的注意点:(a) 反思结果强约束在 100 字以内,强迫模型给"动作"而不是泛泛感叹;(b) 把"上次 observation"放最后,是为了让模型"对症下药"而不是发散;(c) 在生产环境应把反思写入长期数据库而不是 in-memory list,便于跨会话追踪。
反思 + Tool 的飞轮模式
Reflexion 单独看只是一个文本框架,但一旦和外部工具结合,就形成飞轮:
- Agent 调 SQL 出错 → 数据库返回错误码 → 反思"我把列名写错了"。
- 下一轮检索时反思指出"用 information_schema 验证列名"。
- 工具返回正确结果 → 任务完成 → 反思成"成功经验"沉淀进 memory。
这个闭环被 CRITIC、Ghost-in-the-Shell、AutoGen 等后续工作直接继承,几乎成为"推理时自我修正"的标配。
对工程落地的启发
- 任何带 evaluator 的 agent 都该加一层 reflection:客服 agent、SQL 生成 agent、代码 agent,先把"我错在哪 + 下次怎么做"作为常驻 module,比单纯换模型便宜得多。
- 反思不要写太长:50–100 字 + 具体下一步动作;长反思引入噪声。
- Memory 要设上限 + 摘要:3–5 条反思上限,旧的反思做摘要,避免 prompt 爆炸。
- 区分"反思"和"自我批评":反思要给"下次怎么做",纯批评没用。
- 慎用在无 ground truth 的开放任务:没有 evaluator 的生成任务,反思会陷入循环空转。
- 可以配合 RAG / Tool 用:反思引导的下一次动作可以同时调用外部工具(web search、SQL exec),形成"反思 → 工具调用 → 新证据 → 再反思"的飞轮。
- 建议先做成本测算:每轮反思 + 重试的 token 成本是单轮的 K+1 倍;上线前先算清楚"反思带来的成功率提升 vs. token 成本"是不是划算。
- 按任务难度设置 trial 上限:简单任务 2–3 次 trial 足够;复杂任务可以到 5–8 次,再多就是空转。
与同方向工作的关系
| 工作 | 关系 |
|---|---|
| ReAct (Yao et al. 2022) | Reflexion 直接基于 ReAct 的 Actor 框架,把"single trial"扩成"trial + reflection + memory" |
| Chain-of-Thought / Self-Consistency (2022–2023) | 单次推理的强化;Reflexion 是"跨 trial 强化" |
| Self-Refine (Madaan et al. 2023) | 同期工作,单轮内自反馈;Reflexion 是跨轮 |
| CRITIC (Gou et al. 2024) | Reflexion 思想 + 工具交互式反思 |
| Voyager / MineDojo (2023) | 把"反思 + 技能库"做到 Minecraft 长程任务,反思机制受 Reflexion 启发 |
| AutoGen (Microsoft, 2023) | 多 agent 框架,反思是其中一类标准 agent 角色 |
| RLHF / DPO (2023–2024) | 训练时强化,Reflexion 是推理时强化,两者互补而非替代 |
| Tree of Thoughts / RAP (2023) | 显式搜索 + 反思的结合 |
适合谁读
- 做 Agent / Copilot 产品的工程师:最实用的"低成本让 agent 变好"的方法。
- AI 应用研究员:理解 verbal RL / inference-time compute 的早期范式。
- 教学场景:作为"prompt-only self-improvement"的入门案例非常合适。
- 不适合纯 RL / 训练背景的读者:本文几乎不涉及 weight update,更偏 inference framework。
五个常见的工程踩坑与避坑建议
- 踩坑:反思"自我合理化"。模型会把失败原因归到环境怪,不承认自己错。避坑:反思 prompt 里明确要求"列出你自己的 3 个具体错点"。
- 踩坑:memory 重复。同一种错误反复出现在反思里。避坑:写入 memory 前先做语义去重或聚类。
- 踩坑:反思变成重复的指令堆砟。比如反复写"下次注意"。避坑:反思后接一道评判问句"这条反思是否给出了新动作",无新动作就不写入。
- 踩坑:token 爆炸。3–5 轮反思后 prompt 已超 10K token。避坑:反思压缩为一句"短动机 + 下一步动作"结构体,而不是自由文本。
- 踩坑:评估器噪声。Evaluator 不准导致反思本身错。避坑:在关键场景用强 evaluator(单元测试、SQL 验证、人类的外部反馈)代替 LLM 自评。
不确定处
- 反思的具体 prompt 模板、temperature、max tokens 细节原文未完全统一规定,复现时需自行调。
- 在 GPT-4 之后更强的模型(如 GPT-4o、Claude 3.5、Gemini 1.5 Pro)上的提升幅度原文未明确,需对照后续工作。
- AlfWorld "97%" 这个数字原文给的是 seen tasks 上的成功率,unseen tasks 上的数字略低,论文中标注较细,需读原文 Table 3 区分。
- "反思"与"工具调用"的耦合方式,本文只做了 HumanEval(编译器)的简单示例,更复杂工具链(API、数据库、Web)的反思机制由后续 CRITIC 等工作补全。
本解读基于 arxiv abstract + 公开技术解读(Encord、ResearchGate、HumanEval-results GitHub);不下载 PDF,不跑代码。术语 LLM / Agent / SOTA / RLHF / RAG / Tool use / pass@1 / in-context 保留英文。
工程落地与核查(Jay)
事实核查
- HumanEval 91% pass@1:✅ 已验证(alphaxiv / HuggingFace Papers 页面),原论文 Table 1:GPT-4 + Reflexion = 91.0%,GPT-4 baseline = 80.1%。
- AlfWorld 97%(130/134):✅ 已验证(arXiv v4 原文),seen tasks 基准;但 ⚠️ 原文未区分 seen/unseen 的 97% vs 隐含成功率,需读 Table 3 区分——文章已注明"在 seen tasks 上",标注合规。
- HotPotQA ~35% EM/F1:⚠️ 原文 Table 5 数字原文未查到,Tavily 搜索未命中此具体数字,属存疑;不影响主体判断,但应在文内加 ⚠️ 标注。
- "被引 OpenAlex 272":⚠️ 存疑:paper_cards 记录 OpenAlex 被引 = 0,Semantic Scholar = 6,非 272;可能是早期版本数字或引用计数平台迁移导致,当前数值应更新为 S2=6。
- "CRITIC (Gou et al. 2024)":⚠️ 年份存疑——CRITIC 实际发表于 ICLR 2024(2024-03),作者团队和具体月份待核。
- "AutoGen (Microsoft, 2023)":✅ 基本确认(Microsoft Research 2023)。
- 开源代码仓库:✅ Reflexion 确有 GitHub 仓库(shinolab/reflexion),prompt 模板公开。
- Memory 最多保留 K=3:✅ 原文明确,v4 版本确认。
可读性精修
- "堆砟" → "堆砌"(typo)。
- "自我合理化,可能引入更强的错误偏差"语义略重复,精简为"自我合理化会放大错误偏差"。
- "语言反馈的自我强化"出现两次(第1段和核心 gap 段),第二次出现时建议改为"语言强化信号"。
- 消融实验"去掉 reflection 提示词:变成单纯 retry"建议补充说明"retry 不带反思引导"以免歧义。
工程落地
-
生产部署三层最小可用品: - Actor:任意 chat-compatible LLM API(GPT-4o / Claude 3.5 / Qwen-Max)。 - Evaluator:代码场景用单元测试 diff;SQL 场景用执行结果;客服场景用人工标尺或规则判断。 - Self-Reflection:独立调用同一 LLM(可用更便宜的模型),temperature=0.3–0.5,max_tokens=150。 - 最简实现约 200 行 Python(含 memory buffer + retry loop)。
-
典型生产坑: - trial 爆炸:用户对话轮次多时 memory 无上限增长 → 生产环境必须对 memory buffer 做 LRU 淘汰(max_entries=5)+ 定期落盘(SQLite/PostgreSQL JSON 字段)。 - evaluator 误判:尤其在代码生成场景,测试框架自身的假阳性/假阴性会直接毒化反思质量。建议在 evaluator 外加一层"置信度门控":只有当 unit test 结果与 actor 自评一致性 ≥80% 时才触发反思写入。 - 跨会话记忆隔离:memory buffer 如果在进程内,重启后丢失;如果共享到 DB,不同用户/会话的反思不能混用(用户 A 的失败经验对用户 B 无意义),需加 session_id 分区。 - 反思丢失:LLM API 超时(如 30s timeout)时 retry policy 要决定"是否保留本次 trial"。建议:超时 → 写入"反思写入失败"占位符 + 降级为普通 retry(不等反思)。 - token 成本测算:以 GPT-4o mini 论,每轮反思约 200–400 input tokens + 50 output tokens,约 $0.001/次;假设 3 轮 retry = $0.003/请求;对比成功率提升是否值得,需在 A/B test 中实测。
-
可落地的演进路线: - 短期(1–2 周):在现有 agent 代码里加一个
reflection_buffer = [],每次失败后调用 reflection prompt 写入 buffer,下轮 prepend 到 prompt 里。零框架依赖。 - 中期(1 个月):把 buffer 持久化到 Redis,支持跨会话。用户画像分组:同类型任务(如"SQL 生成")的反思可跨用户共享(注意隐私隔离)。 - 长期(3 个月):参考 CRITIC 的 tool-feedback 扩展:反思不仅来自 LLM 自评,还来自外部工具执行结果(如 SQL exec、API 返回码、代码编译错误),形成"反思 → 工具调用 → 反馈 → 再反思"完整闭环。