AI原理性能优化

KV Cache 与 Prompt Caching:大模型加速背后的两层缓存

大模型推理为什么越来越快、越来越便宜?答案藏在两层不同但相互配合的缓存机制里——一层在模型内部,一层在 API 平台上。

2026年06月30日
13分钟

当你使用大模型 API 时,可能注意到一个现象:同样的系统提示反复发送,响应会变快,费用也会降低。这背后不是魔法,而是缓存在起作用。

但"缓存"这个词在大模型领域至少有两个完全不同的含义:KV Cache 和 Prompt Caching。它们在不同层级工作,解决不同问题,却经常被混为一谈。

Section 01先给出结论

如果你只记住一件事,记住这个:

KV Cache 是模型内部的缓存,Prompt Caching 是 API 平台的缓存。

它们不是同一层的两种方案,而是不同层级的优化机制,彼此配合:

  • KV Cache 解决的是:在一次推理中,避免重复计算已处理 token 的注意力向量
  • Prompt Caching 解决的是:在多次 API 请求之间,复用已处理过的 prompt 前缀

下面逐层拆开来说。

KV Cache Lifecycle

KV Cache 如何让逐 token 生成变快

Prefill 先把已有上下文的 K/V 算出来并保存;Decode 每次只处理新 token,同时复用历史 K/V。

Prompt Tokens
输入上下文

用户问题、系统提示和历史消息先被切成 token 序列。

Prefill
一次性预填充

模型处理已有 token,并计算每层注意力里的 Key / Value。

KV Cache
保存历史 K/V

已经算好的 K/V 被暂存起来,后续生成不用反复重算。

Decode
逐 token 生成

新 token 只计算当前 Q/K/V,同时读取历史 K/V,再追加自己的 K/V。

Next Token
输出下一个 token

生成结果进入上下文,下一轮继续复用缓存。

Key point

KV Cache 缓存的是注意力层中已经算好的 Key / Value 向量,不是最终回答。

Section 02KV Cache:模型推理时的"短期记忆"

要理解 KV Cache,需要先回忆一下 Transformer 的注意力机制。在生成每个新 token 时,模型需要把当前 token 和前面所有 token 做注意力计算。这个过程涉及三个向量:Q(查询)、K(键)、V(值)。

没有 KV Cache 会怎样

假设模型已经处理了 1000 个 token,现在要生成第 1001 个。如果没有缓存,模型必须:

  1. 重新计算前 1000 个 token 的 K 和 V
  2. 再计算第 1001 个 token 的 Q、K、V
  3. 用 Q 对所有 K 做注意力,再加权所有 V

然后生成第 1002 个 token 时,又要重新算一遍前 1001 个 token 的 K 和 V。每多生成一个 token,计算量都在增长。

KV Cache 怎么解决这个问题

KV Cache 的思路很简单:前 1000 个 token 的 K 和 V 已经算过了,结果又不会变,那就存起来。

生成第 1001 个 token 时:

  • 从缓存读取前 1000 个 token 的 K 和 V
  • 只计算当前 token 的 Q、K、V
  • 把新的 K 和 V 追加到缓存

生成第 1002 个 token 时,缓存里已经有 1001 个 token 的 K/V,只需追加一个。这样每一步的计算量变成常数级,而不是随着上下文长度不断增长。

KV Cache 存在哪里

KV Cache 通常存储在 GPU 显存中,因为它需要和模型的注意力计算紧密配合。这也是为什么长上下文模型非常吃显存——上下文越长,KV Cache 越大。

在实际的推理服务中,KV Cache 的管理是一个专门的工程问题:

  • GPU 显存:主缓存,直接参与注意力计算
  • CPU 内存:低延迟的本地扩展缓存,可在 GPU 显存不足时暂存
  • 分布式存储:如 Redis,用于多节点间共享缓存

这种多层缓存架构让推理服务能够在显存有限的情况下,仍然高效处理大量并发请求。

KV Cache 的局限

KV Cache 并非万能。它有两个重要限制:

只加速 prefill,不加速 decode。 KV Cache 让已处理的 token 不用重新计算,但每生成一个新 token,模型仍然需要跑一遍完整的注意力计算。生成速度的瓶颈往往在 decode 阶段,缓存帮不上忙。

显存占用随上下文线性增长。 100 个 token 的 KV Cache 很小,10 万个 token 的 KV Cache 就很大了。这也是为什么上下文窗口越大的模型,对显存的要求越高。

Section 03Prompt Caching:API 平台的"跨请求复用"

KV Cache 解决了单次推理内部的效率问题,但还有一个更贴近开发者日常的问题:我在多个请求里反复发送相同的系统提示和工具定义,API 能不能不要每次都从头处理?

这就是 Prompt Caching 要解决的问题。

它的工作原理

Prompt Caching 在 API 平台层面对你的请求进行前缀匹配:

  1. 你的第一次请求发送到 API,平台完整处理了 prompt
  2. 平台把处理结果(包括底层的 KV Cache)缓存起来
  3. 下一次请求如果前缀字节完全匹配,平台直接复用缓存
  4. 你只用为缓存命中部分支付很低的费用

关键约束是:前缀必须字节级一致。 你的 system prompt 里如果动态插入了时间戳、请求 ID 或者任何变化的内容,缓存就会失效。不是"差不多一样"就行,而是"一个字节都不能差"。

缓存的渲染顺序

Anthropic 的 Prompt Caching 按固定顺序处理请求内容:

tools → system → messages

这意味着:

  • 工具定义最先被处理,如果不变,最容易被缓存
  • 系统提示其次
  • 消息历史最后

你可以在特定内容块上设置缓存断点,标记"到这里为止都可以缓存"。也可以使用自动缓存模式,让平台自动把断点放在最后一个可缓存块上。

缓存的定价优势

Prompt Caching 的经济价值很直观:

操作相对成本
正常输入
缓存写入1.25×
缓存命中0.1×

缓存命中的成本只有正常输入的十分之一。对于长系统提示、大量工具定义或多轮对话的场景,这个差异非常显著。

缓存默认 5 分钟有效,每次被命中时自动刷新。如果 5 分钟不够,还可以选择 1 小时缓存,写入成本更高(2×),但适合请求间隔更长的场景。

什么时候 Prompt Caching 最有价值

三种典型场景:

长系统提示 + 多轮对话。 系统提示可能有几千个 token,每次对话都要发送。缓存后,系统提示的处理成本降到十分之一。

大量工具定义。 当你给模型定义了几十个工具,这些工具描述可能占 prompt 的大部分。缓存后,工具定义只在第一次请求时按原价处理。

重复的文档上下文。 比如用同一个长文档回答不同问题。文档部分缓存后,后续提问只需要处理不同的问题部分。

Cache Architecture

两层缓存其实是上下游关系

Prompt Caching 是 API 层能力,命中时复用已经处理过的前缀;底层仍依赖 KV Cache 的计算结果。

API 平台层
Prompt Caching

做前缀匹配,跨 API 请求复用稳定的 tools、system 和 messages 前缀。

跨请求复用降低输入成本减少重复 prefill
推理引擎层
Prefix / KV Reuse

命中共享前缀时,直接复用已处理部分,跳过重复计算。

提升吞吐优化 prefill调度缓存命中
模型内部层
KV Cache

保存历史 token 的 Key / Value 向量,支撑逐 token 生成。

保存 K/V读取历史上下文追加新 token

Section 04两层缓存如何配合

现在可以把两层缓存放在一起看了:

text
1┌─────────────────────────────────────────┐
2│ API 平台层:Prompt Caching │
3│ 跨请求复用已处理的 prompt 前缀 │
4│ ↓ 命中时复用底层的 KV Cache │
5├─────────────────────────────────────────┤
6│ 推理引擎层:KV Cache 管理 │
7│ 同引擎内不同请求间的缓存调度 │
8│ ↓ 底层操作 │
9├─────────────────────────────────────────┤
10│ 模型架构层:KV Cache │
11│ 单次推理内的 K/V 向量缓存 │
12└─────────────────────────────────────────┘

当你在 API 上使用 Prompt Caching 且命中缓存时,底层实际上是跳过了对这些 token 的 KV Cache 计算——前缀已经被处理过,K/V 向量已经存在,不需要重新算。

所以 Prompt Caching 本质上是 KV Cache 在 API 层面的暴露和商业化:平台帮你管理哪些 KV Cache 可以跨请求复用,并按缓存命中的折扣价收费。

Section 05容易混淆的地方

Prompt Caching 不是"缓存回答"

有些人以为 Prompt Caching 是把模型的回答缓存起来,下次相同问题直接返回。不是的。它缓存的是 prompt 前缀的处理结果,不是最终回答。每次请求模型仍然会生成新的回答。

KV Cache 不是 Prompt Caching 的替代品

它们解决不同层面的问题。没有 KV Cache,Prompt Caching 无法实现,因为底层没有可复用的计算结果。没有 Prompt Caching,KV Cache 只能在单次请求内发挥作用,跨请求时前缀需要重新计算。

缓存命中率取决于你的设计

Prompt Caching 不是自动生效的魔法。如果你的 system prompt 里嵌入了动态内容(当前时间、用户 ID、随机标识符),每次请求的前缀都会不同,缓存命中率就是零。

好的做法是:

  • 把稳定内容放在前面(系统提示、工具定义)
  • 把动态内容放在后面(用户问题、上下文信息)
  • 不要在 system prompt 里插入会变化的内容

Section 06一个直觉类比

如果这些概念还是有点抽象,可以这样类比:

KV Cache 就像你读书时做的笔记。 读到第 200 页时,前面 199 页的要点已经记在笔记本上了。继续读第 201 页,你不需要从第 1 页重新读起,翻翻笔记就行。

Prompt Caching 就像图书馆的馆际互借。 你第一次借一本书,图书馆要走完整个流程。但如果你反复借同一本书,图书馆会记住你的借阅记录,后续的手续大幅简化。

两层缓存配合起来:笔记让你单次阅读更快,馆际互借让你跨次借阅更省。一个是阅读时的效率,一个是借阅时的效率。

Section 07对开发者的实际意义

理解这两层缓存,对日常开发有直接的指导价值:

系统提示要稳定且前置

把不会变化的内容放在 prompt 的最前面:角色定义、行为约束、工具描述。变化的内容放在最后:用户的具体问题、动态上下文。

工具定义不要频繁变动

每次增删工具,整个工具列表的缓存就失效了。如果你的应用有多种工具组合,考虑把核心工具和可选工具分开管理。

长上下文是成本,也是机会

长上下文意味着更大的 KV Cache,更高的显存占用和成本。但如果前缀稳定,Prompt Caching 可以把长上下文的边际成本大幅降低。

监控缓存命中率

通过 API 返回的 usage 字段,可以看到 cache_read_input_tokens(缓存命中的 token 数)和 cache_creation_input_tokens(缓存写入的 token 数)。如果缓存命中率低,检查你的 prompt 前缀是否足够稳定。

Section 08结语

KV Cache 和 Prompt Caching 不是两个独立的优化技巧,而是同一套缓存思想在不同层级的体现。KV Cache 在模型内部避免重复计算,Prompt Caching 在 API 层面跨请求复用前缀。理解它们的关系,才能在设计应用时做出正确的性能和成本权衡。

下一次当你配置系统提示、设计工具列表或优化 prompt 结构时,记住:你不仅在和模型对话,也在和两层缓存对话。让它们命中,响应更快、成本更低;让它们失效,再好的模型也会变得又慢又贵。