claude cache 理解

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

claude 提示词缓存

Claude API 文档:提示缓存(Prompt Caching)

提示词缓存是一项强大的功能,它允许从提示词中的特定前缀继续处理,从而优化API的使用。这种方法能显著减少重复性任务或具有一致元素的提示词的处理时间和成本。

一、使用示例

以下是如何使用包含cache_control块的Messages API实现提示词缓存的示例:

第一次请求

curl https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
      },
      {
        "type": "text",
        "text": "<the entire contents of Pride and Prejudice>",
        "cache_control": {"type": "ephemeral"}
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "Analyze the major themes in Pride and Prejudice."
      }
    ]
  }'

第二次请求(和上面同样的请求)

curl https://api.anthropic.com/v1/messages

两次的输出结果token cache情况,可以看到第二次的 cache_read_input_tokens 值会变大

{"cache_creation_input_tokens":188086,"cache_read_input_tokens":0,"input_tokens":21,"output_tokens":393}
{"cache_creation_input_tokens":0,"cache_read_input_tokens":188086,"input_tokens":21,"output_tokens":393}

复用缓存的二次调用

当需要针对《傲慢与偏见》发起新的分析请求时,只需修改 messages 中的用户提问,无需重复传输全书文本,系统会自动复用缓存内容:

curl https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
      },
      {
        "type": "text",
        "text": "<the entire contents of Pride and Prejudice>",
        "cache_control": {"type": "ephemeral"}
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "Analyze the character of Elizabeth Bennet in Pride and Prejudice."
      }
    ]
  }'

二、工作原理

  1. 缓存检查:发送带缓存配置的请求时,系统会检查近期请求中是否存在匹配的提示前缀缓存(截止到 cache_control 标记的断点)。

  2. 缓存命中:若找到匹配缓存,直接复用已处理的前缀内容,减少计算量。

  3. 缓存写入:若未命中,系统会处理完整提示,并将前缀内容写入缓存,供后续请求使用。

缓存有效期规则

  • 默认有效期:5 分钟,每次命中缓存时会免费刷新有效期。

  • 付费延长有效期:支持配置为 1 小时有效期,需按更高费率计费,具体见"定价"章节。

1 小时缓存持续时间配置

1. 配置方法

cache_control 参数中添加 ttl_seconds: 3600,即可将缓存有效期延长至 1 小时:


{
  "type": "text",
  "text": "Your long-term static context here...",
  "cache_control": {
    "type": "ephemeral",
    "ttl_seconds": 3600
  }
}
2. 限制说明
  • 1 小时有效期为最佳努力的服务级别目标(SLO),不保证缓存一定存在 1 小时,可能因系统策略提前被清除。

  • 无法为已存在的缓存条目延长有效期,需重新提交内容以创建新的 1 小时缓存。

  • 不支持自定义缓存到期时间,仅支持 5 分钟(默认)和 1 小时两种时长。

3. 适用场景对比
缓存时长优势适用场景
5 分钟成本较低,适合高频短时间复用单次用户会话、短期批量任务、快速迭代测试
1 小时有效期更长,跨会话复用多用户共享固定上下文、长时间批处理作业、每日更新的静态内容

缓存范围说明

提示缓存的范围为按顺序排列的完整前缀,包含以下内容块(按优先级排序):

toolssystemmessages

缓存截止到并包含配置了 cache_control 参数的内容块。

自动前缀检查机制

系统会基于以下三个核心原则,自动查找最长匹配的缓存前缀:

  1. 缓存键累积性:缓存的哈希键由断点之前的所有内容块顺序生成,每个块的缓存依赖于前置内容的一致性。

  2. 向后顺序检查:从显式断点开始,反向遍历前置内容块,确保匹配最长的可用缓存。

  3. 20 块回顾窗口:系统最多检查断点前的 20 个内容块,超出范围的内容无法触发缓存命中。

"20块回看窗口"详细解析

"20块回看窗口"是 Claude 提示缓存机制中的一个重要概念,直接影响缓存命中效果。以下从核心概念、详细示例、关键要点及实用建议展开说明:

核心概念解释

什么是"块" (Block)?

  • 在 Claude API 中,每个独立的内容单元就是一个"块"

  • 例如:一条系统消息、一个工具定义、一条用户消息、一条助手回复

  • 每个 text 类型的content 通常被视为一个块

什么是"回看窗口" (Lookback Window)?

  • 系统在寻找缓存命中时,会从你设置的缓存断点开始,向前最多检查20个块

  • 如果在20个块内找到了匹配的缓存,就使用它

  • 如果检查了20个块还没找到匹配,就停止查找,认为没有缓存命中

详细示例说明
场景设定

假设你有一个对话历史,包含30个内容块:


[块1]  系统指令
[块2]  工具定义1
[块3]  工具定义2
...
[块25] 用户消息:"请分析文档A"
[块26]  助手回复:分析结果
[块27] 用户消息:"文档B有什么不同?"
[块28]  助手回复:对比分析
[块29] 用户消息:"再总结一下"
[块30]  助手回复:总结内容 + 你在这里设置了 `cache_control` 断点
情况1:理想情况(修改最近内容)

请求1(已处理):

  • 块1-30都处理完毕

  • 在块30设置了缓存断点,所以块1-30的完整前缀被缓存

请求2(发送新请求):


[块1-30] 完全不变(与请求1相同)
[块31]   新的用户消息:"还有别的观点吗?"

系统检查过程

  1. 从块30(你的缓存断点)开始向前检查

  2. 检查块30 → 匹配!(因为块1-29没变,块30的缓存键有效)

  3. 结果:缓存命中在块30,只需处理块31

  4. 节省:块1-30都不用重新处理

情况2:修改中间内容(在20块窗口内)

请求2(修改了块25):


[块1-24] 不变
[块25]   修改后的用户消息:"请深入分析文档A"
[块26-29] 不变(但这些回复可能已过时)
[块30]   不变
[块31]   新消息

系统检查过程

  1. 从块30开始向前检查

  2. 块30 → 不匹配!(因为块25变了,块30的缓存键是基于块1-29的哈希,现在失效了)

  3. 块29 → 不匹配!(依赖块1-28,块25变了)

  4. 块28 → 不匹配!(依赖块1-27,块25变了)

  5. …(持续向前检查)

  6. 块25 → 不匹配!(这是修改过的块)

  7. 块24 → 匹配!(块1-24没变)

  8. 结果:缓存命中在块24,需要重新处理块25-31

  9. 节省:块1-24不用重新处理

情况3:修改早期内容(超出20块窗口)

请求2(修改了块5):


[块1-4]  不变
[块5]    修改后的工具定义
[块6-29] 不变
[块30]   不变
[块31]   新消息

系统检查过程

  1. 从块30开始向前检查

  2. 块30 → 不匹配

  3. 块29 → 不匹配

  4. …(持续向前检查)

  5. 块11 → 检查了20次(块30到块11),停止!

  6. 结果:没有缓存命中,需要处理块1-31的所有内容

为什么?

  • 系统只检查了块30到块11(20个块)

  • 块5的修改超出了这个20块的"回看窗口"

  • 即使块1-4没变,系统也检查不到

关键要点
1. 缓存键的累积性

每个块的缓存键都是基于之前所有块的内容计算出来的哈希值。所以:

  • 修改块5会导致块6-30的所有缓存键都失效

  • 这就是为什么系统需要从后往前检查

2. 20块限制的原因
  • 性能权衡:检查所有历史块(可能上百个)会很慢

  • 实用考量:大多数修改发生在对话的最近部分

  • 平衡点:20块覆盖了典型的近期对话历史

3. 解决超出窗口的问题

如果你知道早期内容可能会修改,应该在关键位置设置多个缓存断点:


// 在可能修改的内容后面设置断点
{
  "type": "text",
  "text": "工具定义内容...",
  "cache_control": {"type": "ephemeral"}  // 第一个断点
},
{
  "type": "text", 
  "text": "系统指令...",
  "cache_control": {"type": "ephemeral"}  // 第二个断点
},
// ... 其他内容
{
  "type": "text",
  "text": "最近的用户消息...",
  "cache_control": {"type": "ephemeral"}  // 第三个断点
}
实用建议
  1. 最少一个断点:总是在对话末尾设置一个缓存断点

  2. 关键位置加断点:在可能独立修改的内容后面加断点

  • 工具定义后面
  • 系统指令后面
  • 大的上下文文档后面
  1. 组织内容:把最稳定、最少修改的内容放在最前面

  2. 监控命中率:通过API响应查看缓存命中情况,调整断点位置

设计逻辑

这个设计基于一个观察:在真实使用中:

  • 70-80%的修改发生在最后10条消息内

  • 工具定义和系统指令相对稳定

  • 用户查询和最新对话变化最频繁

20块的窗口覆盖了大多数常见场景,同时在性能和缓存效果之间取得了平衡。如果有经常修改早期内容的使用场景,建议使用多个缓存断点来"分段"缓存提示内容。

混合不同的生存时间

你可以在同一个请求中同时使用1小时和5分钟的缓存控制,但有一个重要限制:具有较长TTL的缓存条目必须出现在较短TTL的缓存条目之前(即,1小时的缓存条目必须出现在任何5分钟的缓存条目之前)。

混合TTL时,我们会在您的提示词中确定三个计费位置:

  1. 位置A:最高缓存命中处的token计数(如果没有命中,则为0)。
  2. 位置B:在A之后最高1小时cache_control块处的token计数(如果不存在,则等于A)。
  3. 位置C:最后一个cache_control块的token计数。

您将被收取以下费用:

为A缓存读取token。

  1. (B - A)的1小时缓存写入token。
  2. (C - B)的5分钟缓存写入token。
  3. 以下是3个示例。这展示了3个请求的输入标记,每个请求都有不同的缓存命中和缓存未命中情况。因此,每个请求在彩色框中显示的计算价格也不同。

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=claude%20cache%E3%80%90%E7%94%9F%E5%AD%98%E6%97%B6%E9%97%B4%E6%B7%B7%E5%90%88%E7%A4%BA%E4%BE%8B%E3%80%91.png&pos_id=img-todMPKSs-1770024033244

三、技术分析

1. 核心原理

提示词缓存的节省并非来自“推理token”的减少,而是来自预处理阶段的优化。大语言模型完整工作流程如下:


输入文本 → Tokenization(分词) → KV Cache计算(最耗时) → 注意力机制 → 生成输出

缓存通过跳过重复的KV Cache计算环节,实现性能提升与成本节省。

2. 核心技术:KV Cache(键值缓存)

KV Cache是提示词缓存的核心,缓存的是输入token经过计算后的Key(键)和Value(值)向量,而非原始文本。

2.1 模拟实现流程
# 伪代码
def process_prompt(tokens):
    kv_cache = []
    
    # 对每个token计算键值对(这一步最耗时)
    for token in tokens:
        key = compute_key(token)      # 矩阵运算
        value = compute_value(token)  # 矩阵运算
        kv_cache.append((key, value))
    
    return kv_cache  # 这就是被缓存的内容
2.2 有无缓存对比

未使用缓存:
文本输入 → Tokenization → KV计算(10,000 tokens × 多层) → 推理
                         ↑ 这一步非常耗时

使用缓存:
文本输入 → 直接读取已计算好的KV Cache → 推理
          ↑ 跳过了重复计算
2.3 未缓存与启用缓存的处理流程

未缓存时的处理流程:


输入: [token1, token2, token3, ..., token_n]
处理: 每个token都要重新计算它与其他所有token的注意力
      - token1: 计算K1, V1
      - token2: 计算K2, V2, 并与K1, V1交互
      - token3: 计算K3, V3, 并与K1, K2, V1, V2交互
      ... 依此类推
复杂度: O(n²) 的注意力计算

启用缓存后的处理流程:


第一次请求(缓存写入):
输入: [token1, token2, token3, ..., token_m, ...]
处理: 
    - 计算token1-m的K1-m, V1-m并存储到缓存
    - 生成响应

第二次请求(缓存命中):
输入: [相同的token1-m] + [新token_m+1...]
处理:
    - 直接从缓存读取K1-m, V1-m (几乎零计算)
    - 只计算新token_m+1...的K,V
    - 注意力计算时,新token与缓存的K1-m, V1-m交互
复杂度: 只对新token进行O(n)计算

四、定价机制

提示缓存针对不同操作(写入、读取)和缓存时长,设置了差异化的定价标准,核心定价逻辑为基于基础输入token价格的乘数计算。

1. 定价乘数规则

操作类型定价乘数说明
5 分钟缓存写入1.25×基础输入价格首次写入缓存时的计费标准
1 小时缓存写入2×基础输入价格延长缓存有效期的计费标准
缓存命中与刷新0.1×基础输入价格复用缓存内容时的计费标准
基础输入1×基础输入价格未缓存内容的常规计费标准
输出token独立定价生成结果的计费标准,与缓存无关

2. 各模型详细定价表(每百万token)

模型基础输入token5分钟缓存写入1小时缓存写入缓存命中与刷新输出token
Claude Opus 4.5$5$6.25$10$0.50$25
Claude Opus 4.1$15$18.75$30$1.50$75
Claude Opus 4$15$18.75$30$1.50$75
Claude Sonnet 4.5$3$3.75$6$0.30$15
Claude Sonnet 4$3$3.75$6$0.30$15
Claude Sonnet 3.7$3$3.75$6$0.30$15
Claude Haiku 4.5$1$1.25$2$0.10$5
Claude Haiku 3.5$0.80$1$1.6$0.08$4
Claude Opus 3$15$18.75$30$1.50$75
Claude Haiku 3$0.25$0.30$0.50$0.03$1.25

五、实现指南

1. 支持的模型

提示缓存功能支持以下 Claude 模型:

  • Claude Opus 系列:4.5 / 4.1 / 4 / 3

  • Claude Sonnet 系列:4.5 / 4 / 3.7

  • Claude Haiku 系列:4.5 / 3.5 / 3

2. 提示构建规范

  • 静态内容前置:将工具定义、系统指令、固定上下文、示例等不随请求变化的内容放在提示开头。

  • 标记缓存断点:在可重用内容的末尾块配置 cache_control 参数,标记缓存截止位置。

  • 可变内容后置:将用户查询、动态参数等随请求变化的内容放在缓存断点之后。

3. 缓存限制

(1)最小缓存长度限制

只有当缓存内容的token数超过模型阈值时,缓存才会生效,各模型阈值如下:

模型类别最小缓存token长度
Claude Opus 4.5 / Haiku 4.54096 token
Claude Opus 4.1/4 / Sonnet 全系列1024 token
Claude Haiku 3.5 / 32048 token
(2)其他限制
  • 并发请求时,缓存条目仅在第一个请求响应开始后才可用,并行请求需等待首个请求完成以确保缓存命中。

  • 目前仅支持 ephemeral 类型的缓存,无持久化缓存选项。

4. 缓存成本说明

缓存断点无额外成本:添加多个断点不会增加费用,仅根据实际缓存的内容量计费。

  1. 缓存写入:当新内容写入缓存时(对于5分钟的生存时间,比基础输入token多25%)
  2. 缓存读取:使用缓存内容时(基础输入token价格的10%)
  3. 常规输入token:用于任何未缓存的内容

六、缓存性能跟踪

1. 响应 usage 字段解析

API 响应中的usage 字段会返回缓存相关的token使用数据,用于分析缓存效果:


{
  "cache_creation_input_tokens": 188086, // 本次写入缓存的token数
  "cache_read_input_tokens": 0,          // 本次读取缓存的token数
  "input_tokens": 21,                    // 本次未缓存的基础输入token数
  "output_tokens": 393                   // 本次生成的输出token数
}

2. 缓存计数规则

  • 缓存写入计数:仅当缓存内容达到模型最小长度阈值,且为新缓存条目时,才会统计写入token数。

  • 缓存读取计数:缓存命中时,匹配的前缀内容token数按读取规则统计。

  • 基础输入计数:断点后的动态内容,或缓存未命中时的全部内容,按基础输入规则统计。

七、最佳实践与故障排除

最佳实践

  • 最大化缓存前缀长度:将尽可能多的静态内容纳入缓存范围,减少重复处理。

  • 严格区分动静内容:确保缓存断点前无动态内容,避免因微小变化导致缓存失效。

  • 按需配置多断点:仅在内容更新频率差异较大时使用多断点,避免过度分段。

  • 并行请求等待缓存写入:并发场景下,先发送一个请求完成缓存写入,再发起后续请求以确保命中。

  • 结合业务周期选择缓存时长:短期任务用 5 分钟缓存,跨时段任务用 1 小时缓存。

场景进行优化

  • 对话智能体:降低长时间对话的成本和延迟,尤其是那些包含冗长指令或上传文档的对话。
  • 代码助手:通过在提示词中保留代码库的相关部分或摘要版本,来改进自动补全和代码库问答功能。
  • 大型文档处理:在提示词中纳入包含图像的完整长格式材料,且不会增加响应延迟。
  • 详细的指令集:分享大量的指令、步骤和示例,以微调Claude的响应。开发者通常会在提示词中包含一两个示例,但借助提示词缓存,通过包含20个以上不同的高质量答案示例,你可以获得更好的性能。
  • 智能体工具使用:在涉及多次工具调用和迭代代码更改的场景中提升性能,这些场景中每一步通常都需要新的API调用。
  • 与书籍、论文、文档、播客文字稿以及其他长篇内容对话:通过将整个文档嵌入提示词,让任何知识库“活”起来,让用户可以向它提问。

常见陷阱

  • 过早缓存:对尚未定稿的静态内容设置缓存,后续修改会导致缓存失效。

  • 过度分段:多数场景下单个断点即可满足需求,多断点会增加配置复杂度。

  • 忽略最小长度限制:未达到模型阈值的内容无法缓存,需提前评估token数。

  • 依赖缓存可靠性:缓存是优化手段而非可靠存储,不可作为数据持久化方案。

故障排除

问题现象排查方向
缓存未生效1. 检查 cache_control 参数格式是否正确2. 验证缓存内容是否达到模型最小token长度3. 确认使用的模型在支持列表中4. 查看响应 usage 字段,确认无 cache_creation_input_tokenscache_read_input_tokens
缓存命中率低1. 检查请求之间的静态内容是否完全一致2. 确认断点位置是否合理,是否包含了变化的内容3. 排查是否因超过 20 块回顾窗口导致匹配失败4. 确认请求间隔是否超过缓存有效期
性能未改善1. 缓存优化效果体现在后续请求,首次请求仍需全量处理2. 短提示的缓存收益有限,适合长静态内容场景3. 检查是否每次请求都修改了缓存前缀内容

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值