拆.
协议与适配——AI 怎么对接不同 LLM · 第 08

Prompt Caching 三种姿态

cache_control vs prompt_cache_key vs 无

4500读完约 23 分钟craft:B+发布于 2026-06-21

一、原理:prompt 缓存为什么是核心成本优化

我们前面多次提到 prompt caching——Anthropic 的 cache_control 能省 90% input cost。这一章我们专门讲 prompt caching——它是长 session AI 产品最重要的 cost 优化

为什么这么重要?因为 AI Agent 的 prompt 结构有个天然规律——大部分内容重复使用

每次 turn 的 prompt 包含:

  • system prompt(5 张脸 + AGENTS.md + 工具描述)—— ~10K tokens,几乎不变
  • messages 历史 —— 累积增长
  • 用户最新输入 ——

如果有 50 turns 的 session——system prompt 那 10K 被发送了 50 次。每次都付全价 input cost——重复消费。

这是个巨大的浪费。同样的内容为什么要重复付钱?

prompt caching 解决这个问题——LLM provider 在服务端缓存常见的 prompt 前缀。第二次见到同样前缀——只付 read cost(10% normal)而不是 full cost。

这听起来理想——但实现方式各家不同。我们看 3 种姿态。

姿态 1:Anthropic 的显式 cache_control

Anthropic 的方式——用户显式标记哪些段可以缓存:

{
  "system": [
    {
      "type": "text",
      "text": "...big stable content...",
      "cache_control": {"type": "ephemeral"}
    },
    {
      "type": "text",
      "text": "...changing content..."
    }
  ]
}

用户标记后——Anthropic 服务端做哈希、存缓存、5 分钟内同样内容命中 0.1x 价格。

优点

  • 用户可控——你知道哪部分缓存了、能预测命中率
  • 高效——精准标记减少 cache miss
  • 折扣大——0.1x normal(节省 90%)

缺点

  • 用户要主动设计 prompt 结构("哪些放前面让缓存覆盖")
  • 写 cache_write 时付 1.25x normal——首次写入贵
  • TTL 5 分钟——长间隔 session 缓存失效

姿态 2:OpenAI 的隐式 prompt_cache_key

OpenAI 的方式——服务端自动识别重复 prompt:

API 不需要任何特殊字段——只要你的 prompt 前缀跟上次请求一样——服务端自动命中缓存。

但你可以选择性传一个 prompt_cache_key header(参考最新 OpenAI 文档)——这是个字符串 hint让 OpenAI 优先在同 key 的请求间共享缓存。

X-Prompt-Cache-Key: my-system-v1

优点

  • 零配置——大多数情况自动 work
  • 不需要改 prompt 结构

缺点

  • 不可控——你不知道哪部分缓存了
  • 命中率不预测——服务端算法决定
  • 折扣较小——50% 折扣(vs Anthropic 90%)
  • prompt_cache_key 是 hint 不是 guarantee

姿态 3:Bedrock / 大部分小 provider 的"无 caching"

很多 provider 完全不支持 caching:

  • Bedrock 上的 Claude(早期)—— 不支持 cache_control
  • Cerebras / Cloudflare AI —— 不支持
  • xAI —— 不支持

这些 provider 上每次请求都付全价——长 session 成本飙升。

把这 3 种姿态合起来——prompt caching 的支持度极不均匀:

  • Anthropic:完整支持(cache_control 显式)
  • OpenAI:部分支持(自动 + 可选 hint)
  • Gemini:单独 API(cachedContent,独立工作流)
  • Bedrock / Azure:取决于具体 model 和 region
  • 其他 provider:基本不支持

你的 AI 产品的 cost 优化能做到什么程度——很大程度上取决于你选哪个 provider。

我们看 opencode 怎么处理这 3 种姿态。

二、案例:opencode 怎么处理三种缓存机制

opencode 的 caching 策略因 provider 而异

Anthropic:精心设计 cache_control 位置

我们在 6.1 章看过 opencode 的 Anthropic request body——system 数组分 3 段,其中 1-2 段标 cache_control:

{
  "system": [
    {
      "type": "text",
      "text": "[5 张脸 + 工具描述 + AGENTS.md]",
      "cache_control": {"type": "ephemeral"}
    },
    {
      "type": "text",
      "text": "[环境信息每次都变]"
    }
  ]
}

第一段稳定不变——缓存覆盖它和它之前的所有内容(包括 tools 数组)。

第二段每次变——不缓存。

这种精心设计让缓存命中率最大化。R8 阶段的研究告诉我们——opencode 在 Claude 上的命中率能到 60-70%,长 session 上更高。

OpenAI:依赖自动 caching

OpenAI 上 opencode 不做特殊处理——它知道 OpenAI 服务端会自动 cache 重复部分。

但 opencode 会保持 prompt 结构稳定——稳定 system prompt + 稳定 tools 数组——让 OpenAI 的自动 caching 算法更容易识别。

这是个间接优化——不需要 explicit API,但 prompt 设计要配合。

Bedrock:不优化

Bedrock 上 opencode 不发 cache_control(Bedrock 大多数 model 不识别)——接受全价。

Bedrock 用户付出的额外成本是用 AWS 合规便利的代价——opencode 没法补偿这个差异。

caching 的产品判断

opencode 在 caching 上的判断有几个细节:

判断 1:自动 cache_control 标记(不让用户配置)

opencode 不让用户手动设置 cache_control——而是adapter 自动决定哪些段标记。

为什么不让用户控制?因为 caching 是个专业话题——大多数用户不懂。让 adapter 用最佳实践默认标记——比让用户瞎配置好。

判断 2:tools 数组也缓存

opencode 把 cache_control 标在 tools 数组最后一个 tool 上——这样整个 tools 数组都被缓存(cache 从这个点往前覆盖)。

15 个工具的描述 3-5K tokens——缓存后省一大笔。

判断 3:5 分钟 TTL 接受失效

opencode 不做 "heartbeat 保活"(每 4 分钟发个小请求保 cache 不过期)——它接受 TTL 失效。

理由:保活有成本(每个请求都付钱)——比让 cache 自然过期后偶尔 cache_write 更贵。

权衡后选择"让 cache 自然管理"。

判断 4:cost UI 显示 cache 数据

opencode UI 上展示 cost 分项——让用户看到"cache_read 占了多少、省了多少":

Input: $0.012 (100 tokens × $3/M, non-cached)
Cache hit: $0.0036 (12,000 tokens × $0.3/M)
Output: $0.030 (200 tokens × $15/M)
Total: $0.046

[Note: cache_read 折扣 90%, saved $0.0324 this turn]

让用户感受到 caching 的价值——也让他们知道 opencode 在优化 cost。

判断 5:跨 provider 价值传递不均

opencode 在 Anthropic 上的 cost 优化能做到 60-90% 节省。

opencode 在 OpenAI 上 50% 左右节省(自动 caching,但折扣率低)。

opencode 在 Bedrock 上几乎 0% 节省(不支持)。

这种不均是 provider 自身能力决定的——opencode 没法弥补。但 opencode 会在 UI 上让用户感知到——"如果你用 Anthropic 替代 Bedrock,能省 X 钱"。

这是个有意思的产品姿态——既支持 Bedrock 又告诉用户"Bedrock 不是最佳选择"。诚实优于 marketing。

三、设计启示:缓存策略对长 session 的影响

这一章的核心论点:Prompt caching 是 LLM AI 产品最重要的 cost 优化——必须利用、必须设计对

如果你做 AI 产品考虑 caching,下面几条原则有用:

1. 默认用 Anthropic caching

如果你能用 Anthropic——cache_control 是 90% 折扣的杀手锏。

不要错过这个——10x cost 差异是巨大的。

2. prompt 结构为 caching 设计

caching 要求 prompt 前缀稳定——稳定部分在前、变化部分在后。

设计你的 system prompt 拼装链时——考虑哪些是稳定、放哪里。

opencode 的"5 张脸 + AGENTS.md + 工具描述" 在前、"环境信息" 在后——是为 caching 优化。

3. tools 数组也要缓存

15 个工具描述加起来 3-5K tokens——别忘了缓存它们。

cache_control 标在 tools 最后一个——覆盖整个 tools 数组。

4. 自动标记,不让用户配置

caching 是专业话题——用户不该手动配 cache_control。

让你的 adapter 用最佳实践默认标记——用户无感知地享受优化。

5. 监控 cache hit rate

每次响应 usage 告诉你 cache_read 多少——能算命中率。

监控你的产品平均命中率:

  • 60-70% 是合理范围
  • < 30% 说明 prompt 设计有问题(变化部分太多/位置太前)
  • 80% 说明可能 prompt 太死板(不够 dynamic)

6. UI 显示 cache savings

让用户看到 "this session saved $X via caching"——增加产品价值感知。

也作为差异化——"我们的产品比同类省钱"。

7. 跨 provider 时 caching 能力差异巨大

不要假设"换 provider 不影响 cost"——caching 差异让 cost 跨 provider 差几倍。

让用户在选 provider 时知道这个——避免他们以为"模型类似所以 cost 类似"。

8. 5 分钟 TTL 设计应对

如果你的产品的 session 经常间隔超过 5 分钟——Anthropic cache 失效——cost 飙升。

应对方案:

  • 接受失效(简单)
  • heartbeat 保活(成本高)
  • 在 UI 上提示用户"session 间隔长会增加 cost"

opencode 选择"接受失效"——简单可靠。

第 6 篇小结

第 6 篇我们看了 10 个 LLM provider 协议的 8 章。核心论点贯穿全篇:

LLM API 协议是 AI 产品的物理底层——10 个 provider 各有自己的真实差异

围绕这个论点:

  1. LLM API 结构(6.1)—— 所有 provider 的最小公分母
  2. Anthropic reference 实现(6.2)—— 最丰富的协议
  3. OpenAI 最小公分母(6.3)—— 简洁但能力受限
  4. Gemini 的 quirks(6.4)—— schema sanitize 150 行
  5. Bedrock 二进制协议(6.5)—— AWS 传统的代价
  6. 10 个 adapter 对照(6.6)—— 选 provider 的多维决策
  7. Token 算账(6.7)—— 4 种 usage 字段语义
  8. Prompt caching 3 种姿态(6.8)—— cost 优化最重要的杠杆

这些机制有共同的产品哲学

  • 协议是核心资产——adapter 层是 AI 产品的真实差异化
  • 借鉴而非自创——OpenAI Chat 是事实标准、其他 provider 跟随
  • 接受现实——不是所有 provider 都好——但用户选谁不由你决定

读完第 6 篇你应该有了 AI Agent 的"协议模型"——理解 LLM API 怎么工作、各 provider 真实差异、选择和优化策略。

接下来第 7 篇我们看 AI 产品的安全与权限——AI 能动手做事意味着 AI 也能做错事,怎么管控?