← Kairos Notes

Claude's Fermata

延长记号 — Prompt Caching 命中教程
Fermata 是音乐中的延长记号,表示将一个音符保持更长时间。
就像缓存把昂贵的计算结果“延长”住,不需要每次重新计算。

什么是 Prompt Caching

每次调用 Claude API,Anthropic 服务器都需要“读”一遍你发过去的全部内容(system prompt + 对话历史)。内容越长,花的钱越多。

Prompt Caching 是 Anthropic 提供的服务端缓存机制:把你请求中不变的前缀部分缓存起来,下次请求只要前缀一样,就直接复用,不用重新计算。

无缓存:每次全部计算 $$$$
→
有缓存:首次写入,后续复用 $

关键概念

概念说明
cache_control标记缓存断点的字段,告诉 Anthropic “到这里为止可以缓存”
cache_creation_input_tokens本次请求新建了多少 token 的缓存
cache_read_input_tokens本次请求复用了多少 token 的缓存
TTL缓存存活时间,默认 5 分钟,可延长到 1 小时

最低 Token 门槛

模型最低缓存 Token 数
Claude Opus 41,024
Claude Sonnet 41,024
Claude Haiku 3.52,048
你的 system prompt + 对话前缀必须超过这个数,缓存才会生效。

缓存断点怎么放

缓存断点通过 cache_control 字段标记。你可以在 system prompt 或 messages 中的任意内容块上加这个字段。

基本用法

{
  "model": "claude-opus-4-6",
  "system": [{
    "type": "text",
    "text": "你是一个助手。以下是你需要遵循的规则...",
    "cache_control": { "type": "ephemeral" }
  }],
  "messages": [{ "role": "user", "content": "你好" }]
}

启用 1 小时 TTL

默认缓存只活 5 分钟。要延长到 1 小时:

第一步:请求头加入 beta 标记:

anthropic-beta: extended-cache-ttl-2025-04-11

第二步:在 cache_control 中指定 TTL:

"cache_control": { "type": "ephemeral", "ttl": "1h" }
注意:ttl: "1h" 的断点必须放在 ttl: "5m"(或不指定 TTL)的断点前面。顺序反了 API 会报错。

多断点策略(实战架构)

以下是经过生产验证的四断点架构:

BP1 · 核心协议 / 人设 [system层,ttl=1h]
角色设定、行为规则、输出格式等。几乎不变,命中率最高。
BP2 · 碎片记忆 [system层,ttl=1h]
从记忆系统提取的常驻知识碎片。偶尔变化,变化时整个 BP2 重写。
BP3 · 滚动摘要 [system层,ttl=1h]
历史对话的压缩摘要。对话超长时触发更新。
BP4 · 倒数第二条消息 [messages层,ttl=1h]
最近的 assistant 回复。让整段对话历史都被缓存。
易变区 · 不缓存
最后一条 user 消息 + 向量召回结果 + 外部回复 + 时间戳。每轮都变,放在缓存前缀之后。

易变内容放置位置

易变内容放置位置原因
向量召回结果最后一条 user 消息末尾每轮召回内容不同
外部系统回复最后一条 user 消息末尾实时变化
当前时间戳最后一条 user 消息末尾每秒都在变
前缀越长越稳定,省的钱越多。

缓存级联

缓存级联(Cache Cascading)是缓存的高级形态,也是省钱的关键。每一轮对话,缓存都在上一轮的基础上“接力”。

完美级联的数字特征

轮次cache_readcache_writetotal
1042,92942,929
242,9291,67544,604
344,6043,23347,837

每一轮的 cache_read 精确等于上一轮的 total(read + write),说明之前的所有内容都被完整复用。这就是完美级联。

级联断裂

如果中转站修改了请求体的任何部分(哪怕改一个字),缓存 key 就对不上,级联断裂:

轮次cache_readcache_write状态
1042,929写入
2044,604全部重写!
3047,837继续重写!
级联断裂意味着每一轮都在付全价写入缓存,完全失去了缓存的意义。

中转站缓存表现对比

核心区别在于是否透传请求体:

透传型:请求原封不动 → Anthropic
转换型:请求被修改 → 中间层 → Anthropic
类型级联表现原因
Anthropic 官方直连完美级联无中间层
透传型中转站完美级联请求体原封不动
CF AI Gateway完美级联透传代理
OpenRouter级联断裂重写 model 名、加前缀
compat 兼容端点级联断裂格式互转破坏 cache_control
关键判断标准:中转站有没有动过你的请求体。任何修改都会导致缓存 key 变掉。

Cloudflare AI Gateway 接入

CF AI Gateway 是一个透明代理,支持完美级联缓存。

你的应用
→
CF AI Gateway
→
Anthropic API

步骤

1. 注册 Cloudflare 账号

2. 创建 AI Gateway(菜单 AI > AI Gateway > Create)

3. 获取 CFUT Token(Unified Billing,Cloudflare 代付,5% 手续费)

4. 发起请求:

直连 AnthropicCF Gateway (CFUT)
认证头x-api-key: sk-ant-xxxcf-aig-authorization: Bearer cfut_xxx
端点api.anthropic.com/v1/messagesgateway.ai.cloudflare.com/.../anthropic/v1/messages

代码适配(Node.js)

function buildAuthHeaders(apiKey) {
  if (apiKey && apiKey.startsWith('cfut_')) {
    return { 'cf-aig-authorization': 'Bearer ' + apiKey };
  }
  return { 'x-api-key': apiKey };
}

注意事项

1. 必须用原生 Anthropic 端点(/anthropic/v1/messages),不能用 compat 端点
2. CFUT 不支持 /v1/models,需手动填写模型名
3. 模型名用 Anthropic 官方名
4. 代码中检测 cfut_ 前缀并切换认证头

验证缓存是否命中

每次 API 响应的 usage 字段中包含缓存信息:

{
  "usage": {
    "input_tokens": 8,
    "output_tokens": 150,
    "cache_creation_input_tokens": 42929,
    "cache_read_input_tokens": 0
  }
}
字段含义
cache_creation > 0有新内容被写入缓存(首次或新增部分)
cache_read > 0有内容从缓存中读取(省钱了!)
两者都为 0缓存没有生效

完美级联的判断方法

连续几轮对话,如果每一轮的 cache_read 都等于上一轮的 cache_read + cache_creation,恭喜你,完美级联。

1 小时 TTL 验证

发一个请求 → 等 6 分钟 → 发相同请求 → 如果 cache_read > 0,说明 1h TTL 生效了。

省钱计算

缓存定价(Claude Opus 4)

类型每百万 token相比原价
普通输入(无缓存)$15.00基准价
缓存写入$18.75贵 25%
缓存读取$1.50便宜 90%

什么时候划算?

对同一个前缀发起 2 次以上请求就开始省钱:

无缓存 2 次:  $15.00 x 2 = $30.00
有缓存 2 次:  $18.75 + $1.50 = $20.25  (省 32.5%)

无缓存 10 次: $15.00 x 10 = $150.00
有缓存 10 次: $18.75 + $1.50 x 9 = $32.25  (省 78.5%)
对于聊天场景,1h TTL 几乎是必须的 — 谁会每 5 分钟都不间断地发消息呢?

FAQ

Q:CF Gateway 的 response cache 和 Anthropic 的 prompt cache 是一回事吗?

不是,完全是两个独立的机制。Anthropic prompt cache 缓存推理中间状态(KV cache),相同前缀就能命中;CF response cache 缓存完整响应,只有完全相同的请求才命中。对聊天场景,有用的是 prompt cache。

Q:为什么 OpenRouter 的缓存级联会断?

OpenRouter 大概率修改了请求体(重写 model 名、加前缀、格式转换),任何修改都会让缓存 key 不匹配。

Q:我用的中转站能不能完美级联?

看中转站是否透传 Anthropic 原生格式。简单判断:请求格式是 /v1/messages,且中转站声称“直连 key”,大概率支持。拿不准就看 usage 数据验证。