Usage 字段与计费对账

不同接口会沿用各自协议的 usage 命名,因此同样是输入和输出用量,可能分别返回 prompt_tokens / completion_tokensinput_tokens / output_tokens,或者只返回视频输出 Token、秒数等任务用量。字段名不同不代表计费口径冲突,也不表示所有接口必须返回同一套结构。

信息

usage 表示用量,不直接等于金额。计算费用时,还要结合请求使用的模型、模型广场中实际展示的计费项、单价和计价单位。不要把响应中的每个数字都相加计费。

先识别协议

接口或协议输入字段输出字段总量字段
OpenAI Chat Completionsprompt_tokenscompletion_tokenstotal_tokens
OpenAI Responsesinput_tokensoutput_tokenstotal_tokens
Anthropic Messagesinput_tokensoutput_tokens通常不返回统一的 total_tokens
OpenAI Images 兼容接口input_tokensoutput_tokenstotal_tokens
部分视频生成接口可能不返回输入 Tokencompletion_tokens 或任务输出 Tokentotal_tokens
部分按时长计费的视频接口input_secondsoutput_secondstotal_seconds

原厂协议 Bypass 接口会尽量保留厂商原始字段。兼容接口则使用对应兼容协议的字段命名。业务侧可以把这些字段映射为自己的统一名称,但不要要求所有响应都包含同样的 key。

Anthropic Messages 使用缓存时,cache_creation_input_tokenscache_read_input_tokens 会与 input_tokens 并列返回,而不是嵌套在 input details 中。分析完整输入构成时需要同时查看这些字段;实际是否拆分计费,仍以该模型的价格项和请求日志 bo_usage 为准。

顶层总量与明细字段

*_tokens_details 是顶层 Token 的分类或子集,不是另一份需要重复累加的用量。

字段含义对账规则
prompt_tokens / input_tokens协议的主要输入字段OpenAI 兼容接口为输入总量;Anthropic 缓存场景需同时看并列缓存字段
completion_tokens / output_tokens输出总量作为输出侧顶层总量
total_tokens输入与输出的总量通常应等于输入总量加输出总量
text_tokensimage_tokens文本或图片分类明细已包含在对应的输入或输出总量中,不要再加一次
audio_tokensvideo_tokens音频或视频分类明细已包含在对应的输入或输出总量中,不要再加一次
reasoning_tokens输出中的推理 Token 子集通常已包含在输出总量中,不要直接叠加到输出总量
cached_tokens输入总量中的缓存命中部分用于选择缓存计费项,不要与输入总量重复相加
cache_creation_* / cache_write_tokens本次缓存创建用量不同协议可能作为输入子集或并列字段;按实际价格项对账

明细字段可能只返回部分分类,因此 text_tokens + image_tokens 不一定总能还原顶层 Token。字段缺失表示接口没有提供该明细,不能在业务代码里一律解释为“实际用量为 0”。只有接口明确约定该字段为零,或者请求日志中相应计费项为零时,才能按零处理。

图片接口的数量字段

图片生成接口除了 Token,还可能返回按次或按张计费的数量字段:

字段含义
ti_quantity文生图实际生成张数
ii_quantity单图生图实际生成张数
mi2i_quantity多图生图实际生成张数
req_count成功同步请求的计次,通常为 1

具体模型可能按 Token、按请求或按张数计费。以模型广场实际展示的计费项为准;同一图片产出不会因为响应同时包含 Token、请求次数和张数,就把三种费用全部重复相加。

三个响应怎么读

图片输入与图片输出都有 Token

{
  "input_tokens": 1550,
  "input_tokens_details": {
    "image_tokens": 1536,
    "text_tokens": 14
  },
  "output_tokens": 301,
  "output_tokens_details": {
    "image_tokens": 301,
    "text_tokens": 0
  },
  "total_tokens": 1851
}

这组数据的结构关系是:

输入明细:1,536 + 14 = 1,550
输出明细:301 + 0 = 301
顶层总量:1,550 + 301 = 1,851

计费时不要计算成 1,550 + 1,536 + 14 + 301 + 301。如果模型广场分别展示“图片输入、文本输入、图片输出”价格,就使用明细字段分别计算;如果只展示通用输入和输出价格,则使用顶层的 input_tokensoutput_tokens

只返回视频输出 Token

{
  "completion_tokens": 108900,
  "total_tokens": 108900
}

这类视频任务的接口定义可能把输入 Token 记为 0,因此 total_tokenscompletion_tokens 相等。只能在该接口明确采用这一结构时按此理解;不能据此推断所有缺少 prompt_tokens 的响应都没有输入用量。

Chat Completions 形式的生图响应

{
  "prompt_tokens": 50,
  "prompt_tokens_details": {
    "text_tokens": 50
  },
  "completion_tokens": 1120,
  "completion_tokens_details": {
    "image_tokens": 1120
  },
  "total_tokens": 1170
}

这里的 prompt_tokens 是输入总量,completion_tokens 是输出总量;两个 details 对象分别说明输入由文本构成、输出由图片构成。结构校验为 50 + 1,120 = 1,170,计费项仍以该模型的价格配置为准。

从 usage 算到金额

单项费用按下面的公式计算:

单项费用 = 实际计费用量 / 计价单位 × 该项单价
本次请求费用 = 所有实际命中计费项的单项费用之和

例如,模型广场只展示输入和输出价格时,响应中的图片、文本和推理明细用于解释用量构成,不再额外重复收费。模型广场展示分类价格时,才按文本、图片、音频、视频或缓存等对应明细分别计算。完整计费原则见按量计费说明

警告

不要只根据字段名推测单价,也不要把 total_tokens 与输入、输出再次相加。total_tokens 是校验总量,不是第三个独立计费项。

单次请求对账流程

  1. 从响应头记录请求 ID,同时保存请求时间、模型 ID、接口路径和完整 usage
  2. 根据接口协议确定输入、输出和总量字段,先检查顶层关系是否自洽。
  3. 打开 Modelink 模型广场,确认该模型在请求发生时使用的计费项、单价和计价单位。
  4. 通过请求日志接口按时间、模型或 API Key 找到这次请求。
  5. 对比日志中的 usagebo_usagebo_usage_cost,确认平台实际选择了哪些计费项。
  6. 按计费项重新计算金额,并与账单或消费明细核对。

请求日志中的三个对象作用不同:

日志字段用途
usage平台归一化后的用量统计,key 会随文本、图片、视频等服务类型变化
bo_usage本次请求实际命中的计费项及计费用量
bo_usage_costbo_usage 同名计费项对应的人民币费用

如果响应 usage 包含多个明细,但 bo_usage 只出现其中一组计费项,说明平台根据该模型的价格配置选择了实际计费口径,而不是把响应中的所有字段都收费。

对不上时提供什么信息

出现差异时,请先排除价格档位、缓存、重试和异步任务终态的影响,再准备以下信息联系支持团队:

  • 响应头中的请求 ID;
  • 请求时间、模型 ID 和接口路径;
  • 完整响应 usage
  • 请求日志中的 usagebo_usagebo_usage_cost
  • 期望金额及使用的单价、计价单位和计算过程。

涉及图片或视频任务时,还应提供任务 ID、输出尺寸、质量、时长、分辨率、是否包含音频和参考素材数量。