KV Cache 与 Prompt Cache 有什么区别?
| 维度 | KV Cache | Prompt Cache |
|---|
| 层级 | 模型内部机制 | 推理引擎/API 服务商的优化 |
| 作用域 | 单次推理过程内的 token 生成 | 多次 API 请求之间 |
| 复用对象 | 已计算 token 的键值对 | 相同前缀对应的 KV Cache |
| 目标 | 避免同一次生成内重复计算 | 减少跨请求的重复计算成本 |
| 共同原理 | 前缀不变性 | 前缀不变性 |
- 工作方式: 服务商匹配请求前缀,前缀相同的部分直接复用已算好的 KV Cache;
- 成本: 缓存读取远低于首次计算,Anthropic、DeepSeek、GPT-5 约为十分之一;
- 启用差异: 有的自动启用、有的需手动指定,计费细节各异,使用前需查最新文档;
- 关系: Prompt Cache 构建在推理引擎 KV Cache 之上,是 KV Cache 的跨请求版本;
缓存经济性如何约束架构设计?
- 原则: 缓存一致性会反过来主导系统的架构选择;缓存经济性不是事后优化而是前置约束;
- 提示词结构: 系统提示词被一个缓存边界标记分为两部分——边界之前可跨用户、跨会话全局缓存,之后是用户与会话特定信息;
- 排序依据: 提示词的排列顺序首先由缓存经济性决定,其次才是语义逻辑;
- 变体爆炸: 每个运行时条件(操作系统、模式、用户偏好)若放在边界之前,就会把缓存键变体数量翻倍;
- 量化: 若条件均为二值,N 个条件产生 2N 种缓存键;例如 macOS/Linux × 普通/调试 × 中文/英文 = 8 种;
- 推论: 所有动态元素都必须放到缓存边界之后;
- 子 Agent 对齐: 子 Agent 继承父 Agent 上下文时,提示词、工具定义、模型配置、消息前缀、思考配置必须与父 Agent 逐字节匹配,才能命中 Prompt Cache; 若子 Agent 使用不同上下文或提示词,则不要求对齐;
- 替换字符串冻结: 大工具输出被替换为摘要预览后,替换字符串被持久化保存,会话重启后也使用完全相同的字符串,以保证恢复后的字节流与缓存一致;
- 启示: 越早把缓存约束纳入架构设计,后续的工程代价越小;
KV Cache 是否只能一次性写入?
- 前提: 以上讨论都建立在“前缀改一个字节、后面缓存全废”这条铁律上;
- 反直觉观察: 在 prefill 阶段,模型其实在“做笔记”——读到某个字段时,不是原样缓存,而是把“这个字段意味着什么”的结论写进后面每一层的 KV 状态;
- 测量: 一个字段自身那几个 token 的 KV 对最终决策的贡献往往不到 1%,真正影响输出的是它在下游留下的“读书笔记”;
- 编辑(Editing): 结论已写进下游笔记,改掉字段后若模型有显式思维链,改动可顺着已缓存的思考传播,用约 1% 算力得到与整段重算一致的结果;
- 编辑的边界: 没有 CoT 时,孤立地改字段会被忽略——结论已固化在下游状态中,却没有一条思考路径去更新它;
- 组合(Composition): 把预先算好的“技能”缓存通过旋转位置编码(RoPE)挪到新位置拼接进另一段上下文,无需重算注意力;
- 复杂度: 用模块化缓存块拼出长上下文,从 O(L2) 重算降到 O(L) 拼接,结果与完整重算难以区分;
- 实测: vLLM 上首 token 延迟(p90)最多降低数十至数百倍,前缀缓存命中率约 98.5%,跨 12 个模型 logit 余弦相似度 0.90–0.999;
- 定位: 仍属研究阶段;当前生产系统中“前缀不可改”依然是应遵守的默认原则;
- Agent 意义: 指向“上下文可变、但缓存收益还在”的可能——换工具、更新记忆字段、注入新状态时不必每轮推倒重来;