上下文窗口是什么,为什么 AI 聊久了会变笨

AI 编程上下文科普

刚开始用 AI 编程工具的人,几乎都会在某个下午遇到这一幕:上午还配合得很好,到了第四十轮对话,它开始重复你已经否决过的方案,开始忘记你反复强调的约定,改出来的东西越来越离谱。

大多数人的第一反应是”模型今天状态不好”或者”是不是被降智了”。这两个解释都不对。真正发生的事情有名字,而且是可以被主动管理的——上下文窗口被填满了。

窗口里装的不只是你说的那几句话

先纠正一个很常见的误解:上下文窗口不是”AI 的记忆容量”,它更像一张每次对话都要重新铺开的桌子,桌面尺寸固定。

每轮对话开始时,桌上会摆着这些东西:系统提示词和工具定义(包括你接的每一个 MCP 服务器、启用的每一个插件,它们的工具说明都要占位置)、项目里的规则文件(比如 Claude Code 读的 CLAUDE.md、Codex 读的 AGENTS.md)、你从第一句到现在说过的所有话、模型说过的所有话,以及最占地方的一类——它读过的每个文件的内容、跑过的每条命令的完整输出。

在编程场景里,最后一类是绝对的大头。你让它排查一个 bug,它 grep 了一遍仓库、读了五个文件、跑了一次测试,这几步产生的文本量可能超过你们前二十轮对话的总和。而这些内容不会自动消失。

这里还有一个关键机制:每一轮对话,整个会话历史都会被重新发送一遍。模型本身不记得上一轮,是工具把之前所有内容重新铺一遍桌子递给它。这解释了为什么会话越长,单轮响应越慢、消耗也越大。

变笨的三个机制,是叠加的

搞清楚窗口里装了什么,“越聊越笨”就不再神秘了。

第一层是注意力被稀释。你在第三轮说的”这个项目不用 async”,到第四十轮时被埋在几万个 token 的文件内容中间。它没有”忘记”,只是这条信息在一大堆同等权重的文本里不再突出。

第二层是错误示范的积累。这一层最反直觉:你纠正过的错误,留在上下文里的不只是正确答案,还有那次错误的完整示范。你纠正两次,桌上就摆着两份写错的代码和两句”抱歉我改一下”。第三次尝试是在一个已经被污染的环境里进行的——它面前有两个错误样本,一个正确说明。

第三层是任务混杂。同一个会话里先修 bug、再改样式、顺手问个不相干的问题,三件事的上下文互相干扰。有个很形象的说法叫”厨房水槽式会话”:什么都往里扔,最后什么都捞不出来。

三层叠加,就是那种”它明明前面答应得好好的”的体感。

四个动作,各管一段

好消息是这套机制完全可以主动干预。以 Claude Code 为例,日常够用的动作只有四个:

  • /context:看当前窗口被什么占满了。感觉变慢、变笨时的第一诊断动作,不要凭感觉,先看一眼。
  • /compact:把会话压缩成摘要,释放空间。用在当前任务没做完但对话已经很长的时候,还可以带指示,比如只保留某个模块相关的结论、丢掉前面失败的尝试。
  • /clear:清空对话历史,项目规则文件仍然生效。用在切换到一个不相干的新任务时。
  • /rewind:回退到某个岔路口,走错方向时用。

有个容易被忽略的成本差异:压缩本身是一次很大的请求,而清空几乎不花钱。所以任务确实结束时,清空优于压缩,不要用 /compact 去挽救一个已经没用的会话。Codex 的命令名不同,但同一套判断成立。

还有一个进阶动作值得知道:把吃上下文的探索工作外包给子代理。“在仓库里找出所有还在用旧版 formatDate 的地方”这类任务可能要读三十个文件,让子代理在独立的上下文窗口里读,只把文件清单和摘要回传给主会话,主会话就还有空间做真正的实现。

一条可以贴在显示器上的阈值

上面都是动作,还差一个”什么时候做”的判断标准。最实用的一条是:

同一个问题纠正两次仍未解决,就清空会话,然后带着你刚学到的东西重写提示。

它的逻辑就是前面说的第二层机制。与其在污染过的环境里做第三次尝试,不如把两次纠正中学到的信息(哪个文件是真正的入口、哪个方案不可行)直接写进新提示的第一句。一个干净的会话配上更好的提示,几乎总是胜过一个积累了大量纠正的长会话。

最后提醒一句:真正有价值的结论应该被写进项目规则文件或者你自己的笔记,而不是留在会话里。舍不得清,是因为把会话当成了存储;一旦你养成把结论沉淀出去的习惯,清空就不心疼了。

想把这套做法落到具体命令和配置上,可以读《Claude Code 上手指南》第 5 章:上下文是唯一稀缺资源,或者从第 1 章开始建立整体的心智模型。用 Codex 的话,《把 Codex 用成队友》里有对应的会话管理章节。