深度 1:Reflection 反思机制——Agent 做错了能自己改吗
发布时间:2026/8/11 2:04:54
分类:文化教育
浏览:1234

深度 1Reflection 反思机制——Agent 做错了能自己改吗这是「Agent 工程化」系列的深度篇。从这篇开始我们不再只讲广度而是把 Agent 工程里最容易含糊、最值得挖透的点讲到底。第一篇选Reflection 反思机制——“Agent 做错了能不能自己改”是它区别于一次性生成器的关键能力也是最容易讲错的一个概念。开场一个你肯定遇到过的场景你让 Agent 写一段 SQL它交上来的查询里表名拼错了。你很自然地说了一句“你再检查一下。”神奇的事情发生了它真的发现了问题改对了。于是反思机制这个词很容易给人一种感觉Agent 好像有了自我纠错能力像人一样在脑子里复盘。但这个看似简单的直觉里藏着一个关键的坑“再生成一次和反思后改进”本质区别在哪想清楚这个问题就理解了反思机制的全部。再生成一次是随机重试反思是带着评估结论的定向修改——差别就像重新掷骰子和看清哪个数字错了再改。为什么掷骰子没用因为 LLM 的生成是逐 token 采样同样的 prompt 每次走的采样路径不同但都在同一个盲区里——模型一次生成时看不到的漏洞重试一百次也大概率看不到。反思的价值在于它让模型把输出当作被审查的对象重新推理一遍这才有机会跳出盲区。反思的本质一个必须闭环的三段式反思不是一个动作是一个闭环PASS 通过发现问题生成 Generator评估 Evaluator评估通过输出最终结果改进 Generator 定向修改三个环节缺一个都转不起来但很多人只看到了生成和改进漏掉了最关键的评估。为什么评估是闭环的灵魂生成器负责写评估器负责查改进器负责改。但真正决定反思有没有效果的是评估这一步能不能找到真问题。这背后其实是个朴素的事实LLM 对什么是好的答案的判断力远高于它一次生成出好答案的能力。打个比方一个人写代码时可能漏了边界条件但你让他 review 这段代码有没有处理空输入他大概率能指出来。模型也一样——生成是高难度创作评估是低难度检查。反思机制就是把这个不对称利用起来用模型的判断力去补它生成的不足。评估这一步有两个决定成败的设计设计一必须给出具体的检查维度。“请检查一下你的输出这种笼统指令LLM 会回答看起来不错”——什么都不发现。要给维度清单比如代码场景“是否通过类型检查、是否有未处理的边界、命名是否规范”SQL 场景“表名是否存在、字段是否匹配、是否有 NULL 陷阱”。维度越具体评估越不走形式。设计二必须有 PASS 出口。如果评估后没问题要允许它输出PASS并终止。没有这个出口LLM 会为了找出问题而强行挑毛病把原本对的改成错的无限循环。这个设计的原理值得多说一句评估器本质上在做一个挑错任务而挑错是个永远可以继续的任务——任何答案都能被挑出可以更好的地方。如果不给它够好了就停的出口它会一路改下去越改越偏离正确答案。这跟强化学习里的探索与利用平衡是一个道理不是所有反馈都该被采纳要有一个明确的终止信号。用伪代码看整个闭环forroundinrange(max_rounds):resultgenerator(task,reflection_notes)# 生成/改进issuesevaluator(task,result)# 评估按维度找问题ifissuesPASS:returnresult# 够好了停reflection_notesreflect(result,issues)# 反思为什么错# 达到最大轮次强制返回returnresult三种实现范式不只是自己检查自己反思机制在工程上有三条主流实现路线它们的反馈来源不同适用场景也不同范式核心思路反馈来源典型场景Self-Refine生成 → 自评 → 自改LLM 自评文案润色、代码生成Reflexion执行 → 环境反馈 → 语言反思 → 存记忆工具结果/报错等环境反馈工具调用、代码执行、多轮试错ReAct Reflection思考-行动-观察循环 失败后反思重规划Observation 反思复杂多步推理任务关键区别在第一行的 Self-Refine 和 Reflexion 之间Self-Refine 的反馈来自模型自己——“我觉得这里不对”。它擅长发现表达类问题逻辑跳跃、遗漏细节、含糊不清。Reflexion 的反馈来自环境——工具报错了、测试没跑过、结果不符合预期。它擅长发现事实类问题因为环境反馈是硬事实不会骗你。一个容易被忽略的结论能用环境反馈就别依赖模型自评。环境反馈报错信息、测试结果、工具返回值是确定性的模型自评只是概率性的。反思机制的成熟度排序大致是环境反馈 独立评审 模型自评。完整实现一个可运行的 Self-Refine理论讲完给一个真正能跑的完整实现OpenAI 兼容接口替换 key 即可运行fromopenaiimportOpenAI clientOpenAI()defgenerate(task:str,notes:str)-str:生成器完成任务的首次输出或根据反思笔记定向修改promptf任务{task}\nifnotes:promptf历史反思{notes}\n请针对上述问题修正后重新输出。\nrespclient.chat.completions.create(modelgpt-4o-mini,messages[{role:user,content:prompt}],temperature0.7,)returnresp.choices[0].message.contentdefevaluate(task:str,result:str)-str:评估器按固定维度检查输出 PASS 或问题清单dimensions1) 表名是否存在 2) 字段是否匹配 3) 是否遗漏 WHERE 条件 4) 是否有 NULL 陷阱respclient.chat.completions.create(modelgpt-4o-mini,messages[{role:user,content:(f任务{task}\n输出{result}\nf按以下维度逐项检查若无问题仅输出 PASS若有问题输出具体问题清单\n{dimensions})}],temperature0.0,# 评估要确定性temperature 归零)returnresp.choices[0].message.contentdefreflect(task:str,result:str,issues:str)-str:反思器把问题转成一句可复用的教训供下一轮生成器使用respclient.chat.completions.create(modelgpt-4o-mini,messages[{role:user,content:(f任务{task}\n当前输出{result}\n发现的问题{issues}\nf请用一句话总结最核心的教训下轮生成时直接遵守。)}],temperature0.3,)returnresp.choices[0].message.contentdefself_refine(task:str,max_rounds:int3)-str:反思闭环主循环notesresultgenerate(task)for_inrange(max_rounds):issuesevaluate(task,result)ifissues.strip().upper()PASS:print(f[第{_1}轮] 评估通过停止反思)breaknotesreflect(task,result,issues)resultgenerate(task,notes)# 带着教训重新生成returnresultif__name____main__:sqlself_refine(写一条 SQL查 2026 年 8 月所有订单按金额降序)print(sql)三个实现细节值得注意评估器的 temperature 归零——检查必须是确定性的不能这次说有问题、下次说没问题反思输出一句可复用的教训——不是把问题原样贴回去而是提炼成下轮能直接遵守的指令这直接通向后面要讲的 Reflexion 记忆最大轮次兜底——即使评估始终不 PASS循环也会在 3 轮后强制退出防止烧穿预算步骤级 vs 任务级反思放在哪一层问题来了反思该放在整个任务的哪个位置两种粒度各有取舍步骤级反思任务级反思时机每完成一个子步骤就检查整个任务完成后整体检查优点错误早发现后续步骤不白做开销小能看到整体问题前后矛盾、衔接不自然代价每步多一次 LLM 调用10 步任务调 20 次中间出错要到最后才发现前面全白费适合步骤强依赖多步数学推导步骤较独立生成一份报告权衡一句话强依赖用步骤级重整体用任务级别每步都做。自评 vs 互评为什么别人看比自己看管用单 Agent 自我反思有个隐蔽的缺陷叫自洽偏见评估者和生成者是同一个模型它生成时形成的逻辑评估时大概率沿用了——它看不出自己逻辑里的漏洞不是故意放水是真看不出来。就像作者本人读自己的稿子总觉得逻辑通顺因为大脑已经把跳跃的地方脑补上了。解决方案让另一个 Agent 来审。独立设置一个 Critic Agent职责只有一个找问题没有生成时的思维包袱视角天然更客观。有没有执行 Agent 干活Critic Agent 挑刺有问题验收通过代价当然也有多一次模型调用、多一套 Prompt。适合质量要求高、出错代价大的场景代码生成、金融文案日常任务用不上。Reflexion把反思写进记忆才能吃一堑长一智Self-Refine 有个遗憾这次改对了下次遇到类似问题还是从头想一遍。Reflexion解决了这个——它把反思的结论语言化、存进记忆下次执行时带着教训上场。执行 → 评估 → 语言反思哪里错了、为什么错→ 存入记忆 → 下一轮带着教训执行举个例子第一次写 SQL 表名拼错Reflexion 会沉淀一句生成 SQL 前先核对 schema 里的表名。这句不是简单的我错了而是具体的原因分析存进记忆后后续所有 SQL 任务都受益。这里串上了整个系列的两块知识Reflexion 的记忆就是本系列「Memory 记忆系统」里的经验沉淀只是它的写入时机由反思失败触发。反思给 Agent 装了自省能力Memory 让自省的结果留得下来两者配合才是完整的越用越聪明。而 Reflexion 和「护栏」的关系也值得一提反思让 Agent 更努力地做对护栏防止它努力过头——反思轮次必须计入 token 预算并用最大轮次兜底。两个机制是两个方向的力缺一个都会出事。工程权衡反思不是免费的反思的代价很直接——每反思一轮就是一次额外的 LLM 调用token 变多、延迟变高。所以生产实践有一条铁律反思只用在质量要求高、出错代价大的关键节点不是每步都做。生成 SQL、代码 → 值得反思错了代价大简单查询回答 → 不值得多烧一次调用收益却很小三个最容易踩的坑坑一把反思当重试。不满意就重新生成不是反思是掷骰子。没有评估环节重试一百次也可能犯同样的错。判别标准有没有带着检查结论去改。坑二评估没有 PASS 出口。没有出口的反思会无限挑毛病把对的改错。PASS 出口 最大轮次上限两个都要。坑三全局无差别反思。每个步骤都反思token 翻倍、延迟翻倍收益却不翻倍。只在关键节点启用。常见疑问问反思和 CoT思维链是一回事吗不是。CoT 是想清楚再答反思是答完再检查。CoT 解决的是推理过程本身反思解决的是对输出结果的校验。两者可以叠加先 CoT 生成再反思校验。问反思一定能提升质量吗不一定。研究如 Self-Refine 相关工作表明反思对表达能力类任务写作、代码生成提升明显但对某些任务可能无效甚至有害——尤其是评估器挑不出真问题时多轮反思只是在烧 token。所以生产上要用评测集验证反思到底有没有用而不是默认它有用。问反思和 RLHF 有关系吗有。反思本质上是把人类反馈→模型改进的过程在推理时用模型自己替代了。RLHF 是在训练阶段用人类反馈调权重反思是在推理阶段用模型自评改输出——一个练内功一个靠临场发挥。总结一句话记住它反思机制是生成 → 评估 → 改进的闭环不是不满意就重来。关键在评估环节给具体检查维度 设 PASS 出口。分步骤级和任务级两种粒度质量要求高时可以用独立的 Critic Agent 互评减少自洽偏见。进阶的 Reflexion 把反思结论存进记忆实现跨任务学习。代价是每轮多一次 LLM 调用所以只在关键节点启用。小结反思 生成 → 评估 → 改进的闭环评估环节决定成败检查维度 PASS 出口为什么评估能救生成模型判断好坏的能力远高于一次生成好答案的能力反思利用了这份不对称三种范式Self-Refine自评、Reflexion环境反馈、ReActReflection循环内反思——能用环境反馈就别依赖自评两种粒度步骤级早发现vs 任务级看整体强依赖用前者重整体用后者互评 自评Critic Agent 没有自洽偏见Reflexion 串起 Memory反思结论语言化存进记忆跨任务受益反思 护栏互为对手反思让 Agent 做对护栏防它烧光预算代价明确每轮多一次调用只在关键节点启用下一篇深度篇记忆压缩方法——上下文装不下时怎么把记忆压得又小又准。这是 Memory 系统的核心工程问题也是为什么有些 Agent 越聊越聪明、有些越聊越失忆的答案。本系列路线从 0 到 1Agent 是什么 → 手写最小 ReAct → Function Calling 与工具设计 → 上下文管理 → Memory 记忆系统 → RAG 知识库 → Skill 自学习 → 编排模式与多 Agent → 给 Agent 装护栏 → 生产部署与可观测 → 评测与回归 →番外框架横评 → LangGraph 深挖 → 框架选型决策 → 深度篇Reflection 反思 → 记忆压缩 → 更多