AI 编程与智能体

[AI 上下文 #1] 智能体为什么会忘记指令

使用 Claude Code 这类编程智能体时,屏幕底部会出现“Context left until auto-compact: 8%”之类的警告。这是聊天型 AI 中不会出现的提示。不过,能解释这个数字为什么减少、归零后会发生什么的人,意外地并不多。

5 分钟阅读
[AI 上下文 #1] 智能体为什么会忘记指令 封面图

使用 Claude Code 这类编程智能体时,屏幕底部会出现“Context left until auto-compact: 8%”之类的警告。这是聊天型 AI 中不会出现的提示。但能解释这个数字为何减少、归零后会发生什么的人,意外地很少。如果你在会话开始时明确说过“不要改测试”,一小时后智能体却若无其事地修改了测试文件,十有八九就与这个数字有关。

本文是从原理到实践介绍 AI 智能体上下文的系列第 1 篇。什么时候使用 /compact 和 /clear、为什么用子智能体拆分任务等实践技巧,都建立在“上下文窗口是有限的”这一约束之上。因此第一篇从基础讲起:上下文窗口究竟是什么,为什么不能无限扩大,并通过 Token、注意力和 KV 缓存这三把钥匙进行说明。

Token,AI 计算文本的单位

上下文窗口的单位既不是字符,也不是单词,而是 Token。LLM 无法整体读取文本,而是接收分词器切分出的片段序列。切分依据是 BPE(Byte Pair Encoding)系列算法,原理很简单:训练数据中经常相邻出现的字符组合,会被合并成一个片段。像英文“the”和“ing”这样的常见组合会成为一个 Token,而罕见单词会被拆成多个片段。

这里有一个对韩语用户很重要的事实。由于分词器的训练数据中英文占比压倒性地高,即使内容相同,韩语通常也比英语多使用 1.5~2 倍 Token。“20 万 Token 的上下文窗口”按英文文档计算相当于两部长篇小说,但放入韩语文档后,体感容量会大幅减少,原因就在这里。

上下文窗口以 Token 为单位,表示“模型一次能读取的最大量”。系统提示、对话历史、附件文档,以及模型当前正在生成的回答,都必须放在这个上限内。

智能体的上下文为什么特别容易填满

首先要知道,LLM 是一种无状态(stateless)机器。处理完一个请求后,它不会把内容保存到任何地方。别说昨天的对话,就连上一轮对话在模型看来也从未存在过。

那么对话是如何延续的?答案简单得令人泄气:应用在每一轮都会从系统提示开始,把截至当前的全部历史重新发送一遍。模型写第十个回答时,并不是“记住”了前九次对话,而是刚刚又从头读了一遍。

如果是聊天型 AI,历史只有人类输入的句子和模型回答,因此增长较慢。智能体则不同,因为每一轮都会伴随工具调用。读取一个文件,就会把文件的全部内容加入上下文;运行测试,就会加入数百行失败日志;执行搜索,就会加入全部搜索结果。用户只输入了一行“帮我修复 Bug”,但如果智能体读取十个文件、运行三次构建,一个回合就会消耗数万个 Token。这就是编程智能体显示上下文剩余量的原因:聊天需要几天才会耗尽的容量,智能体一两个小时就可能用完。

仅一个回合的工具调用就能积累数万个 Token,而且每轮都会重新发送全部内容
仅一个回合的工具调用就能积累数万个 Token,而且每轮都会重新发送全部内容

达到上限后,应用必须丢弃一些内容。它可能从最早的回合开始截断,也可能压缩成摘要。如果会话初期确定的“不要改测试”之类的指令在这个过程中被挤出去,模型就会在仿佛从未做过约定的状态下开始下一轮。不是记忆力变差了,而是它本来就没有记忆,只是指令被推到了可读范围之外。

有限的原因一:注意力的平方级成本

那把窗口扩大到大约 1 亿 Token 不就行了吗?Transformer 的核心运算注意力(attention)会在这里构成瓶颈。

注意力机制在处理新 Token 时,会计算它与之前所有 Token 的相关程度。代码中出现变量 user 时,模型能把它与 3,000 行之前的声明联系起来,靠的就是这种能力。这是 LLM 看似理解上下文的原因,也是成本的根源。

由于每个 Token 都要关注所有 Token,计算量与长度的平方成正比。上下文长度增加 10 倍,注意力运算就增加 100 倍。得益于稀疏注意力、滑动窗口、FlashAttention 等优化,如今已经出现 100 万 Token 的模型,但本质没有改变:引用完整上下文的能力会随着长度产生陡增的成本。

有限的原因二:KV 缓存这张内存账单

问题不只是计算。内存方面还有另一张账单,叫作 KV 缓存(Key-Value cache)。

模型逐个生成回答 Token 时,如果每次都从头重新计算完整上下文,会非常浪费。因此,它会把每个 Token 已计算出的注意力中间结果(Key、Value 向量)存入 GPU 内存并重复利用,这就是 KV 缓存。问题在于,这个缓存会按层、按注意力头分别累积,并随上下文长度成正比增长。

以 700 亿参数级的开源模型为例,即使采用节省内存的技术(GQA),每个 Token 的 KV 缓存也约为 300KB。上下文填满 12.8 万个 Token 后,仅缓存就约占 40GB,会在模型权重之外独占一块高端 GPU 的全部内存。这就是扩展上下文窗口不只是软件设置,而是硬件和资金问题的原因。

这项成本会直接反映在用户费用中。LLM API 按输入 Token 数量计费,再加上每轮都重新发送完整历史的机制,就能解释为什么长会话越到后面越昂贵、越慢。

无状态模型的记忆每轮都从头重读,因此越长越慢、越昂贵
无状态模型的记忆每轮都从头重读,因此越长越慢、越昂贵

总结

  • 上下文窗口是模型一次能读取的最大 Token 数。韩语比英语多使用 1.5~2 倍 Token,因此不能直接相信规格数字。
  • LLM 是 stateless。对话记忆其实是每轮重新发送全部历史;智能体还会累积工具调用结果,所以上下文比聊天型 AI 快得多就会填满。
  • 窗口之所以有限,是因为注意力运算按长度的平方增长,而 KV 缓存按长度占用 GPU 内存。上下文既是能力,也是成本。

下一篇将打破一个常见观念:上下文越大越好。多项研究已经确认,上下文越长,模型性能反而越低。我们将介绍 lost in the middle、context rot,以及规格数字为何不同于实际有效容量。

延伸阅读