模型好像变笨了:怎么分清错觉、上下文变脏、版本切换和真实退化

2026-07-28

数据截至 2026-07,各产品的额度与报错口径以官方最新说明为准。

十次里有七八次,「模型变笨了」的真实成因不在模型那一侧,而在你自己那一段越攒越长、越攒越脏的上下文里。 这是我反复踩过之后形成的判断,不是什么定论。但它有一个很实用的推论:当你产生「不对劲」的感觉时,最该做的第一件事不是去搜有没有别人也在抱怨,而是开一个干净会话,把同一件事再问一遍。这个动作花不到一分钟,却能把四类成因里最常见的两类当场排掉。

这篇文章讲的是从直觉到结论之间的那一段路:你手上还没有任何评测数据,只有一个「今天写出来的代码质量掉了」的印象,接下来按什么顺序查、每一步查什么、什么时候该停手。站内另外两篇管的是别的事:模型名对不对得上、接入方是不是拿另一个后端顶替你选的型号,那是身份问题,看 模型别名与型号顶替的风险;怎么给一套 Agent 流程建长期的评测口径和指标,那是工程体系问题,看 Agent 评测方法。本篇是夹在两者中间的应急那一步。

一、先把「变笨」拆成四类可观测的成因

「变笨」是感受,不能直接排查。你得先把它拆成四类互斥的假设,然后按验证成本从低到高逐个排。

第一类是你的错觉。 这不是贬义,人的判断本来就没有对照组。常见的三种:任务本身变难了(上周是加个字段,今天是改一处并发逻辑,你却在拿同一把尺子量);你的期望在漂移(用顺手之后你不再夸它对,只记得它错的那几次);样本太小(连续两次不理想就下结论,而这个工具在同一题上本来就有波动)。

第二类是上下文变脏。 长会话里,一个早期的错误结论会被后续每一轮当成既定前提反复引用;你顺手引进来的无关文件占掉了大量注意力;改过又废弃的代码片段还留在对话里,模型分不清哪版是现行的。表现出来就是「它开始答非所问」「它坚持一个我已经说过不对的方案」。窗口机制本身的介绍在 上下文窗口是什么,会话里怎么主动控制在 Agent 上下文管理

第三类是版本或路由静默切换。 你以为在用 A,实际跑的是 B。触发路径有好几条:你自己配的多模型回退在某次超时后生效了并且没退回去;工具的默认型号跟着版本更新变了;接入层在高峰期把请求转到了别的后端;团队里有人改了共享的配置文件。这一类的特征是「行为风格整体变了」,不是某道题做错,而是措辞、篇幅、爱用的库都跟着变。

第四类才是真实退化。 同一个模型标识下,服务侧的部署发生了变化。这类事情客观存在,但它是概率最低的假设,也是你最难独立证实的假设——所以放最后。

二、判别表

现象大概率成因怎么验证处置动作
长会话里越聊越偏,反复回到一个你否掉的方案上下文变脏开新会话,只给最小必要输入,重问同一题新会话正常就直接弃旧会话;把有效结论写进项目规则文件,不靠对话记忆
只有一两次不理想,换个说法就好了你的错觉/正常波动同一题在干净会话里连跑三次,记下通过与否三次里两次以上正常就不用查了,继续干活
语气、篇幅、代码风格整体变了版本或路由切换先看返回体里的模型名字段,但这个字段有可能只是把你请求的名字回显一遍,所以必须再加一步:同一组题换另一条接入链路跑一遍做对照;同时查自己的配置文件近期改动把型号显式钉死,别依赖默认值;回退配置改动
任务变复杂之后质量下滑任务难度上升把任务拆成两三个独立小步,逐步跑拆任务、补上你自己的约束条件,而不是换模型
突然频繁截断、半句停住、工具调用失败网络或接入层问题看 HTTP 状态码与网络错误名(429/500/ETIMEDOUT/ECONNRESET)按错误类型处理,重试或换链路,别归因于智力
提示额度已用尽或权限不足计费与鉴权401 看凭据本身,403 看权限范围与区域,429 看限流;各家的额度口径和限流粒度不同且会调整,以官方最新说明为准换凭据、降并发、等窗口恢复
换项目、换机器、换人都能复现同一类错误有可能是真实退化跑完整回归题,跟历史存档逐题比对有数据了再决定要不要换型号或换供应方

这张表的用法不是查字典,是限制你的搜索空间。看到「越聊越偏」就别去查模型版本,看到「风格整体变了」就别急着优化你的指令写法。

三、建一组自己的回归题

上面那张表能帮你处理单次事件,但只要你怀疑的是第三、第四类成因,就必须有一组固定题目。没有它,你永远只能停留在「我觉得」。这组题不需要做成正式的评测系统,一次坐下来就能攒出可用的第一版。

题目从你自己的失败史里来。 翻一翻最近几周被你手动改掉的生成结果,挑那些「它本来应该做对」的。这些题比任何公开题库都准,因为它们贴着你的代码库、你的技术栈、你的约定。我一般凑三类:一类是纯代码题(给一段有 bug 的函数,让它定位并修),一类是需要读多个文件才能答对的题(考它会不会真的去看),一类是需要它拒绝或反问的题(给一个前提本身有错的需求,看它是照做还是指出问题)。每类三到五道就够起步。

执行条件必须固定。 每道题一个干净会话,输入逐字一致,仓库停在同一个提交上,工具集不变。这四条里任何一条飘了,结果就不可比。仓库状态用一条命令记住:

git rev-parse --short HEAD

评分只用二值。 通过或不通过,加一句失败原因。别用一到五分制,你自己隔一周的打分尺度就会变,比模型的波动还大。原始输出全部落盘存档,目录按日期分:

bench/
  2026-07-28/
    code-01.md
    multifile-02.md
    refuse-03.md
    result.csv

result.csv 里三列:题号、通过与否、失败原因,第二列只写 10。通过率用一行命令算,不需要工具:

python -c "import csv
rows=[x for x in csv.reader(open('bench/2026-07-28/result.csv',encoding='utf-8')) if len(x)>1 and x[1] in ('0','1')]
print(sum(1 for x in rows if x[1]=='1'),'/',len(rows))"

那个 len(x)>1 and x[1] in ('0','1') 的过滤不是摆设:表头行、手工编辑时留下的空行、以及第二列被你写成「通过」两个字的那几行,都会在这里被跳过,否则分母虚高或者直接抛异常。这类小护栏值得一开始就加上,因为回归题集是要被你隔月再打开的东西,那时候你早忘了当初的格式约定。

把整个 bench 目录纳入版本管理。 这是关键一步,也是最容易省掉的一步。跨月比对靠的是历史存档,不是记忆。等到某天你真的想说「它退化了」,你需要拿得出两个日期的两份输出,而不是一段描述。

有了这组题,前面那四类假设才第一次变得可判:错觉会被通过率打掉,上下文污染在干净会话下不出现,版本切换会让整组题的输出风格同时变,真实退化则表现为特定题型稳定掉、且能在别的机器上复现。想把这套东西往正规评测方向做,接口和指标怎么设计另说,那属于 Agent 评测方法 的范围。

四、按顺序执行的动作

顺序本身就是方法。每一步都比下一步便宜,能在前面结束就别往后走。

一,干净会话重跑。 新开会话,只贴必要的那点输入。正常了,成因就是上下文,到此结束。

二,缩小输入。 如果新会话仍然不对,把输入砍到最小可复现的样子:去掉附带的文件、去掉背景铺垫、只留那一段代码和那一句要求。缩到不能再缩还是错,说明这道题确实超出它当前的能力边界,或者你的要求里有歧义。这一步经常暴露的是后者。

三,核对模型标识与路由。 看你实际拿到的返回来自哪个型号。多数兼容 OpenAI 接口风格的服务,返回体里会带一个模型名字段,把它取出来:

jq -r '.model' response.json

没装 jq 的话用标准库也一样:python -c "import json;print(json.load(open('response.json'))['model'])"

这里有一层必须说清楚,否则这一步会给你假的安全感:这个字段是服务端自报的,中间任何一跳都可以原样回显你请求里写的名字。所以它只能用来抓「我配错了型号」这类自己造成的错,不能用来证明对面真的在跑那个模型。想把身份这件事查瓷实,得靠行为指纹和交叉对照,那是 模型别名与型号顶替的风险 那篇的活。

用工具而不是裸 API 的话,看它的会话信息或状态输出里是否显示当前型号。同时检查环境变量和配置文件有没有被改过:

env | grep -i -E 'api_base|api_url|model|proxy'
git log --oneline -10 -- .env.example .claude/ .cursor/

第二条命令有个前提要提醒:真正生效的 .env 通常写在 .gitignore 里,git log 是查不到它的改动的,能查到的只有入库的模板和规则目录。本地那份就只能靠修改时间来判断,ls -l 看一眼时间戳,如果它的时间跟你「开始觉得不对劲」的那天对得上,基本就锁定了。

配了多模型回退的,重点看回退是否已经生效、有没有在故障恢复后自动退回主型号——不会自动退回的实现很常见,这一条我建议你亲手验一次。

四,换一条链路做对照。 同一道题,走另一条接入路径跑一次。两条链路都错,问题在题或在模型;只有一条错,问题在链路。这是唯一能把「接入层的锅」和「模型的锅」分开的手段。

五,跑全套回归题,跟历史比。 到这一步才值得花这个时间。逐题对比,看是散点失败还是成组失败。散点是波动,成组才是信号。

六,排查非模型因素。 状态码和网络错误名会直接告诉你答案:429 是限流,401 是凭据无效,403 是权限或区域问题,500 是服务侧异常;ETIMEDOUT 和 ECONNRESET 是网络层;如果公司出口有中间设备做流量解密,你会看到证书链校验失败,因为客户端不认那张自签发的根证书。这些都不是「变笨」,但它们造成的截断、重试、丢工具调用,感受上跟变笨一模一样。最简单的连通性对照:

curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' https://example.com/

七,看你自己最近改了什么。 项目规则文件、工具清单、自定义指令,任何一处改动都可能整体改变行为。工具挂太多本身就会稀释注意力。这一步用 git 就能查完,成本极低,我却见过太多人跳过它,直接跑去怀疑供应方。

顺带说一句区域问题:几家海外的编程工具与模型服务,官方对中国大陆有区域限制、不支持直连,遇到 403 或握手失败先想这一层。市面上存在第三方中转,我不背书也不给具体渠道,只提醒一点——中转链路上换后端是常事,这恰好是第三类成因的高发地带。

五、什么情况下别再折腾

排查也有沉没成本,得给自己划线。

止损点:单个任务上,三十分钟没定位就停。 把这次的活手工干完或者拆开重做,先交付。故障排查和交付是两件事,别让前者堵住后者。你可以把这道题记进回归题集,等下次成批处理。

回滚点:只要你在近期改过规则文件、工具配置或型号设置,先回滚再谈别的。 回滚是最快的二分法。回滚后正常,你就直接拿到了答案;回滚后依旧,你也排掉了一大片可能性。所以每次改这些文件都单独提交,别混在功能提交里——混了你就没法回滚。

换条路的判断依据有三条。 其一,同一道题在两条独立链路上都失败,说明不是接入问题,换供应方也不一定救得回来,这时该改的是任务拆法。其二,回归题成组掉且能在另一台机器上复现,这时候换型号是合理动作,因为你有对照数据了。其三,某类任务它一直做不好、跟今天不对劲无关,那就固定用别的方式做,不要每周重试一遍指望它突然会了。

反过来,什么时候值得继续深挖:跨项目复现、多人复现、回归题成组掉,三者中出现两个以上。只有你一个人在一个项目里感觉不对,大概率还是前两类成因。

六、避坑清单

在同一个长会话里反复调试同一个问题。 为什么会踩:换个说法再问一遍是最省力的动作,而你正在调试的错误答案已经躺在上文里被当成前提了。怎么避:每次重试都开新会话,把有效的约束写进项目规则文件而不是靠对话累积。写法参考 Claude Code 上下文管理 里的做法。

没有对照就宣布退化。 为什么会踩:印象天然是有偏的,你只记得错的那几次。怎么避:任何「变笨了」的结论,先跑三次同题,再看回归题的历史通过率,两者都不支持就当没发生。

改了配置又忘了改过。 为什么会踩:调链路、试型号、加工具,这些改动往往顺手做完就忘,且多人共享的配置别人也会动。怎么避:这类文件的改动单独提交并写清原因,排查第一步先看 git log

把限流、超时、截断都算成智力问题。 为什么会踩:从体验上看,回答半截停住和答得很差是同一种「不好用」。怎么避:先看状态码和错误名,把传输层的问题从质量问题里切出去,两者的处置动作完全不同。

把默认型号当成确定值。 为什么会踩:不显式指定的时候,工具用的是它当前默认值,而默认值会随版本变。怎么避:能配置的地方把型号写死,会话里养成看一眼当前型号的习惯。

回归题里塞进无法客观判定的题。 为什么会踩:「写一段介绍」这种题看起来好出,但没有通过标准,一个月后你自己也判不出来。怎么避:每道题必须有明确的通过条件——测试跑绿、能定位到指定行、能指出前提中的错误,缺一条就别收进来。

回归题存档只留结论不留原文。 为什么会踩:记录「第三题失败」很省事,但下次比对时你无法判断这次的失败和上次是不是同一种。怎么避:原始输出整段落盘,用日期目录分开。

一次只改一个变量这条规矩被破坏。 为什么会踩:着急的时候容易同时换型号、清上下文、改规则文件,然后好了——你不知道是哪一个起了作用,下次照样懵。怎么避:宁可多花两轮,也一次只动一处。

收束

「模型变笨了」这个判断,绝大多数时候是一个归因错误,而不是一个事实描述。你需要的不是更强的直觉,而是一条固定的排查顺序和一组能存档比对的题目。前者让你不浪费时间,后者让你在真的遇到问题时说得出话。

临时自检,从上往下走,任何一步命中就停:

  • 开干净会话重跑了吗?正常就是上下文的事。
  • 输入砍到最小了吗?还错就先怀疑要求本身有歧义。
  • 当前实际用的是哪个型号?配置和环境变量最近动过吗?
  • 换一条链路对照过吗?
  • 全套回归题跑了吗?是散点失败还是成组失败?
  • 状态码和网络错误名看过吗?传输层的问题别算在质量头上。
  • 三十分钟到了吗?到了就先把活干完,把题记下来。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。