文档

Claude 上下文缓存使用指南

通过 Claude Messages API 或 OpenAI 兼容的 Chat Completions API 缓存重复使用的提示词前缀,减少重复处理长内容产生的 token 成本。

通过 Claude Messages API 或 OpenAI 兼容的 Chat Completions API 缓存重复使用的提示词前缀,减少重复处理长内容产生的 token 成本。

Claude 上下文缓存(Context Cache)适合重复使用系统提示、文档、代码库或对话历史等长前缀。为稳定前缀添加 cache_control 后,首次请求创建缓存,后续请求可以读取未过期的缓存。

使用前请设置 API 密钥:

export API_KEY="你的 API 密钥"
注意
本文示例使用 `claude-sonnet-5`。其他模型是否支持上下文缓存,请以平台中的模型说明为准。

适用场景

当多个请求会重复携带相同的大段内容时,可以缓存稳定前缀,例如:

  • 长 system prompt
  • 固定的知识库或产品文档
  • 多轮对话中保持不变的历史消息
  • 重复使用的代码库、工具定义和说明

上下文缓存适合“前面的内容保持不变,最后的问题持续变化”的请求。

Claude Messages API

5 分钟缓存

在需要缓存的内容块上添加 cache_control

curl "https://api.openveer.com/v1/messages" \
  -H "x-api-key: $API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "这里放需要重复使用的长前缀……",
        "cache_control": {
          "type": "ephemeral"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "请根据上面的内容回答问题。"
      }
    ]
  }'
警告
`system` 必须写成内容块数组。字符串形式的 `system` 无法添加 `cache_control`。

省略 ttl 时,缓存有效期默认为 5 分钟。

1 小时缓存

使用 1 小时缓存时,需要同时添加 anthropic-beta 请求头,并将 ttl 设置为 1h

curl "https://api.openveer.com/v1/messages" \
  -H "x-api-key: $API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: extended-cache-ttl-2025-04-11" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "这里放需要重复使用的长前缀……",
        "cache_control": {
          "type": "ephemeral",
          "ttl": "1h"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "请根据上面的内容回答问题。"
      }
    ]
  }'

支持的 TTL:

TTL 含义
5m 缓存 5 分钟;省略 ttl 时使用此值
1h 缓存 1 小时;需要同时添加对应的 anthropic-beta 请求头

响应用量字段

Claude Messages API 会在 usage 中分别返回普通输入、缓存写入和缓存读取 token:

{
  "usage": {
    "input_tokens": 23,
    "cache_creation_input_tokens": 2619,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_5m_input_tokens": 2619,
      "ephemeral_1h_input_tokens": 0
    },
    "output_tokens": 24
  }
}

总输入 token 的计算方式为:

input_tokens
+ cache_creation_input_tokens
+ cache_read_input_tokens

这三项互不重叠。第一次请求通常会出现 cache_creation_input_tokens > 0;再次发送相同稳定前缀时,应看到 cache_read_input_tokens > 0

OpenAI 兼容 API

请求示例

通过 /v1/chat/completions 使用缓存时,cache_control 的写法与 Claude Messages API 类似:

curl "https://api.openveer.com/v1/chat/completions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "system",
        "content": [
          {
            "type": "text",
            "text": "这里放需要重复使用的长前缀……",
            "cache_control": {
              "type": "ephemeral"
            }
          }
        ]
      },
      {
        "role": "user",
        "content": "请根据上面的内容回答问题。"
      }
    ]
  }'

1 小时缓存

OpenAI 兼容格式同样支持 1 小时缓存。只需在请求中增加 anthropic-beta 请求头,并在 cache_control 中设置 ttl: "1h"

-H "anthropic-beta: extended-cache-ttl-2025-04-11"
"cache_control": {
  "type": "ephemeral",
  "ttl": "1h"
}

content 必须使用数组

在 OpenAI 兼容格式中,cache_control 必须放在具体的内容块内,不能挂在字符串形式的消息上。

{
  "role": "system",
  "content": "这里放长前缀……",
  "cache_control": {
    "type": "ephemeral"
  }
}

上面的写法不会启用缓存,而且请求不会因此报错。正确写法如下:

{
  "role": "system",
  "content": [
    {
      "type": "text",
      "text": "这里放长前缀……",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ]
}
警告
如果 `content` 使用字符串,缓存标记会被忽略,输入内容仍按普通输入处理。请通过响应中的缓存用量字段确认是否命中。

缓存 user 或 assistant 内容块

cache_control 也可以放在 userassistant 消息的内容块上,用于缓存长文档或多轮对话前缀:

{
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": "这里放需要重复使用的长文档……",
      "cache_control": {
        "type": "ephemeral"
      }
    },
    {
      "type": "text",
      "text": "请总结上面文档中的三个核心观点。"
    }
  ]
}

将稳定内容和当前问题拆成不同的内容块,并只在稳定内容块上添加 cache_control

响应用量字段

OpenAI 兼容格式使用不同的字段报告缓存用量:

{
  "usage": {
    "prompt_tokens": 1942,
    "completion_tokens": 22,
    "prompt_tokens_details": {
      "cached_tokens": 1921,
      "cache_write_tokens": 0
    },
    "claude_cache_creation_5_m_tokens": 0,
    "claude_cache_creation_1_h_tokens": 0
  }
}

字段对照:

含义 Claude Messages API OpenAI 兼容 API
总输入 三个输入字段之和 prompt_tokens
缓存读取 cache_read_input_tokens prompt_tokens_details.cached_tokens
通用缓存写入字段 cache_creation_input_tokens prompt_tokens_details.cache_write_tokens(无 TTL 细分时才有值)
5 分钟缓存写入 cache_creation.ephemeral_5m_input_tokens claude_cache_creation_5_m_tokens
1 小时缓存写入 cache_creation.ephemeral_1h_input_tokens claude_cache_creation_1_h_tokens
输出 output_tokens completion_tokens
注意
如果 `prompt_tokens_details.cache_write_tokens` 为 `0`,仍需检查 `claude_cache_creation_5_m_tokens` 和 `claude_cache_creation_1_h_tokens`;存在 TTL 细分字段时,缓存写入量会通过对应字段返回。
注意
`claude_cache_creation_5_m_tokens` 和 `claude_cache_creation_1_h_tokens` 中的数字与单位之间包含下划线,请直接使用响应返回的字段名。
警告
OpenAI 兼容接口即使没有显式传入 `stream: true`,也可能返回 SSE 流式响应。客户端应支持解析 `chat.completion.chunk`,用量位于最后一个包含 `usage` 的数据块中。

缓存命中的条件

前缀长度达到最低门槛

示例模型的缓存前缀通常至少需要约 1024 token。前缀不足时,缓存标记可能被忽略且不会报错。

前缀保持逐字节一致

缓存前缀中的文字、空格、换行和内容块顺序必须保持一致。不要在稳定前缀中加入时间戳、随机 ID 或请求计数等动态内容。

请求未触发模型拒答

如果请求触发模型拒答,响应可能仍报告缓存创建 token,但该缓存不会在下一次请求中被读取。排查缓存未命中时,请同时检查 stop_reason 是否为 refusal

缓存仍在有效期内

缓存有效期为 5 分钟或 1 小时,并从最后一次访问开始计算;缓存命中会刷新有效期。

计费用量

缓存相关用量分为三类:

用量 产生时机
缓存写入 首次建立缓存
缓存读取 后续请求命中缓存
普通输入 缓存前缀之外的输入

三类用量互不重叠。缓存写入的成本通常高于普通输入,缓存读取的成本通常低于普通输入,因此上下文缓存更适合会在 TTL 内重复使用的稳定前缀。

最小可复现示例

下面的脚本先生成一个足够长的稳定前缀,再连续发送两次相同请求。第二次响应应出现 cache_read_input_tokens > 0

python3 - <<'PY' > /tmp/claude-cache-request.json
import json

paragraph = (
    "Prompt caching stores a prefix of the request so that later requests "
    "can reuse the same byte-identical prefix without processing it again. "
)

system_text = (
    "You are a documentation assistant. Reference material follows.\n\n"
    + paragraph * 40
)

print(json.dumps({
    "model": "claude-sonnet-5",
    "max_tokens": 32,
    "system": [{
        "type": "text",
        "text": system_text,
        "cache_control": {"type": "ephemeral"}
    }],
    "messages": [{
        "role": "user",
        "content": "In one sentence, what must remain unchanged?"
    }]
}))
PY

for request_number in 1 2; do
  echo "第 ${request_number} 次请求"
  curl -s "https://api.openveer.com/v1/messages" \
    -H "x-api-key: $API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "Content-Type: application/json" \
    --data @/tmp/claude-cache-request.json \
  | python3 -c "import json, sys; print(json.load(sys.stdin)['usage'])"
done

预期结果:

第 1 次请求:cache_creation_input_tokens > 0,cache_read_input_tokens = 0
第 2 次请求:cache_creation_input_tokens = 0,cache_read_input_tokens > 0

排查清单

缓存未命中时,请按顺序检查:

  • stop_reason 是否为 refusal
  • 缓存前缀是否达到模型要求的最低 token 数
  • 两次请求的稳定前缀是否逐字节相同
  • OpenAI 兼容格式中的 content 是否为数组
  • cache_control 是否位于具体的内容块内
  • 1 小时缓存是否同时设置 ttl: "1h" 和对应的 anthropic-beta 请求头
  • 缓存是否已经超过 TTL
  • 是否读取了当前接口对应的缓存用量字段