跟一位做客服 Agent 的朋友聊天,他说上线第一个月烧了 18000 美元,老板拍桌子,他熬一周改完 Prompt Cache 直接降到 3500。Prompt Cache 听起来是”打开就能省钱”的开关,但真实情况要复杂得多——TTL、最小命中长度、命中粒度、计费规则,三家主流厂商各自一套。同样一个 Agent,配置错了反而比不缓存更贵。
这篇把 Anthropic、DeepSeek、OpenAI 三家的 Prompt Cache 机制拆开讲清楚,给出一套 Cache-First 的 prompt 设计模式,并附真实账单数据。
为什么 2026 年 Prompt Cache 突然变成必修课
三个变化叠加:
第一,Agent 应用普及,单次调用的上下文体量从几百 token 涨到几万。一个像样的 Coding Agent,system prompt + 工具定义 + 文件 chunk 起步就 30k token,每轮对话都重发一遍,token 烧得肉眼可见。
第二,长上下文模型变便宜了,但”便宜的输入”也是钱。Claude Sonnet 4.5 输入 token 是 3 美元/百万,看似便宜,30k token × 1000 万次调用 = 90 万美元。
第三,三家厂商在 2025 下半年到 2026 初密集更新 cache 策略,差异变大。OpenAI 把命中阈值降到了 1024 token 全自动命中,Anthropic 推出了 1 小时 TTL 选项,DeepSeek 改成了硬盘 cache 按 token 计价。同一个 prompt 在三家成本能差 5 倍。
三家机制核心差异
我把三家文档撸了一遍,整理成对比表。这是全文最重要的一张图。
| 维度 | Anthropic Claude | DeepSeek | OpenAI GPT |
|---|---|---|---|
| 命中方式 | 显式标记 cache_control | 自动(前缀匹配) | 自动(前缀匹配) |
| 最小命中长度 | 1024 token(Sonnet) | 64 token | 1024 token |
| TTL | 5 分钟 / 1 小时(可选) | ~24 小时(磁盘) | 5-10 分钟 |
| 写入成本 | 1.25× 或 2× 基础输入价 | 与基础输入同价 | 免费 |
| 命中读取成本 | 0.1× 基础输入价 | 0.1× 基础输入价 | 0.5× 基础输入价 |
| 命中粒度 | 显式 breakpoint | 自动按前缀 | 自动按前缀 |
| 跨用户共享 | 不共享 | 不共享 | 不共享 |
| 命中可观测 | response 里有 cache_creation_input_tokens | response 里有 prompt_cache_hit_tokens | response 里有 cached_tokens |
几个关键解读:
Anthropic 是”贵但稳”。写入贵 25%-100%,但读取打到 1 折,TTL 可选 1 小时。适合超长 system prompt + 工具定义 + 几小时内反复调用的场景。坑在于必须显式打 cache_control 标记,最多 4 个 breakpoint,新手很容易标错位置导致 cache 永远不命中。
DeepSeek 是”便宜但有延迟”。写入不加价,读取 1 折,TTL 长达约 24 小时(实际是磁盘 cache,命中后还有几十毫秒额外延迟)。最小命中只要 64 token,对短 prompt 也友好。适合后台批处理、长尾低频请求。
OpenAI 是”自动但折扣浅”。完全自动命中、写入免费,但读取只打 5 折。适合不愿意改代码的场景,省钱效果不如另外两家。
Cache-First Prompt 设计的三条铁律
不管哪家,要让 cache 真正命中,prompt 结构必须遵守三条铁律。我见过太多人打开了 cache 但命中率个位数,根本原因都在结构上。
铁律一:不变的放前面
Cache 是按前缀匹配的。哪怕只有第 1 个 token 不一样,整个 cache 就失效了。所以 prompt 要严格按”稳定度”从前往后排:
[system prompt 模板] → 几乎不变
[工具定义 JSON Schema] → 偶尔加新工具
[知识库 / 文档 chunk] → 按会话变
[历史消息] → 每轮都变
[当前用户输入] → 每次都变
很多人喜欢把当前时间戳塞进 system prompt 第一行,这一下就让所有 cache 全废。
铁律二:稳定段独立成块
Anthropic 用显式 breakpoint,必须把稳定段单独标出来:
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": SYSTEM_PROMPT_TEMPLATE, # 5k token,几乎不变
"cache_control": {"type": "ephemeral", "ttl": "1h"},
},
{
"type": "text",
"text": TOOL_DEFINITIONS_JSON, # 8k token,偶尔变
"cache_control": {"type": "ephemeral"},
},
{
"type": "text",
"text": KNOWLEDGE_CHUNKS, # 15k token,按会话变
},
],
messages=conversation_history,
)
# 关键:必须读 usage 确认命中
print(f"创建: {response.usage.cache_creation_input_tokens}")
print(f"命中: {response.usage.cache_read_input_tokens}")
DeepSeek 和 OpenAI 是自动的,但前缀必须 byte 级一致。注意 JSON 序列化的字段顺序、空格、换行——任何一处不一致都会导致 cache miss。建议在序列化时强制 sort_keys=True、固定缩进。
铁律三:用 usage 字段做监控
打开 cache 不等于在用 cache。没有命中率监控的 cache 工程都是耍流氓。三家都在 response 里返回了命中字段,至少要做到:
def calc_hit_rate(usage):
"""命中率 = 命中 token / (命中 token + 创建 token + 普通输入 token)"""
hit = getattr(usage, "cache_read_input_tokens", 0) or 0
create = getattr(usage, "cache_creation_input_tokens", 0) or 0
plain = usage.input_tokens - hit - create
total = hit + create + plain
return hit / total if total else 0.0
# 上线后接入监控,命中率 < 60% 就告警
我自己跑过的 Coding Agent,把命中率从 12% 调到 78%,靠的就是这一行 usage 监控加 dashboard——能看到才能调。
一个真实账单对比
下面是同一个长上下文 Agent 应用(system prompt 5k + 工具定义 8k + 文档 chunk 15k,平均每个会话 5 轮对话,每月 1000 万次调用)在三家上的成本估算(基于 2026 年 Q1 公开定价,仅作量级参考):
| 方案 | 单次输入 token | 月成本估算 | 备注 |
|---|---|---|---|
| Claude 不开 cache | ~28k | ~$12,000 | 基线 |
| Claude + 5min TTL | 13k cache + 15k 普通 | ~$3,800 | 命中率 70% |
| Claude + 1h TTL | 13k cache + 15k 普通 | ~$2,400 | 命中率 85% |
| DeepSeek + 自动 cache | 13k cache + 15k 普通 | ~$1,100 | 模型本身便宜 |
| OpenAI GPT-5 + 自动 | 13k cache + 15k 普通 | ~$5,200 | 5 折优惠 |
数字按公开定价 × 流量假设估算,跟具体业务结构会差不少。请用自己的真实流量带进去算。
几个能复用的结论:
- Claude 1h TTL 比 5min 多花 25% 写入费,但命中率能涨 15-20 个点,长会话场景净省钱
- DeepSeek 是”长尾后台 + 大语料”任务的成本王者,但延迟和模型能力要单独评估
- OpenAI 自动 cache 是”懒人友好”,但同样命中率下成本是 Anthropic 1h 方案的 2 倍以上
容易踩的五个坑
跑过几个项目踩过的真实坑,列在这里省别人时间:
- JSON 序列化顺序不一致 —— Python
dict转 JSON 默认按插入顺序,但跨进程/跨版本可能不同。所有 cache 段强制json.dumps(obj, sort_keys=True)。 - System prompt 里塞动态时间戳 —— 直接让 cache 命中率归零,时间相关信息放 user message 里。
- Anthropic 的 4 个 breakpoint 限制 —— 多了会报错,把”稳定+次稳定”两段就够,剩下交给前缀匹配。
- DeepSeek 磁盘 cache 命中有延迟 —— 实测会多 30-80ms,对要求 P99 严格的实时场景不划算。
- 不同模型不共享 cache —— 你 fallback 到 Haiku 时,原来 Sonnet 上的 cache 用不了,路由策略要把 cache 命中也算进选模成本。
落地 Checklist
按这个顺序排查,可以快速把命中率从个位数拉到 70% 以上:
- Prompt 按”稳定度”重新排序,不变的放最前
- System prompt 里没有时间戳、随机数、UUID
- 所有 JSON 序列化用
sort_keys=True+ 固定缩进 - Anthropic:在 system 段最多打 2 个
cache_control - 接入 cache 命中率监控(hit / total),dashboard 里看得到
- 跑一次 A/B:开 cache vs 不开 cache,对比真实账单
- 长会话场景评估 1h TTL 是否值得(按命中率涨幅算 ROI)
- 路由策略:fallback 到其他模型时,把 cache 失效成本算进决策
选型建议
- 强 SLA + 长 system prompt(客服、Coding Agent) → Claude + 1h TTL,贵但稳
- 后台批处理 + 大语料 RAG → DeepSeek 自动 cache,便宜量大
- 快速接入、不愿改代码 → OpenAI 自动 cache,省心但省钱有限
- 混合架构 → 主路径用 Claude 1h,cold path 走 DeepSeek,按命中后单价做 LLM Router
Prompt Cache 不是”打开开关就行”的功能,它是一种 prompt 设计纪律。把”稳定段”和”易变段”分开,是 2026 年长上下文 Agent 工程师的基本功。早一周改完,月底账单就能差出一辆车。