Skip to main content
每个 LLM 响应都带有一个 usage 对象,报告该请求消耗的令牌。Sunra 按您所调用 endpoint 的语义报告用量:Messages 响应遵循 Anthropic 契约,Chat Completions 或 Responses 响应遵循 OpenAI 契约。 这些结构不同,而且是刻意为之。读取 Chat Completions 响应的 OpenAI SDK 会假定 OpenAI 语义,读取 Messages 响应的 Anthropic SDK 会假定 Anthropic 语义。每个 endpoint 都遵守自身规范所承诺的内容,而不是被强行统一成同一种结构。
/v1/messages/v1/responses 都使用 input_tokens 这个字段名,但两者的含义并不相同。在 Messages 上它只表示全新输入;在 Responses 上它表示整个提示,包含缓存令牌。

Messages

/v1/messages 上,三个输入桶是互斥的。没有任何令牌被重复计数,因此提示总量就是它们之和:
integer
仅为全新输入令牌。不含两个缓存桶。
integer
本次请求写入缓存的令牌数。
integer
从缓存提供给本次请求的令牌数。
integer
模型生成的令牌数。
integer
三个输入桶加上 output_tokens。在非 streaming 响应中存在。
缺失或为 null 的桶按零计。

实例演算

同一段 19,000 令牌的前缀向 claude-opus-4-8 发送两次。第一次请求写入缓存,第二次请求读取缓存。
冷请求(写缓存)
暖请求(读缓存)
两次请求中 input_tokens 都保持为 8,因为每次真正新增的输入就是这 8 个令牌。那段 19,349 令牌的前缀从创建桶转移到了读取桶。两次请求的总令牌数同为 19,359,但成本并不相同:缓存写入和缓存读取各按自己的单令牌价格计价,这正是它们被分成独立桶上报的原因。

Chat Completions 和 Responses

这些 endpoint 原样上报 OpenAI 语义。提示计数是整个提示,缓存令牌是其中的一个子集,另行单独上报。
/v1/chat/completions
prompt_tokenscached_tokens 相加会重复计数。要在这些 endpoint 上得到全新输入,需要做减法:
同样的规则适用于 /v1/responsesinput_tokensinput_tokens_details.cached_tokens

sunra_usage_semantics 标记

经 Sunra 归一化处理的响应会在 usage 内带有一个标记:
这个标记是一项关于响应的承诺,而不是关于某个单独事件或字段的承诺。在非 streaming 的响应中,它位于根部的 usage 对象内;在 streaming 的响应中,它出现在携带输入桶的那个事件 message_start 上。当它以该值出现时,本页的各项保证成立:三个输入桶互斥,且 total_tokens(在存在时)等于它们之和加上 output_tokens 它的缺失同样是一项承诺。 Sunra 只对自己实测过的响应结构做归一化。其余响应都会原封不动地从上游服务商转发出来,不带标记;不带标记的响应,就是 Sunra 不为其各个桶背书的响应。 请对该标记做断言,而不要通过查看数字来猜测某个响应遵循哪种约定。这个字段存在的意义正是取代结构嗅探——诸如”这些桶相加超过了提示计数,所以它们一定是互斥的”这类启发式判断,可以被不止一种约定同时满足,迟早会把某个响应读错。
只有 /v1/messages 的响应才会带这个标记。Chat Completions 和 Responses 遵循 OpenAI 规范,不带标记。 该值带有版本。对这些字段含义的破坏性变更会以新的值发布,因此对 anthropic.exclusive.v1 做等值检查,不会在无声无息中开始读取另一套契约。

Streaming

在 streaming 的 Messages 请求中,用量分两个事件到达。message_start 携带输入侧和标记。末尾的 message_delta 只携带 output_tokens。请对 message_start 中的标记做断言,然后按通常的方式把两个事件合并——用后一个事件的 usage 覆盖前一个——即可得到上文记录的取值。 streaming 响应中会省略 total_tokens。没有哪个单独的事件同时知道输入侧和输出侧,因此在流进行过程中算出的任何总数都会是错的。请在流结束后自行把各个桶相加。

从旧行为迁移

Sunra 此前在 /v1/messages 上原样转发上游的 usage 对象。部分服务商前面的翻译层会把缓存创建令牌折叠 input_tokens,因此按 Anthropic 契约把三个桶相加的调用方,会把缓存创建令牌计算两次。
  • 如果您把三个桶相加,正如 Anthropic 契约所描述的那样,那么您现在是正确的。您这边无需改动。
  • 如果您曾为旧行为做过补偿——自行从 input_tokens 中减去 cache_creation_input_tokens,或以其他方式逆向还原这种折叠——请停止。该修正现在减掉的是本已被排除的令牌,会低估您的输入。
  • 如果您读取 total_tokens,它仍然报告完整计数:全新输入、两个缓存桶以及输出。
请以该标记而不是部署日期作为这次变更的判定条件,这样同一条代码路径对带标记和不带标记的响应都是正确的。