指导和见解

构建 AI API 计费账本:报价、预留、结算和协调每个模型调用

多模型网关的实用计费控制模式:在请求之前估算成本、保留租户预算、规范提供商使用情况、结算实际费用以及核对发票,而无需单独依赖原始提供商响应。

面向客户的AI API计费不能每月导出原始提供商使用情况。如果网关向租户、团队或合作伙伴公开多个模型,则计费必须在发票存在之前回答一个更难的问题:现在是否应该允许此请求,以及稍后将如何解释其成本?

实用模式是一个包含四个阶段的记账分类账:报价、保留、结算和对帐。在提出请求之前报价可能的费用。预留足够的租户预算以应对允许的最坏情况。了解使用情况后结算实际费用。根据提供商方记录协调网关分类帐,以便发票保持合理性。

本文介绍了多模型 API 网关的控制循环。无论网关向内部团队、预付费客户、代理客户还是下游合作伙伴计费,这都很有用。

结算问题:提供商使用情况不是客户发票

事实: 主要 AI 提供商不会公开一种通用代币计数器或一种通用价格。 OpenAI 通过单独的输入、缓存输入和输出令牌率发布每个模型的价格。 OpenAI 提示缓存在 API 响应使用字段中报告缓存的令牌使用情况。 Anthropic 记录正常输入令牌、缓存创建输入令牌、缓存读取输入令牌和输出令牌的单独计数器。 Gemini 定价区分输入、输出和其他令牌类别,包括特定模式的使用,例如音频令牌。

这意味着网关无法通过将 total_tokens 乘以一个价格来安全地计费。它需要提供商中立的计费架构背后的特定于提供商的适配器。

在以下情况下问题会变得更加明显:

  • 预付积分:在租户支出低于零之前,网关必须拒绝请求。
  • 合作伙伴加价:合作伙伴需要自己面向客户的发票,而不是提供商帐单的副本。
  • 流式传输:响应在得知最终令牌使用情况之前开始。
  • 提示缓存:缓存的输入可能比未缓存的输入便宜,但前提是单独测量。
  • 推理和工具使用:某些模型会公开其他使用维度、隐藏的输出类或媒体单元。
  • 提供商价格变更:价目表变更后,上个月的发票必须仍然可以重现。

建议:将结算视为仅附加的财务分类帐,而不是对请求日志的仪表板查询。

核心架构

可靠的结算架构由六个组成部分组成:

  1. 租户帐户:客户、工作区、经销商客户或内部成本中心。
  2. 价目表服务:提供商、型号、结算类别、货币和加价规则的版本价格。
  3. 估算器:根据请求参数和模型政策计算预检报价。
  4. 预订分类帐:在提供商调用开始之前保存预算。
  5. 使用规范化器:将提供商特定的使用字段转换为内部结算单位。
  6. 结算和对账作业:最终确定费用并将其与提供商方记录进行比较。

控制流程如下所示:

client request
  -> authenticate tenant and key
  -> select model and rate-card version
  -> estimate input and max output cost
  -> reserve tenant balance
  -> call provider
  -> normalize returned usage
  -> settle actual cost
  -> release unused reservation
  -> emit invoice-ready ledger event

重要的设计选择是请求不仅仅被遵守。执行前后均受到财务控制。

第 1 步:在提供商调用之前报价

预检报价应足够悲观以执行预算,但又应足够可解释以向客户或合作伙伴展示。

输入通常包括:

  • 租户 ID 和结算计划;
  • API 密钥 ID 或项目 ID;
  • 应用路由规则后的提供商和模型 ID;
  • 估计的未缓存输入令牌;
  • 已知的缓存输入资格(如果有);
  • max_tokens、max_output_tokens或同等输出上限;
  • 工具、图像、音频或其他模态参数;
  • 合作伙伴加价、折扣或经销商定价规则;
  • 货币和舍入政策。

用于文本生成的简单引用公式可能是:

estimated_cost =
  estimated_uncached_input_tokens * input_rate
+ estimated_cached_input_tokens   * cached_input_rate
+ max_output_tokens               * output_rate
+ request_fee
+ partner_markup

建议:当最终输出长度未知时,保留配置的最大输出。如果应用程序使输出上限不受限制,则网关应应用租户或模型默认值。如果没有最大责任,预算执行就无法具有确定性。

这可以拒绝一些实际上成本较低的请求。这就是权衡。对于预付费系统,更安全的默认方式是悲观预留,结算后释放未使用的资金。对于已开具发票的企业客户,团队可能会允许软超额并将报价主要用于提醒。

第 2 步:预留租户预算

预留可防止租户帐户支出超过允许的余额。它应该是原子的:要么预订成功并且可以开始提供程序调用,要么在产生任何提供程序成本之前拒绝请求。

预订记录可能包括:

{
  "reservation_id": "res_01J...",
  "tenant_id": "tenant_123",
  "api_key_id": "key_456",
  "request_id": "req_789",
  "provider": "example_provider",
  "model": "model-a",
  "rate_card_version": "2026-08-01",
  "quoted_amount": "0.032100",
  "currency": "USD",
  "status": "reserved",
  "expires_at": "2026-08-11T12:05:00Z"
}

针对网络故障和客户端断开连接,使用较短的预留过期时间。清理工作应该释放从未达成结算的过期保留。但是,不要仅仅因为客户端断开连接就释放预留;提供商调用可能仍会完成并产生费用。单独跟踪提供程序请求状态。

建议:通过请求 ID 或幂等密钥使预留幂等。客户端、网关或工作线程的重试不应为同一逻辑请求创建多个预算保留。

第 3 步:规范提供商的使用

提供商响应应转换为小型内部架构。即使提供商添加新的使用字段,也能保持稳定。

实用的标准化使用模式:

{
  "input_uncached_tokens": 1200,
  "input_cached_tokens": 800,
  "cache_write_tokens": 0,
  "output_tokens": 650,
  "reasoning_or_hidden_output_tokens": 0,
  "tool_or_media_units": [],
  "request_fee_units": 1,
  "provider_request_id": "prov_abc",
  "usage_source": "provider_response",
  "is_estimated": false
}

此架构故意与任何提供商的响应不同。它捕获发票所需的结算维度,同时为特定于提供商的单位保留逃生舱口。

缓存的令牌需要自己的行

事实: 提示缓存的定价与未缓存输入的定价不同。如果缓存的令牌合并到总输入令牌中,则客户可能会被多收费,或者网关可能会低估提供商的成本。缓存的输入应在分类帐和发票中显示为其自己的计费类别。

缓存写入和缓存读取并不总是相同

一些提供商区分创建缓存条目和从缓存读取。规范化器不应假设缓存的输入始终意味着一个计费率。如果提供程序具有缓存写入令牌和缓存读取令牌,请将它们单独映射或将它们保留为特定于提供程序的子单元。

推理和隐藏输出需要政策

某些模型会公开与推理相关的用法或隐藏的输出计数器。如果提供商对这些单位进行计费,网关必须决定是直接显示它们、将它们汇总到输出类别中还是将它们列为单独的发票行。

建议:面向客户的发票应使用通俗易懂的语言。例如:“推理输出标记”比原始提供者字段名称更清晰。保留原始字段以供审核,但不要强迫每个客户了解提供商的内部结构。

第 4 步:结算实际费用

结算将标准化使用量转换为最终分类帐条目。它应该是仅附加的,并引用用于请求的价目表版本。

已解决的事件可能如下所示:

{
  "ledger_event_id": "led_01J...",
  "event_type": "settlement",
  "tenant_id": "tenant_123",
  "request_id": "req_789",
  "reservation_id": "res_01J...",
  "provider": "example_provider",
  "model": "model-a",
  "rate_card_version": "2026-08-01",
  "lines": [
    {
      "billing_class": "input_uncached_tokens",
      "quantity": 1200,
      "unit": "token",
      "unit_price": "0.00000250",
      "amount": "0.003000"
    },
    {
      "billing_class": "input_cached_tokens",
      "quantity": 800,
      "unit": "token",
      "unit_price": "0.00000125",
      "amount": "0.001000"
    },
    {
      "billing_class": "output_tokens",
      "quantity": 650,
      "unit": "token",
      "unit_price": "0.00001000",
      "amount": "0.006500"
    }
  ],
  "total_amount": "0.010500",
  "currency": "USD",
  "status": "settled"
}

如果请求为 0.032100 保留并在 0.010500 结算,分类帐会将 0.021600 释放回可用余额。

建议: 切勿根据当前定价表重新计算旧发票行。存储不可变的价目表版本,并将版本 ID 附加到每个报价、预订和结算事件。否则,在提供商更新模型价格后,发票可能无法重现。

流式传输请求:先预留,后结算

流式传输使计费变得复杂,因为用户在网关知道最终使用情况之前就开始接收输出。答案不是跳过飞行前检查。网关应在打开流之前进行预留。

使用此工作流程:

  1. 估计输入令牌和最大输出成本。
  2. 预留租户预算。
  3. 打开提供商流。
  4. 将块转发到客户端。
  5. 在提供商发送最终使用情况或有后续使用记录可用时捕获最终使用情况。
  6. 结算实际费用并释放未使用的预留。

如果最终使用量不可用,请将结算标记为估算值,而不是假装它是准确的:

"usage_source": "gateway_estimate",
"is_estimated": true,
"reconciliation_status": "pending"

建议:每日调节应优先考虑估计的流式传输事件、失败的请求、超时和重试。这些是最有可能在网关记录和提供商发票之间造成差异的区域。

价目表版本控制和标记规则

价目表应该是版本化的对象,而不是可变的电子表格。

最少字段:

  • 提供商;
  • 型号 ID;
  • 结算类别;
  • 单位,例如令牌、请求、图像、音频秒或工具单位;
  • 单价;
  • 货币;
  • 有效的开始和结束时间戳;
  • 舍入政策;
  • 租户计划或合作伙伴加价规则;
  • 来源参考和审批元数据。

标记规则应明确。例如:

  • 成本加成:提供商成本加成 20%。
  • 固定零售:租户支付固定代币价格,无论提供商价格如何。
  • 分层:先按一个费率发放 1000 万个代币,然后按较低费率发放。
  • 包含的积分:使用量会在超额计费开始之前消耗每月津贴。

权衡:价目表版本控制增加了运营工作,但它可以防止发票争议成为考古问题。客户支持代理应该能够解释为什么 8 月 3 日的请求按特定费率计费,而无需检查今天的提供商定价。

将帐单与分析分开

分析和结算具有不同的容差。分析可以被聚合、延迟、采样或纠正。计费必须完整、幂等、可审核且可解释。

使用分析来解决以下问题:

  • 哪些团队使用的代币最多?
  • 哪些模型增长最快?
  • 提示缓存可以在哪些方面降低成本?
  • 哪些键会产生异常昂贵的请求?

使用结算分类帐来解决以下问题:

  • 此请求是否已根据租户余额获得授权?
  • 哪个价目表版本产生了这笔费用?
  • 未使用的预留是否已释放?
  • 客户发票是否符合已确定的使用情况?
  • 网关使用情况与提供商端使用情况相符吗?

事实: OpenTelemetry GenAI 语义约定包括令牌使用属性,例如输入和输出令牌。这对于可观察性和将跟踪连接到成本事件非常有用。但遥测属性不能替代价目表、预订、结算、舍入和发票状态。

每日对帐工作流程

对账会将网关的结算账本与提供商端的使用情况进行比较。我们的目标并不是在每个中间领域都完美一致。目标是尽早检测材料差异,以更正发票、价目表或适配器。

实用的日常工作:

  1. 按提供商、模型、租户或 API 键、计费类别和 UTC 日期对网关分类账事件进行分组。
  2. 获取按可用维度分组的提供商端使用情况,例如API密钥 ID、型号和日期。
  3. 尽可能通过用于请求响应的相同适配器代码规范提供程序导出。
  4. 按计费类别比较数量和费用。
  5. 标记超出阈值的差异,例如 0.5% 的数量差异或任何较大的绝对成本差异。
  6. 对差异原因进行分类:流式估算、重试、请求失败、缓存记帐、模型别名更改、提供商记录延迟或请求 ID 缺失。
  7. 创建调整事件而不是编辑旧的结算事件。

建议:在操作可行的情况下为每个租户使用提供程序 API 密钥,因为这样可以简化协调。如果这会产生过多的密钥管理开销,请将内部租户 ID 映射到受支持的提供商元数据,并保持可靠的请求 ID 桥接。

客户可以理解的发票行

面向客户的发票不应反映提供商JSON。它应该以稳定的商业术语解释该法案。

有用的发票列:

  • 日期范围;
  • 租户、项目或API关键标签;
  • 型号或型号配置文件;
  • 请求计数;
  • 未缓存的输入令牌;
  • 缓存的输入令牌;
  • 输出标记;
  • 媒体或工具单元(如果适用);
  • 折扣、积分或加价;
  • 总金额和币种。

对于合作伙伴,仅当业务模式需要时才包含批发成本和零售费用。许多经销商发票应仅显示零售用量,而合作伙伴信息中心可能会单独显示利润。

权衡:统一的发票架构提高了可读性,但提供商特定的结算详细信息仍然需要逃生舱口。默认情况下保持发票行简单,并为需要详细审核字段的高级客户提供导出。

实施清单

发布前

  • 为所有受支持的提供商定义标准化结算类别。
  • 创建具有生效日期的不可变价目表版本。
  • 要求输出上限或应用网关默认值。
  • 使用幂等性密钥实现原子预留。
  • 为每种货币设置舍入规则。
  • 决定如何对缓存令牌、推理令牌、媒体单元和请求费用开具发票。
  • 测试重试、超时、客户端断开连接和提供程序错误。
  • 构建调整事件机制,而不是编辑已确定的事件。

请求处理期间

  • 验证租户和密钥。
  • 在路由和后备策略之后解决最终模型。
  • 选择正确的价目表版本。
  • 引用最坏情况的成本。
  • 保留余额或拒绝请求。
  • 记录提供商请求 ID(如果可用)。
  • 根据响应标准化使用情况。
  • 结算、释放未使用的预留并发出发票就绪事件。

请求处理后

  • 按提供商、密钥、型号、结算类别和日期运行每日核对。
  • 查看预估的流媒体结算金额。
  • 标记缺少价目表条目的模型使用情况。
  • 监控缓存令牌记账引起的差异。
  • 在最终结算之前生成客户发票预览。

要计划的预测

预测:人工智能API计费将变得更加多维,而不是更少。随着模型功能的变化,令牌类、缓存类、媒体单元、工具执行和推理相关计数器可能会不断扩展。

预测:客户将期望获得请求、密钥、项目和发票级别的使用说明。没有可追踪订单项的每月总额不足以让团队转售 API 访问权限或强制执行预付费预算。

预测: 已经将报价、预订、结算和对帐分开的网关将更快地适应新的定价模型,因为它们可以添加结算类别,而无需重写整个发票系统。

可行的结论

如果您通过一个网关公开多个 AI 提供商,请在结算争议导致问题出现之前构建结算分类账。从四个保证开始:

  1. 每个计费请求都会收到预检报价。
  2. 每个预付费或有上限的租户都在提供商通话开始之前预留了预算。
  3. 每个提供商响应都会标准化为稳定的结算类别。
  4. 每张发票都可以根据提供商方的使用情况和当时使用的确切价目表版本进行核对。

该控制循环使得统一的 AI API 计费能够为客户所理解,对预付积分可执行,对合作伙伴加价灵活,并且在提供商定价或使用格式发生变化时可进行审核。

相关阅读

FAQ

常见问题

为什么不直接从提供商发票中计费?
提供商发票对于调节很有用,但它们在使用发生后到达,并且不会在请求时强制执行租户预算。网关计费分类账允许您在提供每月提供商发票之前报价、预订和结算每个请求。
是否应该向客户显示缓存的令牌?
通常是的,至少作为单独的汇总发票行。缓存的令牌可能与未缓存的输入具有不同的价格,因此将它们分开可以使折扣和费用更容易解释。
流媒体请求应如何计费?
根据最大输出上限在流开始前预留预算。最终使用可用后,结算实际费用并释放未使用的预留。如果最终使用情况丢失,请将事件标记为估计并稍后进行协调。
分析仪表板可以取代账单分类账吗?
不可以。分析可以聚合或延迟,但计费需要与价目表版本、预订、结算事件和发票状态相关联的完整、幂等、仅附加记录。