Claude Prompt Caching
UniGateway 支持通过 Claude Messages API 兼容接口为稳定的提示词前缀创建临时缓存。将长期不变的系统指令、工具定义和参考资料放在请求前部,将本轮问题、时间戳和实时检索结果放在缓存断点之后,可在后续请求复用已创建的缓存。
缓存是否命中取决于请求前缀是否完全一致、缓存是否仍在有效期内、模型是否支持该能力以及当前账户可用状态。模型 ID、能力和可用性请以 UniGateway 模型库 与当前文档为准。
接口说明
| 项目 | 值 |
|---|---|
| 方法 | POST |
| 路径 | /v1/messages |
| API 地址 | https://api.unigateway.ai/v1/messages |
| 鉴权 | x-api-key: $UNIGATEWAY_API_KEY |
| 版本请求头 | anthropic-version: 2023-06-01 |
| Content-Type | application/json |
本文仅适用于使用 Claude Messages API 兼容格式调用的 Claude model。Chat Completions 调用的字段和用量格式不同,不适用本文的请求示例。
准备工作
请前往 UniGateway API Keys 创建或获取 API Key。请按业务要求配置 API Key 的访问控制、轮换和安全管理。
将 API Key 配置为环境变量,不要将其写入源代码、前端代码、日志或代码仓库:
export UNIGATEWAY_API_KEY="<YOUR_UNIGATEWAY_API_KEY>"
Windows PowerShell:
$env:UNIGATEWAY_API_KEY = "<YOUR_UNIGATEWAY_API_KEY>"
下文的 claude-sonnet-4-6 仅用于说明请求格式。实际调用时,请使用 UniGateway 模型库中标注的请求 model ID,并以本文列出的支持范围和最小可缓存长度为准。
生效条件与缓存断点
在需要缓存的内容块上配置 cache_control。缓存断点会覆盖该断点之前的 tools、system 和 messages 前缀,因此断点应放在最后一个稳定内容块上。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
cache_control.type | string | 是 | 固定为 ephemeral。 |
cache_control.ttl | string | 否 | 缓存有效期。省略时使用 5m;可设置为 5m 或 1h。 |
缓存断点之前的上下文必须达到所选 model 的最小可缓存长度,cache_creation.ephemeral_5m_input_tokens 或 cache_creation.ephemeral_1h_input_tokens 才会产生缓存写入量。最小长度因 model 而异:
当 cache_control 配置在 system 的 type: "text" 内容块时,应以该内容块的 text 判断是否达到最小可缓存长度;不要通过后续 messages、当前轮问题或其他 system 内容块补足该 text 的长度。以 claude-sonnet-4-6 为例,该 model 的最小可缓存长度为 1024 token;带有 cache_control 的 system text 少于 1024 token 时,请求仍会正常执行,但不会写入缓存。
| Claude model | 最小可缓存长度 |
|---|---|
| Claude Fable 5 | 1024 token |
| Claude Opus 4.7 | 2048 token |
| Claude Opus 4.6、Claude Opus 4.5 | 4096 token |
| Claude Opus 4.8、Claude Sonnet 5、Claude Sonnet 4.6、Claude Sonnet 4.5 | 1024 token |
| Claude Haiku 4.5 | 4096 token |
UniGateway 的最小可缓存长度以当前文档为准。
短于最小长度的请求仍会正常执行,不会返回错误,但不会创建缓存。若响应中的 cache_creation_input_tokens 与 cache_read_input_tokens 均为 0,表示本次没有创建或读取缓存,常见原因是缓存前缀未达到该 model 的最小可缓存长度。
不要用字符数或字数代替 token 阈值判断。不同 model 的分词结果不同;应以接口返回的 usage 为准确认是否实际创建了缓存。
缓存固定资料和工具定义
适用于客服知识库、代码规范、产品规则等稳定资料不变,而每次用户问题不同的场景。tools 位于 system 之前,缓存断点放在最后一段稳定资料上;因此工具定义、系统指令和资料都属于可复用前缀。
cURL 请求示例
本示例将缓存断点设置在 system[0]。因此,对 claude-sonnet-4-6,带有 cache_control 的 system[0].text 本身必须达到至少 1024 token;少于该长度时,请求不会产生缓存写入。
将 system[0].text 中的占位文本替换为实际的稳定系统规则、工具资料或知识库内容。缓存断点之前的完整上下文必须达到所选 model 的最小可缓存长度;不要将当前日期、用户标识、检索结果或本轮问题放入该内容。如使用 5 分钟缓存,将 "1h" 替换为 "5m"。
curl https://api.unigateway.ai/v1/messages \
-H "x-api-key: $UNIGATEWAY_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 600,
"system": [
{
"type": "text",
"text": "<替换为达到所选 model 最小可缓存长度的稳定系统规则、工具资料或知识库内容>",
"cache_control": {"type": "ephemeral", "ttl": "1h"}
}
],
"messages": [
{
"role": "user",
"content": "Order UG-20260721-001 is delayed. Please check its status."
}
]
}'
响应中的 usage.cache_creation.ephemeral_1h_input_tokens 大于 0,表示已创建 1 小时缓存。首个请求创建缓存后,再使用完全相同的 system 和 cache_control 发送下一次请求,并将新的动态问题放在 messages 末尾;通过 usage.cache_read_input_tokens 验证是否命中。
Python SDK 请求示例
以下 Python 示例读取本地 knowledge-base.md。该文件只能包含稳定的指令和参考资料,缓存断点之前的总上下文必须达到所选 model 的最小可缓存长度。
安装 SDK:
pip install anthropic
import os
from pathlib import Path
import anthropic
MODEL = "claude-sonnet-4-6"
CACHE_TTL = "1h"
tools = [
{
"name": "get_order_status",
"description": "Look up the status of an order by its ID.",
"input_schema": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The order ID supplied by the customer.",
}
},
"required": ["order_id"],
"additionalProperties": False,
},
}
]
stable_reference = Path("knowledge-base.md").read_text(encoding="utf-8")
if not stable_reference.strip():
raise ValueError("knowledge-base.md must contain stable reference content.")
client = anthropic.Anthropic(
api_key=os.environ["UNIGATEWAY_API_KEY"],
base_url="https://api.unigateway.ai",
)
response = client.messages.create(
model=MODEL,
max_tokens=600,
tools=tools,
system=[
{
"type": "text",
"text": "You are an order-support assistant. Follow the supplied policy exactly.",
},
{
"type": "text",
"text": stable_reference,
"cache_control": {"type": "ephemeral", "ttl": CACHE_TTL},
},
],
messages=[
{
"role": "user",
"content": "Order UG-20260721-001 is delayed. Please check its status.",
}
],
)
print(response.content)
print(response.usage)
SDK 会自动请求 POST /v1/messages;base_url 必须为 https://api.unigateway.ai,不要附加 /v1。将 CACHE_TTL 改为 "5m" 可创建 5 分钟缓存;选择 1 小时 TTL 前,应确认稳定前缀会在该时间窗口内被再次使用。
首次请求会创建缓存,usage 的示例结构如下。数值仅用于说明字段含义,实际 token 数以接口返回为准:
{
"cache_creation_input_tokens": 2534,
"cache_read_input_tokens": 0,
"input_tokens": 22,
"output_tokens": 148,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 2534
}
}
本例的稳定前缀达到所选 model 的最小可缓存长度时,ephemeral_1h_input_tokens 才会大于 0。如改用 "5m",应检查 cache_creation.ephemeral_5m_input_tokens;未创建缓存的 TTL 字段可能为 0 或不返回。
追加式多轮对话
当会话历史只会在末尾追加新消息时,可在请求顶层添加 cache_control。服务会在最近的可缓存历史内容处自动建立缓存断点,并随追加的会话历史向前推进。
本节只讨论 messages 多轮历史,不包含固定资料、system 或工具定义。每一轮请求都必须保留既有消息的内容和顺序,只在 messages 末尾追加新的消息。
自动缓存断点之前的会话上下文达到所选 model 的最小可缓存长度后,ephemeral_5m_input_tokens 才会生效。下面的简短文本仅用于说明结构;实际使用时,随着会话历史持续追加并达到该长度,再通过 usage 验证缓存创建和读取。
cURL 请求示例
发送首轮消息:
curl https://api.unigateway.ai/v1/messages \
-H "x-api-key: $UNIGATEWAY_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 600,
"cache_control": {"type": "ephemeral"},
"messages": [
{
"role": "user",
"content": "What is the refund request deadline?"
}
]
}'
首轮响应使用以下结构。id、content.text 和各项 token 数会随请求而变化:
{
"model": "claude-sonnet-4-6",
"id": "msg_xxx",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Please provide the company or service so I can identify its refund deadline."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"stop_details": null,
"usage": {
"input_tokens": 15,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 0
},
"output_tokens": 18
}
}
缓存条目在首个响应开始后才可用于后续请求。使用本节的非流式 cURL 命令时,等待首轮命令返回后,再保留首轮 user 消息和响应中的 assistant 内容,并在末尾追加新的 user 消息。纯文本响应时,将首轮响应 content 中的文本填入下例的 text;如首轮包含其他内容块,必须保留其原始数组结构和顺序:
curl https://api.unigateway.ai/v1/messages \
-H "x-api-key: $UNIGATEWAY_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 600,
"cache_control": {"type": "ephemeral"},
"messages": [
{
"role": "user",
"content": "What is the refund request deadline?"
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "<替换为首轮响应 content 中实际返回的文本>"
}
]
},
{
"role": "user",
"content": "Does the deadline change for a damaged item?"
}
]
}'
当自动缓存断点之前的历史达到所选 model 的最小可缓存长度,且首个创建缓存的请求已经完成时,第二次及后续响应的 usage.cache_read_input_tokens 大于 0 表示命中。不要将创建缓存的请求与后续请求并发发送;缓存尚未创建完成时,后续请求不能复用它。
Python SDK 请求示例
以下代码与 cURL 示例相同,只演示纯文本多轮对话:
def send(messages):
return client.messages.create(
model=MODEL,
max_tokens=600,
cache_control={"type": "ephemeral"},
messages=messages,
)
history = [
{
"role": "user",
"content": "What is the refund request deadline?",
}
]
first_response = send(history)
history.append(
{
"role": "assistant",
"content": [block.model_dump(exclude_none=True) for block in first_response.content],
}
)
history.append(
{
"role": "user",
"content": "Does the deadline change for a damaged item?",
}
)
second_response = send(history)
print(second_response.content)
print(second_response.usage)
当会话历史已达到缓存阈值,且第二次请求命中缓存时,usage 可包含以下结构:
{
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 2534,
"input_tokens": 57,
"output_tokens": 116
}
cache_read_input_tokens 大于 0 才表示实际从缓存读取。会话历史未达到所选 model 的最小可缓存长度时不会创建临时缓存;继续追加历史后重新检查该字段。
可缓存与不可缓存内容
大多数请求内容块都可以自动缓存,或通过 cache_control 标记为缓存断点:
| 内容 | 可缓存范围 |
|---|---|
| 工具定义 | tools 数组中的工具定义。 |
| 系统消息 | system 数组中的内容块。 |
| 文本消息 | messages[].content 中 user 和 assistant 消息的文本内容块。 |
| 图像和文档 | user 消息 messages[].content 中的图像和文档内容块。 |
| 工具调用和工具结果 | messages[].content 中 assistant 和 user 消息的相关内容块。 |
以下内容不能直接作为缓存断点:
- 思考内容块不能直接配置
cache_control。它们出现在先前 assistant 轮次时,可随同其他可缓存内容读取,并计入缓存读取输入 token。 - 引文等子内容块不能直接缓存,应缓存其所属的顶层内容块。例如,作为引文来源的顶层文档内容块可以缓存。
- 空文本内容块不能缓存。
TTL 与前缀一致性
cache_control 未指定 ttl 时使用 5 分钟缓存。每次成功读取缓存会刷新该缓存的 TTL。预计稳定前缀会在超过 5 分钟、但不超过 1 小时的窗口内再次使用时,可将断点配置为 "ttl": "1h";1 小时缓存的写入成本高于 5 分钟缓存,不应为不会复用的请求启用。
单个请求最多可使用 4 个缓存断点,顶层自动缓存也计入此上限。大多数场景只需在最后一个稳定内容块设置一个显式断点;不要无目的混用顶层自动缓存和多个显式断点。
缓存按 tools → system → messages 的层级处理。修改 tools 会使工具、系统消息和消息历史的后续缓存失效;修改 system 会使系统消息和消息历史的后续缓存失效;修改 messages 只会影响对应消息层级及其后续缓存。
同一请求混用两种 TTL 时,所有 1h 断点必须位于所有 5m 断点之前。例如,较稳定的基础资料可使用 1h,而短期不变的会话资料可使用 5m:
{
"system": [
{
"type": "text",
"text": "Long-lived policy and product reference content.",
"cache_control": {"type": "ephemeral", "ttl": "1h"}
},
{
"type": "text",
"text": "Short-lived session reference content.",
"cache_control": {"type": "ephemeral", "ttl": "5m"}
}
]
}
命中要求断点之前的前缀完全一致。以下任一变化都会导致已有缓存不能作为该请求的复用前缀:
- 更换 model,或修改
tools、工具 schema、工具顺序。 - 修改系统指令、稳定参考资料或其中的图像内容及顺序。
- 修改或移动
cache_control,或在断点之前插入时间戳、检索结果、用户标识等动态值。 - 重写、重排或以不同格式重新序列化已有历史消息。
将动态内容放在断点之后,并在每次请求中使用相同的构造顺序。这样即使本轮问题不同,稳定前缀仍可复用。
验证缓存命中
先发送一次请求以创建缓存。缓存条目在首个响应开始后才可用于后续请求;非流式调用可等待首个请求返回,流式调用应等待首个响应开始后再发送需要命中的并发请求。随后发送一个稳定前缀完全相同、仅在断点后追加或替换动态内容的请求。不要将并发的首次请求当作缓存命中测试。
检查每个响应的 usage:
| 字段 | 说明 |
|---|---|
input_tokens | 未被计入缓存创建或缓存读取的输入 token 数。它不表示请求的全部输入 token。 |
cache_creation_input_tokens | 本次新建或重建缓存的输入 token 总数。首次创建缓存时通常大于 0。 |
cache_read_input_tokens | 本次从已有缓存读取的输入 token 数。大于 0 表示实际命中缓存。 |
cache_creation.ephemeral_5m_input_tokens | 按默认 5 分钟 TTL 新建的缓存 token 数。仅当缓存断点前上下文达到所选 model 的最小可缓存长度时生效。 |
cache_creation.ephemeral_1h_input_tokens | 按 1 小时 TTL 新建的缓存 token 数。仅当缓存断点前上下文达到所选 model 的最小可缓存长度且断点配置 "ttl": "1h" 时生效。 |
output_tokens | model 在本次响应中生成的输出 token 数,与缓存读写 token 分开统计。 |
cache_creation_input_tokens 用于查看本次缓存写入总量,cache_creation 对象用于区分写入使用的 TTL。首次请求中所有缓存字段为 0,表示缓存断点前的上下文尚未达到所选 model 的最小可缓存长度,或未成功创建缓存;cache_read_input_tokens 为 0 表示本次没有读取已有缓存。
对一组重复请求,可按 token 计算缓存复用率,而不是按请求次数计算:
cache_read_input_tokens
------------------------------------------------
input_tokens + cache_creation_input_tokens + cache_read_input_tokens
将同一请求流量中每次响应的字段分别求和后再计算。首次创建缓存的请求是写入操作,不应计为命中;后续请求的 cache_read_input_tokens 才是复用证据。
常见问题
Q: 为什么 ephemeral_5m_input_tokens 或 ephemeral_1h_input_tokens 没有返回,或值为 0?
先确认所选 model 的最小可缓存长度,再检查请求中带有 cache_control 的内容块之前的稳定上下文是否达到该长度,并确认配置为 "type": "ephemeral",TTL 为 "5m" 或 "1h"。随后查看同一响应的 usage.cache_creation_input_tokens。上下文未达到该 model 的最小长度时,不会创建对应的临时缓存;请扩充稳定资料后重新发送首个请求,再检查 usage.cache_creation.ephemeral_5m_input_tokens 或 usage.cache_creation.ephemeral_1h_input_tokens。
Q: 第二次请求的 cache_read_input_tokens 仍为 0,如何处理?
确认首个请求已完整返回,再发送第二个请求。逐项比较两次请求的 model、tools 内容及顺序、system 内容及顺序、cache_control 位置和断点前消息历史;这些内容必须完全一致。将本轮问题、时间戳和实时检索结果移动到断点之后,然后重新验证第二次响应的 usage.cache_read_input_tokens。缓存过期后需要重新创建,5 分钟与 1 小时 TTL 的适用窗口分别以实际配置为准。
Q: 应选择 5m 还是 1h?
默认使用 5m。仅当同一稳定前缀预计会在超过 5 分钟、但不超过 1 小时内再次使用时,才配置 "ttl": "1h"。修改 TTL 后视为缓存断点配置变化,应使用新配置重新发送首个请求,并通过 usage.cache_creation.ephemeral_1h_input_tokens 验证新的 1 小时缓存是否已创建。
安全与计费建议
- API Key 仅保存在服务端环境变量中,不要写入示例、浏览器代码、日志或代码仓库。
- 缓存内容可能包含系统规则、参考资料和历史消息。只将允许传递给所选 model 的数据放入缓存前缀,并按业务要求处理敏感信息。
- 缓存会产生对应的读写用量。上线前使用固定测试流量记录
usage,并在 UniGateway 控制台的用量明细中核对缓存读写 token 与费用。