Claude API 缓存为什么没命中?读取为 0 的排查
cache_read_input_tokens: 0 只说明这次响应报告的缓存读取量为零。第一次请求可能正在写入缓存;后一次请求也可能改了前缀、超出有效时间,或未满足缓存条件。先保留两次完整响应中的 usage,再排查,别只凭一个零判定服务不支持缓存。
本文按 Anthropic Messages 原生字段语义说明,资料核对于 2026 年 10 月 24 日。第三方接口若映射了字段,需要先确认口径;本文没有对云岚API或其他服务执行真实缓存调用。
先把“零”和“没返回”分开
| 响应中的证据 | 能判断什么 | 下一步 |
|---|---|---|
| 读取量大于零 | 本次响应报告了缓存读取 | 再看读取覆盖了多少输入,以及实际账单 |
| 读取为零,创建量大于零 | 有写入、没有报告读取 | 留下这一笔,作为下一次请求的比较基线 |
| 读取和创建都明确为零 | 本次没有报告读写缓存 | 核对缓存配置、模型最低长度和输入前缀 |
| 读取字段缺失、为 null 或格式不对 | 证据不完整 | 查接口文档或原始响应,不能自行补成零 |
原生 input_tokens 是未从缓存读取、也未写入缓存的输入;输入总量应加上 cache_creation_input_tokens 和 cache_read_input_tokens。创建量若另列 5 分钟、1 小时细分,它们属于创建合计,不应重复相加。字段定义见 Anthropic 提示缓存文档。
用离线工具先查已有记录
下载云岚API缓存检查包,解压后运行:
python3 claude-cache-usage.py example-write.json
python3 claude-cache-usage.py example-read.json
工具使用 Python 标准库,只读取你指定的本地 JSON,不联网、不读取 Key、不发起 API 调用。它接受完整的非流式 Messages 响应,或你从完整响应中提取的 usage 对象;不要直接输入 SSE 文本或单个流事件。输出只有计数、字段校验和判读,不会打印请求正文。
包内两个文件是合成示例:第一笔普通输入 120、写入 2000、读取 0;第二笔普通输入 120、写入 0、读取 2000。第二笔输入总量为 2120,报告的缓存读取占比约 94.34%。这个比例不是费用节省率,也不是多次请求的成功率。它们用于验证工具的计算,不代表任何平台的实测性能。
处理自己的记录时,把文件名换为本地路径即可。字段缺失显示“未知”;非法计数会明确报错。工具不会根据 JSON 猜测模型身份、网关能力或账单金额。
两次请求怎么比较才有用
检查包中的 claude-cache-comparison.csv 可以直接填写。已有日志够用时先分析日志;确需补发请求时,会按所用平台规则产生用量。
建议先选同一账户、同一接口和同一模型下的两笔相邻请求,记录请求开始时间、缓存配置、前缀变化和三个输入计数。只改一个待验证因素,避免同时换模型、换路由、缩短输入,最后仍无法归因。
| 观察结果 | 先查哪一处 | 什么证据可以推进排查 |
|---|---|---|
| 第一笔写入,第二笔仍只有写入 | 前缀是否改变、时间是否可比 | 对比两次实际发送的结构,不只对比用户最后一句话 |
| 两笔读写都为零 | 缓存控制位置、模型最低长度 | 查对应模型和平台的要求,确认标记覆盖的前缀长度 |
| 本地请求相同,平台报告不同 | 中间处理或路由差异 | 在自己的日志中关联请求,向服务方询问字段及路由口径 |
| 一部分读取、一部分新写入 | 可能是复用了早期前缀 | 检查新增内容位置,不要强求所有输入都来自缓存 |
Anthropic 默认缓存有效期为 5 分钟,也有 1 小时选项;最低可缓存长度因模型而异,过短的请求可能正常完成但不产生缓存。按当前模型要求核对,不要一律套用“超过 1024 token 就一定命中”。有效期以请求开始时间计算;长时间生成也会占用这段时间。有效期与最低长度说明
想估算输入长度,可以参考 官方 token counting 接口。计数接口本身不执行缓存逻辑,因此计数成功不能证明缓存已经写入。
别只看消息,工具和配置也会改变前缀
两次都问“继续”,不代表实际输入相同。检查工具定义、system 内容和历史消息是否变化:例如每次把当前时间写入 system,或重新排序工具列表,都值得单独验证。还要记录 tool_choice、thinking、effort 等设置有没有改变。
官方工具文档说明,缓存按 tools → system → messages 的前缀层级工作;前层改变会影响后层,部分参数变化的影响还取决于模型。排查时保留这些设置的变化摘要,比只记“提示词没改”更有用。工具与提示缓存的关系
不要为了命中而保留已经错误的工具定义或过时上下文。先保证任务正确,再减少无意义的动态内容;需要修改的输入应照常修改。
官方 diagnostics 能补充哪些证据
Claude API 提供可选的缓存诊断:两次请求都带 diagnostics,后一次关联前一次响应 ID,可辅助定位模型、system、工具或消息的差异。它诊断请求结构,实际读取量仍看 usage。
注意三种状态:diagnostics: null 可能是未开启、首轮或没有发现差异;cache_miss_reason: null 表示比较尚未完成;previous_message_not_found、unavailable 没有产生可用比较,不能解释成“前缀没变化”。官方缓存诊断说明
这项能力的官方适用范围是 Claude API。第三方兼容接口是否支持,需要单独确认;遇到不支持的字段,不要反复重试来证明其存在。普通的两请求记录表仍可用于人工排查。
命中了,为什么账单还是高
缓存读取只覆盖一部分输入成本;输出、新写入、未缓存输入及其他计费项仍需核对。缓存价格还随模型、平台和时长变化,不能把整笔账单直接乘一个“缓存折扣”。Anthropic 当前价格
将已确认口径的计数填入 API 成本对账表,再核实际扣费。若使用云岚API,以对应分组的当前价格和控制台记录为准;不要把客户端按官方价格估算的金额直接当本站扣费。月预算可继续用 Claude Code 月成本计算器。
常见问题
第二次读取还是零,能确定中转不支持缓存吗?
不能。先确认第一笔确实报告写入、两笔条件可比较,以及读取字段的语义。排除输入差异和时长等因素后,再请服务方核对缓存支持与路由记录。
日志只有 input_tokens,能算出缓存占比吗?
不能按本文口径计算。读取和创建字段缺失时保留“未知”,先询问它们是否被映射到别处。不同 API 的同名字段也不一定含义相同。
Claude Code 里看到的比例能直接填进这张表吗?
表格按单次 API 响应记录。客户端会话汇总应另记统计范围,不要与某一笔响应混算。安装和连接配置见 Claude Code 接入教程。
要把完整请求发给客服吗?
先提供时间段、模型、协议、计数和变化摘要,并通过服务方的私密支持渠道关联请求。无需公开 API Key、完整提示词或业务数据;具体错误另见 API 报错排查。
