大模型在物理底层不存在真正意义上的生物记忆,只有在显卡高带宽内存(HBM)中随序列长度线性堆叠的 Key-Value Cache,以及在数学上随序列拉长而被急剧稀释的注意力权重分布。Claude Code 呈现给开发者的所谓长程对话能力,本质上是一套在硬件显存与精度边界夹缝中运行的缓存逐出流水线,伴随着不可逆的信息失真与前缀失效代价。
在长周期编程任务中,开发者常常对 AI 助手的健忘感到困惑:明明第 5 轮确认过的接口规范,到了第 25 轮模型却视若无睹;明明前文明确修复过的类型定义,在一次 /compact 之后又被重新写回旧的缺陷模式。这是物理约束与信息论共同收紧的客观结果。
物理底座的硬约束:KV Cache 与显存爆炸 #
在基于 Transformer 架构的自注意力机制中,推理阶段(Decode Phase)为了避免对历史 Token 进行重复投影计算,系统会将每一层自注意力计算生成的 Key 与 Value 矩阵固化在显存中,这即是 KV Cache。
我们可以推导单个会话在自回归生成时的物理显存占用。设模型层数为 $L$,模型隐藏层维度为 $D$,注意力头数为 $H$。在现代生产级模型普遍采用的分组查询注意力(GQA,Grouped Query Attention)配置下,设 Key/Value 头的数量为 $H_{kv}$,每个注意力头的维度为 $D_h = D / H$。当上下文序列长度达到 $S$ 时,使用 FP16 精度(每个参数 2 字节),单请求的显存占用为:
$$\text{KV Cache Size} = 2 \times 2 \times L \times H_{kv} \times D_h \times S \text{ bytes} = 4 \times L \times H_{kv} \times D_h \times S \text{ bytes}$$以典型的 70B 级别模型(如 $L=80$, $H_{kv}=8$, $D_h=128$)为例,每增加一个 Token,KV Cache 就需要吞掉约 $320 \text{ KB}$ 显存。当上下文滑向 200,000 Token 时:
$$\text{Memory} \approx 4 \times 80 \times 8 \times 128 \times 200,000 \approx 65.5 \text{ GB}$$这仅是单个并发请求在纯 KV Cache 上的显存开销。在多并发集群中,服务商不可能让用户的历史会话毫无节制地霸占高昂的 HBM。
更致命的是首字生成延迟(TTFT,Time to First Token)的物理墙。在没有命中前缀缓存的情况下,对 150k Token 历史上下文执行 Prefill 计算的时间复杂度是 $O(S^2)$。没有工程手段干预的长上下文调用,交互延迟会迅速突破数十秒,彻底摧毁 CLI 工具的实时反馈闭环。
数学与认知的双重衰减:注意力稀释与 Lost-in-the-Middle #
除了硬件显存,长上下文在算法层面面临更严峻的注意力稀释(Attention Dilution)。自注意力机制的核心公式为:
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{Q K^T}{\sqrt{d_k}}\right) V$$在 Softmax 计算中,第 $i$ 个查询向量对所有历史 Token 的注意力权重总和必须归一化为 1:
$$\alpha_{i,j} = \frac{\exp\left(\frac{q_i k_j^T}{\sqrt{d_k}}\right)}{\sum_{m=1}^S \exp\left(\frac{q_i k_m^T}{\sqrt{d_k}}\right)}$$当序列长度 $S$ 从 2,000 膨胀到 150,000 时,分母项的累加项增加了近百倍。即使模型拥有基于 RoPE(旋转位置编码)的外推能力,背景噪声 token 依然会均摊有限的概率质量。
经典论文 Liu et al. (2023) Lost in the Middle: How Language Models Use Long Contexts 揭示了长序列注意力的物理衰退规律:
|
|
模型对位于上下文起始区域的系统提示(定义身份与工具契约)和位于末端的最新错误输出具备最高的召回敏感度。而深陷在序列中段的编译日志、前期探索的局部代码片段以及过往的架构决议,其注意力权重不可避免地跌入谷底。在长程推理中指望大模型精确记住第 15 轮某工具返回的变量名,违背了当前的数学物理现实。
Claude Code 的四级压缩管线与失真传导 #
面对显存压力与注意力衰减,Claude Code 构筑了一套四级梯级压缩管线。表面上它维系了长对话的连贯性,但在工程底层,每一级都在向信息熵妥协。
1. 观察结果裁剪(Observation Trimming) #
在 Think-Act-Observe 循环 中,最凶猛的上下文消耗源来自工具调用的回显——一次 npm test 或 cargo check 很容易吐出上万行的栈追踪日志。
Claude Code 的第一道防线是对已完成工具结果实施定长截断。由于源代码与测试文件实体持久化在磁盘上,运行结果属于即时消耗品,系统会剥离中间的冗长输出,仅保留退出状态码与前后关键几行。这是整个管线中信息损失比最小的压缩操作。
2. 对话重写压缩(Conversation Compaction / /compact)
#
当序列总长度触碰安全阈值(如额定窗口的 75%)时,系统启动对话压缩。其机制是启动一个独立的子调用,让模型对前半段已沉淀的历史消息生成结构化摘要:
- 梳理已完成的代码修改与已验证的事实;
- 罗列未完成的待办事项与已知技术障碍;
- 用数百 Token 的抽象描述彻底覆盖成千上万 Token 的原始多轮交互。
/compact,后半段的模型实际上是在阅读一份「对前序观察的概括的概括」。信息在递归压缩中发生语义漂移,模型会逐渐自信地根据自身摘要的语法歧义产生全新的认知偏差。
3. 上下文滑动窗口规划(Window Management) #
压缩管道需要精确的动态 Token 记账。在向 Anthropic API 发起每次请求前,系统必须动态预留至少 4k 到 8k Token 作为模型的输出配额。
如果在当前上下文长度加上系统指令后,剩余空间无法满足模型的输出阈值,滑动窗口控制器会强制剔除更早的消息体。这种裁决属于纯粹的机械内存页面淘汰。
4. 分层提示词动态注入(Selective Injection) #
在 System Prompt 工程 中拆解过的洋葱分层架构,在此处发挥限流作用。核心身份(Core Identity)常驻,而次要的 Skill 定义、非核心工具 Schema 以及跨文件规范(CLAUDE.md),仅在检测到相关触发词时按需注入,从而将基础占位空间压缩到极限。
商业落地的算力博弈:Prompt Caching 与前缀破坏的代价 #
如果上下文管理仅仅是删减文本,系统架构尚可算作单纯。但在现代大模型商业化计费体系下,压缩行为直接撞上了 Prompt Caching(前缀提示缓存) 的经济与延迟杠杆。
Anthropic 的 API 计费规则提供了一项关键特性:对完全命中前缀缓存的上下文,输入 Token 价格直降 90%,且 Prefill 计算由服务端直接复用物理显存中的 KV Cache 镜像。这不仅将计费成本压缩至十分之一,更将首字延迟压低至百毫秒级。
|
|
这里构成了残酷的工程悖论:
- 不压缩:上下文线性增长,每次交互虽然命中前缀缓存,但总 Token 基数持续攀升,显存膨胀逼近硬上限,且模型在 Lost-in-the-Middle 效应下智商线性下滑;
- 执行压缩:
/compact抹掉了历史序列的中间部分,替换为精简的摘要。但这彻底破坏了前缀的字节级一致性。服务端原先缓存的数万 Token KV Cache 瞬间全部失效。系统为了省下几千 Token 的窗口空间,下一轮请求却必须按 100% 的全价重新对长达数万 Token 的上下文执行 Cold Prefill,造成显著的计费跳涨与交互卡顿。
在节省显存窗口与保护缓存前缀之间,没有任何免费的午餐。
工程实践的硬核解法:BYF 的 Observation Masking 与 CacheStaking #
针对 Claude Code 全量压缩导致的缓存失效与语义丢失,开源项目 BYF 在 ADR 0011 中提出了一套精细化的确定性治理方案:
1. 阈值带观察掩码(Threshold Bands) #
BYF 摒弃了「平时不管、满了全局压一次」的粗放策略,引入了基于上下文容量的梯级水位线:
- 低水位(60% 上下文压力):仅掩码易过期的感知类工具输出,如
glob、grep的长文件列表,将其压缩为单行元数据[Glob: 42 files matched]; - 高水位(80% 上下文压力):掩码非关键的
bash执行日志,保留最近 5 行与退出码; - 核心契约免死:
write_file与edit的实际代码 diff 受到最高保留优先级保护,直到达到 85% 极限水位前绝不丢弃。
2. 输出卸载到物理磁盘(Output Offloading) #
当某个工具输出超过 8,000 Token(例如超大测试报告或代码反编译结果)时,BYF 拒绝将其直接塞入上下文。系统将全量文本写入本地沙箱的临时文件(如 /tmp/byf-output/turn-12.log),在上下文中仅暴露:
|
|
若模型后续在推理时确实需要特定细节,它必须主动调用 read_file 配合行号定位读取。这一设计强制把上下文内存压力转化为文件系统的磁盘 I/O。
3. Turn 边界缓存桩(CacheStakingStrategy) #
为了最大化利用 Anthropic 的前缀缓存折扣,BYF 建立了严格的「3+1」缓存断点协议:
- 静态桩:系统指令、核心工具元数据;
- 动态桩:固定在上一轮最后一条 Assistant 消息的结尾。
在会话生命周期中,只要未发生致命的上下文溢出,系统绝不重写任何已经固化的历史轮次。所有观察掩码的操作全部严格在历史生成后延期执行,确保前缀缓存断点在物理内存中保持最长存活时间。
结语:戒断“无限上下文”的技术执念 #
工业界对“百万 Token 窗口”与“终身记忆 Agent”的狂热,很大程度上是一种掩盖系统工程无能的营销修辞。
一个成熟的系统架构师应当清醒地认识到:Transformer 的注意力机制是一块昂贵、易挥发且对距离极度敏感的物理缓存。依托有损摘要强行堆砌的长程会话,终究会在信息熵增的重力下蜕变为漏洞百出的虚幻沙盒。
在真实的软件工程实践中,当一次交互超过 30 个轮次、执行过多次重写之后,最具专业素养的做法是敲下 git commit,将确定的代码状态沉淀在版本控制中,然后果断输入 /clear。带着干净利落的架构契约开启全新的空白会话,彻底摆脱泥潭般的历史缓存干扰。