# 提示缓存（一）：到底缓存了什么

> prompt caching 省下的不是网络往返，而是 prefill 阶段的算力。本文讲清 KV cache 从哪来、前缀哈希为什么要求逐 token 一致、TTL 为什么必须存在，以及缓存写入为什么会比不缓存更贵。

- 作者: zhuermu
- 发布: 2026-08-17
- 网页版: https://zhuermu.com/blog/prompt-cache-1-how-it-works/

---
有个说法流传很广：提示缓存省的是重复传输的 token。

这个说法是错的，而且错得有后果——它会让你以为缓存是个网络层优化，于是把注意力放错地方。

prompt 每次都要完整发给服务端，一个字都不会少传。省下的是**服务端算它的那一遍**。

搞清楚这件事之后，后面所有反直觉的现象都能解释：为什么改一个空格就全盘失效、为什么开启缓存可能比不开更贵、为什么同一个模型换个云跑成本模型就变了。

这是系列第一篇，只讲原理。[第二篇](/blog/prompt-cache-2-platform-comparison/)比五家模型厂商和三家云的当期账单差异，[第三篇](/blog/prompt-cache-3-debugging-cache-misses/)讲工程上真正会把缓存打穿的那些坑，[第四篇](/blog/prompt-cache-4-bedrock-threshold-test/)是在 Bedrock 上的实测——顺手测出了官方文档的一处错误。

## 一、缓存的是 prefill，不是流量

先看一次请求在服务端被拆成什么。

![Prefill 与 Decode 两阶段：KV cache 是 prefill 的产物](/images/prompt-cache/prefill-decode.svg)

Transformer 生成时，每个 token 都要对它之前的所有 token 做注意力。前面那些 token 的 K/V 投影算过一次就没必要再算，于是被缓存下来——这就是 **KV cache**。

一次请求分两段，特性完全不同：

**Prefill** 把整个 prompt 并行算完，一次前向传播搞定，**算力密集**。10 万 token 的上下文，这一段就是实打实的一大坨浮点运算。

**Decode** 逐 token 生成，每生成一个都要读一遍上面那份 KV，**显存带宽密集**。

`prompt caching` 干的事就是：把 prefill 算出来的那份 KV state 跨请求留下来。下次发来同样的前缀，服务端认出来，跳过 prefill 直接进 decode。

所以它的收益是两重的——**省钱**（读取价约是输入价的 10%）和**省首 token 延迟**（prefill 那一大坨算力不用再花）。后者在 agent 场景里常常比省钱更值钱。

顺带一个推论：**缓存对输出不产生任何影响。** 官方文档明确写了，模型基于缓存的前缀重新生成，采样过程不变，所以两次相同请求该不一样还是不一样。它纯粹是省了重复计算，不是把答案存下来了。这和很多人第一反应的「结果缓存」是两码事。

## 二、为什么必须逐 token 一致

既然缓存的是 KV state，那能不能只改一个词、复用剩下的？

不能。而理由就藏在注意力的定义里。

![前缀哈希：改动点之后全部连带作废](/images/prompt-cache/prefix-hash.svg)

注意力是**因果的**——第 k 个 token 的 K/V 依赖它前面所有 token。你把第 5 个 token 改了，第 5 个之后每一个 token 的 KV 都算错了。

所以缓存只能按**前缀**匹配，而且是逐 token 完全一致的前缀。服务端通常按块（常见 64 token 一块）对前缀做哈希，命中就跳过那一段。

由此得出这个领域唯一一条铁律：

> **静态内容放前面，易变内容放后面。**

system prompt、工具定义、参考文档放前面；时间戳、session ID、用户本轮输入放后面。

一个动态时间戳插在 prompt 开头，整条缓存归零。**而且它不会报错**——推理照常成功，回答照常正确，只有账单变贵。这是这类 bug 最难受的地方，后面第三篇会专门讲。

三家厂商都在文档里点名了这个场景。OpenAI 给了一条很实用的建议：只用于日志或调试的动态值，塞进 request metadata，别塞进 prompt。

### 层级顺序也是前缀的一部分

Anthropic 把前缀的层级定得很明确：`tools` → `system` → `messages`。改动前面一层，后面所有层的缓存一起失效。

改工具定义的名称、描述或参数，**三层全部作废**。

OpenAI 的表述更直白：工具定义、**工具顺序**、结构化输出的 schema 都参与构成前缀。

「工具顺序也算」这一条，是实际工程里最容易踩的——你的工具列表如果是从一个 map 里收集出来的，或者由插件动态注册，顺序可能每次进程重启都不一样。第三篇会给出可复现的例子。

## 三、TTL 为什么必须存在，以及它是滑动的

KV state 很大。10 万 token 在大模型上是几十 GB 量级，占着 HBM 或 SSD。厂商不可能永久替你存着，所以必须淘汰。

于是有了 TTL。而这里有两个细节决定了实际怎么调参。

![TTL 滑动窗口，以及间隔越界后的反转](/images/prompt-cache/ttl-window.svg)

**第一，TTL 在读取时刷新，而且刷新不额外收费。**

Anthropic 文档明写：缓存每次被使用时都会刷新，不额外计费。这是滑动窗口，不是从写入起固定计时。

整个「保温」（keepalive）思路就立在这条上面——停顿期间定时重发同一个前缀，把窗口一直续下去。而这不是社区野路子：Anthropic 官方文档直接建议，5 分钟档要保温就至少每 5 分钟发一次预热请求，并为此提供了专门的 `max_tokens: 0` 请求形式，读入 prompt、写缓存、立刻返回，**输出 token 不计费**。

**第二，间隔一旦超过 TTL，这个优化会反转符号。**

这是我认为最值得记住的一点。假设 TTL 是 5 分钟而你每 8 分钟 ping 一次，那么每一次 ping 都落在一个已经死掉的缓存上。于是它不再是一次便宜的读取，而是一次**全价 prefill，外加一次写入费**。

本该花 0.1× 的动作变成花 1.25×，单次贵 12.5 倍，而且你在反复做。Maxim Khailo 在他的[跨厂商保温实测](https://blog.mempko.com/your-agentic-workflows-cache-keepalive-costs-8x-too-much-v2-the-interval-frontier/)里测过这一格：Anthropic 上用 8 分钟间隔，账单是完全不 ping 的 **4 倍**。

绝大多数调参调错了只是效果变差。这个参数有一道悬崖——**过了线，优化本身变成病灶**。

### 一个容易忽略的时序陷阱

Anthropic 文档里还有一句，我第一次读漏了：

**生命周期从写入或读取缓存的那个请求「开始」时刻计算，不是从响应结束。生成响应花的时间要算进 TTL。**

举个例子就明白严重性：一个流式输出跑了 4 分钟的响应，那么复用同一前缀的后续请求，必须在它完成后约 1 分钟内发出。

这意味着社区流传的「4 分钟最优间隔」是**空转条件下的结论**。真实 agent 负载里，一次带扩展思考的长回复流两三分钟很常见，而这段时间全部计入那 5 分钟。**你的安全间隔要比 4 分钟更短，短多少取决于你自己响应时长的分布。**

顺便说一句，Aider 是最早公开实现缓存保温的工具（v0.53.0 起有 `--cache-keepalive-pings`），它用的间隔是 **5 分钟**——正好踩在 Anthropic 的 TTL 边缘上。按上面这条规则，在流式长响应的场景下这个间隔有越界风险。这是个可以自己测出来的点。

## 四、写入不是免费的，所以缓存可能让你更贵

最后一块拼图：缓存写入本身要花钱。

- **Anthropic**：5 分钟档写入 **1.25×** 基准输入价，1 小时档 **2×**，读取 **0.1×**
- **OpenAI**：GPT-5.6 之前写入免费；**从 GPT-5.6 起写入收 1.25×**
- **Bedrock 上的 Claude**：与 Anthropic 一方 API 完全一致的 1.25× / 2× / 0.1×
- **Gemini**：读取统一 90% off（即 0.1×），但显式缓存**另外按 token-hour 收存储费**

把这几个数字放一起，一个结论浮出来：

> **如果你的前缀每次都在变，开启缓存比不开更贵。**

因为你每次都付了写入溢价，却永远读不到。这不是假想——第三篇里那些「代理层静默删掉缓存标记」的案例，最终账单长的就是这个样子：功能正常、日志干净、成本上升。

还有一个更隐蔽的门槛：**前缀太短会静默不缓存。**

各家都有最小可缓存 token 数，不达标时的行为是——推理成功、不缓存、**不报错**。Anthropic 文档标的门槛按模型从 512 到 4096 不等。

而这些数字本身也未必可靠：我在 Bedrock 上实测过 Claude Sonnet 4.5，**真实门槛是 1,024，而 AWS 文档写的是 4,096**，差 4 倍。同一套方法测的另外三个模型倒是都和文档吻合。所以门槛这种数字，用之前值得自己验一次——两个请求就够，方法在[实测篇](/blog/prompt-cache-4-bedrock-threshold-test/)。

## 小结

四条，按重要性排：

**缓存的是服务端的 prefill 算力，不是网络流量。** 收益是省钱加省首 token 延迟，且不改变输出内容。

**前缀必须逐 token 一致，改动点之后全部连带作废。** 由此只有一条铁律：静态在前，易变在后。工具定义和工具顺序都算前缀。

**TTL 是滑动窗口，读取免费刷新——但它从请求开始计时，流式输出的时间也算。** 间隔超过 TTL 会让优化反转成 4 倍成本。

**写入要付溢价，前缀不稳就是净亏。** 而前缀太短会静默不缓存——门槛因模型而异，且文档给的数字未必准。

[下一篇](/blog/prompt-cache-2-platform-comparison/)把五家模型厂商和三家云的当期倍率、TTL 档位、最小门槛、跨区域路由摊开来比，算清楚在哪家、什么停顿长度下该拧哪个旋钮。

写作时点是 2026 年 8 月中旬，文中所有价格与倍率都来自当期官方文档并附在文末参考文献里。这个领域的定价半衰期短得惊人——就在我整理这批数据的当天，其中一家刚改了计价方式。抄结论之前请自己核一遍。

---

## 常见问题

### 提示缓存省下的是网络传输吗？

不是。prompt 每次都要完整发给服务端，网络开销一分不省。省下的是服务端 prefill 阶段的算力——那段 KV state 服务端刚算过，直接复用，因此只收约 10% 的读取价，同时跳过大部分首 token 延迟。

### 为什么改一个字就整条缓存失效？

注意力是因果的，每个 token 的 K/V 都依赖它前面的所有 token。改动第 k 个 token，第 k 个之后的 KV 全部作废。所以缓存只能按前缀匹配，且必须逐 token 完全一致。

### 缓存写入为什么可能比不缓存还贵？

多数厂商对写入收溢价（Anthropic 5 分钟档 1.25×、1 小时档 2×，OpenAI GPT-5.6 起 1.25×）。如果你的前缀每次都在变，就会每次付写入溢价却永远读不到，比完全不用缓存更贵。


---

## 参考资料

- [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) — Anthropic 官方文档
- [Prompt caching](https://platform.openai.com/docs/guides/prompt-caching) — OpenAI 官方文档
- [Prompt caching for faster model inference](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html) — AWS Bedrock 官方文档
- [Context caching](https://ai.google.dev/gemini-api/docs/caching) — Google Gemini API 官方文档
- [Your Agentic Workflow's Cache Keepalive Costs 8x Too Much (v2)](https://blog.mempko.com/your-agentic-workflows-cache-keepalive-costs-8x-too-much-v2-the-interval-frontier/) — Maxim Khailo，跨厂商保温实测
