← 返回博客列表

把 LLM 账单砍掉 80%:Prompt Cache 三家机制深度对比与工程化实战

跟一位做客服 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 ClaudeDeepSeekOpenAI GPT
命中方式显式标记 cache_control自动(前缀匹配)自动(前缀匹配)
最小命中长度1024 token(Sonnet)64 token1024 token
TTL5 分钟 / 1 小时(可选)~24 小时(磁盘)5-10 分钟
写入成本1.25× 或 2× 基础输入价与基础输入同价免费
命中读取成本0.1× 基础输入价0.1× 基础输入价0.5× 基础输入价
命中粒度显式 breakpoint自动按前缀自动按前缀
跨用户共享不共享不共享不共享
命中可观测response 里有 cache_creation_input_tokensresponse 里有 prompt_cache_hit_tokensresponse 里有 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 TTL13k cache + 15k 普通~$3,800命中率 70%
Claude + 1h TTL13k cache + 15k 普通~$2,400命中率 85%
DeepSeek + 自动 cache13k cache + 15k 普通~$1,100模型本身便宜
OpenAI GPT-5 + 自动13k cache + 15k 普通~$5,2005 折优惠

数字按公开定价 × 流量假设估算,跟具体业务结构会差不少。请用自己的真实流量带进去算。

几个能复用的结论:

  • Claude 1h TTL 比 5min 多花 25% 写入费,但命中率能涨 15-20 个点,长会话场景净省钱
  • DeepSeek 是”长尾后台 + 大语料”任务的成本王者,但延迟和模型能力要单独评估
  • OpenAI 自动 cache 是”懒人友好”,但同样命中率下成本是 Anthropic 1h 方案的 2 倍以上

容易踩的五个坑

跑过几个项目踩过的真实坑,列在这里省别人时间:

  1. JSON 序列化顺序不一致 —— Python dict 转 JSON 默认按插入顺序,但跨进程/跨版本可能不同。所有 cache 段强制 json.dumps(obj, sort_keys=True)
  2. System prompt 里塞动态时间戳 —— 直接让 cache 命中率归零,时间相关信息放 user message 里。
  3. Anthropic 的 4 个 breakpoint 限制 —— 多了会报错,把”稳定+次稳定”两段就够,剩下交给前缀匹配。
  4. DeepSeek 磁盘 cache 命中有延迟 —— 实测会多 30-80ms,对要求 P99 严格的实时场景不划算。
  5. 不同模型不共享 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 工程师的基本功。早一周改完,月底账单就能差出一辆车。