事情本身不复杂,线索都在日志里。按官方示例在 messages 的最后一段加 cache_control ephemeral,调 claude-3-5-sonnet 长文档问答,usage 里 cache_creation_input_tokens 一直是 0,文档再长也没有缓存。

第一反应是「缓存需要前缀达到最小 token 数,文档太短不生效」,验证下来不成立。

排查方向其实有限,先把可能性排一排。缓存断点要放在长前缀的末尾,而不是整段对话末尾。也可能是断点之前的内容每次请求都变了,前缀无法复用。

少数情况下是把断点加在 user 消息上而 system 前缀每次重写。

动手时先打印 usage 字段确认缓存相关计数

python -c "import json;print(json.load(open('resp.json'))['usage'])"

然后把断点移到 system 长文档的最后一个块

python -c "b=blocks[-1];b['cache_control']={'type':'ephemeral'};print(b['type'])"

再往下确保断点前的内容逐字节一致

python -c "import hashlib;print(hashlib.md5(open('prefix.txt','rb').read()).hexdigest())"

连发两次请求看第二次是否命中

python cache_probe.py --model claude-3-5-sonnet --repeat 2

怎么算真的好了,看的是同一批现象。第二次请求的 cache_read_input_tokens 大于 0,账单里这部分按折扣价计费,首字延迟也明显下降。

补一句。缓存是按前缀命中的,断点位置决定了哪些内容被缓存,放在对话末尾等于只缓存最后一句,几乎不会有收益。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。

作者 9823189