如果你用 Claude Code、Cline、Cursor,或者自己写代码调 Claude API,Prompt Cache 是把账单打下来最直接的一件事——命中缓存的部分只按 0.1× 计费,相当于打 1 折。 本页基于 Anthropic 官方文档整理(Documentation Index
Fetch the complete documentation index at: https://docs.apiyi.com/llms.txt
Use this file to discover all available pages before exploring further.
docs.claude.com/en/docs/build-with-claude/prompt-caching),并按 API易 的接入方式给出可直接复制的示例。
一句话理解
把一段反复使用的长 prompt(系统说明 / 长文档 / few-shot 示例)打上cache_control 标记,服务器会把它存起来。下次相同前缀的请求来,服务器跳过重复处理,便宜约 10 倍、也更快。一段时间内没人再用就会过期。
为什么要用 —— 看账单倍率
以模型原始输入 token 价为 1× 计:| 类型 | 价格 | 说明 |
|---|---|---|
| 普通输入 | 1× | 没缓存的部分,原价 |
| 缓存写入(5 分钟 TTL) | 1.25× | 第一次写入贵 25% |
| 缓存写入(1 小时 TTL) | 2× | 想存更久要付更多 |
| 缓存读取(命中) | 0.1× | 后续每次便宜 90% |
- 5 分钟 TTL:只需 2 次复用同一前缀即可回本(1.25 + 0.1 = 1.35,比两次不缓存的 2.0 便宜)。
- 1 小时 TTL:需要 3 次才回本(2 + 0.2 = 2.2,比 3.0 便宜)。
TTL 是滑动窗口:每次命中都会把过期时间重置,因此活跃的会话不会平白过期。只有真正闲置超过 TTL 才会失效。
适合场景
- 同一份长系统提示词被多次调用(Agent、客服机器人)
- 多轮对话(每加一轮,前面的历史都能复用)
- 批量处理同一份文档(一份合同问 50 个问题)
- RAG 把检索到的稳定文档块作为前缀
不适合场景
- 每次 prompt 从第一个字开始都不一样
- 整体很短,根本到不了最小 token 阈值(见下)
触发缓存的三个硬条件
缺一不可。1. 必须显式打标记 cache_control
content 不能是纯字符串,必须是 content block 数组,在要缓存的那一块上加 cache_control:
2. 长度必须达到最小阈值
短于阈值的内容,就算打了标记也不会缓存(不报错,静默忽略)。按模型不同:| 模型 | 最小 tokens |
|---|---|
| Sonnet 4.5 / 4 / 3.7 | 1024 |
| Sonnet 4.6 / 早期 Haiku | 2048 |
| Opus 4.5 / 4.6 / 4.7、Haiku 4.5 | 4096 |
3. 前缀必须逐字节相同
缓存按前缀匹配:从请求开头一直到cache_control 标记位置,这段字节流必须和上一次完全一样。改任何一个字符——哪怕是空格、JSON 字段顺序、时间戳——都算”新前缀”,会重新写入而不是命中。
实践含义:稳定的东西放前面,易变的东西放后面。
最小可运行示例
跑两次同一段长文 + 不同问题,第一次写入缓存,第二次命中:read ≈ 第 1 次的 write,说明同一段前缀被命中复用了。
怎么判断命中没命中 —— 看三个字段
每次响应的usage 里:
| 字段 | 含义 | 计费倍率 |
|---|---|---|
input_tokens | 没被缓存的剩余输入 token | 1× |
cache_creation_input_tokens | 这次写入缓存的 token 数 | 1.25× 或 2× |
cache_read_input_tokens | 这次从缓存读取的 token 数 | 0.1× |
cache_read_input_tokens > 0,你就在省钱。
最常见的踩坑
| 现象 | 原因 |
|---|---|
write 永远是 0 或字段不存在 | 没打 cache_control 标记 / 长度没到阈值 / 用了 OpenAI 兼容格式 |
第 2 次 write 又 > 0,read 还是 0 | 前缀变了。常见:prompt 里有 datetime.now()、UUID、变化的用户 ID;JSON 序列化顺序不稳定;带时间戳的 system 提示 |
| 隔了一会儿再调又变成写入 | 闲置超过 TTL 过期。要常驻可加 {"type": "ephemeral", "ttl": "1h"} |
| 同一份 prompt 切换模型后没命中 | 缓存按模型隔离,换模型相当于换 key |
| 长对话最近几轮不命中 | 单次请求最多 4 个 cache_control 断点;且每个断点的前缀查找窗口为 20 个 block,更久远的内容不会被纳入命中检查 |
进阶:多轮对话怎么打
把cache_control 打在最近一条 user 消息的最后一个 content block 上。每加一轮,缓存读取范围会自动延伸到上一轮结束的位置:
- 单次请求最多 4 个
cache_control断点。 - 每个断点的前缀查找只回溯最近 20 个 content block——超出 20 个 block 的更久远内容不会再被检索去拼命中。换言之:很长的多轮对话靠”最末一次打标记”是兜不住前面所有历史的。
API易 关于缓存的说明
API易完整透传缓存字段。 你在请求里写的
cache_control 会原样转发给上游 Claude(AWS Claude 或 Claude Official),响应里的 cache_creation_input_tokens / cache_read_input_tokens 也会原样回吐给你——所以你的代码无需为中转层做任何额外适配。- 第一次发送时观察响应
usage.cache_creation_input_tokens > 0(写入成功)。 - 几秒后用相同前缀再发一次,应看到
usage.cache_read_input_tokens > 0(命中)。 - 后台账单里会单独显示缓存写入 / 缓存读取两类计费项,倍率与官方一致(1.25× / 2× / 0.1×)。
要点回顾
1. 打标记
cache_control: {"type": "ephemeral"} 加在 content block 上,纯字符串 content 永不缓存。2. 够长度
Sonnet 4.6 ≥ 2048 tokens,Opus 4.7 / Haiku 4.5 ≥ 4096 tokens,否则静默忽略。
3. 稳前缀
稳定内容在前、易变内容在后;任何一个字符变化都会让缓存失效。
4. 看 usage
cache_read_input_tokens > 0 才说明真的省钱了。相关链接
- 父页面:Claude API 调用基础说明
- 获取 / 管理令牌:
https://api.apiyi.com/token - Anthropic 官方文档:
docs.claude.com/en/docs/build-with-claude/prompt-caching