Prompt 缓存 API 完全指南:用 Anthropic 和 OpenAI 缓存机制把重复调用成本压到最低
为什么 prompt 缓存 API 值得你认真研究
调用大模型的成本里,有一块被严重低估:重复传输的 system prompt 和上下文。一个典型的 RAG 应用,每次请求都要把几千 token 的文档上下文塞进 prompt;一个代码审查 bot,每次都要附带几百行的规范说明。这些内容在单次对话里几乎一字不差,但每次都按全量 token 计费。
Anthropic 和 OpenAI 都提供了 prompt 缓存 API 机制来解决这个问题。两家的实现思路不同,命中条件也不同,用错了照样按原价跑。本文把两家的缓存逻辑拆开来看,并给出一套可以直接落地的结构设计方法。
两家缓存机制的核心差异
Anthropic:显式标记,精确控制
Claude Opus 4.8 / Sonnet 4.6 / Haiku 4.5 使用的是显式缓存机制,开发者需要在请求体里用 cache_control 字段手动标记需要缓存的 block:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[
{
"type": "text",
"text": "你是一个代码审查助手,以下是完整的编码规范文档...",
"cache_control": {"type": "ephemeral"}
}
],
messages=[{"role": "user", "content": user_question}]
)
关键参数和规则:
type: "ephemeral"是目前唯一支持的缓存类型,TTL 为 5 分钟(官方数据),超时后自动失效- 最多可以设置 4 个
cache_control断点(breakpoint) - 最低缓存门槛:Opus 4.8 需要 ≥ 1024 tokens,Sonnet 4.6 和 Haiku 4.5 需要 ≥ 2048 tokens,不满足则不缓存,但不会报错
- 写入缓存(cache write)的费率是标准输入价格的 1.25 倍,命中缓存(cache read)则是标准价的 0.1 倍——也就是说,同样内容第二次起节省 90%
返回的 usage 对象里会包含 cache_creation_input_tokens 和 cache_read_input_tokens,可以直接监控命中情况。
OpenAI:自动缓存,无需标记
GPT-5.5 / GPT-5.4 / GPT-5.4-mini 使用的是隐式缓存机制,不需要任何额外字段,系统自动对 ≥ 1024 tokens 的 prompt 前缀进行缓存:
response = client.chat.completions.create(
model="gpt-5.4",
messages=[
{"role": "system", "content": long_system_prompt},
{"role": "user", "content": user_question}
]
)
# 命中情况在 usage 里查看
print(response.usage.prompt_tokens_details.cached_tokens)
OpenAI 缓存规则:
- 缓存以 128 token 为粒度对 prompt 前缀做匹配,前缀必须完全一致才能命中
- TTL 约为 5~10 分钟(低流量期可能更短),官方未公开精确值
- 命中缓存的 token 折扣:GPT-5.4 系列约为标准价的 50%(相比 Anthropic 的 90% 折扣力度小一些)
- 不支持手动标记,也不支持强制刷新
对比一览
| 维度 | Anthropic | OpenAI |
|---|---|---|
| 缓存方式 | 显式 cache_control |
自动前缀匹配 |
| 最低门槛 | 1024 / 2048 tokens | 1024 tokens |
| 命中折扣 | 标准价 × 0.1(节省 90%) | 标准价 × 0.5(节省 50%) |
| TTL | 5 分钟 | 5~10 分钟 |
| 最大断点数 | 4 个 | 不限(自动) |
| 监控字段 | cache_read_input_tokens |
cached_tokens |
最大化缓存命中率的结构设计方法
两家机制不同,但有一条共同的核心原则:把不变的内容放前面,把变化的内容放后面。
原则一:严格的内容稳定性分层
把 prompt 的内容按变动频率分成三层,从上到下排列:
- 静态层(完全不变):角色定义、任务描述、输出格式要求、few-shot 示例、大段知识文档
- 半静态层(按会话变化):当前对话的历史记录
- 动态层(每次请求都变):用户当前输入
对于 Anthropic,在静态层末尾打上 cache_control 标记;对于 OpenAI,确保 system message 和 few-shot 示例放在 messages 数组最前面,且内容逐字节不变。
原则二:few-shot 示例的位置很关键
很多人把 few-shot 示例放在 user message 里,这在 OpenAI 的自动缓存下会导致每次前缀长度不固定,缓存无法命中。正确做法是把示例统一挪到 system message,或在 messages 数组里作为固定的前置对话轮次出现(role: user + role: assistant 交替),并保证它们在动态内容之前。
messages = [
# 这两轮是固定 few-shot,始终在最前面
{"role": "user", "content": "示例输入 A"},
{"role": "assistant", "content": "示例输出 A"},
{"role": "user", "content": "示例输入 B"},
{"role": "assistant", "content": "示例输出 B"},
# 动态内容从这里开始
*conversation_history,
{"role": "user", "content": current_user_input}
]
原则三:控制请求频率以维持 TTL
Anthropic 的 5 分钟 TTL 意味着,如果你的应用请求间隔超过 5 分钟,缓存就会失效,下一次又是 cache write 价格。对于低频场景,有两种应对方式:
- 定时心跳请求:每 4 分钟发一次极短的请求(1 token 输出),保持缓存热身——注意这本身也有成本,适合缓存内容 token 数 > 5000 的场景
- 接受重建成本:把 cache write 的 1.25× 溢价算进总成本,评估是否仍然划算
原则四:用 Anthropic 的多断点做分段缓存
4 个 cache_control 断点可以应对"部分内容变、部分不变"的场景。比如一个法律助手,有一段固定的通用法规(2000 tokens),还有一段每个用户不同的合同文本(1500 tokens):
system=[
{
"type": "text",
"text": FIXED_LEGAL_RULES, # 所有用户共享,永远缓存
"cache_control": {"type": "ephemeral"}
},
{
"type": "text",
"text": user_specific_contract, # 同一用户的多轮对话里缓存
"cache_control": {"type": "ephemeral"}
}
]
这样通用法规对所有用户共享缓存,用户合同对单个用户的多轮对话内缓存,两层各自独立命中。
实际降本效果估算
以一个典型的文档问答应用为例:system prompt 4000 tokens,每次用户问题 50 tokens,模型回答 300 tokens,每天 10000 次调用。
使用 Claude Sonnet 4.6:
- 无缓存:4050 × 10000 × $3/M = $121.5/天
- 有缓存(命中率 80%):首次写入 4000 × 2000 × $3.75/M + 命中 4000 × 8000 × $0.3/M + 每次动态 50 tokens = 约 $31/天,节省约 74%
命中率能做到 80% 以上,前提是你的请求间隔稳定在 5 分钟以内,且 prompt 结构严格遵循"静态在前"原则。
如果你在做这类精细化的 API 成本控制,顺带推荐一下我用的接入方案:XycAi 词元平台(https://www.xyc.ai)。它是 OpenAI 兼容协议,一个 API key 能接 200+ 模型,Claude Code、Codex、Gemini CLI 都支持一键配置。GPT-5 和 Claude Opus 4.8 这类旗舰模型有时候低至官方价 1.4 折,加上全球 CN2 直连节点,延迟比直连官方 API 还低——对于需要频繁刷新缓存心跳的场景,这个延迟优势还挺实在的。企业用的话也有大模型算法备案号和全球发票支持。
一个 API 接入 200+ 全球 AI 模型
GPT · Claude · Gemini 官方模型低至 1.4 折起,持大模型算法备案号,CN2 直连低至 5ms,可开全球合规发票。
立即体验 XycAi →