提示缓存(四):文档说 4096,实测 1024

AWS 文档给 Claude Sonnet 4.5 标的最小可缓存前缀是 4096 token。我在 Bedrock 上做了 20 多次夹逼调用,真实门槛是 1024——和 Anthropic 一方 API 一样。同时验证了另外三个模型,其中三个文档准确,只有 Sonnet 4.5 这一条错了 4 倍。

zhuermu··10 分钟阅读

先说结论。

AWS Bedrock 文档给 Claude Sonnet 4.5 标的最小可缓存前缀是 4,096 token。我实测的结果是 1,024——和 Anthropic 一方 API 完全一样。文档这一行错了 4 倍。

这不是笼统的「文档不可信」。我用同一套方法测了四个模型,三个都和文档吻合,只有 Sonnet 4.5 这一条不对。所以真正的结论是更实用的那个:门槛这种数字必须自己验一次,而验一次只需要两个请求。

整个实验在一台 EC2 上用 AWS CLI 做完,Sonnet 4.5 那部分 16 次调用花了 $0.0887。

为什么值得测#

上一篇平台对比里,我把「同一个 Claude 模型在不同平台门槛不同」当成核心论点,数字全部来自官方文档。写完之后我发现一个方法论问题:我的实验设计根本没法验证那个数字。

最初我只测了两个点——566 token(不缓存)和 4,401 token(缓存),然后宣称「低于 4,096 不缓存」。但 567 到 4,400 这三千多 token 的区间我一个点都没碰。那句结论是从文档抄的,只是被摆在了实测数据旁边,看起来像被验证过。

这是个很容易犯的错:用一个不能区分假设的实验,去”确认”一个你已经相信的数字。 补上夹逼测试之后,文档就露馅了。

实验环境#

日期         2026-08-17 12:00 CST
平台         AWS Bedrock, us-east-1, US inference profile
调用方式     AWS CLI v2.36.23
               Claude:  bedrock-runtime converse    (cachePoint)
               GPT-5.6: bedrock-runtime invoke-model (prompt_cache_breakpoint)
判定标准     响应 usage 里 cacheWrite/cacheRead 任一非零 = 缓存生效
Sonnet 4.5 部分实付   $0.0887(16 次调用)

前缀用 The quick brown fox jumps over the lazy dog. 重复拼接,靠改变重复次数来调 token 数。注意各模型分词器不同——同样 70 段文本,Sonnet 4.5 算出 779 token,Sonnet 5 算出 1,271 token,所以每个模型的重复次数要单独校准。

Claude Sonnet 4.5:二分定位#

totalInput    是否缓存
     566        NO
     779        NO
     944        NO
     999        NO      ← 下界
   1,054       YES      ← 上界,跨越点
   1,211       YES
   1,541       YES
   2,421       YES      ← 文档说这里应该不缓存
   3,741       YES      ← 文档说这里也应该不缓存
   4,401       YES

跨越点夹在 999 和 1,054 之间,也就是 1,024

而 2,421 和 3,741 这两个点是直接反证:它们都低于文档写的 4,096,却都正常写入并命中。

三个对照模型:文档都是对的#

如果只测 Sonnet 4.5,我没法区分「文档写错了」和「文档整体不可信」。所以加了三个对照。

模型文档门槛实测下界(不缓存)实测上界(缓存)判定
Claude Sonnet 4.54,0969991,054文档偏高 4 倍
Claude Sonnet 4.61,0241,0001,055✅ 吻合
Claude Sonnet 5表中未列9831,055实测 1,024
GPT-5.6 Terra1,0248171,504✅ 吻合

四个模型的真实门槛全部是 1,024。 文档里唯一与实测不符的就是 Sonnet 4.5 那一行的 4,096。

这个分布让结论变得可靠:不是我的测法有问题(否则三个对照也该偏),也不是 Bedrock 文档整体不可信(三个都准),而是具体那一行数据不对。至于是当初写错、还是模型上线后门槛下调过而文档没跟着更新,从外部看不出来。

缓存生效时长什么样#

Sonnet 4.5,4,401 token 前缀,连续两次相同前缀:

第一次   cacheWriteInputTokens = 4401   cacheRead = 0     inputTokens = 15
第二次   cacheWrite = 0                 cacheRead = 4401  inputTokens = 15

cacheDetails 还会告诉你写入用的是哪个档位:

"cacheDetails": [ { "ttl": "5m", "inputTokens": 4401 } ]

注意 inputTokens 只有 15——它表示的是断点之后那部分,不是总输入。总输入要三项相加:inputTokens + cacheReadInputTokens + cacheWriteInputTokens。这是算成本时最容易出错的地方。

命中带来的节省是实打实的:4,401 token 的前缀走全价是 $0.01337,命中后是 $0.00149,省 89%

不达门槛时到底有多安静#

这是整件事最需要警惕的部分。999 token 的那次调用,完整 usage 是:

{
    "inputTokens": 999,
    "outputTokens": 8,
    "totalTokens": 1007,
    "cacheReadInputTokens": 0,
    "cacheWriteInputTokens": 0
}

没有 error、没有 warning、没有「你的 cachePoint 被忽略了因为……」。模型正常回答,totalTokens 看着合理。除非你专门去看那两个缓存字段,否则一切正常。

GPT-5.6 在 817 token 时同样安静,只是字段名不同——它在 usage.prompt_tokens_details.{cached_tokens, cache_write_tokens} 里。

顺带一个平台差异:GPT-5.6 在 Bedrock 上走的不是 Converse API。 给它发 cachePoint 会返回 AccessDeniedException,提示信息是「你调用了不支持的模型,或你的请求不允许提示缓存」——这句话会把人带向错误方向,让你以为模型不支持缓存。实际上它支持,只是要用 invoke-model 配 Chat Completions 格式的 body,断点参数叫 prompt_cache_breakpoint。而且它不接受 max_tokens,要用 max_completion_tokens

你该做的两件事#

第一,别信门槛数字,自己验。 方法就是上面这个:拿一个刚好在你怀疑的门槛附近的前缀,发两次,看 usage。两个请求、几分钱、一分钟。你可以顺手用 token 计数器 先量一下自己 system prompt 加工具定义有多少 token,再决定测哪个区间。

第二,把缓存命中打进监控。 无论门槛是多少,不达标时的失败都是静默的。cacheRead 长期为零就该告警——这是唯一能让静默失败发出声音的办法。具体怎么做在排查篇里有脚本。

一个附带的好消息:既然 Sonnet 4.5 的真实门槛是 1,024 而不是 4,096,如果你之前因为文档而认为自己的 prompt 太短用不上缓存,现在可以回去重新算一遍。 1,024 token 是个很低的门槛,一个像样的 system prompt 加几个工具定义基本就够了。

本系列:原理篇平台对比篇排查篇 → 本篇(实测)

参考资料

  1. Prompt caching for faster model inference(含各模型最小 token 数表) — AWS Bedrock 官方文档
  2. Amazon Bedrock pricing — AWS 官方定价页
  3. Prompt caching — Anthropic 官方文档

常见问题

我的 prompt 有 2000 token,在 Bedrock 上跑 Claude Sonnet 4.5 能用缓存吗?
能。AWS 文档说这个模型要 4096 token 才能缓存,但我实测 1054 token 就已经正常写入和命中。真实门槛是 1024,与 Anthropic 一方 API 一致。文档这一行不准。
那文档是全错还是只错这一处?
只错这一处。我用同样方法测了 Claude Sonnet 4.6、Claude Sonnet 5 和 GPT-5.6 Terra,三个的实测门槛都与文档一致(都是 1024)。错的只有 Sonnet 4.5 那一行的 4096。
怎么自己验证?
发两次带缓存断点的同一前缀,读响应 usage 里的 cacheWriteInputTokens 和 cacheReadInputTokens。第一次应该有 write,第二次应该有 read。两个都是 0 就说明没达到门槛——而且 API 不会报错。
分享这篇文章 微博 X LinkedIn
微信扫码

用微信扫一扫,把文章带到聊天或朋友圈。

继续阅读