提示词缓存
提示词缓存是一个强大的功能,通过允许从提示词中的特定前缀恢复来优化您的 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 # rest of inputimport anthropic
client = anthropic.Anthropic()
response = client.messages.create(
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'."}],
)
print(response.usage.model_dump_json())
# 使用相同的输入直到缓存检查点再次调用模型
response = client.messages.create(.....)
print(response.usage.model_dump_json())import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
const response = await client.messages.create({
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'."
}
]
});
console.log(response.usage);
// 使用相同的输入直到缓存检查点再次调用模型
const new_response = await client.messages.create(...)
console.log(new_response.usage);import java.util.List;
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.CacheControlEphemeral;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
import com.anthropic.models.messages.TextBlockParam;
public class PromptCachingExample {
public static void main(String[] args) {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.CLAUDE_OPUS_4_20250514)
.maxTokens(1024)
.systemOfTextBlockParams(List.of(
TextBlockParam.builder()
.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")
.build(),
TextBlockParam.builder()
.text("<the entire contents of 'Pride and Prejudice'>")
.cacheControl(CacheControlEphemeral.builder().build())
.build()
))
.addUserMessage("Analyze the major themes in 'Pride and Prejudice'.")
.build();
Message message = client.messages().create(params);
System.out.println(message.usage());
}
}{"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}在这个示例中,《傲慢与偏见》的全部文本使用 cache_control 参数进行缓存。这使得可以在多个 API 调用中重复使用这个大型文本,而无需每次都重新处理。仅更改用户消息允许您在利用缓存内容的同时提出关于这本书的各种问题,从而导致更快的响应和提高的效率。
提示词缓存如何工作
当您发送启用了提示词缓存的请求时:
- 系统检查提示词前缀(直到指定的缓存断点)是否已从最近的查询中缓存。
- 如果找到,它使用缓存版本,减少处理时间和成本。
- 否则,它处理完整提示词,并在响应开始后缓存前缀。
这对以下情况特别有用:
- 包含许多示例的提示词
- 大量上下文或背景信息
- 具有一致指令的重复任务
- 长多轮对话
默认情况下,缓存的生命周期为 5 分钟。每次使用缓存内容时,缓存都会以无额外成本的方式刷新。
如果您发现 5 分钟太短,Anthropic 还提供 1 小时缓存持续时间需额外付费。1 小时缓存目前处于测试阶段。
有关更多信息,请参阅 1 小时缓存持续时间。
提示词缓存缓存完整前缀
提示词缓存引用整个提示词 - tools、system 和 messages(按该顺序)直到并包括用 cache_control 指定的块。
定价
提示词缓存引入了新的定价结构。下表显示了每个支持的模型的每百万个令牌的价格:
| Model | Base Input Tokens | 5m Cache Writes | 1h Cache Writes | Cache Hits & Refreshes | Output Tokens |
|---|---|---|---|---|---|
| Claude Opus 4.1 | $15 / MTok | $18.75 / MTok | $30 / MTok | $1.50 / MTok | $75 / MTok |
| Claude Opus 4 | $15 / MTok | $18.75 / MTok | $30 / MTok | $1.50 / MTok | $75 / MTok |
| Claude Sonnet 4.5 | $3 / MTok | $3.75 / MTok | $6 / MTok | $0.30 / MTok | $15 / MTok |
| Claude Sonnet 4 | $3 / MTok | $3.75 / MTok | $6 / MTok | $0.30 / MTok | $15 / MTok |
| Claude Sonnet 3.7 (deprecated) | $3 / MTok | $3.75 / MTok | $6 / MTok | $0.30 / MTok | $15 / MTok |
| Claude Haiku 4.5 | $1 / MTok | $1.25 / MTok | $2 / MTok | $0.10 / MTok | $5 / MTok |
| Claude Haiku 3.5 | $0.80 / MTok | $1 / MTok | $1.6 / MTok | $0.08 / MTok | $4 / MTok |
| Claude Opus 3 (deprecated) | $15 / MTok | $18.75 / MTok | $30 / MTok | $1.50 / MTok | $75 / MTok |
| Claude Haiku 3 | $0.25 / MTok | $0.30 / MTok | $0.50 / MTok | $0.03 / MTok | $1.25 / MTok |
上表反映了提示词缓存的以下定价倍数:
- 5 分钟缓存写入令牌是基础输入令牌价格的 1.25 倍
- 1 小时缓存写入令牌是基础输入令牌价格的 2 倍
- 缓存读取令牌是基础输入令牌价格的 0.1 倍
如何实现提示词缓存
支持的模型
提示词缓存目前支持:
- Claude Opus 4.1
- Claude Opus 4
- Claude Sonnet 4.5
- Claude Sonnet 4
- Claude Sonnet 3.7
- Claude Haiku 4.5
- Claude Haiku 3.5
- Claude Haiku 3
- Claude Opus 3 (已弃用)
构建您的提示词
将静态内容(工具定义、系统指令、上下文、示例)放在提示词的开头。使用 cache_control 参数标记可重用内容的结尾以进行缓存。
缓存前缀按以下顺序创建:tools、system,然后是 messages。这个顺序形成了一个层次结构,其中每个级别都建立在前一个级别之上。
自动前缀检查如何工作
您可以在静态内容的末尾使用一个缓存断点,系统将自动找到最长的匹配前缀。理解这如何工作有助于您优化缓存策略。
三个核心原则:
-
缓存键是累积的:当您使用
cache_control显式缓存一个块时,缓存哈希键是通过按顺序对话中所有先前块进行哈希生成的。这意味着每个块的缓存取决于它之前的所有内容。 -
向后顺序检查:系统通过从您的显式断点向后工作来检查缓存命中,按相反顺序检查每个先前的块。这确保您获得最长的可能缓存命中。
-
20 块回溯窗口:系统只检查每个显式
cache_control断点之前最多 20 个块。在检查 20 个块而没有匹配后,它停止检查并移动到下一个显式断点(如果有)。
示例:理解回溯窗口
考虑一个有 30 个内容块的对话,其中您仅在块 30 上设置 cache_control:
-
如果您发送块 31 且不更改先前的块:系统检查块 30(匹配!)。您在块 30 处获得缓存命中,只需处理块 31。
-
如果您修改块 25 并发送块 31:系统从块 30 → 29 → 28... → 25(无匹配)→ 24(匹配!)向后检查。由于块 24 未更改,您在块 24 处获得缓存命中,只需重新处理块 25-30。
-
如果您修改块 5 并发送块 31:系统从块 30 → 29 → 28... → 11(检查 #20)向后检查。在 20 次检查后未找到匹配,它停止查找。由于块 5 超出 20 块窗口,不会发生缓存命中,所有块都需要重新处理。但是,如果您在块 5 上设置了显式
cache_control断点,系统将继续从该断点检查:块 5(无匹配)→ 块 4(匹配!)。这允许在块 4 处缓存命中,演示了为什么应该在可编辑内容之前放置断点。
关键要点:始终在对话末尾设置显式缓存断点以最大化缓存命中的机会。此外,在可能可编辑的内容块之前设置断点,以确保这些部分可以独立缓存。
何时使用多个断点
如果您想要以下情况,可以定义最多 4 个缓存断点:
- 缓存以不同频率变化的不同部分(例如,工具很少变化,但上下文每天更新)
- 对缓存的内容有更多控制
- 确保缓存距离最终断点超过 20 个块的内容
- 在可编辑内容之前放置断点以保证缓存命中,即使在 20 块窗口之外发生更改
重要限制:如果您的提示词在缓存断点之前有超过 20 个内容块,并且您修改早于这 20 个块的内容,除非您在更接近该内容的地方添加额外的显式断点,否则您不会获得缓存命中。
缓存限制
最小可缓存提示词长度为:
- 对于 Claude Opus 4.1、Claude Opus 4、Claude Sonnet 4.5、Claude Sonnet 4、Claude Sonnet 3.7(已弃用)和 Claude Opus 3(已弃用),为 1024 个令牌
- 对于 Claude Haiku 4.5,为 4096 个令牌
- 对于 Claude Haiku 3.5 和 Claude Haiku 3,为 2048 个令牌
较短的提示词无法缓存,即使用 cache_control 标记也是如此。任何缓存少于此数量令牌的请求将在没有缓存的情况下处理。要查看提示词是否被缓存,请参阅响应使用字段。
对于并发请求,请注意缓存条目仅在第一个响应开始后才可用。如果您需要并行请求的缓存命中,请在发送后续请求之前等待第一个响应。
目前,"ephemeral"是唯一支持的缓存类型,默认生命周期为 5 分钟。
理解缓存断点成本
缓存断点本身不会增加任何成本。 您只需为以下内容付费:
- 缓存写入:当新内容写入缓存时(对于 5 分钟 TTL,比基础输入令牌多 25%)
- 缓存读取:当使用缓存内容时(基础输入令牌价格的 10%)
- 常规输入令牌:对于任何未缓存的内容
添加更多 cache_control 断点不会增加您的成本 - 您仍然根据实际缓存和读取的内容支付相同的金额。断点只是让您控制哪些部分可以独立缓存。
可以缓存的内容
请求中的大多数块都可以使用 cache_control 指定为缓存。这包括:
- 工具:
tools数组中的工具定义 - 系统消息:
system数组中的内容块 - 文本消息:
messages.content数组中的内容块,用于用户和助手轮次 - 图像和文档:
messages.content数组中的内容块,在用户轮次中 - 工具使用和工具结果:
messages.content数组中的内容块,在用户和助手轮次中
这些元素中的每一个都可以用 cache_control 标记以启用该部分请求的缓存。
无法缓存的内容
虽然大多数请求块都可以缓存,但有一些例外:
-
思考块无法直接用
cache_control缓存。但是,当思考块出现在先前的助手轮次中时,它们可以与其他内容一起缓存。以这种方式缓存时,它们在从缓存读取时确实计为输入令牌。 -
子内容块(如引用)本身无法直接缓存。相反,缓存顶级块。
在引用的情况下,作为引用源材料的顶级文档内容块可以缓存。这允许您通过缓存引用将引用的文档来有效地使用提示词缓存。
-
空文本块无法缓存。
什么使缓存失效
对缓存内容的修改可能会使部分或全部缓存失效。
如构建您的提示词中所述,缓存遵循层次结构:tools → system → messages。每个级别的更改会使该级别及所有后续级别失效。
下表显示了不同类型的更改使缓存的哪些部分失效。✘ 表示缓存失效,✓ 表示缓存保持有效。
| 什么改变 | 工具缓存 | 系统缓存 | 消息缓存 | 影响 |
|---|---|---|---|---|
| 工具定义 | ✘ | ✘ | ✘ | 修改工具定义(名称、描述、参数)会使整个缓存失效 |
| 网络搜索切换 | ✓ | ✘ | ✘ | 启用/禁用网络搜索会修改系统提示词 |
| 引用切换 | ✓ | ✘ | ✘ | 启用/禁用引用会修改系统提示词 |
| 工具选择 | ✓ | ✓ | ✘ | 对 tool_choice 参数的更改仅影响消息块 |
| 图像 | ✓ | ✓ | ✘ | 在提示词中的任何地方添加/删除图像会影响消息块 |
| 思考参数 | ✓ | ✓ | ✘ | 对扩展思考设置(启用/禁用、预算)的更改会影响消息块 |
| 传递给扩展思考请求的非工具结果 | ✓ | ✓ | ✘ | 当在启用扩展思考的请求中传递非工具结果时,所有先前缓存的思考块都会从上下文中删除,任何跟随这些思考块的上下文中的消息都会从缓存中删除。有关更多详情,请参阅使用思考块缓存。 |
跟踪缓存性能
使用这些 API 响应字段监控缓存性能,在响应中的 usage 内(或如果流式传输,则在 message_start 事件中):
cache_creation_input_tokens:创建新条目时写入缓存的令牌数。cache_read_input_tokens:为此请求从缓存检索的令牌数。input_tokens:未从缓存读取或用于创建缓存的输入令牌数。
有效缓存的最佳实践
要优化提示词缓存性能:
- 缓存稳定、可重用的内容,如系统指令、背景信息、大型上下文或频繁的工具定义。
- 将缓存内容放在提示词的开头以获得最佳性能。
- 战略性地使用缓存断点来分离不同的可缓存前缀部分。
- 在对话末尾和可编辑内容之前设置缓存断点以最大化缓存命中率,特别是在处理超过 20 个内容块的提示词时。
- 定期分析缓存命中率并根据需要调整您的策略。
针对不同用例的优化
根据您的场景定制您的提示词缓存策略:
- 对话代理:降低扩展对话的成本和延迟,特别是那些具有长指令或上传文档的对话。
- 编码助手:通过在提示词中保留相关部分或代码库的摘要版本来改进自动完成和代码库问答。
- 大型文档处理:在您的提示词中包含完整的长篇材料(包括图像),而不会增加响应延迟。
- 详细指令集:共享广泛的指令、程序和示例列表以微调 Claude 的响应。开发人员通常在提示词中包含一两个示例,但使用提示词缓存,您可以通过包含 20 多个高质量答案的多样化示例来获得更好的性能。
- 代理工具使用:增强涉及多个工具调用和迭代代码更改的场景的性能,其中每个步骤通常需要新的 API 调用。
- 与书籍、论文、文档、播客记录和其他长篇内容交谈:通过将整个文档嵌入提示词中并让用户提出问题来激活任何知识库。
排查常见问题
如果遇到意外行为:
- 确保缓存部分相同,并在调用中的相同位置用 cache_control 标记
- 检查调用是否在缓存生命周期内进行(默认 5 分钟)
- 验证
tool_choice和图像使用在调用之间保持一致 - 验证您缓存的令牌数至少是最小数量
- 系统自动检查先前内容块边界处的缓存命中(在您的断点之前约 20 个块)。对于超过 20 个内容块的提示词,您可能需要在提示词中较早的地方添加额外的
cache_control参数以确保所有内容都可以缓存 - 验证您的
tool_use内容块中的键具有稳定的排序,因为某些语言(例如 Swift、Go)在 JSON 转换期间随机化键顺序,破坏缓存
对 tool_choice 的更改或提示词中任何地方图像的存在/不存在将使缓存失效,需要创建新的缓存条目。有关缓存失效的更多详情,请参阅什么使缓存失效。
使用思考块缓存
当使用扩展思考与提示词缓存时,思考块具有特殊行为:
与其他内容自动缓存:虽然思考块无法使用 cache_control 显式标记,但当您使用工具结果进行后续 API 调用时,它们会作为请求内容的一部分被缓存。这通常发生在工具使用期间,当您传递思考块以继续对话时。
输入令牌计数:当思考块从缓存读取时,它们在您的使用指标中计为输入令牌。这对成本计算和令牌预算很重要。
缓存失效模式:
- 当仅提供工具结果作为用户消息时,缓存保持有效
- 当添加非工具结果用户内容时,缓存失效,导致所有先前的思考块被删除
- 即使没有显式
cache_control标记,也会发生此缓存行为
有关缓存失效的更多详情,请参阅什么使缓存失效。
工具使用示例:
请求 1:用户:"巴黎的天气如何?"
响应:[thinking_block_1] + [tool_use block 1]
请求 2:
用户:["巴黎的天气如何?"],
助手:[thinking_block_1] + [tool_use block 1],
用户:[tool_result_1, cache=True]
响应:[thinking_block_2] + [text block 2]
# 请求 2 缓存其请求内容(不是响应)
# 缓存包括:用户消息、thinking_block_1、tool_use block 1 和 tool_result_1
请求 3:
用户:["巴黎的天气如何?"],
助手:[thinking_block_1] + [tool_use block 1],
用户:[tool_result_1, cache=True],
助手:[thinking_block_2] + [text block 2],
用户:[文本响应, cache=True]
# 非工具结果用户块指定新的助手循环,所有先前的思考块都被删除
# 此请求的处理方式就像思考块从未存在过一样当包含非工具结果用户块时,它指定新的助手循环,所有先前的思考块都从上下文中删除。
有关更多详细信息,请参阅扩展思考文档。
缓存存储和共享
-
组织隔离:缓存在组织之间隔离。不同的组织永远不会共享缓存,即使他们使用相同的提示词。
-
精确匹配:缓存命中需要 100% 相同的提示词段,包括直到并包括用缓存控制标记的块的所有文本和图像。
-
输出令牌生成:提示词缓存对输出令牌生成没有影响。您收到的响应将与不使用提示词缓存时收到的响应相同。
1 小时缓存持续时间
如果您发现 5 分钟太短,Anthropic 还提供 1 小时缓存持续时间需额外付费。
要使用扩展缓存,请在 cache_control 定义中包含 ttl,如下所示:
"cache_control": {
"type": "ephemeral",
"ttl": "5m" | "1h"
}响应将包含详细的缓存信息,如下所示:
{
"usage": {
"input_tokens": ...,
"cache_read_input_tokens": ...,
"cache_creation_input_tokens": ...,
"output_tokens": ...,
"cache_creation": {
"ephemeral_5m_input_tokens": 456,
"ephemeral_1h_input_tokens": 100,
}
}
}请注意,当前 cache_creation_input_tokens 字段等于 cache_creation 对象中的值之和。
何时使用 1 小时缓存
如果您有定期使用的提示词(即每 5 分钟以上使用一次的系统提示词),继续使用 5 分钟缓存,因为这将继续以无额外成本的方式刷新。
1 小时缓存最适合用于以下场景:
- 当您有可能每 5 分钟使用不到一次,但每小时使用超过一次的提示词时。例如,当代理端代理将花费超过 5 分钟时,或者当存储与用户的长聊天对话时,您通常期望该用户在接下来的 5 分钟内可能不会响应。
- 当延迟很重要且您的后续提示词可能在 5 分钟后发送时。
- 当您想改进速率限制利用率时,因为缓存命中不会从您的速率限制中扣除。
5 分钟和 1 小时缓存在延迟方面的行为相同。对于长文档,您通常会看到改进的首令牌时间。
混合不同的 TTL
您可以在同一请求中使用 1 小时和 5 分钟缓存控制,但有一个重要的限制:较长 TTL 的缓存条目必须出现在较短 TTL 之前(即 1 小时缓存条目必须出现在任何 5 分钟缓存条目之前)。
混合 TTL 时,我们在您的提示词中确定三个计费位置:
- 位置
A:最高缓存命中处的令牌计数(如果没有命中,则为 0)。 - 位置
B:在A之后最高 1 小时cache_control块处的令牌计数(如果不存在,则等于A)。 - 位置
C:最后一个cache_control块处的令牌计数。
如果 B 和/或 C 大于 A,它们必然是缓存未命中,因为 A 是最高缓存命中。
您将被收费:
- 位置
A的缓存读取令牌。 - 位置
(B - A)的 1 小时缓存写入令牌。 - 位置
(C - B)的 5 分钟缓存写入令牌。
以下是 3 个示例。这描绘了 3 个请求的输入令牌,每个请求都有不同的缓存命中和缓存未命中。每个都有不同的计算定价,如彩色框所示。
提示词缓存示例
为了帮助您开始使用提示词缓存,我们准备了一个提示词缓存食谱,其中包含详细的示例和最佳实践。
以下是展示各种提示词缓存模式的几个代码片段。这些示例演示了如何在不同场景中实现缓存,帮助您理解此功能的实际应用: