生成比评价难。Reflection 就是利用这个不对称
有一个反直觉的事实:一个 LLM 评价自己刚写的答案,经常比第一次直接生成答案要好得多。
这不是什么玄学。背后的原因一句话能说清:生成比评价难。第一次生成时,模型面对无限多的可能性,要从 token 概率分布里采样出一条路径。做评价时,要判断的空间小很多——给定一个已经写好的答案,只需要判断"它好不好、哪里不好"。
这个不对称性是所有 Reflection 模式的理论基础。这一篇讲透三种相关的范式:Self-Critique、Reflexion、Evaluator-Optimizer,以及什么时候反思真的有用、什么时候是白花 token。
最朴素的 Self-Critique
最简单的反思模式就两步:生成 → 批评 → 修订。
def self_critique(task: str, rounds: int = 2):
draft = llm(f"完成这个任务:{task}")
for _ in range(rounds):
critique = llm(f"""这是一份草稿,请挑出其中的问题:
任务: {task}
草稿: {draft}
从正确性、完整性、清晰度三个维度挑问题。如果没有问题,直接回答 'NO_ISSUES'。""")
if "NO_ISSUES" in critique:
break
draft = llm(f"""请根据批评修改草稿:
任务: {task}
当前草稿: {draft}
批评意见: {critique}""")
return draft
短短 15 行,就把输出质量提升了一个台阶。对文本生成类任务(写邮件、写代码、写文案)普遍有 10~30% 的质量提升。
但有几个细节值得说:
必须有明确的"终止条件"。上面的 NO_ISSUES 是一个简单但有效的信号。没有它,模型会无限批评下去——因为它总能找到"还可以更好"的地方。
评价维度要具体。只说"挑毛病"会让模型说些"这里可以写得更生动"这种没用的废话。给定三到五个具体维度,批评就落到实处。
轮数不要太多。2~3 轮是甜点,超过就边际递减。经验上第一轮进步最大,第二轮小幅,第三轮往后经常变差(改得过度,引入新问题)。
Reflexion:为失败积累经验
2023 年的 Reflexion 论文把反思推到了更有意思的地方——反思不只是当前这次的改,而是为下次留下经验。
它的做法是:Agent 跑完一次任务失败了,不是简单 retry,而是先写一段"失败反思"存到 memory 里,下次任务开始前把这段反思注入到 prompt 里。
class ReflexionAgent:
def __init__(self):
self.memory: list[str] = [] # 存历史反思
def run(self, task: str):
prompt = self.build_prompt(task)
trajectory = self.execute_trajectory(task, prompt)
if self.is_success(trajectory):
return trajectory
# 失败了,写一段反思
reflection = llm(f"""你刚刚失败了。
任务: {task}
你的执行过程: {trajectory}
反思一下:
1. 哪一步开始偏离了正轨?
2. 是什么认知导致了这个偏离?
3. 下次遇到类似任务应该怎么做?
用 3 句话简明地写,会被放进未来的 prompt""")
self.memory.append(reflection)
return self.run(task) # 带着新反思重试
def build_prompt(self, task: str):
lessons = "\n".join(self.memory[-5:])
return f"过去的教训:\n{lessons}\n\n任务:{task}"
这个架构的精髓在于:模型把自己的错误转化为可复用的知识。在 HotpotQA、HumanEval 这些 benchmark 上,Reflexion 把成功率提升了 10~20%,而成本只是增加了一次 retry。
Reflexion 的一个现实应用场景是编程 Agent。写一段代码,跑单元测试,失败;读错误信息,反思"哦我误解了这个函数的返回类型";下次重写,pass。这个闭环就是把一个愚笨的 LLM 变成一个会"学习"的程序员的关键。
Evaluator-Optimizer:两个模型的分工
前两个模式里,同一个模型既生成又评价。但如果让两个不同的模型或两个不同角色来分别做这两件事,效果往往更好。
这就是 Evaluator-Optimizer 模式:
class EvaluatorOptimizer:
def __init__(self, generator_model, evaluator_model):
self.gen = generator_model
self.eval = evaluator_model
def run(self, task: str, max_iters: int = 3):
output = call(self.gen, f"完成任务: {task}")
for _ in range(max_iters):
verdict = call(self.eval, f"""作为严格的评审,给这份输出打分(0-10)并指出不足。
任务: {task}
输出: {output}
返回 JSON: {{"score": int, "issues": [...], "verdict": "pass"|"revise"}}""")
if verdict["verdict"] == "pass" or verdict["score"] >= 9:
return output
output = call(self.gen, f"""根据评审意见修改:
原输出: {output}
问题: {verdict['issues']}""")
return output
为什么两个模型比一个模型好?
避免 self-confirmation bias。同一个模型评价自己生成的东西,天然倾向于认为"这个已经挺好的了"。换一个视角、换一个模型(甚至同一模型但不同 persona),更容易发现问题。
可以用不同强度的模型。Generator 可以用便宜的 gpt-4o-mini 快速出草稿,Evaluator 用贵但更挑剔的 o4 做审查。成本比"全用 o4"低 5 倍,质量比"全用 gpt-4o-mini"高一档。
专业化角色。评估模型可以有非常明确的 persona——"你是一个最挑剔的 Senior Code Reviewer,对边界情况和性能问题零容忍"。这种人格化的 Prompt 用在 Generator 上会让它过度保守,用在 Evaluator 上刚好合适。
Reflection 什么时候真正有用
Reflection 不是银弹。有一些任务反思得越多越差,值得说清楚:
反思有用:
- 有可验证的正确标准——代码通过单元测试、数学题有正确答案、SQL 返回结果可以对比
- 生成空间大——写文章、写报告、开放性回答
- 风格重要——做 brand voice 的文案、PR 的语言润色
- 模型一次性输出容易遗漏细节——长内容、多约束的需求
反思没用甚至有害:
- 事实查询——问"巴黎人口",反思不会让答案更准,反而可能在细节上引入幻觉
- 模型本身就答不出的问题——知识盲区,反思一万次也出不来
- 任务非常简单——反思开销比直接答还大
- 有更强的验证手段——能调 API 核对的事实,直接调 API 比反思靠谱
判断是否上 Reflection 的一条经验法则:你能不能明确写出"好输出应该具备哪 3~5 条特征"。能写清楚,就让评估模型照着这个打分,反思有用。写不清楚,反思就是随机扰动。
成本和延迟的真实代价
Reflection 好是好,但要注意它把一次调用变成了两三次:
- 纯 Self-Critique 2 轮:1 次生成 + 2 次批评 + 2 次修订 = 5 次调用
- Evaluator-Optimizer 3 轮:1 次生成 + 3 次评估 + 2 次修订 = 6 次调用
对面向用户的实时 Agent(每次等 10 秒的那种),很难直接上三轮反思。几个常见的权衡:
只对关键步骤反思。不是每一步都反思,只在"生成最终输出"前反思一次。Plan-Execute 的 Plan 阶段尤其值得反思。
条件反思。让一个便宜的分类模型先判断"这个输出看起来靠谱吗",不靠谱才进入反思链。大部分正常情况下跳过反思。
离线反思。面向用户的那一路直接出结果,同时把 trace 扔进一个后台队列做反思,结果写到训练集里供未来改 prompt 或微调用。
反思和规划的关系
Reflection 和 Plan-Execute 是正交的两件事,经常组合使用:
- Planner 出完整计划
- 对计划本身做 Reflection("这个计划有遗漏吗?")
- Executor 执行每一步
- 对每一步的输出做 Reflection("这一步的结果符合预期吗?")
- 全部执行完后对最终产出做 Reflection
组合起来就是一个非常稳健的 Agent 架构。下一篇 Tree of Thoughts 再把这个架构推进一步——不只是反思单一路径,而是同时生成多条路径、评估、选最优,形成真正的搜索式推理。
相关阅读
- Reflexion: Language Agents with Verbal Reinforcement Learning (2023)
- Self-Refine: Iterative Refinement with Self-Feedback (2023)
- Evaluator-Optimizer Pattern (Anthropic) — 官方给出的设计模式
- Generation Evaluation Gap (Paper) — 论证"评价比生成容易"的理论工作
版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。
(采用 CC BY-NC-SA 4.0 许可协议进行授权)
本文标题:05. Reflection:让 Agent 自己挑毛病、自己改
本文链接:https://www.sshipanoo.com/blog/ai/ai-agent/05-Reflection/
本文最后一次更新为 天前,文章中的某些内容可能已过时!