Long-form

深度长文:Context Rot——百万 token 上下文为什么会「越喂越笨」

6 min read ·

💡 一句话总结:上下文窗口大小是「容量」,不是「能力」。Chroma 的 Context Rot 研究证明,模型表现会随上下文变长而不均匀地退化,连简单任务都会翻车。会策展上下文,比有大上下文重要得多。本文剖析机制、coding agent 的受害方式,以及真正有效的工程应对。

一、百万 token 竞赛的另一面

2026 年的模型发布会有个固定环节:报上下文长度。200K、500K、1M、2M……数字一路飙升,仿佛上下文越长,模型就越聪明、越无所不能。

但一线工程师的体感和这个叙事拧着来:为什么我把整个代码库塞进去之后,AI 助手反而开始胡说八道?

Chroma 的 Context Rot 研究把这个体感变成了实证。他们系统评估了 18 个当时最强的模型——GPT-4.1、Claude 4 系列、Gemini 2.5 等——核心结论一句话就能概括:

模型的表现并不随上下文长度线性保持,而是随长度增长不均匀、不可预测地退化。

更扎心的是,这种退化不挑任务难度。哪怕是模型在短上下文下闭着眼都能做对的简单任务,一旦把输入拉长(哪怕新增的内容和任务无关),准确率也会往下掉。

这就是 Context Rot——上下文的「腐烂」。它不是某个模型的 bug,而是当前 Transformer 架构下的普遍现象。

二、它和「Lost in the Middle」不是一回事

很多人会把 Context Rot 等同于经典的 Lost in the Middle(Liu et al.)。后者说的是:把关键信息放在长上下文的中间位置,模型最容易忽略它,召回率呈 U 形曲线——两头高、中间低。

Lost in the Middle 是关于信息位置的现象,是 Context Rot 的一个子集。Context Rot 涵盖的范围更广,它包括但不限于:

换句话说,Lost in the Middle 告诉你「别把重点放中间」,而 Context Rot 告诉你「别让上下文太长,无论重点放哪」。

三、机制:为什么会「越喂越笨」

退化的根源可以从三个层面理解。

第一,注意力的稀释。Transformer 的注意力是个 softmax 归一化的分配过程——总注意力是守恒的。上下文里的 token 越多,每个 token 平均分到的注意力就越少。当真正相关的几百个 token 淹没在几十万个无关 token 里,模型很难把注意力精准聚焦到它们身上。这是物理性的稀释。

第二,干扰项的增多。长上下文里几乎必然包含和目标相似但不正确的内容。代码库里有十个名字相近的函数、文档里有五段讲类似概念的话——上下文越长,这种「看起来对其实不对」的干扰项越多,模型被误导的概率就越高。

第三,训练分布的偏移。模型虽然标称支持 1M 上下文,但训练时真正见过的超长、且要求在超长上下文里精确推理的样本,远比短上下文样本稀少。于是模型在接近上下文上限的区间,实际上是在「分布外」工作,能力自然打折。标称长度和有效长度之间,往往有相当大的差距。

这三者叠加,就构成了 Context Rot:上下文越长,信噪比越差、干扰越多、越偏离训练分布,表现于是不均匀地下滑。

四、Coding Agent 是重灾区

如果说 Context Rot 对一次性问答只是「偶尔翻车」,那么对 coding agent 来说,它是慢性中毒。

原因在于 coding agent 的工作方式天然会让上下文膨胀:

  1. 文件越读越多:为了理解代码,agent 不断读入新文件,上下文持续增长。
  2. 历史越积越长:多轮交互里,每一轮的对话、工具调用结果、报错堆栈都留在上下文里。
  3. 废弃决策不清理:早期尝试过、后来否决的方案仍躺在上下文里,成了干扰项。

于是出现了那个熟悉的现象:会话开头 agent 很聪明,越往后越蠢。它开始改错文件、引用早就删掉的函数、重新提出几轮前已经被否决的方案。本质上不是模型退化了,是它的上下文被自己污染了——相关信号被无关历史稀释,旧决策成了误导。

这也解释了为什么「开一个新会话」常常能立刻让 agent 恢复聪明——你清空了被污染的上下文。

五、工程应对:从「堆砌」到「策展」

理解了机制,应对就清晰了。核心是一句话:把上下文当稀缺资源来策展,而不是当垃圾桶来堆砌。一线团队真正在用的手段有四类。

其一,检索而非灌入。不要把整个代码库塞进上下文,而是用检索(向量检索 / 关键词 / 符号索引)只取当前任务最相关的片段。这正是 RAG 在 agent 时代的核心价值——它不是「让模型读更多」,而是「让模型只读该读的」。

其二,上下文压缩(compaction)。对长会话定期压缩历史。但要警惕:激进的摘要式压缩会丢掉代码里的字面细节(变量名、行号、报错原文)。更稳的做法是 verbatim compaction(保真压缩)——保留关键片段的原文、只丢弃确实无关的部分,而非把一切改写成摘要。实践中常分层处理:近期/关键内容保真,久远/次要内容才摘要。

其三,子 agent 隔离上下文。把一个大任务拆成子任务,每个子任务交给独立的子 agent,各自维护干净、聚焦的上下文,只把结论回传给主 agent。这样主 agent 的上下文不会被每个子任务的过程细节污染。这也是当下多 agent 架构流行的深层原因之一——它本质是一种上下文隔离机制

其四,主动清理与重置。定期清掉过时的历史、被否决的方案、已完成步骤的中间产物。必要时果断开新会话。清理不是浪费,是给模型卸下噪声包袱。

六、架构启示:容量不等于能力

Context Rot 给系统设计者的最大启示,是把两个常被混为一谈的概念分开:

百万 token 提供的是容量,而你的系统是否聪明,取决于你如何在这个容量里策展信息。这也是「上下文工程」(context engineering)正在成为一门独立工程学科的原因——在模型能力既定的前提下,怎么往上下文里放东西、放多少、何时清理,成了决定 agent 表现的关键杠杆。

⚠️ 一个反直觉的结论:很多时候,给模型更少但更相关的上下文,效果好过给它更多但更杂的上下文。「信息越全越好」在长上下文时代是个陷阱。

七、结语

百万 token 上下文是了不起的工程成就,但它不是免费的智能。Context Rot 提醒我们:模型不是你喂得越多就越懂你,而是你喂得越准它才越懂你。

下次当你想把整个代码库、整份文档、全部聊天记录一股脑塞给模型时,先停一秒问自己:这些信息里,有多少是这个任务真正需要的?剩下的,都是在稀释模型的注意力、增加它犯错的概率。

在长上下文时代,克制是一种能力。会管理上下文的工程师,会比拥有更大上下文的工程师走得更远。

Frequently asked questions

Context Rot 和经典的「Lost in the Middle」是一回事吗?
不完全是,Context Rot 是更大的概念。Lost in the Middle(Liu et al.)说的是模型对放在上下文中间的信息召回最差,呈 U 形曲线——这是关于「信息位置」的现象。Context Rot 是 Chroma 提出的更广泛的发现:随着上下文整体变长,模型在各种任务上的表现都会退化,且退化不均匀、不可预测,即使任务本身很简单、目标信息位置也不刁钻。Lost in the Middle 是 Context Rot 的一个子现象,但 Context Rot 还包括干扰项增多、相似内容混淆、长输入下推理能力下降等更多失效模式。
那模型厂商宣传的百万 token 上下文是骗人的吗?
不是骗人,但要区分「能装下」和「能用好」。百万 token 是容量指标——模型确实能接收这么长的输入不报错。但 Chroma 的研究说明,容量不等于在全长度上都保持能力。一个 1M 上下文的模型,在塞到几十万 token 时,表现可能已经显著低于它在几千 token 时的水平。所以正确的理解是:大上下文是一个有用的工程上限,但不该被当成「可以随便往里灌」的许可证。真正决定效果的是你往里放了什么、放了多少。
为什么我的 AI 编码助手在大项目里反而越用越笨?
这就是 Context Rot 在 coding agent 上的直接体现。随着会话进行,agent 把越来越多的文件、报错、历史对话堆进上下文,窗口被填得越来越满。一方面相关信息被海量无关代码稀释,模型注意力被分散;另一方面长会话里积累的旧决策、废弃方案成了干扰项,模型可能引用早已过时的代码。结果就是:开头几轮很聪明,越往后越容易答非所问、改错文件、重复已经否决的方案。这不是模型变笨了,是上下文被污染了。
上下文压缩(compaction)会不会丢失关键信息?
有风险,取舍在于压缩策略。最激进的摘要式压缩(把历史对话总结成一段话)压缩率高但容易丢细节,尤其是代码里精确的变量名、行号、报错堆栈这些「字面信息」一旦被总结就回不来了。所以现在更受推崇的是 verbatim compaction(保真压缩)——保留关键片段的原文,只丢弃确实无关的部分,而不是把所有东西都改写成摘要。实践中往往是分层的:近期、关键的内容保真,久远、次要的内容才摘要。关键是别把还要精确引用的内容压成模糊摘要。
面对 Context Rot,开发者最该改变的一个习惯是什么?
把默认动作从「全塞进去」改成「只放需要的」。很多人看到模型支持长上下文,第一反应是把整个代码库、整份文档、全部历史一股脑灌进去,觉得「信息越全模型越聪明」。Context Rot 说明恰恰相反——无关信息是噪声,会主动拉低表现。正确的习惯是把上下文当成稀缺资源精心策展:用检索只取最相关的片段、定期清理过时历史、用子 agent 隔离不同子任务的上下文。一句话:管理上下文,而不是堆砌上下文。
// next.txt ›

Some outbound links in this post are affiliate links — see disclosure.