我把一段提示词改了八遍。
每次它答错,我就回去改那句话:换个说法、加个条件、再把"务必"两个字加重一点。改到第八遍我停下来想——它答错,真是因为话没说清楚?
那天它给的答案里,用到了一个三天前就已经删掉的字段。那个词不在我的提示词里,在上下文里,是几轮之前留下来的。
我一直在改它听到的那句话,它错在看见的那一整堆东西。
上下文是有预算的
Anthropic 的工程博客里有个词叫 context rot,直译过来是"上下文腐烂":上下文窗口里的 token 越多,模型准确回忆其中信息的能力反而越弱。
这个说法最早来自 Chroma 的一份技术报告,他们一口气测了十八个模型,包括几家的旗舰,结论是所有模型的性能都会随着输入变长而往下滑——而且是渐进地滑,不是撑到某个点才突然断崖。
Anthropic 引用这个结论的时候,补了一句自己的判断:上下文必须被当成一种有限的资源,它的边际收益是递减的。
这不是哪家模型没做好,是这类架构的通性。原因也不复杂——注意力机制里,每个 token 都要和其他所有 token 算一遍关系,你塞进去的每一个 token 都在分走它有限的注意力预算。
所以"填得越满"和"懂得越多"是两回事。
Andrej Karpathy 把大模型比作一台操作系统:模型本身是 CPU,上下文窗口是内存。顺着这个类比往下想——你开一堆程序把内存占满,机器不会因此变聪明,只会变卡。
从"怎么说"到"让它看见什么"
Anthropic 给的定义是:上下文工程,是在推理过程中持续挑选和维护那批最优 token 的策略集合。
说人话:提示词工程琢磨措辞,上下文工程安排它此刻看见什么。一个是在改句子,一个是在排货架。
网上有句话叫"提示词工程已死",我觉得说得夸张了。措辞依然重要,只是它从全部变成了整个上下文里的一小块。
四个动作
现在主流的做法可以归成四类,这四个词是我见过最好记的框架:
写 —— 把东西放到窗口外面去。
装不下的就别硬装:中间结果写进文件,跨会话的东西存成记忆,项目规矩写成规则文件(Claude Code 的 CLAUDE.md、Cursor 和 Windsurf 的 rules 都算这一类)。上下文窗口是工作台,不是仓库。
选 —— 用到什么拿什么。
别在开场就把整个仓库灌进去。Claude Code 的做法是:CLAUDE.md 这种稳定的东西预加载,具体文件用 glob、grep 现用现查。工具也是同一个道理——工具描述一旦重叠,模型就开始挑错工具,有研究试过改成按需检索工具描述,工具选择的准确率提升到了原来的三倍。
压 —— 只留还需要的。
对话一长必然累积。Claude Code 在上下文用到 95% 的时候会自动压缩整段历史,压缩之后通常只保留最近访问的那五个文件。你也完全可以手动做这件事:把上一阶段的结论写成一份摘要,其余扔掉。
隔离 —— 别让它们互相污染。
研究阶段翻过的那几十个文件,到了实现阶段就只剩噪音。多 agent 的本质就是给每个子任务一个干净的窗口。
代价也得说清楚:Anthropic 自己报告过,多 agent 的 token 消耗最高能到普通聊天的 15 倍。它不是什么免费的优雅习惯。
我现在自己在做的四件事
第一件:出错了先看它看见了什么,别急着改措辞。
把这轮的上下文整个翻一遍,多半一眼就能看出问题——一个早就过期的字段、一堆用不上的工具返回,或者它根本就没拿到那份文件。
第二件:工具按需开。
我图省事把所有 MCP server 一起开着的那段时间,它反而在几个名字很像的工具之间来回试探,半天选不对一个。
第三件:长任务切成阶段。
上一阶段的产出写成一个摘要文件,新任务开新窗口,只带这一份进去。这是目前我试过最省心的一招。
第四件:示例挑三个,别挑三十个。
Anthropic 的原话是不要往提示词里塞一份边缘情况的清单,要挑能代表期望行为的典型例子。堆量解决的是你的焦虑,不是它的准确率。
今天就能做的一件事
挑一个你最近骂过它"怎么这么笨"的任务,把喂给它的完整上下文打印出来看一眼。
多数时候你会看到同一个画面:真正有用的那两三句,被埋在一大片跟当前任务无关的东西中间。
模型能记住多少,我管不了。但它这一刻看见了什么,是我能安排的。