1. 输入、输出、缓存读写、reasoning thinking 与工具附带费用随 Provider 定价变化时,版本化价格字典与请求级归集链路应如何设计,才能保证历史账单在调价后仍可复算
当输入、输出、缓存读写、reasoning thinking 与工具附带费用随 Provider 定价变化时,版本化价格字典与请求级归集链路应如何设计,才能保证历史账单在调价后仍可复算?
- 理解价格字典需要版本化(价格表带版本号与生效时间),而非硬编码或覆盖
- 掌握请求级归集链路(usage 快照 + 价格版本快照 + 归集时点)的时序设计
- 理解"按当时价格计费"与"按当前价格重算"两种口径的取舍
核心原则是"价格与用量分离、各自版本化"。每次请求落地时,把 Provider 返回的 usage 明细(input/output/cached/reasoning 各 token 数)与工具调用费用作为不可变快照持久化,同时记录一份"当时生效的价格版本号"(priceVersion)。归集(cost 计算)不应在请求时点立即算死,而应在计费时点按"请求时点 + 对应价格版本"复算,这样调价后历史账单仍可复算;归集公式按计费项拆解:成本 = Σ(各计费项 token 数 × 当时价格)。价格字典存储为带版本和生效时间的有序列表,每次调价追加新版本(如 price_v1 生效至 2026-01-31,price_v2 自 2026-02-01),查询时按请求时间点二分定位到正确版本。对账时,财务与工程可通过"同一请求、同一价格版本"复算出一致金额,避免口径漂移。
关键洞察是"价格是会变的、历史上是确定的"——只有把价格做成版本化数据而非常量,才能让历史账单可复算、可审计。若只在请求时算死金额,调价后无法回溯;若用当前价格重算历史,则历史账单失真。因此版本化价格字典 + 请求级用量快照是最稳的归集基座。
// 版本化价格字典
public record PriceEntry(String billingItem, int priceVersion,
LocalDate effectiveFrom, LocalDate effectiveTo,
BigDecimal unitPrice) {
public static PriceEntry at(LocalDate when, String item) {
// 事件时间点二分定位到当时生效的价格版本
}
}
// 请求级归集(按请求时点 + 当时价格版本复算)
BigDecimal cost = usage.inputTokens * pIn.getUnitPrice()
+ usage.outputTokens * pOut.getUnitPrice()
+ usage.cachedTokens * pCache.getUnitPrice()
+ usage.reasoningTokens * pReason.getUnitPrice();