开发指南/Claude Prompt Caching

通过 UniGateway 创建并验证 Claude 临时提示词缓存,涵盖缓存断点、TTL、最小长度和用量诊断。

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-Typeapplication/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。缓存断点会覆盖该断点之前的 toolssystemmessages 前缀,因此断点应放在最后一个稳定内容块上。

字段类型必填说明
cache_control.typestring固定为 ephemeral
cache_control.ttlstring缓存有效期。省略时使用 5m;可设置为 5m1h

缓存断点之前的上下文必须达到所选 model 的最小可缓存长度,cache_creation.ephemeral_5m_input_tokenscache_creation.ephemeral_1h_input_tokens 才会产生缓存写入量。最小长度因 model 而异:

cache_control 配置在 systemtype: "text" 内容块时,应以该内容块的 text 判断是否达到最小可缓存长度;不要通过后续 messages、当前轮问题或其他 system 内容块补足该 text 的长度。以 claude-sonnet-4-6 为例,该 model 的最小可缓存长度为 1024 token;带有 cache_controlsystem text 少于 1024 token 时,请求仍会正常执行,但不会写入缓存。

Claude model最小可缓存长度
Claude Fable 51024 token
Claude Opus 4.72048 token
Claude Opus 4.6、Claude Opus 4.54096 token
Claude Opus 4.8、Claude Sonnet 5、Claude Sonnet 4.6、Claude Sonnet 4.51024 token
Claude Haiku 4.54096 token

UniGateway 的最小可缓存长度以当前文档为准。

短于最小长度的请求仍会正常执行,不会返回错误,但不会创建缓存。若响应中的 cache_creation_input_tokenscache_read_input_tokens 均为 0,表示本次没有创建或读取缓存,常见原因是缓存前缀未达到该 model 的最小可缓存长度。

不要用字符数或字数代替 token 阈值判断。不同 model 的分词结果不同;应以接口返回的 usage 为准确认是否实际创建了缓存。

缓存固定资料和工具定义

适用于客服知识库、代码规范、产品规则等稳定资料不变,而每次用户问题不同的场景。tools 位于 system 之前,缓存断点放在最后一段稳定资料上;因此工具定义、系统指令和资料都属于可复用前缀。

cURL 请求示例

本示例将缓存断点设置在 system[0]。因此,对 claude-sonnet-4-6,带有 cache_controlsystem[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 小时缓存。首个请求创建缓存后,再使用完全相同的 systemcache_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/messagesbase_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?"
      }
    ]
  }'

首轮响应使用以下结构。idcontent.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_tokensmodel 在本次响应中生成的输出 token 数,与缓存读写 token 分开统计。

cache_creation_input_tokens 用于查看本次缓存写入总量,cache_creation 对象用于区分写入使用的 TTL。首次请求中所有缓存字段为 0,表示缓存断点前的上下文尚未达到所选 model 的最小可缓存长度,或未成功创建缓存;cache_read_input_tokens0 表示本次没有读取已有缓存。

对一组重复请求,可按 token 计算缓存复用率,而不是按请求次数计算:

cache_read_input_tokens
------------------------------------------------
input_tokens + cache_creation_input_tokens + cache_read_input_tokens

将同一请求流量中每次响应的字段分别求和后再计算。首次创建缓存的请求是写入操作,不应计为命中;后续请求的 cache_read_input_tokens 才是复用证据。

常见问题

Q: 为什么 ephemeral_5m_input_tokensephemeral_1h_input_tokens 没有返回,或值为 0

先确认所选 model 的最小可缓存长度,再检查请求中带有 cache_control 的内容块之前的稳定上下文是否达到该长度,并确认配置为 "type": "ephemeral",TTL 为 "5m""1h"。随后查看同一响应的 usage.cache_creation_input_tokens。上下文未达到该 model 的最小长度时,不会创建对应的临时缓存;请扩充稳定资料后重新发送首个请求,再检查 usage.cache_creation.ephemeral_5m_input_tokensusage.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 与费用。