# LLM Token 用量计量：AI SaaS 架构指南

> 构建能够应对重试、支持多个服务商并生成清晰计费事件的 LLM token 用量计量流水线。了解相关架构与常见问题。
- **Author**: Ayush Agarwal
- **Published**: 2026-05-17
- **Category**: AI, Architecture, Usage-based Billing
- **URL**: https://dodopayments.com/blogs/zh/metering-llm-token-usage-architecture

---

生产环境中的 LLM 用量计量流水线需要四个层次：在调用边界读取服务商 usage 对象的插桩层，将计费与补全请求解耦的队列，将原始事件转换为可计费数量的托管聚合层，以及用于捕捉偏差的对账任务。缺少其中任何一个层次，计量结果都会悄悄偏离服务商实际向你收取的费用。

这就是完整答案，本文其余部分将解释每个层次存在的原因。表面上看，用量计量很简单：服务商会在每次补全请求中返回一个 usage 对象，你把输入和输出 token 数量写入某处，月底再把它们加总并收费。但在实践中，要为真实产品可靠地完成这些工作，需要一套重要的架构；而一旦出错，损失的不仅是金钱，还有客户信任。

本文将介绍一套能够应对真实环境的 LLM 用量计量流水线架构。多个服务商、多步骤代理、重试、部分失败和跨区域流量，都会产生朴素实现容易处理错误的边界情况。本文面向 SaaS 或 AI 产品，而非电商，并且可以与我们更全面的 [构建 AI SaaS 计费系统指南](https://dodopayments.com/blogs/build-billing-system-ai-saas) 配合阅读。

## LLM 用量计量流水线究竟需要完成什么

一条实用的流水线需要同时可靠地完成五件事。

它要在 LLM 调用发生的边界捕获 token 数量，包括输入和输出 token，以及服务商计费的推理 token 或后台调用产生的 token。

它要将每个 token 数量归因到特定客户，通常还要归因到客户下的特定用户，并可选地归因到产品中的某项功能或界面。没有归因信息，这些数据无法用于计费，对分析的价值也非常有限。

它要干净地处理重试。如果代码重试失败的补全请求，计量系统必须记录实际成功的调用，而不能重复计数。如果代码重试事件写入请求，计费系统则必须进行去重。

它要优雅地处理部分失败。如果服务商调用成功，但你的计量事件写入失败，客户已经获得了服务。系统必须进行对账，而不是丢失事件或阻止用户继续使用。

它要支持你实际使用的计费基础能力。如果你的计费模型是按 token 收费，并带有配额和超额用量，计量系统就必须以正确的形式提供数据。如果你的模型包含容量包或预付额度，计量系统还必须与这些余额交互。

能够出色完成这五件事的流水线，可靠、可预测且运营成本低。任何一项做得不好，都会造成收入流失或让客户困惑。

## 架构层次

大多数真实的流水线都可以归纳为四个层次，即使具体实现各不相同。

### 插桩层

这一层的代码负责包装 LLM 调用并观察发生了什么。最简洁的模式是在服务商客户端外包一层轻量包装器，拦截请求和响应，记录服务商返回的 usage 对象，然后继续执行而不改变调用语义。它与 LLM 调用同步运行，但不应阻塞调用。如果包装器内部失败，LLM 调用仍应成功，同时记录该失败。

包装器会捕获输入 token、输出 token、模型名称、客户标识符，以及可选的功能标签。客户标识符来自你的应用上下文。功能标签用于描述该调用属于产品的哪一部分，这对后续分析至关重要。

对于支持多个服务商的产品，包装器会在不同服务商之间进行规范化处理。OpenAI、Anthropic、Google 和 AI SDK 返回的 usage 结构略有不同。包装器会生成统一的内部表示，让下游层无需针对不同服务商的细节编写特殊处理逻辑。

### 传输层

这一层的代码负责将用量事件从你的应用传输到计费系统。朴素版本是由包装器直接调用计费 API。这种方式在规模较小时可行，但在规模扩大或发生故障时就会失效。

更可靠的版本会使用队列。包装器写入本地队列，工作进程从队列中消费事件，并批量提交到计费 API。队列可以吸收流量峰值、平滑突发流量，并独立于 LLM 调用提供重试语义。如果计费 API 短暂不可用，队列会暂存事件，待服务恢复后由工作进程继续处理。

对于流量较大的产品，队列通常采用托管服务，例如 Cloud Pub Sub、SQS、Kafka 或类似服务。对于规模较小的产品，只要持久化是真正可靠的，带持久化存储的进程内队列也可以使用。重启时丢失队列内容，就意味着计费数据丢失。

### 聚合层

这一层负责将事件转换为可计费单位。在 Dodo Payments 及类似平台中，这一层由计费系统自身托管。你可以在平台中定义计量器，描述如何将原始事件聚合为可计费数量。token 用量计量器通常会对 input tokens、output tokens 或 total tokens 属性执行求和聚合。

聚合会持续进行。事件到达后，计量器会更新每个客户的累计总量。订阅和配额会引用这些总量。当总量超过配额时，就会触发超额用量。计费周期结束时，发票会读取这些总量。

你可以在自己的数据库中保留一份聚合数据，用于分析。许多团队都会这样做。计费系统是实际收费金额的事实来源，而你的本地副本则用于仪表盘和产品功能。关于如何定义计量器并将其连接到价格，我们的 [实现按用量计费指南](https://dodopayments.com/blogs/implement-usage-based-billing) 提供了逐步说明。

### 对账层

这一层负责捕捉错误。每条重要的流水线都会有一个每天或每小时运行的对账任务。它会比较服务商发票、写入计费系统的事件，以及你数据库中的本地副本，并记录和调查差异。

差异的真实原因包括：网络分区导致事件在传输途中丢失；由于重试时没有幂等性导致事件重复计数；服务商更改模型后改变 token 计数规则；以及日期边界聚合中的时区不一致。这些都不是什么罕见情况，它们都会发生。

对账任务是一条流水线"正确运行"和"自认为正确运行"之间的区别。没有对账，错误就会悄悄累积。

## 常见的架构错误

有几种模式几乎必然会带来问题，值得从第一天起就避免。

在 token 产生之前计数，而不是在调用完成后计数。根据提示词和回复长度估算 token 很有吸引力，因为它简单，但只有服务商实际返回的数量才与服务商发票一致。始终从服务商响应中读取 usage 对象。

在系统级调用中跳过客户标识符。后台摘要、embedding 刷新和其他内部调用同样会产生成本。如果你不为它们添加客户标识符或内部标签，它们就会以无法归因的成本出现。有些团队会将后台工作归因到触发它的用户。另一些团队则将其归因到一个虚拟的系统客户。两种方式都可以，但不能不加标签。

使用没有幂等性的请求重试。如果代码在没有幂等键的情况下重试失败的计费 API 调用，事件就可能被重复计数。计费系统无法知道第二次调用是重试，还是一个独立事件。为每个逻辑事件传递稳定的幂等键。

在没有队列的情况下，将计量器直接绑定到 LLM 调用。如果计费 API 变慢或短暂宕机，LLM 调用也会变慢或失败。即使 LLM 本身运行正常，客户仍会感受到这次故障。通过队列将两者解耦。

忘记处理多步骤代理调用。一次用户请求可能触发六次服务商调用。如果你只对面向用户的调用进行计量，就会少计。如果同时累加父调用和子调用，又会重复计量。应制定清晰的策略。大多数团队会对每次实际的服务商调用进行计量，而只在分析场景中将其汇总到用户请求，不将汇总结果用于计费。

没有在故障条件下测试流水线。稳定状态下正常运行的流水线并不难。真正值得关注的是：队列填满时会发生什么，计费 API 返回错误时会发生什么，LLM 服务商部分中断时会发生什么，工作进程崩溃时会发生什么。主动运行故障测试，并观察实际结果。

## Dodo Payments 如何融入这一架构

Dodo Payments 提供聚合层，以及供传输层使用的事件写入 API。你可以在仪表盘中定义一个描述聚合方式的计量器，从工作进程调用事件写入 API，然后由平台处理其余工作。

针对 LLM 用例，平台提供事件写入蓝图，也就是包装常见 LLM 客户端并自动发出用量事件的 SDK。这些蓝图支持 AI SDK、OpenAI、Anthropic、OpenRouter、Groq 和 Google Gemini。每个蓝图都会规范化服务商的 usage 对象，并发出带有正确客户标识符和事件名称的事件。

这种架构的优势在于，包装器、传输层和聚合层都经过生产环境测试。你只需将 SDK 添加到应用中，配置 API 密钥和计量器事件名称，用量就会自动被追踪。你仍然需要在其上构建对账层，也仍然需要决定如何处理归因和多步骤代理，但基础连接工作已经解决。

LLM 蓝图和事件写入 API 的完整参考资料位于 [LLM 写入蓝图](https://docs.dodopayments.com/developer-resources/ingestion-blueprints/llm) 和[按用量计费指南](https://docs.dodopayments.com/developer-resources/usage-based-billing-guide)中。本文为你介绍架构，文档则提供实现细节。

## 参考架构

将所有层次组合起来，一条清晰的 LLM 用量计量流水线大致如下。

你的应用代码会在每次补全请求中调用经过包装的 LLM 客户端。包装器从服务商响应中捕获 usage 对象，并将结构化事件写入本地队列。事件包括客户标识符、计量器事件名称、输入和输出 token、模型名称，以及任何功能标签。

工作进程从队列中消费事件，将事件批量处理后，携带幂等键提交到事件写入 API。工作进程会针对临时性失败进行重试，并将持续性失败反馈到监控系统。成功写入的事件会从队列中移除。

计费系统会将事件聚合到计量器中。计量器为订阅和超额用量规则提供数据。计费周期结束时，系统会根据计量器总量生成发票。

对账任务每天运行一次。它会将你发送给计费系统的事件与你的本地副本以及服务商发票进行比较。差异会被记录下来。对于超过告警阈值的差异，由人工进行调查。

你的应用通过计费系统 API 读取计量器总量，并在产品用户界面中展示用量。这些数据与生成发票的数据相同，因此客户不会在你的产品中看到一个数字，却在账单上看到另一个数字。

## 运营维护

一些习惯可以让流水线长期稳定运行。

为队列深度设置告警。队列深度不断增长，意味着工作进程无法跟上事件的进入速度。应在这变成计费延迟之前进行调查。

为事件写入错误率设置告警。持续性错误通常意味着计量器事件名称的配置与你的工作进程发送的内容发生了偏差。

运行对账任务并查看结果。只有人工阅读报告，这项任务才有价值。将它纳入固定的运营流程。

为每个事件添加生成它的应用版本。当你更换模型或调整提示词结构时，token 数量的变化会反映在数据中。没有版本信息，你就无法判断每次请求的平均 token 数量变化究竟来自模型变化、代码变化，还是客户行为变化。

记录多步骤代理和后台调用的处理策略。如果策略只存在于某个人的记忆中，就会逐渐偏移。将其写下来，并在包装器代码中引用，以便未来的工程师能够看到。

## 最后想说

LLM 用量计量看起来是个小问题，最终却会变成一个真正的问题。简单版本----计算 token 并将其写入某处----第一个月可能正常，到第三个月就开始出现问题。可靠版本则具备清晰的插桩、队列、托管聚合层和对账任务。这些层次单独来看都不复杂，但组合起来，就构成了可信赖的计费系统与逐渐偏离现实的计费系统之间的区别。

如果你现在正在构建 AI 产品，请尽早把这套架构做好。第一次正确构建的成本，远低于清理六个月后已经发生偏差的数据；而选择已经托管聚合层的 [AI 计费平台](https://dodopayments.com/blogs/ai-billing-platforms)，通常也比自行维护更便宜。这里介绍的模式并不罕见，它们与可观测性和分析系统多年来使用的模式相同。将这些模式应用到计费数据中，你会发现计费体系的其他部分也更容易理解和管理。

## 常见问题

### 我应该计量输入 token、输出 token，还是两者都计量？

两者都要，并分别计量。大多数服务商对输入和输出 token 采用不同的成本结构，而你的计费模型通常也需要对两者应用不同的费率或权重。将它们作为计量器事件中的独立属性保存后，你就可以根据实际收费方式计算其中一项或同时计算两项。

### 如何处理会将请求分发到多个服务商调用的多步骤代理？

对每一次实际的服务商调用进行计量，让成本数据与服务商发票保持一致。在计费方面，你需要决定是按代理运行次数收费，还是按底层调用次数收费。按代理运行次数收费对客户来说更简单，但你需要承担成本波动。按底层调用次数收费会将波动转嫁给客户，但能与你的成本保持一致。

### 如果我漏掉了一个事件，会发生什么？

漏掉事件意味着收入损失。对账层会将现有数据与服务商发票进行比较，从而捕捉漏记的事件。差距较小时，你可以自行承担；差距较大时，对账告警会提醒你调查流水线。无论哪种情况，你都需要具备可见性。

### 包装器和计费 API 之间的队列有多重要？

非常重要。没有队列，计费 API 的每次波动都会变成客户能够感受到的 LLM 调用波动。有了队列，即使上游变慢几分钟，计费流水线也能吸收这段延迟，而不会影响产品行为。对于任何达到一定规模的产品，队列都是必不可少的。

### 我可以将同一条流水线同时用于分析和计费吗？

同一批事件可以同时提供给两者，但计费的事实来源应当是负责开具发票的平台。你的本地副本适合用于分析仪表盘。当两者出现偏差时，以平台侧记录的客户实际付款金额为准。将这种偏差视为需要运行对账任务的信号。
---
- [More AI articles](https://dodopayments.com/blogs/category/ai)
- [All articles](https://dodopayments.com/blogs)