💡

文章摘要

任何生产 LLM 应用每月 API 账单超过 $500 的团队,都可以通过 prompt caching 系统性降低 50-90% 的输入成本。本文从 Provider 层缓存机制出发,覆盖 Anthropic/OpenAI/Gemini 三大平台的实现差异、breakeven 分析、cache-friendly prompt 设计、生产监控,以及常见陷阱,给出可直接落地的工程决策框架。

一、为什么你需要系统性地降低 LLM API 成本

想象这样一个场景:你的团队运营一个 AI 客服系统,每天处理 5000 次对话。每次对话都包含相同的 3000-token 系统提示(角色定义、业务规则、输出格式),加上变化的用户消息。月底账单出来,光输入 token 就花了 $2,400——其中 70% 是在反复发送相同的系统提示。

你试过压缩 prompt、减少 few-shot 示例、甚至换更便宜的模型,但效果有限。问题不在于 prompt 太长,而在于你在为重复内容反复付费。

Prompt caching(提示缓存) 就是解决这个问题的。它不是客户端的 HTTP 缓存,也不是 CDN 缓存,而是 LLM Provider 在推理层面提供的优化:当你连续发送相同前缀的请求时,Provider 会复用之前计算的中间结果(KV cache),只对新增部分重新计算。结果就是:

  • 成本降低 50-90%:缓存读取的价格通常是正常 input 的 10-50%
  • 延迟降低 20-50%:跳过前缀的 prefill 阶段,首 token 响应更快
  • 零质量损失:缓存的是计算中间态,输出结果与不使用缓存完全一致

本文能帮你做什么:读完之后,你将能够——

  1. 设计 cache-friendly 的 prompt 结构(静态前缀 + 动态后缀分离)
  2. 计算不同 Provider 的 prompt caching breakeven(缓存写入价格 vs 读取价格)
  3. 为 Anthropic/OpenAI/Gemini 分别配置缓存策略
  4. 判断哪些工作负载适合 prompt caching、哪些不适合

先澄清一个常见误解prompt caching 与你在 token-economics 中看到的"工具结果缓存"(Agent Runtime 层)是两回事。工具结果缓存是在你的应用代码里缓存 API 返回的结果,避免重复调用;prompt caching 是 Provider 在推理时缓存 promptKV cache 表示,降低单次调用的计算成本。两者互补,不冲突。

核心术语速览(后文会详细展开):

  • KV cache键值缓存Transformer 模型在推理时存储的中间计算状态。Prompt caching 本质上就是复用这个缓存。
  • Prefix caching(前缀缓存):Provider 层面的优化机制——相同前缀的请求可复用 KV cache。与客户端 HTTP 缓存完全不同。
  • Cache hit/miss(缓存命中/未命中):命中表示前缀匹配成功、复用了缓存;未命中表示需要重新计算。
  • TTL(Time-To-Live):缓存存活时间。不同 Provider 的 TTL 策略差异很大。
  • cache_control:Anthropic 的显式缓存控制参数,用于标记哪些内容块需要缓存。
图表加载中…

二、Provider 层缓存 vs 客户端缓存:本质区别

在深入三大 Provider 的实现之前,必须先搞清楚 prompt caching 与你熟悉的其他缓存机制有什么区别。混淆这些概念会导致错误的优化策略。

HTTP 缓存(浏览器/CDN 层):存储完整的 HTTP 响应。命中条件是 URL + Header 完全匹配。对 LLM API 基本无效,因为每次请求的 body(prompt)都不同,即使系统提示相同,用户消息也不同。

工具结果缓存(应用层):在你的代码里缓存 API 返回的结果。比如用户问"北京天气",你缓存结果 1 小时。这是应用层优化,与 Provider 无关。

Prompt caching(Provider 层):Provider 在推理时缓存 promptKV cache 表示。命中条件是 prompt 的前缀 token 序列完全匹配。缓存的不是响应结果,而是中间计算状态——它不能直接作为响应返回,但能大幅加速后续相同前缀的处理,并降低计算成本。

为什么这个区别重要? 因为命中逻辑完全不同:

  • HTTP 缓存:URL + Header 匹配 → 对 API 调用无效
  • 工具结果缓存:相同输入 → 返回相同输出 → 应用层优化
  • Prompt caching:前缀 token 匹配 → 复用 KV cache → Provider 层优化

从底层工作原理看:LLM 处理每个请求时,Transformer 架构需要先对 promptprefill(预填充)计算,为每个 token 生成 key 和 value 向量并存入 KV cache。前缀相同的请求,前段 token 的 key/value 完全一致,Provider 直接复用已存储的 KV cache,跳过这段 prefill 计算,这就是 prompt caching 的底层实现方式。缓存命中时,模型只需要对新增的后缀 token 执行 prefill,然后进入 decode(逐 token 生成)阶段。

一个具体例子:你的客服系统每次调用都发送相同的 3000-token 系统提示,加上不同的用户消息。

  • HTTP 缓存无法命中(每次请求 body 不同)
  • 工具结果缓存无法命中(每个用户问题不同,结果也不同)
  • Prompt caching 可以命中(前缀 3000 tokens 相同)→ 系统提示部分成本降低 90%

关键洞察prompt caching 是 Provider 专门为 LLM API 的计费模型设计的优化。它不关心你的 HTTP 请求是否相同,只关心 prompt 的前缀 token 序列是否相同。这意味着即使每次请求的用户消息不同,只要系统提示和工具定义相同,就能命中缓存。

图表加载中…

三、三大 Provider 的机制对比与选型

Anthropic、OpenAI 和 Google 的 prompt caching 实现差异显著。选型时不能只看"支持 caching",必须理解各自的触发方式、TTL 策略、最小缓存单元和计费模型。

Anthropic:显式控制,灵活但需手动配置

Anthropic 的 prompt caching 需要开发者在请求中显式标记 cache_control 断点。你可以精确控制哪些内容块(系统提示、工具定义、对话历史)需要缓存。

核心参数

  • 触发方式:在 content block 中添加 cache_control: {"type": "ephemeral"}
  • TTL:默认 5 分钟,可通过 ttl: "1h" 扩展到 1 小时
  • 最小缓存单元:1024 tokens(Haiku 3.5 为 2048 tokens)
  • 计费:缓存写入 = 基础 input 价格 × 1.25,缓存读取 = 基础 input 价格 × 0.1
  • 断点数量:最多 4 个 cache_control 断点

适用场景:需要精细控制缓存策略的复杂应用,如多轮对话 Agent、工具密集型任务。

python
anthropic_caching.py
import anthropic

client = anthropic.Anthropic()

message = client.messages.create(
    model="claude-sonnet-4-5-20250514",
    max_tokens=4096,
    system=[{
        "type": "text",
        "text": "你是一个专业的技术顾问...(2000+ tokens 的系统提示)",
        "cache_control": {"type": "ephemeral", "ttl": "1h"}  # 显式标记缓存
    }],
    messages=[{"role": "user", "content": "分析这段代码..."}]
)

# 检查缓存命中情况
usage = message.usage
print(f"缓存读取 tokens: {usage.cache_read_input_tokens}")
print(f"缓存写入 tokens: {usage.cache_creation_input_tokens}")

💡 一句话理解

Anthropic 的缓存断点本身不产生额外费用,只有实际被缓存的内容才计费。如果 prompt 长度低于最小缓存单元(1024 tokens),cache_control 会被静默忽略(不报错)。并发请求时,第一个响应开始后才能命中缓存,需要串行化首次请求。

三(续)、OpenAI 与 Gemini 的缓存策略

OpenAI:自动缓存,零配置但不可控

OpenAIprompt caching 完全自动,无需任何代码修改。系统会检测相同前缀并自动复用缓存。

核心参数

  • 触发方式:自动,无需手动标记
  • TTL:约 5-10 分钟,不可配置
  • 最小缓存单元:1024 tokens
  • 计费:缓存读取 = 基础 input 价格 × 0.5(50% 折扣)
  • 适用模型:GPT-4o、GPT-4o-mini、o1 系列、o3-mini 等

适用场景:快速集成、不想修改代码的现有应用,或前缀结构简单的场景。

局限性:无法控制哪些内容被缓存;无法调整 TTL;缓存命中率不可观测(API 响应中不返回缓存统计)。

Google Gemini:显式 + 自动混合,TTL 可配置

Gemini 的 cachedContent API 允许预创建缓存对象,显式指定 TTL,适合需要长期缓存的场景。

核心参数

  • 触发方式:通过 cachedContent API 预创建缓存,或在请求中自动触发
  • TTL:可配置,范围 60 秒到 1 小时
  • 最小缓存单元:4096 tokens
  • 计费:缓存存储按小时计费(与 input token 价格独立),缓存读取免费
  • 适用模型:Gemini 1.5 Flash、Gemini 1.5 Pro

适用场景:需要长期缓存(如系统提示数天不变)、对缓存成本可预测性要求高的场景。

关键区别:Gemini 的缓存存储成本是独立的,即使没有命中也会产生费用。适合缓存内容长期稳定的场景,不适合频繁变更的系统提示。

python
openai_auto_caching.py
from openai import OpenAI

client = OpenAI()

# 相同的 system prompt 会自动命中缓存
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "你是一个专业的技术顾问...(2000+ tokens)"},
        {"role": "user", "content": "分析这段代码..."}
    ]
)
python
gemini_caching.py
import google.generativeai as genai

client = genai.Client()

# 预创建缓存
cached_content = client.cached_contents.create(
    model="gemini-1.5-flash-001",
    system_instruction="你是一个专业的技术顾问...(2000+ tokens)",
    ttl="3600s"  # 1 小时
)

# 使用缓存
response = client.models.generate_content(
    model="gemini-1.5-flash-001",
    contents="分析这段代码...",
    cached_content=cached_content.name
)
Provider触发方式TTL最小缓存单元缓存写入成本缓存读取成本适用场景

Anthropic

显式 cache_control

5min / 1h

1024 tokens

基础价 × 1.25

基础价 × 0.1

复杂应用,需精细控制

OpenAI

自动

5-10min

1024 tokens

基础价

基础价 × 0.5

快速集成,简单前缀

Gemini

显式 API + 自动

60s - 1h

4096 tokens

存储费/小时

免费

长期稳定缓存

四、成本建模:计算你的 breakeven point

Prompt caching 不是免费的。缓存写入通常比直接 input 更贵,只有通过多次缓存读取才能摊薄成本。你需要计算 breakeven point(盈亏平衡点):缓存命中多少次才能回本。

通用公式

breakeven_hits = cache_write_cost / (cache_write_cost - cache_read_cost)

三大 Provider 的 breakeven 计算

Provider 缓存写入成本 缓存读取成本 Breakeven 次数 说明
Anthropic 基础价 × 1.25 基础价 × 0.1 2 次 第 2 次读取即开始盈利
OpenAI 基础价(自动) 基础价 × 0.5 2 次 第 2 次读取即开始盈利
Gemini 存储费/小时 免费 取决于使用频率 高频场景 1 次即回本

实际案例

假设系统提示 5000 tokens,使用 Claude Sonnet(基础 input 价格 $3/M tokens):

  • 不使用缓存:每次调用成本 = 5000 × $3/M = $0.015
  • 使用缓存
    • 首次写入成本 = 5000 × $3/M × 1.25 = $0.01875
    • 后续读取成本 = 5000 × $3/M × 0.1 = $0.0015
    • Breakeven = $0.01875 / ($0.01875 - $0.0015) ≈ 1.1 次

结论:只要系统提示被使用 2 次以上,prompt caching 就能降低成本。对于每天调用 1000 次的客服系统,成本可降低 80-90%。

图表加载中…
python
prompt_caching_roi.py
def calculate_roi(
    prompt_tokens: int,
    daily_calls: int,
    base_input_price: float,  # 每百万 token 价格
    cache_write_multiplier: float,  # 如 1.25
    cache_read_multiplier: float,   # 如 0.1
):
    """计算 prompt caching 的 ROI"""
    
    # 不使用缓存的日成本
    no_cache_cost = prompt_tokens * daily_calls * base_input_price / 1_000_000
    
    # 使用缓存的日成本
    cache_write_cost = prompt_tokens * base_input_price * cache_write_multiplier / 1_000_000
    cache_read_cost = prompt_tokens * base_input_price * cache_read_multiplier / 1_000_000
    
    # 首次写入 + 后续读取
    with_cache_cost = cache_write_cost + (daily_calls - 1) * cache_read_cost
    
    # 节省比例
    savings = (no_cache_cost - with_cache_cost) / no_cache_cost * 100
    
    return {
        "no_cache_daily_cost": no_cache_cost,
        "with_cache_daily_cost": with_cache_cost,
        "daily_savings": no_cache_cost - with_cache_cost,
        "savings_percentage": savings
    }

# 示例:客服系统,5000 token 系统提示,每天 1000 次调用
result = calculate_roi(
    prompt_tokens=5000,
    daily_calls=1000,
    base_input_price=3.0,  # Claude Sonnet
    cache_write_multiplier=1.25,
    cache_read_multiplier=0.1
)

print(f"日节省: {'$'}{result['daily_savings']:.2f} ({result['savings_percentage']:.1f}%)")
# 输出:日节省: $13.50 (90.0%)

五、生产部署:cache-friendly prompt 设计

Prompt caching 不是万能的。以下决策框架帮助你判断哪些工作负载适合缓存,如何设计 cache-friendly 的 prompt 结构,以及如何监控和优化。

步骤 1:识别适合缓存的工作负载

适合缓存的特征

  • 系统提示或工具定义重复使用(如客服、RAG、Agent)
  • 多轮对话中前缀稳定(如上下文窗口中的历史消息)
  • 调用频率高(每天 > 100 次)
  • Prompt 长度 > 1024 tokens(低于最小缓存单元无法生效)

不适合缓存的特征

  • 每次请求的 prompt 完全不同(如随机生成的创意写作提示)
  • 调用频率极低(如每天 < 10 次,缓存写入成本无法摊薄)
  • Prompt 长度 < 1024 tokens(无法触发缓存)
  • 需要强一致性的场景(如实时更新的系统提示,缓存可能导致版本不一致)

步骤 2:设计 cache-friendly 的 prompt 结构

核心原则:将不变的内容放在前缀,变化的内容放在后缀。

推荐结构:系统提示(稳定,缓存)→ 工具定义(稳定,缓存)→ 上下文/知识库(半稳定,可选缓存)→ 用户消息(变化,不缓存)。

反模式:用户消息(变化)→ 系统提示(稳定)。前缀变化导致缓存永远失效。

多断点策略(Anthropic 支持最多 4 个断点):如果你的 prompt 包含多个变化频率不同的部分,可以使用多个 cache_control 断点分别标记。

步骤 3:监控与优化

关键指标

  • 缓存命中率:cache_read_input_tokens / (cache_read + cache_creation)
  • 成本节省:对比启用缓存前后的 API 账单
  • 延迟改善:缓存命中时 TTFT(Time To First Token)通常降低 20-50%

优化策略

  • 命中率 < 50%:检查 prompt 结构,确保稳定前缀足够长
  • 命中率 > 90% 但成本仍高:考虑使用更便宜的模型处理缓存命中场景
  • TTL 频繁过期:增加 TTL(Anthropic 支持 1 小时)或提高调用频率
图表加载中…
python
multi_breakpoint_caching.py
# 多断点策略示例
system=[{
    "type": "text",
    "text": "核心系统提示...(1000 tokens)",
    "cache_control": {"type": "ephemeral", "ttl": "1h"}  # 断点 1:长期稳定
}]
tools=[{...}]  # 工具定义较少变化,可自动缓存
messages=[{
    "role": "user",
    "content": [{
        "type": "text",
        "text": "知识库内容...(5000 tokens,每日更新)",
        "cache_control": {"type": "ephemeral", "ttl": "5m"}  # 断点 2:短期缓存
    }]
}]
python
cache_monitoring.py
def track_cache_performance(responses: list):
    """追踪缓存命中率和成本节省"""
    total_cache_read = sum(r.usage.cache_read_input_tokens for r in responses)
    total_cache_write = sum(r.usage.cache_creation_input_tokens for r in responses)
    total_input = sum(r.usage.input_tokens for r in responses)
    
    hit_rate = total_cache_read / (total_cache_read + total_cache_write) if (total_cache_read + total_cache_write) > 0 else 0
    
    print(f"缓存命中率: {hit_rate:.1%}")
    print(f"缓存读取 tokens: {total_cache_read}")
    print(f"缓存写入 tokens: {total_cache_write}")
    print(f"未缓存 input tokens: {total_input}")
    
    # 估算成本节省(假设 Claude Sonnet,节省 90%)
    savings = total_cache_read * 0.9 * 3 / 1_000_000
    print(f"估算节省: {'$'}{savings:.2f}")

六、边界情况与常见陷阱

即使理解了机制,实际部署中仍会踩坑。以下是五个最常见的陷阱及其解决方案。

陷阱 1:缓存断点位置错误

错误做法:在变化的内容上标记 cache_control。前缀每次都不同,缓存永远无法命中。正确做法:在稳定前缀的末尾标记 cache_control。

陷阱 2:忽略最小缓存单元

如果 prompt 长度低于最小缓存单元(Anthropic 1024 tokens,Gemini 4096 tokens),cache_control 会被静默忽略,不会报错但也不会生效。验证方法:检查响应中的 cache_creation_input_tokens,如果为 0 说明未触发缓存。

陷阱 3:并发请求导致缓存未命中

首次请求的缓存只有在响应开始后才能被后续请求命中。如果多个请求同时发出,它们都会触发缓存写入,造成浪费。解决方案:串行化首次请求,或使用预热脚本提前触发缓存。

陷阱 4:TTL 过期导致成本激增

如果调用间隔超过 TTL,缓存会过期,下次调用需要重新写入。对于低频场景(如每小时 1 次),prompt caching 可能不划算。解决方案:选择支持长 TTL 的 Provider(如 Anthropic 的 1 小时),或提高调用频率。

陷阱 5:跨 Provider 缓存不互通

Anthropic 的缓存不能用于 OpenAI,反之亦然。如果你使用多个 Provider,需要分别配置缓存策略。

陷阱 6:Gemini 的存储成本陷阱

Gemini 的缓存存储是按小时计费的,即使没有命中也会产生费用。如果你创建了一个缓存但很少使用,存储成本可能超过节省的 input 成本。解决方案:只在缓存内容长期稳定且高频使用时才使用 Gemini 的 cachedContent API。

陷阱 7:缓存导致输出不一致

虽然 prompt caching 不会改变模型的输出质量,但如果你的系统提示频繁更新,缓存可能导致不同用户看到不同版本的系统提示(取决于缓存是否过期)。解决方案:对于需要强一致性的场景(如合规要求),禁用缓存或使用极短 TTL。

python
cache_warmup.py
# 预热脚本:在应用启动时触发缓存
import anthropic

client = anthropic.Anthropic()

# 首次请求:触发缓存写入
warmup = client.messages.create(
    model="claude-sonnet-4-5-20250514",
    max_tokens=1,
    system=[{
        "type": "text",
        "text": "你的系统提示...",
        "cache_control": {"type": "ephemeral"}
    }],
    messages=[{"role": "user", "content": "warmup"}]
)

print(f"缓存已写入: {warmup.usage.cache_creation_input_tokens} tokens")
# 后续请求即可命中缓存

💡 一句话理解

Prompt caching 的核心是'前缀稳定性'。如果你的 prompt 前缀经常变化,缓存永远无法命中。设计 prompt 时,先把不变的内容放在前面,再考虑缓存策略。

⚠️ 常见踩坑

不要假设 prompt caching 总是划算的。对于低频场景(每天 < 10 次)或短 prompt(< 1024 tokens),缓存写入成本可能超过节省的 input 成本。先用 breakeven 公式计算,再决定是否启用。

七、进阶:多 Provider 混合策略与检查清单

如果你的应用同时使用多个 Provider(如 Anthropic 处理复杂推理,OpenAI 处理简单任务),需要为每个 Provider 设计独立的缓存策略。

策略 1:按任务类型分配 Provider。复杂推理用 Anthropic(显式缓存,长 TTL,90% 折扣);简单补全用 OpenAI(自动缓存,零配置,50% 折扣)。

策略 2:按成本敏感度分配。成本敏感场景(高频客服)用 OpenAI 自动缓存;质量敏感场景(复杂推理)用 Anthropic 显式缓存。

策略 3:Gemini 作为长期缓存层。如果系统提示数天不变(企业级应用的角色定义),使用 Gemini 的 cachedContent API 预创建缓存,避免每次调用都支付写入成本。

关键洞察:多 Provider 混合策略的核心是"按场景优化",而不是"一刀切"。每个 Provider 的缓存机制不同,需要根据具体场景选择最合适的方案。

部署前检查清单

  • 稳定前缀长度 > 最小缓存单元(1024 tokens for Anthropic/OpenAI, 4096 for Gemini)
  • 调用频率 > breakeven point(通常 2 次以上)
  • cache_control 标记在稳定前缀末尾,而非变化内容
  • 并发请求已串行化首次调用,或使用预热脚本
  • TTL 设置与调用频率匹配(高频用短 TTL,低频用长 TTL)
  • 监控缓存命中率和成本节省
  • 跨 Provider 策略已独立配置

实际部署案例:某电商客服团队在启用 prompt caching 前后的对比数据。启用前,每月 API 账单 $4,200,其中系统提示(3,500 tokens)占输入成本的 68%。启用 Anthropic 显式缓存(1h TTL)后,系统提示部分成本降低 87%,整体账单降至 $1,950,月节省 $2,250。缓存命中率稳定在 94%,TTFT 从 1.8 秒降至 1.1 秒。关键成功因素:系统提示连续 6 个月未变更,客服调用频率高(每天 3,000+ 次),TTL 设置与调用间隔匹配(平均 2 分钟一次调用,远小于 1 小时 TTL)。该团队后续还将工具定义部分也加入了缓存断点,进一步将总成本降低了 12%。

失败案例:某初创公司尝试对创意写作应用启用 prompt caching。每次请求的 prompt 都不同(用户输入的故事开头千变万化),缓存命中率始终低于 5%。启用缓存后,由于每次都要支付 1.25 倍的写入成本但几乎没有读取命中,实际成本反而增加了 8%。教训:prompt caching 只适合前缀稳定的场景,对于高度动态的 prompt,应该考虑其他优化策略(如 prompt 压缩、模型降级或语义缓存)。

场景推荐 Provider缓存策略预期成本节省

高频客服(每天 > 1000 次)

Anthropic

显式缓存,1h TTL

80-90%

简单补全(每天 > 500 次)

OpenAI

自动缓存

40-50%

长期稳定系统提示

Gemini

cachedContent API

60-80%

低频复杂推理(每天 < 50 次)

Anthropic

显式缓存,5min TTL

10-30%

多轮对话 Agent

Anthropic

多断点缓存

70-85%

⚠️ 常见踩坑

常见误区:假设一个 Provider 的缓存配置能迁移到另一个(不能);假设自动缓存总是比显式缓存差(不一定,取决于场景);忽略 Gemini 的存储成本(可能导致成本激增)。最佳实践:为每个 Provider 独立设计缓存策略,监控每个 Provider 的缓存命中率和成本节省,定期评估是否需要调整 Provider 分配策略。

参考资料

本文的技术细节和数据来自以下官方文档:

三大 Provider 的定价信息可参考各自的官方定价页面。实际成本节省取决于你的具体工作负载、prompt 结构和调用频率,建议先用本文的 ROI 计算模板估算 breakeven point,再决定是否启用缓存。

延伸阅读prompt caching 是 LLM 成本优化的重要一环,但它不是孤立的。在实际生产中,它通常与以下策略组合使用:prompt 压缩(减少总 token 数)、模型路由(根据任务复杂度选择不同模型)、语义缓存(应用层缓存相似请求的结果)。这些策略在 token-economics 和 llm-034 中有详细讨论,建议结合阅读以构建完整的成本优化知识体系。

🎯 相关面试题

巩固本篇知识点,备战 AI 岗位面试。