同一个 1 万 token 的系统提示,不带缓存每次调用要 0.03,带上缓存后第 4 次起每次只要 0.003。到第 100 次调用,账单是 0.33 而不是 3.00。这个差价,就是
cache_control一个参数带来的。

文章目录
-
- 一、先说结论:重复调用的钱,你一直在白交
- 二、环境信息
- [三、为什么能省 90%:三种 token 定价](#三、为什么能省 90%:三种 token 定价)
- [四、两种用法:自动缓存 vs 显式断点](#四、两种用法:自动缓存 vs 显式断点)
-
- [4.1 自动缓存(最简单)](#4.1 自动缓存(最简单))
- [4.2 显式断点(精细控制)](#4.2 显式断点(精细控制))
- 五、完整实战:长文档批量分析
- 六、踩坑记录:这四个坑,我全踩过
- 七、什么时候该用、什么时候别用
- 八、写在最后
一、先说结论:重复调用的钱,你一直在白交
我在香港做 FinTech,日常会用 Claude API 批量处理一堆东西------解析合同条款、提取财务报告字段、生成周报。最开始图省事,每次调用都把完整的 system prompt(包含一堆行业规则和示例)原样发过去。
结果月底看账单傻眼了:几千次调用,大部分 token 消耗全花在了那段一模一样、每次都重发的系统提示上。
直到我把那段静态内容加上 cache_control 标记,成本直接砍掉一大块。原因很简单------Anthropic 提供了一个叫 Prompt Caching(提示词缓存) 的机制:标记为可缓存的内容,第一次请求时写入缓存(略贵),之后相同前缀的请求直接从缓存读取(便宜 90%)。
这篇文章我把原理、定价、代码、踩坑一次性讲清楚。核心结论先放这:只要你重复调用同一个 Claude 且带长 system prompt / 参考文档 / few-shot 示例,Prompt Caching 就能帮你省掉大部分重复的输入成本。
收藏提示①:文末的缓存封装函数可以直接复用,套到你自己的调用链里就能看到
usage里的缓存命中数。
二、环境信息
| 项 | 版本 |
|---|---|
| Python | 3.13.12 |
| anthropic SDK | 最新版 |
| 模型 | claude-sonnet-4-6(示例用,实际以官方为准) |
| 数据/价格 | Anthropic 官方文档(价格会变,发布前请以官方定价页为准) |
三、为什么能省 90%:三种 token 定价
Prompt Caching 把输入的 token 拆成了三种价格(以 Sonnet 4.6 为例,$3/M 基础输入):
| token 类型 | 含义 | 价格 | 相对基础价 |
|---|---|---|---|
| 缓存写入 | 第一次发可缓存内容,写进服务端缓存 | $3.75/M(5min) | 1.25 倍 |
| 缓存读取 | 后续相同前缀,直接从缓存读 | $0.30/M | 0.1 倍 |
| 普通输入 | 不可缓存、每次重算的部分 | $3/M | 1 倍 |
关键点在于那个 0.1 倍 ------缓存读取只有基础输入的十分之一,也就是省 90%。而写入虽然贵 25%,但这是"一次性投入":只要同一个缓存块被命中两次以上,就开始回本。
算笔账(1 万 token 系统提示,$3/M 基础价):
无缓存:每次 $0.03
有缓存:第 1 次写入 $0.0375,之后每次读取 $0.003
第 1 次调用:有缓存反而多花 $0.0075(写入溢价)
第 4 次调用:开始省钱
第 100 次调用:$0.33 vs $3.00 ------ 省了 89%
调用越频繁、静态内容越长,省得越狠。这就是为什么它最适合"多轮对话 + 长上下文 + 批量处理"的场景。

上图:调用次数从 1 到 100,无缓存成本线性增长,有缓存成本几乎走平------剪刀差就是省下来的钱。
四、两种用法:自动缓存 vs 显式断点
先记住缓存的一个核心规则:缓存按 tools → system → messages 的顺序层级累积,断点之前的静态内容才会被缓存。

4.1 自动缓存(最简单)
在请求顶层 加一个 cache_control 字段即可,系统会自动把断点放到最后一个可缓存的块上,随对话增长自动前移:
python
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
cache_control={"type": "ephemeral"}, # 一行开启自动缓存
system="You are a helpful assistant that remembers our conversation.",
messages=[
{"role": "user", "content": "My name is Alex. I work on machine learning."},
{"role": "assistant", "content": "Nice to meet you, Alex!"},
{"role": "user", "content": "What did I say I work on?"},
],
)
# 打印 usage,能看到缓存相关的三个字段
print(response.usage.model_dump_json())
自动缓存最适合多轮对话------它不用你手动维护断点位置,对话每长一轮,断点就自动前移,之前的内容自动走缓存读取。
4.2 显式断点(精细控制)
把 cache_control 放在具体的 content block 上,精确指定哪些内容缓存:
python
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[
{
"type": "text",
"text": "你是一个合同分析助手,提取关键条款、义务和风险点,输出结构化 JSON。",
"cache_control": {"type": "ephemeral"} # 缓存这段系统指令
},
{
"type": "text",
"text": LONG_INDUSTRY_RULES, # 一堆行业规则,也缓存
"cache_control": {"type": "ephemeral"}
},
],
messages=[{"role": "user", "content": contract_text}], # 每次变化的合同文本,不缓存
)
显式断点适合静态内容 + 变化内容混着的场景------把不变的系统指令、规则、few-shot 示例缓存起来,每次变的正文单独传。
收藏提示②:
cache_control={"type": "ephemeral"}这个字段就是全部关键。自动缓存加在顶层,显式断点加在单个块上。记住这一个参数,就能上手。
五、完整实战:长文档批量分析
下面是我实际用的封装函数,把缓存逻辑包起来,批量分析同一批文档时能明显看到成本下降:
python
import anthropic
client = anthropic.Anthropic()
# 缓存的静态部分:系统角色 + 一份固定的"分析规范"
def build_system() -> list:
return [
{
"type": "text",
"text": "你是香港金融数据分析助手。提取字段:金额、日期、交易对手、风险评级。输出 JSON。",
"cache_control": {"type": "ephemeral"}
},
{
"type": "text",
"text": REFERENCE_GUIDE, # 一份很长的行业分析规范,几千 token
"cache_control": {"type": "ephemeral"}
},
]
def analyze_document(doc_text: str):
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=build_system(),
messages=[{"role": "user", "content": doc_text}], # 每次变化的文档
)
# 看缓存命中情况
usage = resp.usage
print(
f"缓存写入: {usage.cache_creation_input_tokens}, "
f"缓存读取: {usage.cache_read_input_tokens}, "
f"普通输入: {usage.input_tokens}"
)
return resp.content
# 批量处理 50 份文档
for doc in documents[:50]:
analyze_document(doc)
跑起来后你会看到:第一份文档的 cache_creation_input_tokens 很大(写入缓存),从第二份开始 cache_read_input_tokens 稳定出现(命中缓存),input_tokens 只剩每份文档本身的量。
六、踩坑记录:这四个坑,我全踩过
- 最小 token 阈值 :缓存内容不够长,缓存根本不生效。Sonnet 4.6 要 2048 token 以上,Opus 4.6 要 4096 token 以上。如果系统提示只有几百 token,标记了也白标记------系统会静默跳过缓存。
- 断点别放在会变化的内容上 :如果你把
cache_control放在一个包含时间戳或动态 ID 的块上,那每次哈希都不同,缓存永远命中不了,反而每次都在付"写入"的溢价。静态内容放断点,动态内容放断点之后。 - TTL 默认只有 5 分钟 :缓存从最后一次命中起算,5 分钟不用就失效。批量处理时如果中间隔太久,缓存会凉掉,下一次又是全价写入。有需要可以显式指定
"ttl": "1h"(1小时缓存,写入价是 2 倍,但适合长时间批处理)。 - 回溯窗口只有 20 块:缓存命中会向后查找最长匹配前缀,但最多回溯 20 个块。如果对话长得离谱,前一次的缓存条目可能掉出窗口,导致命中失败------长对话记得手动加多个断点。
七、什么时候该用、什么时候别用
值得用(能省大钱):
- 长 system prompt(行业规则、角色设定、详细指令)
- 固定参考文档(合同模板、代码库、规范文件)
- few-shot 示例(几十个示例,每次重发很贵)
- 多轮对话(对话历史自动缓存)
别用(反而亏):
- 每次请求内容完全不同、没有重复前缀
- 静态内容很短(低于最小 token 阈值)
- 调用频率极低(缓存 5 分钟就失效,写入溢价赚不回来)
一句话:缓存省的是"重复"的钱,没有重复就没有节省。
八、写在最后
Prompt Caching 不是什么高深技巧,就是 Anthropic 给"重复发送相同前缀"这件事打了个折。但据我观察,身边不少用 Claude API 的人根本不知道这个参数,每个月都在为同一段系统提示重复付费。
把它加到你的调用链里,去看一眼 response.usage 里的 cache_read_input_tokens------如果这个数是 0,说明你的缓存根本没生效,要么内容太短,要么断点位置错了。把它调对,账单上省下来的数字会非常直观。
需要说明的是,价格和最小阈值是版本敏感信息,会随 Anthropic 调整而变化,本文数据以写作时的官方文档为准,动手前建议先查一下最新的定价页。
收藏提示③:如果这篇帮你省了钱,收藏 + 点赞,下次调整调用链时直接回来查。。
