资讯动态

给AI Agent加上自我反思闭环:从原理到代码,让智能体学会纠错

发布时间:2026/10/20 21:02:01 来源:尧图企业网站定制
说实话我第一次意识到 Agent 非得有自我反思不可是在调试一个多步骤任务时被逼出来的。当时我搭了个能自动抓取网页信息并生成报告的 Agent任务简单但跑起来之后它有一半的概率在第三步就跑了偏明明要的是“提取价格对比”它却把售后政策写进了总结全程没有任何报错像一个自信满满的实习生交了一份自认为完美、实则离题万里的作业。那次踩坑之后我就明白把大模型当成一个“一次生成、永不回头”的函数是现阶段做 Agent 最容易犯的错。真正的智能体应用必须在工作流里加入“自我反思与修正”这个环节让 Agent 能审视自己刚才的输出、定位偏差、重新规划并再次执行。这篇文章我想从一个一线开发者的角度把“自我反思与修正”这个机制从原理到代码再到实际踩坑系统地拆开讲一遍。不管你是刚接触 Agent 的初学者还是已经做了几个 Demo、正在为效果发愁的开发者这篇文章都能给你一套可以直接拿去用的思路和方案。1. 为什么Agent需要自我反思——从一次失败的调度说起1.1 Agent出错的真实场景不是小概率事件很多人对 Agent 的预期是“给它一个目标它自己就能搞定”但真实跑起来完全不是那么回事。Agent 本质上是一个大语言模型加上一组工具、一份提示词再套上一个控制循环。这里面的每一个环节都可能出错。我自己遇到的典型问题可以分成三类。第一类是理解偏差。用户说“帮我总结一下这份合同里关于违约责任的部分”Agent 表面上理解了实际上却把“争议解决”也生拉硬拽进来。这类问题最隐蔽因为你看着输出感觉“好像也有点相关”但交给专业人士一看就会发现重点抓错了。这是语言模型本身的语义对齐问题不是简单加一句“你要理解用户意图”就能解决的。第二类是工具调用失误。Agent 要打开网页、调用数据库、执行一段代码只要某一个参数传错了后面的步骤全部白搭。比如我见过一个 Agent 调用天气接口时把日期参数“2025-06-01”传成了“06/01/2025”接口直接返回错误但 Agent 没读懂这个错误反而把这个错误当作正常结果继续往下推理。第三类是上下文污染。任务一长Agent 会在第 15 步的时候把第 3 步已经处理过的信息又拿出来用或者自己生成了一段和前面结论冲突的内容。做过长上下文任务的人都知道这几乎是必然会发生的事因为语言模型没有真正“记住”前面所有内容它只是在做概率上的续写。这些问题的共同点是Agent 本身并不知道自己错了。它没有内置一个“检查一下我刚才做得好不好”的模块。所以我们必须自己加一个。1.2 自我反思解决的核心矛盾一次生成 vs 循环修正传统的大模型应用是“一次生成”模式输入问题模型直接输出答案。对写文案、翻译这类任务这种模式够用。但对 Agent 这种需要“做事情”的应用来说一次生成远远不够因为做事是一个过程过程中每一步都有出错的可能性。自我反思机制本质上就是把“一次生成”变成“循环修正”。Agent 在执行完一个动作后先停下来自己对自己说我刚才做了什么这个结果符合预期吗哪里可能有问题然后根据这个判断决定是继续下一步还是回头重做。这个逻辑有点像人写代码。你不会写完就把代码直接扔到生产环境你至少会自己 review 一遍跑几个测试用例看到报错再改一改。Agent 也一样它需要“写代码—自测—发现问题—修改—再自测”这样的循环直到通过所有检查为止。我的体会是加了反思循环之后Agent 的成功率提升非常明显。在一些长链路任务上成功率可以从 50% 出头提升到 80% 以上。当然代价是增加了额外的模型调用任务时间会拉长所以这里有一个折中问题后面我会专门讲怎么设置合适的反思轮数。2. 自我反思的实现机制——从三信号到四组件2.1 三个可行的反思信号要让 Agent 学会反思第一步是让它“看到”自己的错误。但语言模型不像人不能用“回头看你那段逻辑是不是不对”这样模糊的指令来驱动它。我们必须给它一个具体的、可被评估的信号。我在实际项目里主要用这三种。第一种是结果信号。以任务目标为准判断最终输出是否满足要求。比如让 Agent 生成一份 JSON 格式的数据那就检查 parse 是否成功、字段是否齐全、类型对不对。这种信号最可靠因为结果是客观可验证的。第二种是执行反馈信号。在 Agent 调用工具时工具会返回状态码、错误信息、空值等。例如查询数据库时返回“数据表不存在”抓取网页时返回“404 Not Found”。这些反馈本身就有纠错价值。关键是 Agent 要能区分“正常结果”和“错误反馈”很多 Agent 出错就是因为把错误反馈也当成正常结果处理了。第三种是自评信号。这个比较有意思我们让大模型给自己的输出打个分或者写一段“自我分析”。比如执行完任务后可以问一句“你觉得这次执行中有什么不完美的地方”有时大模型真的能指出自己哪里可能错了。这就是所谓的 LLM-as-a-Judge 模式我实测下来自评信号在语义偏差这类问题上特别有效因为大模型在“评价”而不是“生成”的时候往往会表现得更严谨。2.2 反思-修正闭环的四组件架构说完了信号再看机制。我把一套完整的反思与修正系统拆成四个组件这也是我在项目里最常用的架构。执行器负责调用大模型完成具体动作比如“生成一段总结”“调用一次搜索接口”“写一段代码”。观察器接收执行器的输出把它和刚才提到的三类信号做比对判断是否正常。反思器是整个系统的核心它接收观察器发过来的偏差信息分析“为什么会出错”输出一份反思结论。修正器根据反思结论调整方案重新生成新的执行指令。这四个组件串起来就是执行器干活 → 观察器检查 → 有问题就反思 → 修正器调整 → 回到执行器重新干活。我拿一个生活场景来类比你让一个实习生去发一封商务邮件。他写完了给你看你发现语气太随意了这就是观察器看到了问题。你告诉他“语气要正式一点”这是反思结论。他重新写一版把开头从‘你好哥们’改成了‘尊敬的客户’这是修正。重新发给你看检查通过任务结束。对 Agent 来说这个流程要能循环执行而且每一轮都要带着上一轮的教训才能真正地“越做越好”。3. 实操搭建一个自带纠错能力的Agent3.1 技术选型与运行环境准备动手之前先说环境。我这次演示用的模型相对通用不需要在特定环境上做独家优化。开发语言我选了 Python理由很简单生态成熟写小工具方便接各家模型服务也顺手。项目里需要一个模型服务的 Python 库我用的是 OpenAI 兼容接口因为很多厂商都支持这种格式换厂商时只需要改 base_url 和 api_key不用动业务代码。这一点非常重要能避免被某一个平台绑死。我的项目结构大概是这样reflective_agent/ ├── main.py # 主流程入口 ├── agent.py # Agent核心控制逻辑 ├── reflect.py # 反思与修正模块 ├── tools.py # 外部工具调用封装 └── config.py # 模型配置超参数等这个结构很简单但足够演示核心机制。实际项目里我会再加一层缓存和日志模块方便排查问题。日志模块尤其重要因为 Agent 的执行过程是黑盒没有日志你就会两眼一抹黑连它到底错在哪一步都找不到。3.2 核心代码实现一个最小可跑的反思循环接下来是核心部分——代码实现。我先从最简单的业务场景开始演示Agent 要完成一个两个步骤的任务每次都让模型先思考、再行动、再反思自己刚才做的事情。import json from openai import OpenAI class ReflectiveAgent: def __init__(self, model_namegpt-4o, max_iterations5): self.client OpenAI() self.model_name model_name self.max_iterations max_iterations def call_model(self, messages): response self.client.chat.completions.create( modelself.model_name, messagesmessages, temperature0.3, ) return response.choices[0].message.content def run(self, task): messages [ {role: system, content: 你是一个智能体请严格按用户要求完成任务。}, {role: user, content: task} ] for attempt in range(self.max_iterations): # 1. 执行生成一次当前方案的输出 output self.call_model(messages) print(f--- 第 {attempt 1} 次执行 ---) print(f输出: {output}\n) # 2. 观察对输出做客观检查 check_prompt f 你是质检员请对下面的输出做严格检查仅回答 OK 或有问题的具体原因: 输出内容: {output} 要求: 1. 输出必须是 JSON 格式 2. JSON 必须包含 {task} 3. 内容必须与用户需求一致 检查结果: check_messages [ {role: user, content: check_prompt} ] check_result self.call_model(check_messages) print(f检查结果: {check_result}\n) # 3. 若检查通过则终止循环 if OK in check_result.upper(): print(检查通过任务完成) return output # 4. 反思让模型自己分析为什么出问题 reflect_messages [ {role: system, content: 你是反思器分析上次执行失败的原因。}, {role: user, content: f 任务: {task} 你的输出: {output} 质检反馈: {check_result} 失败原因可能是什么? 给出具体修改建议: } ] reflection self.call_model(reflect_messages) print(f反思结论: {reflection}\n) # 5. 修正把反思结论追加到对话上下文里重试 messages.append({role: assistant, content: output}) messages.append({role: user, content: f 你之前的输出未通过检查请参考下面的反思结论修改并重新输出: 反思结论: {reflection} 请再次输出完整结果: }) print(已达最大迭代次数任务可能未能完成。) return None代码并不长但整个“执行—检查—反思—修正”的闭环都有体现。如果你直接跑这段代码会发现一个很有意思的现象有些任务它第一轮就过了有些任务则会在第二轮或第三轮迭代时输出质量发生明显变化。为什么我把 temperature 设成 0.3主要是在“稳定性”和“多样性”之间取一个平衡。反思修正场景需要的更多是稳定不希望模型每轮都输出完全不同的内容。但这个值是经验值我后面会给出不同场景下的调整思路。3.3 关键优化用结构化方式提升反思质量上面的代码能跑但它的反思输出是非结构化的自然语言效果不稳定。我在实际项目里很快遇到问题反思器说了一大堆执行器不知道哪些是重点。所以我把反思器改成输出 JSON 结构把反思结论拆成“错误类型”和“修改建议”。{ error_type: missing_field, missing_field: [price], suggestion: 请确保JSON中包含price字段类型为数字单位为人民币元, priority: high }这样做的好处是修正器可以直接从 JSON 里拿到缺失字段名生成更具体、不容易跑偏的修改指令。我把这个机制抽象成ReflectionResult数据类class ReflectionResult: def __init__(self, error_type, suggestion, priority, fieldsNone): self.error_type error_type self.suggestion suggestion self.priority priority self.fields fields or {}在运行中我会检查这个结构化结果的priority字段如果某个错误被标为high下一轮修正时我会让它先修复这个错误再讨论其他问题而不是在一条消息里堆一堆建议。这样模型的注意力集中了修正成功率会明显上升。4. 修正环节的关键设计——按错误类型制定优化策略4.1 错误分类与匹配策略四种典型场景反思搞清楚“哪里错了”之后接下来就是“怎么改”。不同错误类型需要不同的修正策略不能一个 Prompt 走天下。我把常见错误分成四类每一类都配了对应的处理方式。错误类型表现特征推荐处理策略格式错误JSON 解析失败、字段缺失直接指出格式要求让模型重新生成必要时给出模板逻辑错误推理顺序颠倒、结论与前提矛盾让模型复述任务目标拆解子步骤重新推导工具调用错误参数传错、工具不存在、返回异常传入实际错误报文要求模型先解释再修正参数需求偏差输出跑题、遗漏用户重点要求把用户原始需求逐条列出让模型自评是否一一满足我在给某个模拟项目写反思模块时专门做了一个ErrorRouter它会先根据观察器拿到的错误信息判断错误类型再走对应的修正分支。这个设计非常实用比如工具调用错误我根本不让模型“反思人生”直接把错误信息塞进日志让它重试调用就行效率高很多。4.2 避免“越修越错”反思的终止条件与边界控制加了反思循环之后另一个问题立刻暴露出来Agent 有时候会“越修越错”。这不是危言耸听我见过真实案例第一轮输出已经可以用了反思器说“不够详细”它重写了一遍结果把重要信息搞丢了再反思一次又加了一堆幻觉出的数据。要避免这种情况我给反思系统设置了三道边界。第一道是硬性终止条件。在循环里设置最大迭代次数超过次数就放弃或者转人工处理不无限重试。第二道是质量回退检测。每轮的输出都会获得一个质量分如果发现新一轮的质量分比上一轮还低就停止继续迭代退回上一个最优版本。这个逻辑类似于机器学习里的“早停法”实测非常有效。第三道是修改范围限制。不是所有问题都可以大改。我在 Prompt 里明确写明“如果只是格式问题只调整格式如果只是措辞问题不要重构整个回答。”减少 Agent 的自主发挥空间反而能让结果更可控。我的体会是反思机制不是为了让它无限制地“发挥创造力”而是让它在有限范围内精准修正。反思轮数设成 3 轮通常够用若是超过 3 轮还在修很可能不是输出问题而是模型理解任务本身出了问题。5. 常见问题排查与避坑实录5.1 Agent陷入死循环始终无法通过检查这是最容易被问到的问题。代码看起来没毛病但它一遍又一遍地迭代就是跳不出循环。排查时我先看是不是检查标准太模糊了。比如检查 Prompt 里写的是“内容要完整”这是一个很虚的标准模型会反复自我挑刺。把检查标准改成“JSON 必须包含 name、price、stock 三个字段stock 是 int 类型”它通过的概率就会高很多。另一个常见原因是反思输出太宽泛修正器根本不知道具体该改什么。反思结论里写“请更严谨一些”等于没说。要引导反思器输出具体的修改指令。我在实际项目里发现“指出具体的错误字段或步骤编号”这个要求能极大提升修正成功率。5.2 反思器老是出具“无问题”报告假性通过还有一种情况更隐蔽任务明明做得不好但反思器说“OK没有问题”。原因往往在于检查器用的模型能力不够或者没看过客观结果。我的解决办法是把可客观验证的结果放到检查器的 Prompt 里。比如任务要求“报价不能超过 100 元”检查器必须先看到原始报价资料然后再评价。如果你的检查器只是对着 Agent 自己的输出做评价相当于让一个开卷考试的学生自己判卷自然很难发现问题。我个人经验是把“客观事实”和“模型判断”分开。能逻辑判定、能算出来的一律先用代码判定代码判不了、需要语义理解的再交给模型评价。这样混搭反而比纯靠模型检查稳定得多。5.3 修正一次后引入了新的错误如何追查有一次我在帮朋友调一个 Agent 系统第一轮输出缺了一个字段反思后补上了但新的输出把另一个本来就正确的字段删了。这就是典型的“修复 A 破坏 B”问题。事后排查根因是修正 Prompt 里没有提醒它“保留原有正确部分”。我在 Prompt 里加了这么一句“请保留原输出中正确的内容仅修改本次反思提到的错误。”就这么一句回退类问题少了非常多。如果你想让修正过程更稳妥还有一招在每次修正时把上一轮正确的输出段落用BEGIN ORIGINAL CONTENT和END ORIGINAL CONTENT框起来明确告知模型哪些是必须保留的。这样模型就不会因为“注意力漂移”而丢掉之前做对的部分。现象可能原因排查建议反复迭代无法通过检查标准过于模糊检查 Prompt 改为可验证的具体要求反思结果全是 OK检查器模型能力不足引入可代码验证的客观指标修 A 却破坏 B修正指令没有保护原有正确内容在修正 Prompt 中强调保留原输出反思轮数过多任务变慢没有设置早停和边界设置最大迭代次数与质量回退检测6. 做一个会总结经验的Agent以及其它几条实在建议把自己在实际操作中的体会写下来这是我觉得最值钱的部分。第一反思环节用的模型和主 Agent 的模型可以分开。主任务用一个比较强的模型反思和检查环节可以用一个相对便宜且快速的模型。这么做不是为了省钱而是因为反思环节只做判断不需要很强的生成能力便宜模型常常就够了。第二反思的结果一定要缓存。如果同一类错误反复出现完全可以把“错误类型→修改建议”做成一个映射表下一次遇到同类错误直接用映射结果修正省去一轮反思调用。这个机制我再描述得简单一点相当于 Agent 把自己踩过的坑记成了笔记下次不再踩。第三每一次反思和修正都是模型的额外调用成本是必须考虑的。按照我的经验2 到 3 轮反思是性价比最高的区段。超过这个区间成功率提升非常有限但耗时和 token 消耗却会明显上升。最后想分享一个我观察到的现象让 Agent 反思“你哪里做错了”时它常常陷于自我批判说一堆空话但如果你让它反思“你下一次在什么条件下可以做得更好”它给出的建议反而更具体、更可执行。这个发现让我改了不少反思的 Prompt 模板。回头来看自我反思不单单是一个技术方案它更像是给 Agent 补齐了一种“行动后复盘”的能力。现在很多 Agent 应用走不出原型阶段问题不在于模型能力不够恰恰在于缺少复盘机制错了就错到底。给 Agent 加上反思与修正的能力之后我才真正感受到它在“变聪明”而不是一个只能执行指令的提词机器。以后在有复杂任务的项目里我都建议优先考虑把反思机制加进去相信你也会看到明显的变化。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑