返回博客
指南·2026年5月24日·阅读约 8 分钟

Anthropic 提示词缓存——30 分钟内将输入账单降低 90%

完整解析:cache_control 如何工作,为什么 OpenAI 格式需要 Kunavo 为你设置断点,代理循环的四断点模式,哪些情况会悄悄破坏缓存,以及如何验证命中率不为零。包含 Kunavo 按模型提供的缓存费率。

如果你发送很长的系统提示词——RAG 上下文、工具目录、代理规则、示例——你可能每次调用都在支付完整的输入价格。Anthropic 的提示缓存会将缓存部分的费用降至费率的 10%。OpenAI 会在后台隐式执行相同的操作。大多数团队认为这 30 分钟的工作值得,因为它能稳定地将输入费用这一项降低 60–90%。

Kunavo 两种都支持。你自己的 cache_control 分界点会原样传递给 Messages API;而在 Chat Completions 和 Responses API 中,格式没有可发送的此类字段,Kunavo 会替你设置分界点,并在你发送的内容周围补充分界点,同时绝不会超过 4 个的上限。本文将介绍两种情况、会悄悄使缓存失效的陷阱,以及如何验证命中率。

前后对比

一个朴素循环,将相同的 18K token 系统提示词发送十次:

naive.py
# What most people start with: every call re-pays for the whole prompt.
import anthropic

client = anthropic.Anthropic(
    api_key="sk-kn-...",
    base_url="https://api.kunavo.com",
)

SYSTEM = open("system-prompt.md").read()        # 18,000 tokens of rules + examples

# 10 user questions in a session. Every call sends the 18K-token system block.
for question in questions:
    resp = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=600,
        system=SYSTEM,
        messages=[{"role": "user", "content": question}],
    )

# Cost per call (input only): 18,000 × $3 / 1M = $0.054
# 10 calls: $0.54 in input alone.

现在将系统块标记为可缓存——只需增加一个字段:

cached.py
# The fix: mark the static prefix as cacheable. After the first call,
# subsequent calls within ~5 minutes pay 10% the input rate on the cached
# portion. Same answer, 89% cheaper.
resp = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=600,
    system=[
        {
            "type": "text",
            "text": SYSTEM,
            "cache_control": {"type": "ephemeral"},  # mark cacheable
        }
    ],
    messages=[{"role": "user", "content": question}],
)

# First call (cache write):  18,000 × $3.75 / 1M = $0.0675  (1.25× input)
# Calls 2–10 (cache hit):    18,000 × $0.30 / 1M = $0.0054 each
# Total: $0.0675 + 9 × $0.0054 = $0.116  (was $0.54 — 78.5% saved)

你刚刚节省了本次会话输入费用的 78.5%。第一次调用实际上比朴素版本稍微更贵(写入缓存约为输入费率的 1.25 倍)。第 2 到第 10 次调用按 10% 的费率计费。转折点在第 2 次调用——到第 3 次时你已经节省费用。到第 10 次时,差距已经非常明显。

OpenAI 风格:无需操作

OpenAI Chat Completions 格式没有 cache_control 字段,因为 OpenAI 会在自己的服务器上隐式缓存。Claude 不会这样做——它只缓存分界点标记的内容。因此,当你通过 /v1/chat/completions 或 /v1/responses 使用 Claude 模型时,Kunavo 会替你设置分界点:当对话至少包含一轮 assistant 后,在最后一条消息上设置一个滚动分界点,然后在 system 之后和 tools 之后各设置一个。在模型首次回答之后发送的 system 或 developer 消息会留在对话中,而不会被提升到 system(除非它自己的分界点要求一小时缓存)。如果请求以这样一条消息结尾,滚动分界点会放在紧挨着它前面的那个块上;剩余可用的分界点则放在最后几条后面还有内容的此类消息前面。你自己设置的任何分界点都会保持原位——Kunavo 只填充你留空的位置,并且最多填充到 4 个。无需配置,无论通过 Anthropic 路线还是 OpenAI 路线接入,同一模型的费用都相同:

openai_style.py
# OpenAI Chat Completions style — Kunavo sets the breakpoints for you.
# No flag to set. The "usage" object tells you what was cached.
from openai import OpenAI

client = OpenAI(
    api_key="sk-kn-...",
    base_url="https://api.kunavo.com/v1",
)

resp = client.chat.completions.create(
    model="claude-sonnet-4-6",
    messages=[
        {"role": "system", "content": LONG_SYSTEM_PROMPT},  # >1024 tokens
        {"role": "user", "content": "Latest question…"},
    ],
)

# In the response:
#   resp.usage.prompt_tokens_details.cached_tokens  →  17,800
#   resp.usage.prompt_tokens                        →  18,200
# 17.8K/18.2K = 98% of input came from cache. Bill reflects that automatically.

阅读 usage.prompt_tokens_details.cached_tokens,查看有多少内容来自缓存。固定前缀越大,节省越多。经验法则是:如果系统提示词短于可变的用户内容,缓存的作用就不大。重新组织提示词,让静态部分更大并置于前面。

多层缓存——最多 4 个分界点

对于不同层变化速度不同的代理循环,设置多个 cache_control 分界点。每个分界点都是截至该位置的全部内容的快照:

breakpoints.py
# Anthropic supports up to 4 cache breakpoints per request — use them
# to keep the cache hot even as later layers change.
client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=600,
    system=[
        {"type": "text",
         "text": ROLE_AND_RULES,                      # ~3,000 tokens
         "cache_control": {"type": "ephemeral"}},     # breakpoint 1
        {"type": "text",
         "text": LARGE_KNOWLEDGE_BASE,                # ~15,000 tokens, rarely changes
         "cache_control": {"type": "ephemeral"}},     # breakpoint 2
    ],
    messages=[
        {"role": "user",
         "content": [
             {"type": "text",
              "text": CONVERSATION_HISTORY,           # grows each turn
              "cache_control": {"type": "ephemeral"}}, # breakpoint 3
             {"type": "text", "text": new_question},
         ]},
    ],
)

# When CONVERSATION_HISTORY changes, breakpoints 1+2 still hit cache.
# Only breakpoint 3 + the new question pay full input rate.

缓存键是整个前缀。在位置 N 添加一个 token,会使 N 及其之后的每个分界点失效。顺序很重要:最稳定的内容放在最前面。规则层应该很少变化;知识库每周更新;对话每轮增长。

悄悄破坏缓存的常见方式

  • 在提示词中放入当前日期或 request_id。每次调用都会产生新的前缀,缓存命中率为 0%。请对提示词输入进行哈希,并在多次调用之间比较。
  • 以非确定方式组装系统提示词。如果你从字典构建系统提示词,某些 Python 版本中的字典迭代顺序会产生影响。请显式地对键排序。
  • 缓存生命周期约为 5 分钟。流量稀疏时(每 10 分钟调用一次)不会命中缓存。要么批量调用,要么接受这项损失。
  • 1,024 token 的最低要求。低于 1K token 时,OpenAI 风格的缓存不会启用。请将较小的静态片段合并为一个更长的前缀。
  • 工具/函数定义属于前缀的一部分。向目录添加新工具会使所有人的缓存失效。保持工具目录稳定,并对其进行版本管理。

验证命中率

看不见的缓存不是工程,而是祈祷。每次调用都记录 usage:

observe.py
# Always read usage. If cached_tokens is 0 when you expected a hit,
# something's wrong — usually a non-deterministic prefix.
resp = client.messages.create(...)
u = resp.usage
print({
    "input_uncached":  u.input_tokens,
    "input_cache_read": u.cache_read_input_tokens,
    "input_cache_write": u.cache_creation_input_tokens,
    "output": u.output_tokens,
})

# A common gotcha: putting today's date or a request_id in the system prompt
# silently invalidates the cache. Hash your inputs; verify cache_read_input_tokens
# is non-zero on the 2nd identical call.

在 Kunavo 控制台中,使用情况页面会按模型、按天显示缓存拆分。如果你看到 cache_read_input_tokens 占总输入的比例不断增加,说明缓存正在生效。如果它保持为 0 或剧烈波动,请逐项检查上面的陷阱清单。

在 Kunavo 上实际要花多少钱

每个模型的缓存费率都公布在价格页面:

  • Anthropic 模型:缓存读取为输入费率的 10%——在Claude Fable 5.1上的比例为2.5%,在Claude Opus 5.5上的比例为5%。缓存写入为输入费率的 1.25 倍——这是 Anthropic 的五分钟倍率;Kunavo 对一小时写入也按 1.25 倍计费,低于 Anthropic 的 2 倍。
  • OpenAI / Gemini 模型:缓存读取为输入费率的 10%(供应商公布的比例)。GPT-5.6 和 GPT-6 Astra 的缓存写入为 1.25 倍,其他所有模型均按普通输入费率计费。
  • 所有缓存价格都已经包含 Kunavo 的模型折扣(按模型低于上游标价)。因此,Kunavo 上的 Sonnet 4.6 缓存读取价格为 $3 × 0.40 × 0.10 = $0.12 per 1M tokens,比未缓存的上游费率便宜约 25 倍。

缓存不是答案的情况

以下几种情况下,投入可能不值得:

  • 短提示词(总计 <1K token)。开销占主导,直接不要使用缓存。
  • 没有重复流量的一次性任务。第一次调用会稍微更贵,缓存只有从第 2 次调用开始才会回本。
  • 高输出、低输入的任务(创意写作、代码生成)。输入本来就只占账单的一小部分。应将重点放在输出预算上限。

对于其他所有情况——RAG 聊天机器人、使用固定工具目录的代理、基于静态评分标准运行的分类器、使用一致 few-shot 示例的结构化提取流水线——缓存是你在一个下午内就能上线、投资回报率最高的优化。将其与我们的成本优化指南中的另外四种技术结合,在不牺牲任何输出质量的情况下,将成本降低 70% 是现实可行的。

已经在使用 Kunavo?打开 /app/usage,查看你最大模型的缓存列。如果是零,你就白白损失了节省机会。完整指南:/docs/caching。