Skip to content
上新Claude Opus 5.5 与 GPT-6 Sol / Luna 已上线:Opus 5.5 $4 / $20 每百万 token(比 Opus 5 便宜 20%),GPT-6 Sol $2 / $10、Luna $0.10 / $0.50,均为官方牌价接入查看价格
HopBase
← 返回博客

大模型 API 用量对账与部门分摊:实扣金额、明细验算、按 Key 分摊 | HopBase

先说答案:大模型 API 的账要对得上,靠的不是供应商的「透明计费」口号,而是三层能自己复算的数据。第一层是单个任务:在 HopBase,视频、异步生图等异步任务结束后,查询接口的响应里直接带 usage.cost(这一单从余额实际扣掉的金额)和 usage.currency,失败且未扣费的任务报 0,用一条 curl 就能核。第二层是逐笔明细:控制台「使用记录」可按日期、Key、成员、部门、创建人筛选后导出 CSV,每行都带官方费用、折扣、折算率和扣费金额,可以按「官方费用 × 折扣 ÷ 折算率 = 扣费金额」逐行验算。第三层是分摊:每把 Key 显示创建人、可以按 Key 看消耗趋势图,部门负责人能看、能管本部门成员的 Key 和用量,额度可以按 Key、成员、部门分别设。三层对齐了,财务按部门分摊就只是一次筛选加导出。

为什么大模型账单难对

一家公司同时用对话、生图、视频模型时,计费单位至少有四种:对话按 token,生图多按张,视频按秒或按 video token,还有一些按次收费。再叠加几个现实问题,账就很难对上:

  • 异步任务的钱在「结束时」才确定:视频提交时只是预估,真正扣多少要等任务完成;失败的任务是否扣费、扣多少,各家口径不同。
  • 失败请求的口径:请求失败一般不计费,但如果客户端在输出已经生成之后才断开,已生成的部分通常要计费。账单里如果不标清楚,就会出现「明明报错了还扣钱」的争议。
  • 多币种:官方牌价多是美元,账户余额可能是另一种币种,中间差一个折算率;少了这个除数,任何人都没法复算。
  • 多人共用:一把 Key 被多个项目共用,事后就分不清是谁花的。

所以对账的目标很具体:任何一笔钱都能追到「哪个任务 / 哪次请求、哪把 Key、谁建的 Key、属于哪个部门」,并且金额能用公开牌价复算出来

第一层:单个任务,查询响应里直接拿实扣金额

异步任务(视频、异步生图等)结束后(完成、失败或取消),单任务查询接口的响应根对象会多出一个 usage 对象:

  • usage.cost:这个任务从余额实际扣掉的金额,和使用记录里的扣费金额是同一个数;
  • usage.currency:余额币种,当前为 CNY。别默认是美元,以这个字段为准;
  • 失败且没有扣费的任务报 0;个别生图任务在扣费结算之后才失败(比如模型没有返回可用图片),报的是实际扣费;
  • 任务进行中不返回这个字段;而且只有创建任务的那把 Key 查得到。

覆盖的查询路径:GET /v1/video/tasks/{task_id}(Seedance、Grok Imagine、可灵、MiniMax、Midjourney)、GET /api/v1/tasks/{task_id}(万相、快乐马)、GET /v1/images/tasks?task_id=...(GPT Image 与 Gemini 生图的异步任务)。自己核一下只要一条命令:

# 用提交任务的那把 Key 查询;jq 只挑出状态和费用
curl -s https://api.hop-base.com/v1/video/tasks/$TASK_ID \
  -H "Authorization: Bearer $HOPBASE_API_KEY" \
  | jq '{status: (.task.status // .status), usage}'

# 任务结束后的输出形如(金额仅作示意):
# { "status": "completed", "usage": { "cost": 2.4, "currency": "CNY" } }

Seedance 的响应里 task.usage 是计费用的 token 数,根对象的 usage.cost 才是金额,两者别混;MiniMax、万相这类本来就有根 usage 的,costcurrency 会合并进去。这一层的用处是:业务系统可以在任务结束时把实扣金额直接写进自己的订单或工单,不用再定时去控制台翻记录,也不用拿提交时的预估当成本。

第二层:逐笔明细,导出 CSV 并逐行验算

同步的对话请求不产生任务,响应体里只有 token 用量,金额以使用记录为准。控制台「使用记录」页的导出按钮会按页面当前的筛选(日期区间、Key、成员、部门、Key 创建人)导出 CSV,单个文件最多 5 万行、最长 400 天。每行九列:

  1. 时间、模型、用量;
  2. 官方牌价币种、官方费用(原币);
  3. 折扣、折算率、扣费金额(账本币种);
  4. 备注。

中间四列从左到右正好读成验算式:官方费用 × 折扣 ÷ 折算率 = 扣费金额。牌价币种与账本币种相同时折算率留空,等式退化成「官方费用 × 折扣 = 扣费金额」。官方费用可以拿厂商官方价格页自己算,折扣就是你所在分组的折扣,所以每一行都能独立复算,不需要相信任何人的汇总数。早期记录没有牌价快照时,这几列会留空。

失败请求在备注里写明「请求失败,未扣费」;客户端中途断开、但输出已经生成的请求,写明「请求中断,按已生成的用量扣费」,文件末尾分别汇总条数。这正是最容易起争议的两类行,把口径写在明细里,比事后解释省事得多。需要自动化时,GET /v1/usage 用 API Key 就能查余额和这把 Key 的额度用量。

第三层:按 Key、按部门分摊

分摊的前提是「一个成本中心一把 Key」。HopBase 的企业账户里有成员和部门,几个事实决定了分摊能不能落地:

  • 每把 Key 显示创建人:成员自己建的、企业主或部门负责人代建指派给成员的,都分得开;导出也能按创建人筛。
  • 按 Key 看消耗图表:控制台可以按 Key 查看消费趋势、请求数和模型分布,异常消耗一眼能看出来是哪把 Key。
  • 部门负责人的范围:部门负责人能看到并管理本部门成员的 Key 和用量,能给本部门成员建 Key;看不到别的部门。企业主看全公司。成员调岗后,负责人的范围随之变化。
  • 分层额度:Key、成员、部门都可以设额度,任何一层用完都会拦截;超额时返回 402,信息里写明是 Key 额度、成员额度还是部门额度用完,不会只丢一个笼统的「余额不足」。

月底给各部门出账,就是在使用记录里选部门、选月份、导出;每个部门拿到的是自己那份明细,并且可以用上一节的等式自己复算。

一份可以拿去核任何供应商的对账清单

  1. 异步任务结束后,能否从 API 直接拿到这一单的实扣金额,而不是预估或基础成本?
  2. 明细能否导出,是否包含官方费用、折扣、折算率,能否逐行复算
  3. 失败请求与「中途断开但已生成」的请求,明细里是否分开标注
  4. 金额字段有没有写明币种?牌价币种与余额币种不同时,折算率是否可见?
  5. 能否按 Key、成员、部门筛选导出,Key 有没有创建人?
  6. 额度能否分层设置,超额报错能否看出是哪一层?
  7. 你付费调用的是不是你以为的那个模型?这一项可以用API 中转保真检测方法自己测。

这份清单每一项都能用 curl 或导出文件验证,拿去评估任何供应商都适用,包括我们。

常见问题

任务查询里的 usage.cost 和控制台的扣费金额一样吗?

一样。usage.cost 取的就是这笔任务使用记录里的实扣金额,也就是余额真正减少的数,可以直接拿来和导出明细逐笔对。

为什么任务还在跑的时候看不到 usage.cost?

异步任务的最终费用要等任务结束才确定,进行中返回的任何数字都只能是预估。所以只在完成、失败或取消之后返回;进行中的任务响应里没有这个字段,按原来的逻辑继续轮询即可。

失败的任务会扣费吗?

视频任务失败一律不扣费,查询里 usage.cost 报 0。生图任务极少数情况下会在扣费结算之后才失败,这时报的是实际扣费,使用记录里也能看到同一笔。同步请求失败不扣费;客户端中途断开但输出已经生成的,按已生成的部分扣费,并在导出明细里单独标注。

换一把 Key 查同一个任务,为什么没有费用字段?

费用只对创建任务的那把 Key 返回。这是为了让「一个成本中心一把 Key」的分摊边界不被打破,也避免同账户下其他 Key 看到不属于自己的消耗。

对话请求有没有类似的单笔金额?

对话响应里只有 token 用量,没有金额。单笔金额在控制台使用记录里,导出 CSV 可以逐行验算;按 Key 或部门汇总,用筛选加导出即可。