如果你看过自己的 API 账单,会发现一个反直觉的事实:真正花钱的往往不是模型写出来的内容,而是每次请求都要重新发送的那一大段输入——系统提示词、工具定义、项目文档、长长的对话历史。Prompt Caching(提示词缓存)就是专门解决这个问题的机制:把重复出现的前缀缓存起来,下次命中时按远低于普通输入的价格计费,同时首字延迟也会明显下降。
这篇把提示词缓存讲透:它是怎么工作的、Anthropic 和 OpenAI 两家的做法有什么不同、计价该怎么理解、怎样写提示词才能稳定命中,以及它在 Claude Code 这类长会话工具里到底起了多大作用。想先了解 Token 成本怎么算,可以配合阅读 Token 成本计算指南。
提示词缓存是什么
大模型处理一次请求时,要先把全部输入「读一遍」,计算出每个 Token 的内部状态,然后才开始生成。如果两次请求的开头部分一模一样,这部分计算结果其实可以复用——这就是提示词缓存的本质:缓存的是输入前缀的计算结果,不是模型的回答。
所以它有三个关键特征:
- 只对前缀生效:缓存按「从开头开始完全一致」来匹配,中间改了一个字,后面的内容全部失效
- 不影响输出质量:命中缓存和不命中,模型看到的内容完全一样,回答不会因此变差或变「旧」
- 有生命周期:缓存不是永久的,一段时间不用就会过期,需要重新写入
理解了「前缀匹配」这一条,后面所有的命中技巧都是它的推论。
Anthropic:cache_control 显式缓存
Claude 系列采用显式缓存:你需要在请求里用 cache_control 标记「缓存到这里为止」。被标记位置之前的全部内容(按 tools → system → messages 的顺序)会作为一个缓存前缀。
curl https://zivv.pro/v1/messages \
-H "x-api-key: sk-your-zivv-key" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"system": [
{
"type": "text",
"text": "你是资深代码审查助手……(这里放几千 Token 的规范文档)",
"cache_control": {"type": "ephemeral"}
}
],
"messages": [
{"role": "user", "content": "审查下面这段代码:……"}
]
}'几个要点:
- 断点数量有限:一次请求可以设置少量缓存断点(官方文档目前为最多 4 个),适合把「工具定义」「系统提示」「历史对话」分层缓存
- 有最小长度:太短的前缀不会被缓存,门槛因模型而异(大致在一千到几千 Token 量级),以官方文档为准
- 默认生存期较短:默认约 5 分钟,每次命中会刷新计时;官方也提供更长的生存期选项,写入成本相应更高
- 用量字段可观测:响应的 usage 里会分别返回
cache_creation_input_tokens(本次写入缓存的量)和cache_read_input_tokens(本次从缓存读取的量),这是判断是否命中的唯一可靠依据
通过 Zivv 调用时,Anthropic 原生入口是 https://zivv.pro,请求体和官方完全一致,cache_control 会原样生效。需要精确控制缓存时,推荐走原生 /v1/messages 接口,而不是用 OpenAI 兼容格式调 Claude——跨协议转换时缓存标记的表达能力有限。
OpenAI:自动缓存
GPT 系列走的是另一条路线:自动缓存,无需任何代码改动。当输入超过一定长度(官方为 1024 Token 起)时,系统会自动尝试复用最近请求的相同前缀。
你能做的只有两件事:
- 观察命中:响应 usage 里的
prompt_tokens_details.cached_tokens表示本次有多少输入命中了缓存(Responses API 对应input_tokens_details.cached_tokens) - 提高路由一致性:官方提供了
prompt_cache_key一类的参数,让共享相同前缀的请求更可能落到同一缓存上,适合多用户共用同一套系统提示的场景
from openai import OpenAI
client = OpenAI(api_key="sk-your-zivv-key", base_url="https://zivv.pro/v1")
resp = client.chat.completions.create(
model="gpt-5.5",
messages=[
{"role": "system", "content": LONG_STATIC_SYSTEM_PROMPT},
{"role": "user", "content": "总结这份周报"},
],
)
details = resp.usage.prompt_tokens_details
print("cached:", details.cached_tokens if details else 0)两种方案对比
| 维度 | Anthropic(Claude) | OpenAI(GPT) |
|---|---|---|
| 启用方式 | 显式 cache_control 标记 | 自动,无需改代码 |
| 写入成本 | 写入价略高于普通输入 | 无额外写入费 |
| 读取成本 | 远低于普通输入 | 低于普通输入,折扣因模型而异 |
| 可控性 | 高,可分层设断点 | 低,只能靠结构与 cache key 引导 |
| 命中观测 | cache_creation / cache_read 字段 | cached_tokens 字段 |
| 适合场景 | 长文档问答、Agent、编码工具 | 通用对话、固定系统提示的服务 |
Gemini 系列也有类似机制(较新模型支持隐式缓存),思路同样是「稳定前缀 + 观察用量字段」。
计价思路:缓存什么时候划算
先说清楚原则:官方公开的大致倍数是,Claude 缓存写入约为普通输入价格的 1.25 倍(默认生存期),缓存读取约为 0.1 倍;OpenAI 缓存读取的折扣按模型从五折到一折不等。具体价格以官方和 [模型广场](/model-hub) 展示为准,这里只用它们理解思路。
Zivv 的计费方式是「分组倍率 × 官方模型价格」,按实际 Token 计算,缓存读取、缓存写入、普通输入分别按各自的官方单价折算,所以官方缓存省下的钱,在 Zivv 上同样体现。
用一个例子估算:假设系统提示加项目文档共 20,000 Token,每轮用户输入 500 Token,一共对话 20 轮(都在缓存有效期内)。
- 不用缓存:每轮都按普通输入计 20,000 Token,20 轮共 40 万 Token 的「重复输入」
- 用缓存:第一轮按约 1.25 倍写入 20,000 Token,之后 19 轮按约 0.1 倍读取,折合下来重复部分的成本大约只剩原来的一成多
结论很直接:前缀越长、复用次数越多、请求间隔越短,缓存越划算。反过来,只用一次的长前缀加缓存反而会因为写入溢价多花一点钱——这也是 Anthropic 让你显式标记的原因。
提升命中率的七个技巧
- 静态内容放前面,动态内容放后面:工具定义、系统提示、参考文档在前,用户问题和时间戳在后
- 别在系统提示里放当前时间:「现在是 2026-10-14 14:32」这种行每次都变,会让整个前缀失效;确实需要时放到最后一条用户消息里
- 工具列表保持固定顺序:动态生成工具定义时,务必排序后再序列化,JSON 键顺序也要稳定
- 对话历史只追加不改写:中途删改历史消息、重新总结前文,都会打断前缀
- 合理利用多个断点:把很少变的工具定义、偶尔变的项目说明、每轮增长的对话分别设断点,局部变化不会让全部缓存作废
- 控制请求间隔:缓存默认几分钟过期,批处理任务尽量集中跑,不要每条之间隔太久
- 同一会话别频繁换模型:缓存按模型隔离,换了模型就是从零开始
做完这些,用 usage 字段做验证:连续发两次相同请求,第二次的 cache_read_input_tokens 或 cached_tokens 明显大于零,才说明真的命中了。
三个常见误区
误区一:缓存等于「记住了上次的对话」。 不是。缓存只是加速和降价,你仍然要在每次请求里发送完整上下文。没有发送的内容,模型不会凭缓存「想起来」。
误区二:开了缓存就一定省钱。 只有前缀被复用才省钱。如果每次请求的系统提示都带着用户名、时间或随机 ID,缓存永远命中不了,Claude 场景下还会白白支付写入溢价。上线前务必用用量字段验证一遍。
误区三:缓存命中会影响限流计算。 速率限制的计算口径以上游规则为准,不同厂商对缓存 Token 是否计入限额的规定不同。对 Claude Code 重度用户来说,更直接的办法是使用不设速率上限的分组,详见 Claude Code 限流解决方案。
Claude Code 里的提示词缓存
Claude Code 是提示词缓存的「重度受益者」。它每一轮请求都会带上很长的固定前缀:系统提示、全部工具定义、CLAUDE.md、已读取的文件内容和不断增长的对话历史。Claude Code 会自动为这些内容设置缓存断点,你不需要做任何配置。
这意味着几件事:
- 长会话的边际成本并不像想象中那么高:前缀大部分时间是按缓存读取价计费的
- 离开太久再回来,第一轮会贵一点:缓存过期后需要重新写入
- 会话中途切换模型、增删 MCP 工具,会让缓存重建,非必要别频繁切
- `/compact` 压缩上下文后前缀会变化,压缩后的第一轮会重新写入缓存,但之后的每轮都更便宜
通过 Zivv 使用 Claude Code,只需配置 ANTHROPIC_BASE_URL=https://zivv.pro 和 ANTHROPIC_AUTH_TOKEN,走的是原生 Anthropic 协议,缓存机制与官方完全一致。完整步骤见 Claude Code Windows 配置指南 和 Claude Code 文档;重度用户可以了解 Claude MAX 分组。更多省钱思路见 AI 成本优化。
常见问题 FAQ
Q:提示词缓存会让模型回答变旧或变差吗? A:不会。缓存的只是输入前缀的计算结果,模型每次都基于完整输入重新生成回答,命中与否对输出质量没有影响。
Q:怎么确认缓存真的命中了? A:看响应里的用量字段。Claude 看 cache_read_input_tokens,OpenAI 看 cached_tokens。Zivv 控制台的用量明细也会体现输入 Token 的构成。
Q:OpenAI 兼容格式调用 Claude 能用缓存吗? A:跨协议转换时缓存标记的表达有限,行为取决于网关实现。想精确控制,建议直接用 Anthropic 原生接口 https://zivv.pro/v1/messages。
Q:缓存的数据会被别人读到吗? A:缓存在模型厂商侧按组织隔离,且只有前缀完全一致才可能命中。Zivv 本身不存储请求和响应正文,仅记录 Token 用量用于计费。
Q:缓存写入更贵,会不会反而亏? A:前缀只用一次时确实会多花一点。经验上同一前缀会被复用两次以上、且在有效期内,缓存就是划算的。
Q:Claude Code 需要手动开启缓存吗? A:不需要,Claude Code 默认自动使用提示词缓存。你能做的是保持会话连续、少切模型,让缓存持续命中。
写在最后
提示词缓存是成本优化里投入最小、回报最高的一项:调整一下提示词结构,甚至什么都不改,就能让长上下文场景的输入成本大幅下降。把静态内容前置、观察用量字段、保持会话连续,这三件事做到就够了。现在就可以 注册 Zivv,用同一个 Key 在 Claude、GPT 上分别验证一次缓存命中效果。