上一章《Agent 与工具调用》让模型会动手,代价是每一轮历史都要重发进上下文。 这一章接住它:决定效果的是你在那个有限窗口里放了什么、丢了什么。
你和一个助手聊了两个小时,开头说过"我不吃辣",点餐时它却推荐麻辣火锅—— 不是它变笨了,是那句话被挤出了窗口。提示词写得再漂亮也救不回; 能救它的是这一章要讲的上下文工程(Context Engineering): 把模型能看到的全部内容当成一份要分配的预算,决定放什么、丢什么。
| 对比项 | 提示工程 Prompt Engineering | 上下文工程 Context Engineering |
|---|---|---|
| 关注对象 | 用户输入的那一句话 | 整个窗口里的所有内容 |
| 典型问题 | "加不加'请一步步思考'?" | "历史对话要不要压缩?检索到的 20 段文档放几段?" |
| 优化目标 | 让这一次回答更好 | 让整段对话在成本和效果之间最优 |
| 为什么后来更重要 | 模型变强之后,措辞的边际收益越来越小 | 窗口大小和成本是硬约束,永远存在 |
提示工程问「怎么写」;上下文工程问「留什么、丢什么」——窗口有预算,这是一道分配题,不是写作题。
模型的上下文窗口是硬上限,下面这六样东西全在抢同一块地方:
互动 · 上下文预算分配器(超支会真的报警)
这根条就是这一章的全部:窗口固定,六样东西都在抢它。拖一拖看谁最容易被丢掉——后面所有方法都在解决同一件事。
不能丢:系统提示(角色和规则)、用户输入、预留的输出空间(不留位置,输出会被截断)。
可以丢:历史对话(压成摘要)、检索内容(减少条数或重排)。
最难的是工具定义:少了做不了事,多了每轮重付 token——给模型 50 个工具通常是坏主意。
"该记住什么、该忘什么"这个问题,认知科学已经研究了一百年。它的分类意外地贴合 LLM 系统:
| 记忆类型 | 在 LLM 系统里对应什么 | 容量 | 怎么读写 |
|---|---|---|---|
| 工作记忆 Working |
当前上下文窗口 | 很小、很贵 | 直接放进 prompt,用完就没了 |
| 情景记忆 Episodic |
过去的对话记录(向量库) | 可以很大 | 按相似度检索回上下文 |
| 语义记忆 Semantic |
事实知识 —— 模型参数 + RAG 文档库 | 最大 | 训练好就不动;文档走检索 |
| 程序记忆 Procedural |
技能 —— 工具定义 + 微调得到的习惯 | 中等 | 工具写进系统提示;习惯写进权重 |
想象一个在图书馆做研究的人:
工作记忆 = 他此刻摊在桌面上的那几本书。放不下更多了,而且换书很慢。
情景记忆 = 他上周做的笔记。需要时翻出来看一眼。
语义记忆 = 他脑子里早就记住的常识,以及整座图书馆的书。
程序记忆 = 他会用索引系统、会做文献综述——这些是练出来的技能,不是知识。
"上下文工程"要解决的,就是这张桌子的管理问题。
这个类比管到桌面为止:桌上摆什么,由程序决定,不是模型自己去取。
窗口满了必须丢东西,而丢法不同,丢掉的「是什么」就完全不同,还比不丢更糟。下面是统计哪些信息活下来了。
互动 · 四种压缩策略的信息保留率
| 策略 | 怎么做 | 代价 |
|---|---|---|
| 滑动窗口 | 只保留最近 N 轮,更早的直接删 | 简单、无额外开销,但会丢掉最开始的「任务目标」——模型聊到后面就忘了你最初要它做什么 |
| 摘要压缩 | 让模型把旧对话总结成一段话 | 省 token,但有损且不可逆:细节没了就是没了,摘要本身还可能引入错误(模型总结时也会幻觉) |
| 关键信息抽取 | 显式提取出事实、约束、决策,存成结构化字段 | 精准、可控、可校验,但依赖你自己的抽取质量——没被识别为「关键」的信息就永远丢了 |
| 向量检索回忆 | 把全部历史存进向量库,按当前问题检索相关片段 | 可扩展到无限长,但检索会漏:语义相似不等于「这条信息在这个任务里重要」 |
没有通用最优策略,全看任务。任务目标和硬约束做成结构化字段、永远保留在最前面,绝不能进自动压缩; 过程性对话用滑动窗口或摘要;参考资料用检索。把「该不该丢」交给程序按类型决定。
上下文长度 → KV Cache 显存(真实的线性关系)
宣称支持 1M 的模型,代价有三:占显存(KV cache 可能几百 GiB)、花钱(每轮输入都按 token 计费)、不一定有效(信息放中间时最差,回看
第 2 节说上下文是「一块有预算的稀缺资源」,但软在哪?软在注意力是一条总和恒为 100% 的条—— 每多一个无关 token,就从这条 100% 里切走一块。所以「该忘什么」是一道减法题。下面这张图把 softmax 真算了一遍。
互动 · 关键那句话分到多少注意力(真的按 softmax 算)
互动 · 每个符号管图上的哪一块
先把 Δ 拖到 0,再把 m 从 0 拖到 48:关键那句分到的注意力从 100% 掉到 2%; 再把 Δ 拉起来,同样的 m 下它又能站住一大块。这就是这一章全部策略的数学底牌: 要么少放点(压缩、遗忘 → 把 m 降下来), 要么让关键那句更突出(检索、重排、放在开头或结尾 → 把 Δ 抬上去)。 上下文越长越"聪明",只在你把它喂对了的时候才成立。
互动 · 记忆管理方案的演化
年份是「进入工程实践」的时间,不是论文发表年。
| 方案 | 核心做法 | 解决了什么 |
|---|---|---|
| 滑动窗口 | 只留最近 N 轮 | 最简单,代价是早期目标会丢,模型后来跑偏 |
| 摘要记忆 | 定期把旧内容总结成一段 | 省 token、能维持很长对话;但摘要不可逆且可能引入错误 |
| RAG 记忆 | 历史的每一段都存向量库,按需检索 | 可扩展;召回不准时会毒化上下文 |
| MemGPT / 分页记忆 | 把上下文当"内存"管理:分页、换入换出, 模型自己决定"这段要不要存到长期记忆" | 第一次把「管理记忆」变成模型的显式能力,而不是外部写死的规则 |
| 层级记忆 | 短期 / 中期 / 长期分层,各自不同的压缩率 | 贴近认知科学:不同时效用不同策略 |
| 结构化状态 | 用文件、数据库、待办清单当外部记忆, 把"当前进展"变成可读写的结构 | 最可靠的一类:确定性、可校验、可回滚,不依赖模型"记得住" |
整个领域正在从"让模型记住更多"转向"让模型不需要记住——把状态放到外面去", 也就是计算机科学几十年前的老答案:不要依赖易失的内存,把状态持久化到磁盘。
| 代价 | 说明 |
|---|---|
| 压缩不可逆 | 丢掉的 token 拿不回来,以后要用只能重新检索或重问用户。保守一点,关键约束别进自动压缩 |
| 摘要会引入错误 | 模型可能在摘要里写进原对话没有的内容,之后引用就把错误固化了——摘要是幻觉的隐蔽入口 |
| 检索会拉进无关内容 | 相似度高的段落不一定有用,塞进去反而把模型带偏(这叫 context poisoning) |
| 没有通用最优策略 | 压缩比例、保留长度、检索条数都要按任务调,不同任务的最优值可能完全相反 |
| 它会掩盖真正的问题 | 一直溢出,真正的原因可能是提示太啰嗦或检索策略不对;压缩只让症状不那么明显 |
回到第 4 节那个保留率互动,依次切四个选项, 每次切换前先猜保留率会升还是会降:没有一个接近 100%。 那四个读数的差距,就是「压缩是单向的」被量化出来的样子。
这一章的 D 行是全书最直接的一个。
| 暗线 | 这一章的回答 |
|---|---|
| A 信息流动 | 形状是 (batch, n, d):n 是上下文里的 token 数,batch 是第 5 节的「并发数」。
这一章改的就是 n——四种压缩策略是四种「n 怎么缩短」的规则。 |
| D 跑在什么上 | 带宽受限,而且是全书最纯粹的带宽瓶颈:每生成一个 token,KV Cache 要从头读一遍,计算却很少。 量化(字节减半)几乎直接换算成吞吐量翻倍(省的是搬运量);Prompt Caching 省的是开头把前缀算一遍的计算——见 《推理与 KV Cache》。 |
| E 它假设了什么 | 三个假设,第二个最危险:「我知道以后会用到什么」——所有压缩策略都要求你在还不需要时就决定丢什么,这个假设在长任务里几乎总是错的。 另两个:「上下文是均匀可用的」(中间最差)、「压缩后的表示够用」(摘要常丢掉语气、不确定性、精确数字)。 |
下一章《多智能体与工作流》要回答:多几个 agent 分头管理上下文,值不值。
窗口有限,系统提示、工具定义、历史、检索内容、用户输入全在抢同一块地方:丢什么该由程序按类型决定,压缩又全是不可逆的。
序列长度是 KV Cache 的线性项,能塞不等于该塞;最可靠的记忆是把该记的放到模型外面(文件、数据库)。
上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。