生成式 AI 的计费边界
可靠计费依赖于准确区分任务何时被接纳、完成、交付、结算或冲正,而不只是维护一张价目表。
生成式 AI 产品的计费,最开始通常像一道乘法题:统计 Token、图片、秒数或请求次数,查询价格,然后扣除 Credits。
直到产品开始重试、fallback、异步执行、接受取消,或者在超时之后仍然收到结果。
这时,最困难的问题已经不是“这个模型成本多少”,而是:
哪一个事件真正赋予了产品向用户收费的权利?
这是一个伪装成算术的状态与 authority 问题。
报价、预留与结算是不同事件
一条有用的计费生命周期,会把几个很容易混在一起的时刻分开:
- Quote——按照当前输入向用户展示预计价格;
- Reservation——确认余额或额度充足,并临时预留;
- Acceptance——记录产品或外部执行方已经接纳任务;
- Completion——确认任务到达一个有效的终态结果;
- Delivery——让结果能够被用户长期、稳定地获取;
- Settlement——把预留转化为最终扣费;
- Reversal——当约定结果没有交付时,释放或冲正相应费用。
对于快速文本请求,这些时刻可能几乎同时发生。对于媒体生成、批处理、研究任务或其他长任务,它们之间可能相隔数分钟。
如果产品把它们压缩成一次数据库更新,每一条异常执行路径最终都会变成计费特例。
任务生命周期与资金生命周期相关,但并不相同
一个生成任务可能处于 queued、running、succeeded、failed 或 cancelled;一条计费记录则可能处于 reserved、settled、released 或 reversed。
我们很容易把任务状态直接映射为计费状态,但真实世界没有这么对称。
本地 Timeout 不能证明外部任务失败;发出取消请求不能证明取消已经被接受;收到成功响应不能证明输出通过了产品校验;文件生成完成,如果产品没有成功保存并展示,也不能算作已经交付。
因此,计费需要独立而明确的状态转换规则。它应该依据任务生命周期提供的证据,而不是对任务状态作出想当然的推断。
最危险的转换通常是:过早退款,然后自动重试。如果原任务只是执行缓慢,产品可能随后收到两份有效结果,却没有为任何一份完成结算,或者把同一项昂贵任务提交了两次。
先定义可计费结果,再实现扣费
不同能力需要不同的成功定义。
对于流式文本,Contract 可能取决于是否已经产生有用内容;对于生成图片,完成可能意味着获得一个产品能够保存和展示的有效资产;对于异步任务,执行方接纳、任务完成和用户交付可能是三个不同事实。
这个定义至少应该回答:
- 用户购买的究竟是什么?
- 结果需要通过怎样的校验才算可用?
- 部分输出是否具有价值?
- 执行成功但交付失败时怎么办?
- 工作被接纳之后,用户取消会发生什么?
- 界面报告超时之后返回的迟到结果如何处理?
如果没有这份 Contract,success 就会等同于当前集成恰好返回的状态,计费行为也会随着执行路径的变化而不断漂移。
在产品另有约定之前,重试属于内部成本
如果产品自动重试一次暂时故障,或者 fallback 到另一条路径,用户通常认为自己只请求了一个结果,而不是购买了多次基础设施尝试。
这可以形成一条有用的默认边界:
- 用户为产品承诺的结果付费;
- 系统承担内部恢复尝试产生的成本;
- 新增用户扣费必须对应另一个经过用户授权的工作单位。
这并不意味着重试没有成本,而是把成本放在正确的位置:基础设施毛利与路由质量,而不是用户余额。
当一次失败尝试仍然产生上游费用时,这个区分尤其重要。如果每个结果都需要多次付费尝试,最终成功率可以很高,单位经济却可能很差。
因此,产品计费与外部成本核算应该共享关联标识,但它们不应该被当作同一本 Ledger。
幂等同时保护资金与任务
网络重试无法避免。客户端可能不知道请求是否已经到达服务端;Worker 可能完成工作,却在确认完成之前失败;Callback 也可能被重复投递。
Exactly-once Delivery 很少是一个可靠前提。更现实的目标,是让副作用具备幂等性。
同一个业务操作在多次传输重试之间,应该拥有稳定身份。这个身份至少需要保护两个副作用:
- 外部任务不会被意外提交两次;
- 用户不会因为同一个已接纳结果被扣费两次。
单纯使用 HTTP Request ID 通常太窄,因为一次重试会生成新的 Request。真正有用的 Key 应该代表用户授权的那一个工作单位。
幂等也需要保存长期结果。如果系统已经无法找回原始任务、Artifact 或结算记录,只返回一句“已经处理过”并不足够。
Balance 是 Projection,不是审计记录
可变余额很适合读取,却无法解释当前数字是怎样形成的。
可靠计费需要不可变或 Append-only 的事件,保存每次变化的原因:预留、结算、释放、人工调整、过期或冲正。当前余额可以作为这些事件派生或经过校验的 Projection。
这在调查以下问题时非常重要:
- 这项工作被扣费了一次还是两次?
- 使用的是哪一个价格版本?
- 一次退款是在释放预留,还是冲正已经结算的费用?
- 调整是自动发生,还是人工操作?
- 哪项任务与交付结果可以证明这次结算合理?
直接覆盖一个数字,可能修复了用户看到的余额,却同时摧毁了判断这次修复是否正确所需要的证据。
价格必须在决策边界被版本化
价格会变化,模型会被重新路由,促销会开始或结束,输入参数也可能影响费用。
一个任务如果在某个价格下开始,就不应该仅仅因为稍后完成,而使用另一个价格结算。计费决策需要保存当时的 Pricing Context:版本、输入、货币或 Credits 单位,以及产生报价的规则。
这并不要求向用户暴露内部 Provider 经济,而是要求产品保住自己作出的承诺。
同样的原则也适用于长期折扣与订阅额度。使用今天的配置重新计算历史,不是 Reconciliation,而是在事件发生之后重写 Contract。
对账需要三个视角
生成式 AI 计费通常至少包含三种彼此相关的真相:
- 用户权益——用户看到的报价、预留、扣费与返还;
- 产品执行——哪些工作被接纳、尝试、完成并交付;
- 外部成本——基础设施或上游服务最终报告了什么。
它们不会永远即时一致。Callback 可能迟到,外部账单可能使用不同聚合周期,内部校验也可能拒绝一个外部执行成功的结果。
Reconciliation 的目标是解释这些差异,而不是通过静默修改强迫数字一致。
一个可信的系统应该能够从任意一笔扣费,追溯到经过授权的工作、执行证据、交付的 Artifact,以及属于它的外部成本记录。
计费是产品承诺的一部分
用户不会把计费体验成一个后端子系统。他们感受到的是展示的价格是否被遵守,失败是否消耗余额,取消是否真正有效,以及一次修正能否被解释。
最好的计费设计,应该从一份普通人可以理解的 Contract 开始:
- 用户购买的是什么;
- 什么时候预留价值;
- 哪个事件产生最终扣费;
- 失败、Timeout、取消与迟到完成分别如何处理;
- 用户怎样查看并质疑结果。
这些边界一旦清楚,算术通常才是最简单的部分。
可靠计费意味着:在 Happy Path、重试路径、恢复路径与对账路径上作出同一份承诺,并保留足够证据证明这份承诺确实被遵守。


讨论
评论区
关于文章本身,也欢迎留下不同意见或补充。