一、工作原理与核心概念

Prompt Caching 架构图

Prompt Caching 是 Anthropic 为 Claude API 推出的一项优化功能,核心思路极其简单:把那些每次请求都不变的内容缓存起来,后续请求直接复用,不再重新计算 Token

对于需要频繁调用 Claude 的应用(比如文档问答、代码审查、多轮对话助手),大量 Token 消耗其实来自于每次都要重复传入的系统提示、背景文档、示例数据等"静态内容"。开启 Prompt Caching 后,这些内容只需支付一次写入费用,后续读取时价格仅为原始价格的 10%。

缓存的工作流程

每次 API 请求到达 Anthropic 服务器时,系统会按以下顺序检查缓存:

  1. 计算请求中标记为可缓存部分的加密哈希值
  2. 在当前 Organization 的缓存池中查找匹配项
  3. 命中缓存(Cache Hit):直接使用已缓存的 KV 表示,跳过重新计算
  4. 未命中(Cache Miss):正常处理全部 Token,处理完成后将结果写入缓存
ℹ️
缓存的隐私性:缓存按 Organization 隔离,不同账户之间完全独立。Anthropic 只存储 KV 缓存表示(加密哈希),不存储原始 Prompt 文本,满足 ZDR(Zero Data Retention)类似的数据保留要求。

关键参数一览

参数 说明
默认 TTL(存活时间) 5 分钟 每次命中缓存自动刷新计时
延长 TTL 选项 1 小时 额外费用约为基础输入 Token 的 2×
最大缓存断点数 4 个 超过 4 个断点会返回 400 错误
最小可缓存长度(Sonnet/Opus) 1024 tokens 低于此长度不触发缓存
最小可缓存长度(Haiku 3.5) 2048 tokens Haiku 系列门槛更高

二、环境准备与 SDK 安装

环境配置流程图

Prompt Caching 在最新版 Anthropic SDK 中已全面支持,无需手动添加 Beta Header。以下以 Python 为例完成环境搭建。

1
安装或升级 Anthropic Python SDK

确保 SDK 版本 ≥ 0.30.0,旧版需要手动传递 anthropic-beta Header,新版已内置支持。

Shell
pip install --upgrade anthropic
# 验证版本
python -c "import anthropic; print(anthropic.__version__)"
2
配置 API Key

推荐使用环境变量,避免硬编码到代码中。

Shell
export ANTHROPIC_API_KEY="sk-ant-xxxxxxxxxxxxxxxx"

或者在 Python 代码中显式传入(仅适合测试环境):

Python
import anthropic
client = anthropic.Anthropic(api_key="sk-ant-xxxxxxxxxxxxxxxx")
3
验证 API 连通性

发送一条简单请求,确认账号配置正确。

Python
import anthropic

client = anthropic.Anthropic()
resp = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=32,
    messages=[{"role": "user", "content": "Hello, reply with 'OK' only."}]
)
print(resp.content[0].text)  # 应输出 OK
支持的模型列表(截至 2026 年 2 月):Claude Haiku 3、Claude Haiku 4.5、Claude Sonnet 3.5/3.7、Claude Opus 4.1/4.5/4.6。建议使用最新的 claude-opus-4-6claude-sonnet-3-7 获取最佳缓存支持。

三、显式缓存:手动控制缓存断点

显式缓存实现流程

显式缓存是 Prompt Caching 的经典用法,通过在消息块上添加 cache_control 字段,精确标记哪些内容应该被缓存。

场景示例:长文档问答系统

假设你在做一个 PDF 文档问答系统,每次请求都要传入完整文档内容(数万字)。这是显式缓存最典型的适用场景。

1
构建带缓存断点的 System Prompt

将系统角色指令和文档内容分开,分别标记 cache_control。缓存前缀按 tools → system → messages 的层级顺序创建。

Python
import anthropic

client = anthropic.Anthropic()

# 模拟一份长文档(实际使用中替换为真实内容)
long_document = """
[这里是一份数万字的技术文档,每次问答都相同...]
第一章:系统架构
...
第二章:接口规范
...
"""  # 假设此处超过 1024 tokens

response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "你是一位专业的技术文档分析助手,请根据提供的文档回答用户的问题。",
            # 第一个缓存断点:角色指令
            "cache_control": {"type": "ephemeral"}
        },
        {
            "type": "text",
            "text": f"以下是完整的参考文档:\n\n{long_document}",
            # 第二个缓存断点:文档内容(最大收益处)
            "cache_control": {"type": "ephemeral"}
        }
    ],
    messages=[
        {
            "role": "user",
            "content": "请简述第二章的接口规范中关于认证的部分。"
        }
    ]
)

print(response.content[0].text)
# 查看缓存使用情况
usage = response.usage
print(f"\n=== Token 使用情况 ===")
print(f"输入 Token:       {usage.input_tokens}")
print(f"缓存写入 Token:   {usage.cache_creation_input_tokens}")
print(f"缓存命中 Token:   {usage.cache_read_input_tokens}")
print(f"输出 Token:       {usage.output_tokens}")
2
第二次请求:验证缓存命中

5 分钟内用相同文档发送第二个问题,应该看到 cache_read_input_tokens 数值大幅增加,cache_creation_input_tokens 降为 0。

Python
response2 = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "你是一位专业的技术文档分析助手,请根据提供的文档回答用户的问题。",
            "cache_control": {"type": "ephemeral"}
        },
        {
            "type": "text",
            "text": f"以下是完整的参考文档:\n\n{long_document}",
            "cache_control": {"type": "ephemeral"}
        }
    ],
    messages=[
        {
            "role": "user",
            "content": "请列举文档中提到的所有 HTTP 状态码。"  # 不同的问题
        }
    ]
)

usage2 = response2.usage
print(f"=== 第二次请求 Token 使用情况 ===")
print(f"输入 Token:       {usage2.input_tokens}")
print(f"缓存写入 Token:   {usage2.cache_creation_input_tokens}")  # 应为 0
print(f"缓存命中 Token:   {usage2.cache_read_input_tokens}")       # 应大幅增加
print(f"输出 Token:       {usage2.output_tokens}")
⚠️
缓存失效的常见原因:只要标记了 cache_control 的内容有任何变化(哪怕一个字符),缓存就会失效并重新写入。同理,如果在 System Prompt 之前的 tools 定义发生变更,后续所有断点的缓存也会连带失效。

四、自动缓存:零改动享受缓存

自动缓存 vs 显式缓存对比

如果你不想修改现有代码结构,自动缓存(Automatic Caching)是最低成本的接入方案。只需在请求顶层添加一个字段,系统自动为最后一个可缓存块打上断点,并随着对话历史增长自动移动缓存位置。

显式缓存 vs 自动缓存

维度 显式缓存 自动缓存
接入复杂度 需修改每个消息块结构 顶层一行配置即可
控制粒度 精确控制缓存位置 自动选择最后可缓存块
多轮对话支持 需手动管理断点位置 自动跟随对话增长
最大断点数 4 个(手动) 1 个(自动)
适用场景 固定大文档、精细优化 多轮聊天、快速接入

自动缓存代码示例

Python — 多轮对话自动缓存
import anthropic

client = anthropic.Anthropic()

# 对话历史
conversation_history = []

def chat(user_message: str) -> str:
    """支持缓存的多轮对话函数"""
    conversation_history.append({
        "role": "user",
        "content": user_message
    })

    response = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=1024,
        # ✅ 自动缓存:只需这一个字段,无需修改 system/messages 结构
        betas=["prompt-caching-2024-07-31"],
        extra_body={
            "cache_control": {"type": "ephemeral"}  # 顶层缓存控制
        },
        system="你是一位有经验的软件架构师,擅长系统设计与代码审查。",
        messages=conversation_history
    )

    assistant_message = response.content[0].text
    conversation_history.append({
        "role": "assistant",
        "content": assistant_message
    })

    # 输出 Token 使用情况
    u = response.usage
    cache_hit = getattr(u, 'cache_read_input_tokens', 0)
    cache_write = getattr(u, 'cache_creation_input_tokens', 0)
    print(f"[缓存命中: {cache_hit} | 缓存写入: {cache_write} | 输出: {u.output_tokens}]")

    return assistant_message

# 模拟多轮对话
print(chat("请帮我设计一个高并发的消息队列系统"))
print(chat("这个系统应该如何处理消息丢失的问题?"))
print(chat("能给出 Go 语言的实现示例吗?"))
多轮对话的缓存效果:随着对话历史增长,每轮请求中历史消息的 Token 数会不断累积。自动缓存会将这些历史消息缓存起来,第 N 轮对话时,前 N-1 轮的内容几乎全部命中缓存,成本节省效果随对话轮次递增。

五、进阶技巧与最佳实践

缓存最佳实践信息图

1. 延长缓存到 1 小时

默认 5 分钟 TTL 适合快速交互,但对于慢速批处理任务,5 分钟内可能无法完成足够多的请求来充分利用缓存。此时可以升级到 1 小时 TTL:

Python
response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "你的系统提示...",
            # 使用 1 小时缓存(需要额外费用)
            "cache_control": {"type": "ephemeral", "ttl": 3600}
        }
    ],
    messages=[{"role": "user", "content": "用户问题"}]
)

2. 结合 Tool Use 使用缓存

如果你的应用使用了 Function Calling(Tool Use),工具定义也可以被缓存。注意工具定义的缓存断点优先级高于 System Prompt:

Python
tools = [
    {
        "name": "search_database",
        "description": "搜索产品数据库",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {"type": "string"},
                "category": {"type": "string"}
            },
            "required": ["query"]
        },
        # ✅ 工具定义也可以缓存
        "cache_control": {"type": "ephemeral"}
    }
    # 更多工具定义...(最多配合 3 个其他断点,总计不超过 4 个)
]

response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    tools=tools,
    system=[{
        "type": "text",
        "text": "你是一位购物助手...",
        "cache_control": {"type": "ephemeral"}
    }],
    messages=[{"role": "user", "content": "帮我找一款蓝牙耳机"}]
)

3. 批量任务中的缓存策略

对于需要对同一份文档做大量分析的批量任务,推荐使用以下模式,最大化缓存收益:

Python
import asyncio
import anthropic

client = anthropic.Anthropic()

# 一份固定文档,需要用 N 个不同 Prompt 分析
document_content = "... 大型文档内容 ..."

analysis_tasks = [
    "提取所有人名和机构名",
    "总结文档的主要论点",
    "找出文中的数据和统计信息",
    "分析作者的写作风格",
    "列出所有引用的参考文献",
]

def analyze(task: str) -> dict:
    resp = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=512,
        system=[
            {
                "type": "text",
                "text": "你是专业文档分析助手。",
                "cache_control": {"type": "ephemeral"}
            },
            {
                "type": "text",
                "text": f"待分析文档:\n{document_content}",
                "cache_control": {"type": "ephemeral"}  # 核心:文档只写入一次
            }
        ],
        messages=[{"role": "user", "content": task}]
    )
    u = resp.usage
    return {
        "task": task,
        "result": resp.content[0].text,
        "cache_hit": getattr(u, 'cache_read_input_tokens', 0),
        "cache_miss": getattr(u, 'cache_creation_input_tokens', 0)
    }

# 串行执行(或改为并发执行)
results = [analyze(t) for t in analysis_tasks]
for r in results:
    print(f"任务: {r['task'][:20]}...")
    print(f"  缓存命中: {r['cache_hit']} tokens, 缓存写入: {r['cache_miss']} tokens\n")
💡
缓存最大化原则:始终将最稳定、最长的内容放在 Prompt 最开头,变化频繁的内容(用户输入)放在最末尾。缓存是前缀匹配,内容越靠前、越稳定,缓存命中率越高。

六、成本计算与效果评估

成本分析信息图

最新定价(Claude Opus 4.6,每百万 Token)

基础输入 Token
$5.00
per million tokens
缓存写入(5min TTL)
$6.25
+25% 溢价
缓存写入(1h TTL)
$10.00
+100% 溢价
缓存命中(读取)
$0.50
节省 90%!

实际成本计算示例

假设你有一份 10,000 tokens 的文档,每天被查询 100 次

Python — 成本估算计算器
def calculate_cache_savings(
    doc_tokens: int,
    daily_requests: int,
    model: str = "claude-opus-4-6"
):
    """计算 Prompt Caching 的成本节省"""
    pricing = {
        "claude-opus-4-6": {
            "input": 5.0,          # $5 per MTok
            "cache_write_5m": 6.25, # $6.25 per MTok
            "cache_read": 0.50,    # $0.50 per MTok
        }
    }
    p = pricing[model]
    MTok = 1_000_000

    # 不使用缓存
    cost_no_cache = (doc_tokens * daily_requests / MTok) * p["input"]

    # 使用缓存(每 5 分钟最多被使用一次,假设请求均匀分布 8 小时内)
    cache_writes_per_day = 8 * 60 / 5  # 96 次写入
    cache_reads_per_day = daily_requests - cache_writes_per_day

    cost_with_cache = (
        (doc_tokens * cache_writes_per_day / MTok) * p["cache_write_5m"] +
        (doc_tokens * cache_reads_per_day / MTok) * p["cache_read"]
    )

    saving = cost_no_cache - cost_with_cache
    saving_pct = saving / cost_no_cache * 100

    print(f"=== 文档规模: {doc_tokens:,} tokens | 每日请求: {daily_requests} 次 ===")
    print(f"不使用缓存日成本:  ${cost_no_cache:.4f}")
    print(f"使用缓存后日成本:  ${cost_with_cache:.4f}")
    print(f"每日节省:          ${saving:.4f}  ({saving_pct:.1f}%)")
    print(f"每月节省(30天):    ${saving * 30:.2f}")

# 测试不同场景
calculate_cache_savings(doc_tokens=10_000, daily_requests=100)
print()
calculate_cache_savings(doc_tokens=50_000, daily_requests=500)
print()
calculate_cache_savings(doc_tokens=100_000, daily_requests=1000)

如何在 Anthropic Console 监控缓存效果

登录 console.anthropic.com,进入「Usage」→「Prompt Caching」面板,可以查看:

  • 缓存命中率(Cache Hit Rate)趋势
  • 各类 Token 用量分布(输入 / 缓存写入 / 缓存读取 / 输出)
  • 按模型、按时间段的成本分解

七、常见问题排查

常见问题排查流程
缓存从来不命中(cache_read_input_tokens 始终为 0)
最常见原因是可缓存内容不足最小 Token 数(Sonnet/Opus 需 1024 tokens,Haiku 需 2048 tokens)。建议先用 client.messages.count_tokens() 检查实际 Token 数。另一个原因是两次请求间隔超过 5 分钟,缓存已过期。
收到 400 错误:cache breakpoints exceeded
单次请求中显式 cache_control 断点超过了 4 个上限。检查 toolssystemmessages 中的所有 cache_control 字段,确保总数 ≤ 4。工具定义中的断点也计入总数。
文档内容加了图片/附件后缓存失效
缓存是基于完整内容的哈希计算的。在 cache_control 断点之前的任何内容(包括图片、工具调用结果)发生变化,都会导致该断点及其后续断点缓存失效。建议将图片类内容放在缓存断点之后,仅缓存纯文本静态部分。
并发请求时缓存命中率低
高并发下,多个请求可能同时触发缓存写入(而非命中)。这是正常现象,Anthropic 服务器会在第一个响应返回后才正式将缓存写入。解决方案:先用单个"预热"请求建立缓存,再并发发送后续请求;或等待第一批响应返回后再启动第二批。
使用 Bedrock 或 Vertex AI 时如何启用缓存?
截至 2026 年初,自动缓存在 Claude API 和 Azure AI Foundry(预览版)上可用。Amazon Bedrock 和 Google Vertex AI 正在推进支持。显式缓存(cache_control)可通过这些平台的 Claude API 直接访问路径使用,具体请参阅各平台最新文档。
缓存内容有安全风险吗?
缓存按 Organization 严格隔离,不同账户间无法互访。Anthropic 仅存储 KV 缓存表示(加密哈希),不存储原始 Prompt 文本。对于有 ZDR(零数据保留)需求的企业用户,缓存机制可满足相关数据合规要求。

核心要点回顾

  • Prompt Caching 通过复用静态内容,最高节省 90% 输入 Token 成本、85% 响应延迟
  • 显式缓存(cache_control 字段)适合固定文档场景,最多 4 个断点
  • 自动缓存(顶层配置)适合多轮对话,随对话增长自动移动缓存位置
  • 最小缓存长度:Sonnet/Opus 为 1024 tokens,Haiku 为 2048 tokens
  • 缓存默认 TTL 5 分钟,可付费升级到 1 小时;写入比基础价贵 25%,读取便宜 90%
  • 静态内容放前面、动态内容放后面,是最大化缓存命中的黄金法则
  • 通过 usage.cache_read_input_tokens 实时监控缓存命中情况

Prompt Caching 是 Claude API 中为数不多的"用了就能立刻省钱"的功能,无论你是构建 RAG 系统、多轮对话助手,还是批量文档处理管线,只要有重复使用的静态内容,都值得立刻接入。

Prompt Caching Claude API 成本优化 Python SDK 多轮对话 RAG