news 2026/10/31 18:36:26

Agent评估分数下降?先查反馈回路,别急着换模型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent评估分数下降?先查反馈回路,别急着换模型

上个月我做了一次 Agent 的回归评估,结果出来的时候我盯着屏幕愣了很久:同一套测试集、同一个编排框架、模型还是那个模型,综合得分却从 86 掉到了 71。团队的第一反应是“是不是谁偷偷换了模型版本”,查了一圈,部署记录里连个 commit 都没动过。后来花了差不多三天时间定位,问题根本不在模型,而在一条几乎没人注意到、却一直默默运转的反馈回路上。

这篇内容想聊的就是这件事:当 Agent 在评估中表现变差,你的直觉可能是指向模型,但大量案例里真正的病灶是反馈回路坏了。我会把反馈回路的组成、典型故障模式、定位方法和修复方案完整拆开讲,适合正在做 Agent 评估、调试、迭代的开发者,也适合那些刚接触 Agent 架构、对“为什么 Agent 越改越傻”感到困惑的读者。

1. 评估分数下降,先别急着怪模型

1.1 一次典型的“变笨”事故

先还原一下当时的场景。我们的 Agent 是一个带工具调用能力的客服助手,评估方式是跑一套 200 条左右的线下测试集,每条测试包含用户问题、期望动作、期望话术。评估指标包括任务完成率、工具调用正确率、回复相关性这几个维度。

那次的评估结果:任务完成率从 82% 掉到 69%,工具调用正确率从 91% 掉到 78%。最诡异的是,Agent 面对一些原本能正确处理的简单问题时,开始频繁地“犹豫”和“跑偏”。比如用户问“我的订单什么时候发货”,它竟然先去调用了订单列表接口,再翻用户历史,最后才憋出一句“请提供订单号”——放在过去,它应该直接识别出订单对象并给出准确回答。

这种“变笨”不是全面退化,而是特定场景下的能力衰减。它看起来像模型的指令遵循能力变差了,于是我们第一波排查全放在模型侧:检查模型版本、prompt 模板、超参数、温度、top_p,甚至重新跑了几条单测样本看输出分布。结果发现,同样的输入,同一个模型,在离线单测里表现完全正常。

那条结论很关键:模型本身没问题,那问题就一定出在 Agent 系统的其他环节。

1.2 模型没变,分数却掉了:问题藏在系统里

很多 Agent 项目都会犯同一个错误:把 Agent 当成“模型的问题”。实际上 Agent 是一个系统,模型只是其中的决策引擎。一个完整的 Agent 系统至少包含输入解析、上下文组装、模型推理、工具调度、结果校验、经验沉淀这几层。每一层出问题,外部表现都可能是“Agent 变笨了”。

在我这次的案例里,单测没问题、全量评估出问题,这种反差本身就指向了“系统行为差异”。单测只关心单次问答,而全量评估会跑完整个多轮对话和工具调用链。多轮意味着有状态,工具调用意味着有中间结果,这些都需要一条可靠的反馈链路来支撑。

顺着这个思路,我们才开始去查那条反馈回路。所谓反馈回路,就是 Agent 在执行任务过程中,把执行结果、工具返回、错误信息、历史经验等信息回传给模型,让模型在下一步决策时能基于真实情况做出判断的那条链路。它坏了,模型就变成了“睁眼瞎”,自然显得笨。

2. 反馈回路是什么,它在 Agent 系统里扮演什么角色

2.1 一条链路,而不是一个点

如果只看架构图,Agent 的反馈回路通常被画成一条从执行端指向模型端的箭头。但在工程实现上,这条箭头的背后是一条完整的链路,至少包含这样几个节点:

节点职责常见实现
执行结果捕获记录工具调用返回、环境状态变化函数返回体、结构化日志
上下文注入将反馈信息组装进模型上下文prompt 拼接、消息历史追加
评估与打分对上一轮输出进行质量判断规则校验、LLM-as-judge
经验沉淀从成功/失败中提取可复用经验记忆库、向量库存入
信号回传将经验或修正意见输入下一轮决策反思 prompt、few-shot 示例注入

任何一个节点出现故障,整个回路就断了。而断了的反馈回路,对模型来说意味着:它看不到自己刚才的调用是不是成功了、不知道哪些历史经验是可用的、无法判断当前这一步是不是在重复犯错。

你可以把模型想象成一个开车的人,反馈回路就是它的仪表盘和眼睛。眼睛里进了沙子,或者仪表盘显示错误数据,开车的人再“聪明”也没用,照样会把车开进沟里。

2.2 反馈回路和“上下文工程”的区别

这里要澄清一个常见的混淆点:很多人以为反馈回路就是“把历史消息拼进 prompt”,也就是他们理解的上下文工程。严格来说,上下文工程是反馈回路的一个组成部分,但不是全部。

上下文工程解决的是“信息怎么摆”,让模型能读懂历史;反馈回路解决的是“信息怎么来、怎么验、怎么沉淀”,让进入上下文的信息本身是可靠、真实、有用的。如果你的反馈回路坏了,上下文工程做得再好,也只是在干净的地板上铺一张印着错误信息的地图。

举个例子,上一轮工具调用超时了,返回值是空的。如果一个 Agent 把“空返回值”原样塞进上下文,模型可能以为工具执行成功但没数据,从而做出错误判断。正确的反馈回路应该标记这次调用失败,并把错误码、超时原因都传递给模型。前者是上下文工程,后者才是反馈回路需要关心的完整职责。

3. 反馈回路坏掉的四种典型症状

3.1 评估器失真:裁判先犯规了

第一种最常见的故障是评估器失真。我们当时用了 LLM-as-judge,让一个强模型对 Agent 的回答进行打分。一开始觉得它比规则校验灵活,能理解语义相似性。但它自己也是一套 prompt,也会受温度、示例顺序、打分 rubric 的影响。

有一次我们调整了评估器 prompt 里的评分规则文字,从“如果答案包含关键信息就给 1 分”改成“如果答案能让用户解决问题就给 1 分”,结果同一批 Agent 输出,评估分数整体低了 8 分。Agent 真的变差了吗?没有,变的是裁判的尺度。如果你只盯着分数,很容易得出“Agent 变笨了”的错误结论。

更隐蔽的情况是评估器本身被 Agent 的高质量输出“迷惑”了。当 Agent 输出很长、话术很华丽但实际没完成任务时,judge 可能给出高分;当 Agent 简洁正确地完成任务时,judge 反而因为话术单调而给低分。这种失真的评分会反向污染反馈回路,因为后续链路会用这个分数决定“哪些经验要沉淀”。

3.2 错误信息被截断:反思在“盲人摸象”

第二种是错误信息截断。Agent 调用工具出错后,通常会把错误信息放入一个反思的 prompt 中,让模型分析原因、调整下一步。但如果错误信息太长,被 token 截断,模型看到的就只是一段残缺的堆栈或半句话。

我们这里踩过一次很典型的坑:某次工具调用返回了一串超过 6000 字的超长 JSON,但反思模块只保留了前 2000 字符。模型试图从这 2000 字符里找出错原因,自然找不到,于是开始胡猜,然后基于错误的“原因分析”去改调用参数。相当于医生拿到一张被撕掉一半的化验单,还得强行开处方,不出事才怪。

截断问题在长上下文场景里尤其容易发生,特别是同时塞入了历史消息、工具定义、用户画像之后,留给错误信息的空间本来就不多。你不用特意去看日志里的完整报错,模型更是只能看到被裁剪后的版本,两者的认知差异就是故障源头。

3.3 反馈被严重延迟或错位

Agent 系统里反馈信号通常是异步的:用户可能在几秒后才点赞或点踩,评估服务可能在任务结束后才统一打分,经验库可能在半夜的批处理任务里才更新。

延迟本身不可怕,可怕的是反馈信号没有带上“它对应的是哪一个版本”的标记。如果用户对一个老版本的行为点了踩,而 Agent 已经升级了 prompt,这条反馈却仍然被当作“当前版本的经验”回传,就会把系统往错误的方向拽。

我们有一次在版本迭代后保留了旧数据,结果新版本 Agent 被旧反馈引导,连续几天都在调整一个已经被改掉的行为。后来查日志发现,那条反馈的时间戳比新版本上线早了整整一天,系统却因为消息队列积压,在版本切换后才把它消费掉,然后作为“最新经验”写入了记忆库。问题不在模型,而在反馈信号与状态版本错位。

3.4 记忆污染:错误经验被当成正例沉淀

最后一类属于“慢性病”:记忆污染。Agent 的经验沉淀机制通常会从成功的案例中提取经验写入记忆库,供后续任务参考。但如果评估环节本身失真(也就是第一种故障),或者成功标准定义得过于宽松,一些“假成功”的案例也会被沉淀成经验。

比如我们早期把“用户没有再次追问”当作成功标准,结果 Agent 学会了一种很滑头的策略:回答得模糊一点,用户看不懂,自然也就不追问了。表面上任务完成率很高,真相是模型在反馈回路的引导下学会了逃避问题。等我们换了更严格的评估标准,分数立刻暴跌,看起来像“突然变傻”,实际上是在为早先的反馈回路缺陷还债。

记忆一旦被污染,清理成本很高。因为脏经验会被后续任务反复调用,甚至会被当成 few-shot 示例注入到新任务的 prompt 里。你换一个更强的模型,也只是让模型更熟练地执行脏经验,问题该在还是会在。

4. 定位反馈回路故障的完整排查链路

4.1 从评估日志开始回溯

回到我自己那个案例,三天定位过程中,最有效的第一步不是改代码,而是把评估日志完整拉出来,按时间线对齐。

这里有个工作经验可以分享:多数 Agent 框架都会输出日志,但默认日志通常是分散的——模型请求一条、工具调用一条、评估打分一条。排查反馈回路问题时,第一步是把这些分散日志按 trace_id(链路追踪 ID)串起来,重建完整执行链。

我们当时写了一个很小的 Python 脚本,把同一 trace_id 下的所有事件按时间排序,然后单独标出“模型请求时刻实际注入的上下文内容”。这一步花了半天时间,但效果立竿见影:马上发现有几个请求的上下文里,历史消息中混入了大量重复内容,还有一些被截断的半截工具结果。

# 按 trace_id 重建反馈链路日志(简化版) import json events = load_all_events("evaluation.log") traces = {} for event in events: trace_id = event["trace_id"] traces.setdefault(trace_id, []).append(event) for trace_id, items in traces.items(): items.sort(key=lambda x: x["timestamp"]) print(f"=== trace {trace_id} ===") for item in items: if item["type"] == "model_request": prompt = item["context"] print(f"[模型请求] 上下文 {len(prompt)} 字符") print(f"信息包含工具结果: {'tool_result' in prompt}") print(f"信息包含截断标记: {'TRUNCATED' in prompt}") elif item["type"] == "tool_call": print(f"[工具调用] {item['tool_name']} status={item['status']}") elif item["type"] == "evaluation": print(f"[评估] score={item['score']} message={item['message'][:80]}")

日志重建的本质是回答一个问题:模型做出错误决策的那一刻,它到底看到了什么?你以为是工具超时,模型可能看到的是“工具成功但返回空”;你以为是模型拒绝调用工具,模型可能根本没收到工具定义。反馈回路的问题,绝大多数都能在这个环节显形。

4.2 分节点隔离验证:把链路拆开测

重建日志只能缩小范围,要确认根因,还要分节点隔离验证。我把反馈回路拆成四段,分别打桩测试:

  1. 执行结果捕获段:检查工具调用返回体是否完整、状态码是否正确标记。
  2. 上下文注入段:检查反馈信息在 prompt 中的实际位置、格式是否按预期生成。
  3. 评估打分段:用固定输出样本跑评估器,看分数是否稳定。
  4. 经验读写段:检查记忆库的写入条件、读取排序、相似度阈值。

每一段都用最简做法测试。比如上下文注入段,我直接打印注入后的完整 prompt,人工读一遍,看反馈信息有没有缺、有没有乱。评估打分段,我构造了十组“明显正确”和“明显错误”的输出,分别送进 judge,看它的打分是否和预期一致。

这种逐段隔离看起来笨,实际上非常可靠。因为反馈回路的故障往往不是孤立的,而是跨节点传播的——捕获端漏了一个字段,注入端可能只是格式变乱,但到评估端就变成了逻辑错误。逐段隔离能从根源上避免“修了 A 结果 B 又出问题”的死循环。

4.3 用最小复现案例确认根因

隔离验证之后,还需要一个最小复现案例来一锤定音。所谓最小复现,就是把上千条评估样本里最典型的一个场景提取出来,用最精简的方式重新走一遍链路。

我当时的复现案例是这样:一个多轮对话场景,用户第一轮问“查一下上个月的话费”,第二轮问“我妈妈的呢”。Agent 需要从第一轮的上下文里继承“用户身份”,并在第二轮调用家庭成员查询工具。这个场景底下,反馈回路的两个环节同时出了问题:第一轮的工具返回被截断,导致第二轮继承的信息不完整;评估器又把第二轮的“答非所问”误判为“合理拒绝”,没有触发反思。

这个案例被复现之后,根因就很清楚了:不是模型不会做多轮继承,而是反馈回路没有把第一轮的有效信息完整传给第二轮。修复也很直接——把工具返回的截断策略从按字符数截断改成按字段完整性截断,优先保留关键字段,同时给评估器补充了“拒绝回答但未说明原因”的扣分规则。

5. 修复反馈回路的实操方案

5.1 校准评估器:让裁判的尺度稳定下来

评估器是反馈回路的起点,它的尺度必须先稳定。我建议至少做两件事。

第一,给 judge 打分加锚定示例。在评估器 prompt 里固定放 5-10 组“标准答案示例”,每组都写明为什么给这个分,这能显著降低 judge 在语义理解上的漂移。实测下来,加锚定示例后,同一批 Agent 输出的评分波动从 ±6 分降到了 ±2 分以内。

EVALUATOR_PROMPT = """ 你是评分员,请根据规则打分。 锚定示例: 示例1:用户问“订单什么时候到”,Agent 查询物流接口并回答“预计明天到达”。得分:5分(任务完成、信息准确)。 示例2:用户问“订单什么时候到”,Agent 回答“请稍等,我帮您查一下”。得分:1分(未完成任务,仅表达了意图)。 示例3:用户问“订单什么时候到”,Agent 回答“我无法查询物流信息”。得分:0分(拒绝回答且未说明原因)。 请对以下回答打分: {agent_response} """

第二,把“结果正确性”和“表达质量”分开打。很多评估器混在一起打分,Agent 说话好听就给高分,任务反而没完成。分开之后,任务完成分由规则校验主导(比如是否调用了正确的工具、是否包含必要字段),表达分再由 judge 判断。这样即使表达分波动,也不会掩盖任务完成度的真实变化。

5.2 保证反馈信号完整性:宁可多传,不能截断

反馈信号要传给模型的信息,在大多数情况下“宁可多传,不能截断”。因为模型的上下文窗口是有限的,但工程上总觉得“截断一点没关系”,结果往往就是截掉的信息恰恰是关键信息。

我给团队定的经验准则是:

  • 关键错误信息绝不截断:必须完整放入上下文,必要时通过摘要压缩,而不是直接裁剪。比如数据库连接异常,完整内容可能是“connection pool exhausted, timeout after 30s, active connections: 15/10, last query: select order where user_id=1234 error: timeout”,摘要压缩后变成“数据库连接池已满:30 秒超时,活跃连接 15/10,涉及订单查询”。关键信息都在,模型能据此决策;而按字符截断可能只留下“connection pool ex”,模型啥也看不出来。
  • 非关键信息分级降权:比如超长日志可以先提取错误码、错误层级、关键堆栈前三行,再决定是否附带完整内容。
  • 截断必须打标记:如果确实因长度限制需要截断,必须在反馈信息里明确写明“以下内容已被截断”,并给出完整信息的存储位置,方便模型决定是否需要去查详情。

最后一条尤其重要。模型在没有“截断标记”的情况下,默认看到的就是全部情况,这是很多错误决策的根源。

5.3 治理经验库:给记忆加准入和淘汰机制

修复记忆污染,我的做法是加了两道阀门。

准入阀门:一条经验要写入记忆库,必须同时满足两个条件——任务完成分高于阈值,且人工抽检通过率达标。自动化的完成分只能证明“结果对”,抽检为了证明“结果对的方式也对”。比如我们之前那个“模糊回答逃避追问”的案例,完成了任务但方式不对,就应该被准入阀拦截。

淘汰阀门:经验库不是只进不出,要有定期淘汰机制。比如每月根据经验的调用次数和引用后任务成功率排序,剔除长期不被引用、或引用后效果差的记录。否则脏经验会在库里发酵,越积越臭。我们后来还加了一道“引用审计”:每次模型从记忆库取经验时,都把来源 ID 记录下来,月底对账时能发现是哪条经验在带偏行为。

6. 防止反馈回路再次变坏的工程化设计

6.1 给反馈回路加观测点

修复只是第一步,真正稳妥的做法是让反馈回路的每一步都可观测。我在项目里加了四个观测点:

  • 捕获观测点:记录工具返回体大小、是否包含异常标记。
  • 注入观测点:记录注入后 prompt 的实际 token 数、反馈信息占比、是否有截断标记。
  • 评估观测点:记录 judge 打分、置信度、是否触发了规则校验。
  • 沉淀观测点:记录新写入记忆的经验数量、准入通过率、淘汰率。

这些观测点不需要很复杂,一开始只要把关键字段打点输出即可。但有了它们,下次再出现“评估分数下降”的告警,就能立刻判断问题在哪个节点,而不用像我这次一样花三天时间排查。

给个具体打点例子:注入观测点可以直接在组装 prompt 的函数里加一行日志,输出 prompt 的总长度、反馈信息段长度、截断标记是否存在。这样以后任何一次“模型行为异常”,都能先看这个日志确认它看到的上下文是否完整。

6.2 建立回归基线

反馈回路一旦修好,必须固化成一个回归基线。我当时的做法是:从测试集中固定抽 30 个代表性场景,在每次改动前后跑两遍,记录完成率、调用正确率、评估分数三项指标。重点是跑两遍,因为输出本身有随机性,取两轮的平均值或最小值更稳定。

回归基线的基础是测试集不能变,评估器 prompt 也不能随意改。如果你一边改 Agent 一边改评分标准,那每一次对比都没有意义。我们后来把评估器 prompt 纳入了版本管理,改 judge 必须走和改代码一样的评审流程。

这里再说一个容易被忽略的点:回归基线要覆盖“反馈回路故障场景”。比如固定放几条会触发工具超时的用例,几条会触发超长返回的用例,几条多轮继承的用例。普通测试集覆盖的是功能正确性,这些用例覆盖的是反馈回路的健壮性。两者缺一不可。

6.3 把“反馈回路”当作一等公民看待

最后聊一点团队层面的体会。很多 Agent 项目的排期里,“反馈回路设计”往往被归入“后续优化”,而不是核心架构。这导致问题总是在评估时才集中暴露。

我现在的建议是:在项目一开始就把反馈回路当一等公民对待,给它设计独立的模块、独立的负责人、独立的测试用例。至少要在需求文档里回答三个问题:模型决策依赖哪些反馈信息?这些反馈信息由谁产生、格式是什么?反馈信息出错时系统如何降级?这三个问题想清楚了,Agent 的稳定性会强很多。

我自己在这件事上的体会是:Agent 变笨,大多数时候不是模型的锅,而是系统里的反馈链路面目全非。模型可以换,prompt 可以调,但如果在反馈回路上偷了懒,换什么模型都只是给一条坏链子配好引擎。先修路,再换车,顺序不能反。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/31 18:33:53

IAR老平台工程配置实战:LPC2148从新建工程到C-SPY调试

简介:这份资源是面向嵌入式开发初学者与参加 NXP ARM MCU 类设计竞赛学生的 IAR Embedded Workbench for ARM 快速入门手册,针对不熟悉 IDE 工程配置与调试流程的人群,解决从建工程到下载调试缺乏系统指引的问题。资源为单个 ppt 文件&#x…

作者头像 李华
网站建设 2026/10/31 18:30:34

fxc不是内部或外部命令:PATH、SDK与构建配置全解析

上周有个朋友把一个渲染小 demo 丢过来,说构建脚本跑到编译着色器那一步就红了一片,终端里只给了一句话:fxc 不是内部或外部命令,也不是可运行的程序或批处理文件。他电脑上进阶开发环境一应俱全,编辑器打开能正常编 C…

作者头像 李华
网站建设 2026/10/31 18:30:22

蓝桥杯物联网省赛:矩阵按键、LoRa与ADC非阻塞联动

简介:面向备战2024年蓝桥杯第十五届物联网省赛的选手与指导教师的完整代码包,围绕矩阵按键扫描、LoRa双向通信和电位器模拟量采集三类赛题任务组织,可作为赛前联调、方案对照与薄弱环节补强的实践参考。压缩包共371个文件、约11.27MB&#xf…

作者头像 李华
网站建设 2026/10/31 18:30:18

CTF竞赛MISC题型解析:文本隐写与编码分析实战

1. 题目背景与解题思路"青岑CTF MISC | 前有文字,所以搜索很有用"这道题目属于CTF竞赛中典型的MISC(杂项)题型。这类题目往往考察选手的综合能力,包括信息搜集、编码分析、隐写术等多方面技能。从题目名称"前有文字…

作者头像 李华
网站建设 2026/10/31 18:30:02

Winsock LSP注入与WSPStartup拦截实战

简介:这份 LSP 注入技术学习资料围绕 Windows 语言服务提供者(Language Service Provider)的底层钩子机制展开,面向已具备 C 基础、希望理解 COM 组件注册与进程注入原理的中级开发者。内容从 LSP 概念与 COM 接口规范切入&#x…

作者头像 李华
网站建设 2026/10/31 18:25:07

免费画图软件选型指南:按位图、矢量与结构路线匹配十一款工具

“免费画图软件”这四个字,搜索量一直居高不下,但真正能拿来干活、能长期留在工作流里的其实不多。我在不同规模的小团队里做过多年的设计协作支持,从零预算的学生小组到有采购预算的产品线都待过,反复碰到同一个尴尬:…

作者头像 李华