# Claude 上下文缓存
> 通过 `cache_control` 标记要缓存的前缀
> 可以标记多个断点，按层级复用
> 长系统提示与固定文档的典型场景收益最明显
## 机制
Claude 原生结构下，缓存不是自动的，需要在内容块上显式打标记：
```json
{
  "role": "system",
  "content": [
    {
      "type": "text",
      "text": "【这里是很长的固定文档】",
      "cache_control": { "type": "ephemeral" }
    }
  ]
}
```
标记之后，这段前缀会被缓存，后续请求命中就不再重复计费。
> **Note:** 
> 缓存以「标记点之前的全部内容」为单位。也就是说，断点越靠后，缓存的内容越多，能省下的也越多。但前缀只要有一个字符变化，整段缓存就失效。
## 最多几个断点
单次请求最多 4 个缓存断点。适合这样的结构：
| 断点位置 | 缓存内容 | 变化频率 |
|---|---|---|
| 第 1 个 | 系统提示与工具定义 | 几乎不变 |
| 第 2 个 | 产品手册正文 | 偶尔更新 |
| 第 3 个 | 本次会话的早期对话 | 会话内固定 |
| 第 4 个 | 最近一轮上下文 | 每轮变化 |
这样设计可以让不同层级的缓存各自生效，避免一处改动把整条缓存冲掉。
## 参数
- `cache_control.type` (string / 必填) — 目前只接受 `ephemeral`，表示短期缓存。
- `cache_control.ttl` (string / 可选) — 生存时间。不传时用默认值，可显式写成 `5m` 或 `1h`。
## 响应中的用量
- `usage.cache_creation_input_tokens` (integer) — 本次写入缓存的 token 数。首次请求时出现。
- `usage.cache_read_input_tokens` (integer) — 本次从缓存读取的 token 数。命中时出现。
- `usage.input_tokens` (integer) — 未命中缓存的普通输入 token 数。
## 命中判定
| 情况 | cache_read | cache_creation |
|---|---|---|
| 首次请求 | 0 | 大于 0 |
| 完全相同的前缀再次请求 | 大于 0 | 0 |
| 前缀有改动 | 0 | 按新内容计 |
| 缓存已过期 | 0 | 重新写入 |
## 使用示例
### 标记缓存断点
在需要缓存的内容块上加 `cache_control`，从开头到断点的全部内容进入缓存。断点之前的内容要稳定，否则每次都算新内容。
### 多点断点
一段对话里可以在多个位置标记断点，最多四个。每多一个断点就多一层缓存，适合长对话中分段复用。
### 核对命中情况
`usage` 里的 `cache_creation_input_tokens` 是本次写入缓存的数量，`cache_read_input_tokens` 是命中的数量。首次请求前者大于 0，之后应该是后者大于 0。
```bash
curl --request POST https://api.oairoute.com/v1/messages \
  -H "Authorization: Bearer YOUR_OAIRoute_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "messages": [{ "role": "user", "content": "你好" }]
  }' | jq '.usage | {created: .cache_creation_input_tokens, read: .cache_read_input_tokens}'
```
**标记缓存断点{Mark cache breakpoint}::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/v1/messages' \
  --header 'Authorization: Bearer YOUR_OAIRoute_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "system": [{
      "type": "text",
      "text": "以下是三千页技术手册的全文：……",
      "cache_control": { "type": "ephemeral" }
    }],
    "messages": [{ "role": "user", "content": "手册里关于超时重试是怎么规定的" }]
  }'
```
**标记缓存断点{Mark cache breakpoint}::Python**
```
import requests
url = "https://api.oairoute.com/v1/messages"
headers = {"Authorization": "Bearer YOUR_OAIRoute_KEY"}
payload = {
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "system": [{
      "type": "text",
      "text": "以下是三千页技术手册的全文：……",
      "cache_control": { "type": "ephemeral" }
    }],
    "messages": [{ "role": "user", "content": "手册里关于超时重试是怎么规定的" }]
  }
res = requests.post(url, headers=headers, json=payload)
print(res.json())
```
**标记缓存断点{Mark cache breakpoint}::JavaScript**
```
const res = await fetch("https://api.oairoute.com/v1/messages", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "system": [{
      "type": "text",
      "text": "以下是三千页技术手册的全文：……",
      "cache_control": { "type": "ephemeral" }
    }],
    "messages": [{ "role": "user", "content": "手册里关于超时重试是怎么规定的" }]
  }),
});
console.log(await res.json());
```
**多点断点{Multiple breakpoints}::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/v1/messages' \
  --header 'Authorization: Bearer YOUR_OAIRoute_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "system": [{
      "type": "text",
      "text": "以下是三千页技术手册的全文：……",
      "cache_control": { "type": "ephemeral" }
    }],
    "messages": [
      { "role": "user", "content": "手册里关于超时重试是怎么规定的" },
      { "role": "assistant", "content": "手册规定：超时按指数退避重试，最多三次。" },
      { "role": "user", "content": "退避的初始间隔是多少" }
    ]
  }'
```
**多点断点{Multiple breakpoints}::Python**
```
import requests
url = "https://api.oairoute.com/v1/messages"
headers = {"Authorization": "Bearer YOUR_OAIRoute_KEY"}
payload = {
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "system": [{
      "type": "text",
      "text": "以下是三千页技术手册的全文：……",
      "cache_control": { "type": "ephemeral" }
    }],
    "messages": [
      { "role": "user", "content": "手册里关于超时重试是怎么规定的" },
      { "role": "assistant", "content": "手册规定：超时按指数退避重试，最多三次。" },
      { "role": "user", "content": "退避的初始间隔是多少" }
    ]
  }
res = requests.post(url, headers=headers, json=payload)
print(res.json())
```
**多点断点{Multiple breakpoints}::JavaScript**
```
const res = await fetch("https://api.oairoute.com/v1/messages", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "system": [{
      "type": "text",
      "text": "以下是三千页技术手册的全文：……",
      "cache_control": { "type": "ephemeral" }
    }],
    "messages": [
      { "role": "user", "content": "手册里关于超时重试是怎么规定的" },
      { "role": "assistant", "content": "手册规定：超时按指数退避重试，最多三次。" },
      { "role": "user", "content": "退避的初始间隔是多少" }
    ]
  }),
});
console.log(await res.json());
```
**200 标记缓存断点{Mark cache breakpoint}**
```
{
  "id": "msg_01KA",
  "type": "message",
  "role": "assistant",
  "model": "claude-sonnet-5-5",
  "content": [
    {
      "type": "text",
      "text": "手册规定：超时按指数退避重试，最多三次。"
    }
  ],
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 12,
    "output_tokens": 186,
    "cache_creation_input_tokens": 9824,
    "cache_read_input_tokens": 0
  }
}
```
**200 多点断点{Multiple breakpoints}**
```
{
  "id": "msg_01KB",
  "type": "message",
  "role": "assistant",
  "model": "claude-sonnet-5-5",
  "content": [
    {
      "type": "text",
      "text": "初始间隔为 1 秒，之后每次翻倍。"
    }
  ],
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 38,
    "output_tokens": 64,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 9824
  }
}
```
