自动前缀缓存 (Automatic Prefix Caching, APC) 是一种大语言模型(LLM)推理优化机制:把请求的提示词(prompt)切分成固定大小的 block,用递归哈希标记每个 block,命中已缓存 block 时直接复用其 KV 缓存,从而跳过共享前缀的重复计算。

一句话本质:对"前缀重复"的缓存,key 是 token 序列的块级哈希,value 是 KV cache(键值缓存)。

1. 前置:KV Cache 与自回归 (Autoregressive) 生成

大语言模型是自回归(Autoregressive)模型。预测下一个 token 时,模型读入前面所有前缀 token,经过神经网络(核心是 Transformer 注意力层)计算每个候选 token 出现在下一位的概率,再按贪心(greedy)或 top-p 等采样规则挑出下一个 token。

  • prefill(预填充)阶段:一次性处理完整输入,逐层计算出所有输入 token 的键(Key)、值(Value),并存入 KV cache(键值缓存)。
  • decode(解码)阶段:逐 token 生成。新 token 只需用自己算出的 Query 去和已缓存的 K/V 做注意力,不必重新算前面所有 token 的 K/V。
这就是"每生成一个新 token,就能复用之前 token 已经算好的结果,只加上新 token 相关的计算"的原因。KV cache 让增量生成从 O(前缀长度) 降为近似 O(1)。

2. 问题:共享前缀被反复浪费地重算

现实请求经常共享前缀:

  • 每轮都带的 system prompt(系统提示词)
  • 多轮聊天时不断变长的对话历史
  • 固定的 few-shot 示例(少样本示例)、工具定义、RAG 注入的文档上下文

没有缓存时,每个新请求都从零跑一遍 prefill,把同一段前缀的 K/V 重复计算一遍——token 越长、请求越多,浪费越大(对应更慢的 TTFT 首 token 延迟和更高的成本)。

3. APC 的核心机制:Block 切分 + 递归哈希

关键思路:与其让新请求与历史请求逐个 token 逐字节比较(O(n)),不如给每个 block 算一个哈希值,用哈希查表(O(1))。

3.1 把长提示词切成 n 个 block

提示词被切分为等长 token 的块,如:

block_1 | block_2 | block_3 | ... | block_n

不同实现块长不同:Anthropic 的 APC 以 64 token 为一个 block;vLLM 默认 16 token 一个 block。

3.2 递归哈希:后一个 block 依赖前一个 block

对每个 block 计算哈希,但哈希是递归(recursive)的——第 i 个 block 的哈希由"第 i-1 个 block 的哈希 + 第 i 个 block 自己的 token"共同算出:

h_1 = H(tokens_1)
h_i = H(h_{i-1}, tokens_i)      // i >= 2

这带来两个关键性质:

  1. 位置敏感(position-sensitive):同一段 token 出现在不同位置会得到不同的哈希。前缀 [A][B] 和 [X][A][B] 中,后者的 [A][B] 的 h 不等于前者的 h——因为依赖链不同。这避免了错误地"以为两块内容相同就可以复用"。
  2. 前缀一致性(prefix-consistency):两条请求只要共享一段前缀,这段前缀内部每个 block 的哈希就完全相同,天然可以在块边界上对齐。

3.3 命中查找:顺序算哈希,遇 miss 即截断

新请求到达时:

  1. 把提示词切成 block,从前往后依次计算 h_1, h_2, h_3, ...;
  2. 每算出一个哈希,就去全局的"状态缓存序列"(哈希表 / 索引结构)里查这个哈希是否已存在;
  3. 命中(hit)→ 该 block 对应的 KV cache 可直接复用,无需重新 prefill;
  4. 一旦某个哈希未命中(miss)→ 由于后续 block 的哈希都依赖它,后面全部 miss,复用链在此截断;剩余尾部从零计算,算完后再写入缓存。
所以准确说法不是"有一个命中就去整个序列里找",而是:哈希一个个算、一个个查,连续命中的最长前缀被复用;第一个 miss 处就是需要重新计算的起点。 找到最长匹配前缀后,只对非共享的尾巴跑 prefill。

3.4 复用后的收益

命中前缀的 KV 直接加载进显存/内存,prefill 只算尾巴。效果:

  • TTFT(首 token 延迟) 大幅下降;
  • 成本下降:重复部分不再计入前向计算;
  • 长对话、固定 system prompt、few-shot 场景收益最明显。

4. 工程实现

实现机制
Anthropic Claude APIAPC 默认自动开启、无需配置。请求按 64-token block 切分 + 递归哈希缓存。对 system prompt、对话历史、few-shot、工具定义最有效
vLLM--enable-prefix-caching 开启。KV block(默认 16 token)用哈希标识,缓存在 radix tree(基数树) 中,支持请求间前缀复用(RadixAttention 思想)
SGLangRadixAttention,把 KV cache 组织成基数树,支持前缀共享与树形内存池管理

5. 与相近概念的区分

  • 显式 Prompt Caching(提示词缓存):Anthropic 用 cache_control 断点手动标记要缓存的区间,带 5 分钟 TTL、缓存命中输入有折扣定价。APC 是自动的、免费的、按块哈希,二者是两套独立机制,可叠加。
  • 语义缓存(Semantic Cache):按 embedding 相似度命中"语义相近的旧答案"直接返回。APC 不是语义匹配,而是精确到 token 的块级复用,只缓存计算中间态(KV),不缓存答案本身。

6. 局限与注意

  • 只对精确相同(exact)的 token 前缀有效:请求前缀只要有一个 token 不同,该位置之后全部 miss。
  • 需要为缓存预留显存/内存,命中率取决于请求间前缀重叠程度。
  • 命中判定依赖哈希,碰撞概率极低(工程上可接受),但极端情况下需要处理哈希冲突的校验。

参考

  • Anthropic Docs — Automatic Prompt Caching(自动前缀缓存,官方说明)
  • vLLM Docs — Automatic Prefix Caching
  • SGLang — RadixAttention(论文 "Fast and Memory-Efficient LLM Serving with RadixAttention")

相关笔记:MCP (Model Context Protocol) · Caching Strategies (缓存策略)


本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/AI apps