计费(Usage & Billing)
Aidy 的计费是根据 Provider 的 provider_pricings 价格表进行计费的。
记账单位:Credit
Aidy 内的计费不关心法币,使用整数 Credit 作为记账单位。内部所有计费、配额、余额、账单数据结构也统一使用整数 Credit。
法币与 Credit 的换算由业务侧负责,不属于 router 核心职责,建议采用 1 USD = 1_000_000 Credit / 1 CNY = 1_000_000 Credit(相当于四位小数的计费精度)。
配置
计费的配置在 Provider 的 provider_pricings 价格表。其中的 pricing 字段在 API 中返回的是一个 google.protobuf.Struct JSON 结构,但其实际格式应当为 ext.billing.Pricing 的 ProtoJSON 表示。
Pricing Proto
adjustments 的定义和支持目前仍处于调整阶段,请勿使用。
计费口径
所有 rate 数值都表示「每 1M Token 消耗的 Credit」
当前支持四个文本计费项:
textInput未缓存输入价格textOutput输出价格textInputCacheRead缓存读取价格textInputCacheWrite缓存写入价格
计费时将按照最终结果四舍五入得到的整数 Credit 进行结算。
示例
最简单的 basePricing:
{
"basePricing": {
"textInput": 500,
"textOutput": 1500
}
}
带 cache 定价:
{
"basePricing": {
"textInput": 500,
"textOutput": 1500,
"textInputCacheRead": 50,
"textInputCacheWrite": 800
}
}
带 adjustment 的完整结构示例:
{
"basePricing": {
"textInput": 500,
"textOutput": 1500
},
"adjustments": [
{
"mode": "ADJUSTMENT_MODE_MULTIPLIER",
"when": {
"serviceTier": "priority"
},
"values": {
"textInput": 2,
"textOutput": 2
}
}
]
}
计费时机
目前,仅在请求正常结束且上游返回了 usage 信息时才会进行计费。
- 未配置消费者时,不计费
- Tenant 或 Route 允许缺失模型价格,且未配置对应模型的价格表时,不计费
- 请求错误时,不计费
- 上游未返回 usage 信息时,不计费(不做费用估算)
另外,所有的结算采用后付费,在并发请求时可能出现负数余额。
- 不做预扣
- 请求进入时检查只要有可用余额就允许,不预判本次请求最终会不会欠费
- 另外,只要余额为负数就不允许请求 —— 即使对应模型实际上未配置价格表(相当于免费)
- 请求完成后按实际 usage 进行计费
对于别名情况,将按照最终请求的模型进行计费。
对于别名情况,缺失价格检查也按最终请求到上游的模型判断。默认情况下,如果最终模型没有配置 provider pricing,请求会在转发前被拒绝;只有当 Tenant 或 Route 的 allow_missing_model_pricing 任意一个为 true 时才允许继续。
请求日志
请求级计费信息现在存在两个 ext-field:
ext_fields.usage:统计请求的 usage / creditext_fields.billing:记录扣减的 consumer 的 Credit 情况
Proto
示例:
{
"usage": {
"status": "available",
"billed_model": "gpt-4o-mini",
"input_tokens": 10,
"cached_read_tokens": 0,
"output_tokens": 2,
"total_tokens": 12,
"reasoning_tokens": 0,
"billed_status": "calculated",
"billed_credit": 12,
"billed_error": null
},
"billing": {
"status": "settled",
"consumer_id": "cs_xxx",
"consumer_api_key_id": "cak_xxx",
"settled_credit": 12,
"ledger_entry_ids": [
"cle_xxx",
"cle_yyy"
],
"error": null
}
}
字段语义:
usage.status:usage 可用性,当前为available、estimated或unavailableusage.input_tokens:未缓存输入 token 数;当上游同时返回总输入和缓存读取输入时,记录为max(raw_input_tokens - cached_read_tokens - cached_creation_tokens, 0)usage.cached_read_tokens/usage.cached_creation_tokens:缓存读取 / 缓存写入输入 token 数usage.total_tokens:输入总量加输出 token;输入总量包含未缓存输入、缓存读取输入和缓存写入输入usage.output_tokens:上游输出 token 数;不会扣除 reasoning tokenusage.reasoning_tokens:上游返回的 reasoning token 数,仅作为 telemetry 明细记录,当前不单独计费usage.billed_status:计费计算状态,当前为calculated、failed或skippedusage.billed_credit:按 pricing 计算出的本次 credit 消耗事实usage.billed_error:计费计算错误;成功或未尝试计费时为nullbilling.status:当前为settled或settle_failedbilling.settled_credit:本次实际写账并扣减的 credit;失败时固定为0billing.ledger_entry_ids:本次结算生成的账本条目 ID 列表
补充说明:
usage只负责记录事实,不直接修改余额billing才表示 consumer / API key 的实际扣费结果- 上游未返回 usage 时按 upstream > provider 的
missing_usage_policy处理:estimate会估算 token 并以usage.status = "estimated"继续计费;fail会输出usage.status = "unavailable"、usage.billed_status = "skipped",不写billed_credit,客户端模型响应不受影响 - 如果请求本身计算出了费用,但主体是 unlimited credit,则可能出现
usage.billed_credit > 0且billing.settled_credit = 0 request_logs同时承担“请求日志摘要 + 请求级 billing 事实”角色,因此(tenant_id, request_id)必须唯一
账本 metadata
请求结算时写入 credit_ledger_entries.metadata 的审计上下文:
当前至少覆盖这些字段:
route_idrequested_modelsourceoperation
数据库里该列保存的是上面这个 message 的 ProtoJSON 表示。