简介:长会话中大模型为何越改越错?本文解析“上下文腐烂”现象:注意力预算随 token 增长被摊薄,性能是渐变式滑坡而非突然崩溃。文章进一步给出会话切分、主动压缩、精准投喂、外部记忆等可落地的治理策略,帮你把长上下文真正用稳用好。
很多人在使用智能编程助手或对话式 AI 时都有类似体验:会话刚开始,模型响应又快又准,改代码、答问题都干脆利落;但聊到几十轮之后,画风突变——它开始遗忘早期约定,改好 A 却弄坏 B,道歉、修复、再道歉、再修复,在循环里出不来。
第一反应往往是怀疑:是模型今天“状态不好”,还是我的提示词没写清楚?其实两者大概率都不是。业界在长期观察后,给这类现象起了一个形象的名字:上下文腐烂(Context Rot)。
它的核心结论只有一句话:随着上下文不断增长,模型性能会持续下降——注意力被分摊到越来越多的 token 上,早期那些无关紧要的内容,会逐渐干扰当前任务。
可以把上下文理解为模型一次推理所能“看见”的全部信息总量,它通常包括:
可以把它想象成模型面前的一张办公桌:所有材料都要摊在桌面上处理。如今主流模型的这张“桌子”已经做得非常大,从几万 token 一路扩展到百万级,换算成中文约相当于两三部短篇长度的小说体量。各大云平台——包括百度智能云在内的模型服务——也普遍在持续扩大上下文窗口的容量。
听起来很美好,但一个反直觉的事实是:桌子变大,并不意味着工作效率会同步提升。
业界有一个广被接受的类比:就像人类的工作记忆容量有限,模型在解析大量上下文时,也在消耗一份有限的“注意力预算”。
这背后有注意力机制本身的数学原因。自注意力在计算权重时需要做归一化,所有 token 分到的注意力权重之和恒等于 1——也就是说,注意力本质上是一种“零和”分配:上下文里每多一个 token,其余所有 token 能分到的注意力就相应被稀释一点。你多往桌上摊一叠纸,找回之前那份笔记本就要多花几秒;模型多吞一段历史,锁定真正相关信息的能力就弱一分。
除此之外,还有两点公认的加重因素:
关于这一现象,有一个判断非常关键,值得单独强调:上下文腐烂描述的是性能下降,不是能力崩溃。模型不会在某一轮突然失忆,而是缓慢、平滑地变差。
这个差别在工程上极其重要:
所以更实用的做法不是等症状明显才处理,而是主动监控早期信号,例如:模型开始遗忘会话早期定下的约定;对同一问题反复给出不同答案;回复逐渐泛化、套话变多;修改代码时波及本不该动的模块。一旦出现这些迹象,就该考虑做上下文治理了。
很多人把“百万 token 窗口”当成免死金牌:反正装得下,那就把所有材料一股脑塞进去。这恰恰是对长上下文最大的误解。
窗口能装下是一回事,能不能用好是另一回事。超长窗口带来的是管理责任的转移,而不是管理成本的消失——每多聊一轮,你其实都多了一道判断题:这段历史还有没有价值?要不要留下?留多少?
而且从工程角度看,超长上下文也从来不是免费的:更长的输入意味着更高的推理成本与更长的响应延迟,缓存压力也随之上升。把“能装”当成“该装”,等于用最贵的方式,买最差的效果。
上下文腐烂无法根治——它是注意力机制的固有属性,就像重力,不是可以修掉的 bug。但完全可以通过工程手段延缓和管理。以下是实践中被反复验证的六条策略。
不要把所有工作堆在同一个会话里。完成一个功能、修完一个 bug,就果断开新会话。探索性工作尤其如此:试错过程中的死胡同没有留存的必要,它们正是腐烂的主要养料。
当会话不可避免地变长时,主动让模型对当前进展做一次结构化总结——已完成什么、关键决策是什么、还剩什么问题——然后带着摘要开启新阶段,替代原始的几十轮对话。信息密度提高了,token 却少了一个数量级。
避免“整库投喂”。只注入与当前任务直接相关的文件、函数和片段;让检索先行,把大海捞针的工作交给工具完成,而不是让模型在上下文里自己捞。
关键规则写进系统提示并放在开头;超长会话中,在合适时机用一句话重申核心约束。利用模型对开头和结尾更敏感的特性,把最重要的信息放在注意力的“高地”上。
对跨会话的长期任务,最可靠的做法是把“记忆”外置成文件:任务清单、架构决策、进度日志,由模型在每轮收尾时更新、在下次开工时读取。文件系统就是最廉价、最稳定的长期记忆。
一个极简的交接文档模板:
# 任务交接文档## 目标- 为订单模块补充退款接口## 已完成- 表结构已确定(见 schema.sql)- 退款接口主体位于 src/refund/handler.ts## 阻塞项- 外部回调格式与文档不一致,暂以 mock 处理## 硬性约束- 错误统一抛出 AppError,不返回裸字符串- 不改动 src/legacy 目录## 下一步1. 补充退款接口单元测试2. 对接真实回调并移除 mock
配合一个简单的会话生命周期,就能形成闭环:
开始会话 → 读取交接文档 → 执行任务 → 更新交接文档 → 结束会话
新会话冷启动时,只需让模型先读这份文档,就能以接近满血的状态继续工作,而不必背负此前的全部对话史。
命令输出、日志、测试报告是上下文膨胀的大头。投喂前做裁剪:长日志只保留错误堆栈的关键行,测试输出只保留失败用例的摘要。工具结果的“信息密度”,远比它的完整性重要。
回到开头的疑问:模型越聊越笨,既不是它今天状态不好,也不是你没说清楚,而是对话延续过程中必然发生的衰减。
理解“腐烂是重力,不是 bug”这句话,是用好长上下文模型的前提:你无法消灭重力,但可以学会借助工具与流程与它共处——更短的会话、更干净的历史、更精准的投喂、更可靠的外部记忆。把上下文当成一项需要主动治理的工程资源,而不是一个可以无限堆放杂物的大仓库,模型才能在长任务的每一轮里,都保持开局的那个状态。