KV Cache 与 Prompt Caching 看起来像两个名词,其实都在解决同一件事:已经算过的内容,不要再算一遍。区别只是前者主要发生在一次生成内部,后者把复用范围扩大到了不同请求之间。
一句话先记住:KV Cache 让逐 token 生成跑得动;Prompt Caching 让重复长前缀的 API 请求更快、更省。
一、为什么大模型生成一句话,会产生大量重复计算?
大模型生成文本不是一次性把整段答案写出来,而是每次预测一个 token。生成第 2 个 token 时,模型已经看过 Prompt 和第 1 个 token;生成第 100 个 token 时,它需要参考前面的全部内容。
最朴素的做法是:每一步都把整个序列重新送进模型。问题在于,旧 token 对应的 Key 和 Value 已经算过,而且模型参数和旧输入没有变化,再算一次不会得到新信息。
二、KV Cache 到底缓存了什么?
在自注意力里,每个 token 会产生 Query、Key、Value。可以把它们理解成:Query 是当前 token 提出的问题,Key 是历史 token 的索引,Value 是历史 token 携带的信息。当前 token 需要用自己的 Query 去查询前面所有 token 的 Key 和 Value。
历史 token 的 K 和 V 一旦计算完成,在后续生成步骤里不会改变。因此推理框架把它们保存在显存中。下一步只需要计算新 token 的 Q、K、V,再把新 K/V 追加到缓存末尾。
KV Cache 不缓存最终答案,也不缓存注意力输出;它缓存的是模型每一层、每个历史 token 的 K/V 张量。
三、Prefill 和 Decode:看懂延迟从哪里来
Prefill 阶段处理整段输入,负责建立最初的 KV Cache。Prompt 越长,首 token 往往越慢。Decode 阶段逐个生成 token,虽然每一步只计算一个新 token,但需要不断读取越来越长的 KV Cache,所以常常受显存带宽和缓存管理影响。
TTFT(Time to First Token):从请求发出到看到第一个 token 的时间,长 Prompt 和缓存未命中会明显影响它。
TPOT(Time per Output Token):后续每个 token 的平均耗时,通常更受模型大小、并发和 KV Cache 读取效率影响。
四、KV Cache 用速度换显存
KV Cache 的占用会随上下文长度和并发数近似线性增长。这里最容易被忽略的是“KV 头数”:传统多头注意力为每个注意力头保存一套 K/V,而 GQA、MQA 会让多个 Query 头共享较少的 KV 头,能显著缩小缓存。
因此长上下文部署中,经常会看到 PagedAttention、KV Cache 量化、CPU/NVMe 卸载、分层缓存、GQA/MQA 等方案。它们不是改变模型会不会回答,而是在有限显存里容纳更长上下文和更多并发。
五、Prompt Caching:把复用从“同一次生成”扩展到“不同请求”
企业应用里,很多请求都有很长的公共前缀:固定 System Prompt、安全规则、工具定义、Few-shot 示例、知识库文档。真正变化的可能只是最后一句用户问题。若每个请求都从头做 Prefill,会反复消耗计算。
Prompt Caching 的做法是保留相同前缀对应的缓存结果。新请求到达时,系统先检查前缀是否已经存在:命中就从缓存位置继续,只处理新增 token;未命中才重新计算并写入缓存。
六、三个概念不要混在一起
在自建推理服务中,常见叫法是 Prefix Caching 或 Automatic Prefix Caching;在商业 API 中,产品通常叫 Prompt Caching。它们可能都复用 KV 结果,但缓存是否自动开启、能保留多久、怎样计费、前缀最小长度和数据隔离规则,取决于具体平台。
七、缓存命中的核心:固定内容放前面,动态内容放后面
缓存按 token 前缀匹配,而不是按“语义差不多”匹配。哪怕两段文字表达同样意思,只要 token 序列发生变化,就可能在变化处停止命中。
将 System Prompt、工具定义、稳定示例和固定文档放在前面。
把时间、用户问题、检索结果中的动态部分尽量放在后面。
固定 JSON 序列化方式、字段顺序、空格和工具列表顺序。
不要在公共前缀开头插入时间戳、请求 ID、随机数或用户专属信息。
内容更新时采用版本化前缀,避免旧缓存与新规则混用。
八、哪些业务最值得做 Prompt Caching?
Prompt Caching 并不是所有请求都能获益。它最适合“公共前缀长、重复请求多、动态尾部短”的业务。一次性短问答、每次 Prompt 都完全不同,通常命中率不高。
九、工程落地时应该监控什么?
缓存命中率:请求中有多少前缀 token 被复用。
缓存写入与读取 token:判断是否真的复用了足够长的内容。
TTFT 的 P50/P95:不要只看平均值。
单位请求输入成本:写入缓存可能有额外成本,读取通常更便宜,但规则因平台而异。
显存利用率与淘汰率:自建服务里缓存过多也会挤占新请求空间。
数据隔离:不同租户、权限和敏感文档不能因为缓存键设计错误而发生交叉复用。
十、一个简单的 Prompt 组织示例
下面的重点不是某个厂商 API,而是内容顺序:稳定且可共享的部分尽量靠前,变化内容靠后。
SYSTEM_RULES="""你是企业知识库助手。回答必须引用已提供资料,不确定时明确说明。""" TOOLS=load_stable_tool_definitions()# 固定顺序KNOWLEDGE=load_versioned_document("v3")# 相同版本保持不变prompt=[SYSTEM_RULES, TOOLS, KNOWLEDGE, user_question,# 动态内容放最后]十一、常见误区
误区一:Prompt Caching 会缓存完整回答。实际上通常复用的是输入前缀的计算结果,回答仍会重新生成。
误区二:语义相同就能命中。缓存更依赖 token 前缀一致性。
误区三:开启缓存一定更省。若公共前缀很短、命中率低或缓存频繁过期,收益可能有限。
误区四:缓存越久越好。长期缓存会占资源,也会带来规则更新、隐私与版本一致性问题。
误区五:KV Cache 只影响速度。它同时决定显存容量、最大上下文和可承载并发。
十二、总结
KV Cache 解决的是自回归生成内部的重复计算:历史 token 的 K/V 只算一次,后续步骤持续复用。Prompt Caching 则把相同思路扩展到多个请求:公共前缀只做一次 Prefill,后续请求从命中的位置继续。
真正的工程价值不在“有没有打开缓存”,而在于前缀设计是否稳定、命中率是否足够高,以及延迟、成本、显存和数据隔离是否被持续观测。