直接回答
AI 推理成本是系统在既定质量、延迟、安全与可靠性契约下,交付一个已验收结果所需的完整分摊支出。可靠的比较必须拆开托管 API、私有运行时总拥有成本(TCO)与端侧成本,让候选方案执行同一组工作负载,并以满足 SLO 的已验收结果作为分母。Token 单价是重要计量项,但不是最终价值单位。
核心要点
- 建立带日期的计费账本,因为输入、输出、缓存、批处理、工具、多模态、地域与合同可能采用不同费率。
- API、自部署与端侧必须使用同一请求轨迹、模型质量门槛和服务等级目标(SLO)比较。
- 区分完整分摊成本、可避免成本和边际成本,它们回答不同决策。
- 利用率是分母问题:闲置产能会抬高单位成本,但不能再重复记一笔硬件费用。
- 小模型路由上线前必须测量误验收、升级、回退和首次尝试浪费。
- 优化目标应是单次验收结果或单个业务事件成本,而不是孤立的单 Token 成本。
比较方案前先固定成本边界
推理成本模型只有在范围、统计周期、工作负载和验收规则明确时才有效。同一套系统在边际成本视角下可能很便宜,在完整分摊视角下却可能很昂贵。
| 成本口径 | 包含内容 | 回答的问题 |
|---|---|---|
| 完整分摊成本 | 直接用量、平台分摊、人员、安全、冗余、复核与共享服务 | 这项工作负载给企业带来多少完整成本? |
| 可避免成本 | 删除某项负载或路由后会真正消失的支出 | 这次决策实际能省下多少? |
| 边际成本 | 当前已有容量内,新增一次请求或一段流量产生的增量支出 | 现在多处理一个单位要花多少? |
已购买的加速器不能在 TCO 比较中被视为“免费”。它的边际现金支出可能较低,但分摊成本与机会成本仍然存在。反过来,也不能先记录每月硬件折旧,再额外添加一笔“GPU 闲置成本”。闲置时间应通过降低有效利用率、抬高单位交付成本来体现。
FinOps Unit Economics 将单 Token 成本等资源单位指标,与单次辅助、单个已解决工单等业务结果指标分开。这个边界同样适用于推理系统:基础设施计量解释钱花在哪里,验收结果解释支出是否创造价值。
建立带日期的 API 计费账本
供应商定价页只是成本模型的输入,不是成本模型本身。官方定价资料表明,单个“每百万 Token 价格”字段远远不够:输入与输出、Prompt Cache 写入与读取、批处理或优先模式、工具调用和多模态输入都可能采用不同计费单位。
每一种可计费维度都应独立记录:
| 字段 | 必要证据 |
|---|---|
| 服务身份 | 供应商、准确模型 ID、Endpoint、地域与修订版 |
| 用量类型 | 非缓存输入、缓存写入/读取、输出、推理、图片、音频、工具、批处理 |
| 商务口径 | 公开标价、私有合同、承诺用量、额度、币种、税费、生效日期 |
| 工作负载 | 请求数、Token 分布、上下文、输出长度、模态与流量形状 |
| 可靠性 | 超时、重试、取消、失败任务、重复副作用与回退 |
| 对账证据 | 用量导出、发票条目、应用事件与成本归属人 |
不要在常青文章中维护永久供应商价格排名。准确费率应保存在带日期的账本中,并保留来源 URL。当前官方入口包括 OpenAI API 定价、Anthropic API 定价 与 Gemini API 定价。各家的计费维度与叠加规则并不相同,比较总额前要先统一账单字段。
FinOps FOCUS 规范 为账单成本、有效成本、承诺、额度、币种、分摊与对账提供了通用结构。FOCUS 可以统一计费记录,却不会自动统一模型质量、验收规则或 AI 业务结果,这些字段仍要由应用账本补齐。
私有运行时 TCO 如何避免重复核算
私有运行时成本等于已配置产能与围绕它运行的工程体系之和,不能只用 GPU 租金除以峰值吞吐。
monthly_private_tco =
加速器租赁或折旧
+ 主机 CPU、内存与本地存储
+ 能耗与制冷
+ 网络与持久化存储
+ 编排、可观测与安全
+ 工程支持与值班
+ 评测与发布运维
+ 冗余与恢复容量
所有项目必须使用同一核算周期。购买硬件时,按批准的使用年限和预计残值折旧;租赁算力时,要计入闲置期间仍需支付的预留或承诺费用。共享人员与平台成本应采用可解释的分摊驱动,例如机群小时、请求数或已验收结果。
产能指标与加速器遥测必须拆开
没有任何一个“利用率”百分比可以独立解释推理经济性。不同层级应分别记录:
| 指标 | 分子 / 分母 | 支持的决策 |
|---|---|---|
| 机群分配率 | 已分配加速器小时 / 已配置加速器小时 | 容量缩放与回收 |
| 加速器活动率 | 繁忙采样 / 总观测采样 | Kernel 与调度诊断 |
| 显存占用率 | 模型和 Cache 已分配显存 / 可用显存 | 模型放置与并发 |
| 请求有效吞吐 | 已验收且满足 SLO 的请求 / 秒 | 用户可感知有效产能 |
| Token 有效吞吐 | 已验收且满足 SLO 的输出 Token / 秒 | 带质量门槛的生成产能 |
经济模型的分母应是有效交付工作。GPU 即使活动率很高,请求仍可能错过首 Token 延迟(TTFT)、Token 间延迟(ITL)或质量目标;对于突发且延迟要求严格的服务,中等活动率也不必然代表经济性差。
vLLM Serving Benchmark 支持控制请求速率、并发、突发性与 Goodput 条件;vLLM 生产指标覆盖排队、Prefill、Decode、Token、Cache 与请求状态。运行时指标会随版本变化,采集与看板必须固定引擎版本。
用同一服务契约比较 API、自部署与端侧
只有所有候选方案执行相同代表性轨迹,并使用相同验收策略时,部署经济性才可比较。
| 边界 | 托管 API | 私有运行时 | 端侧或设备内 |
|---|---|---|---|
| 主要计量 | 供应商可计费单位 | 已配置机群与运营 | 设备资源、能耗、分发与支持 |
| 弹性 | 供应商配额与商务档位 | 扩缩容与自有容量 | 已安装设备与运行时覆盖 |
| 延迟 | 网络、供应商排队、Prefill、Decode | 本地排队、Prefill、Decode、网络 | 设备负载、温度、运行时、电池策略 |
| 数据控制 | 合同、地域、保留与分包商 | 操作人员、备份、日志与供应链 | 应用权限、遥测、备份与模型包 |
| 变更负担 | 供应商模型或政策漂移 | 运行时、Kernel、权重与硬件 | 设备碎片、升级与兼容 |
| 故障成本 | 限流、服务中断与重试 | 容量、抢占与值班 | 不兼容设备、降频与云端回退 |
端侧执行可能减少供应商调用,但不等于免费或默认隐私。模型打包、下载流量、设备兼容、能耗、升级支持、本地日志、备份、遥测和云端回退都应进入账本。小语言模型与端侧部署指南说明设备适配评测,本地大模型部署指南则覆盖推理运行时选择与生产控制。
用单次验收结果成本做最终决策
单次验收结果成本可以防止低质量尝试伪装成降本。测试模型、路由、缓存或 Prompt 之前,必须先定义验收规则。
cost_per_accepted_outcome =
(供应商成本
+ 私有运行时成本
+ 端侧成本
+ 重试与回退成本
+ 人工复核成本
+ 运营分摊成本)
/ 已验收结果数
已验收结果必须通过可测量的工作负载契约。例如:客服工单解决后未再次打开、代码改动通过测试与 Review、抽取结果匹配标注字段、Agent 在未产生越权副作用的前提下完成动作。
高风险工作流中,成本必须服从发布门禁。NIST AI 风险管理框架提供了可信与风险管理结构。它不规定推理成本公式,但支持把有效性、安全、隐私、安全防护、透明度和责任保留在决策中,避免为了降本直接删除这些约束。
把小模型与路由作为完整系统评估
只有完整路由仍然达标时,小模型才真正降低成本。参数量不是质量契约,窄基准上的胜出也不能证明可以全面替代更大模型。
每个任务切片至少测量:
- 首次验收率与误验收率;
- 升级率与升级原因;
- 回退延迟与回退成功率;
- 回退前已经消耗的 Token 与算力;
- 工具调用 Schema 有效率与副作用正确性;
- 拒答、策略与授权行为;
- 模型包、评测与维护成本。
设 p_small_accept 为小模型路由正确验收的请求比例,p_escalate 为升级到更强模型的比例,p_false_accept 为错误验收比例,则预期成本可先写成:
expected_route_cost =
小模型路由成本
+ p_escalate * 回退成本
+ p_false_accept * 修复与风险成本
这条公式仍必须受质量门禁约束:即使预期支出更低,只要误验收率或安全预算超标就不能上线。还应把确定性规则作为候选方案。分类、校验、检索或模板可能比生成模型成本更低,失败方式也更容易预测。
运行可复现的敏感性模型
敏感性模型应同时输出假设与结果,确保评审者可以复现盈亏点。下面的脚本比较 API 月成本与私有运行时完整分摊 TCO,并计算单次验收结果成本。它把费率和性能作为输入,不在代码中固化供应商价格或基准结论。
from __future__ import annotations
import argparse
import json
from dataclasses import asdict, dataclass
@dataclass(frozen=True)
class Scenario:
monthly_requests: int
input_tokens_per_request: int
output_tokens_per_request: int
api_input_per_million: float
api_output_per_million: float
api_extra_monthly: float
private_fixed_monthly: float
private_variable_per_request: float
api_acceptance_rate: float
private_acceptance_rate: float
api_retry_multiplier: float
private_retry_multiplier: float
def probability(value: float, name: str) -> float:
if not 0 < value <= 1:
raise ValueError(f"{name} must be in (0, 1]")
return value
def nonnegative(value: float, name: str) -> float:
if value < 0:
raise ValueError(f"{name} must be nonnegative")
return value
def evaluate(s: Scenario) -> dict[str, float]:
if s.monthly_requests <= 0:
raise ValueError("monthly_requests must be positive")
for name in (
"input_tokens_per_request",
"output_tokens_per_request",
"api_input_per_million",
"api_output_per_million",
"api_extra_monthly",
"private_fixed_monthly",
"private_variable_per_request",
):
nonnegative(float(getattr(s, name)), name)
probability(s.api_acceptance_rate, "api_acceptance_rate")
probability(s.private_acceptance_rate, "private_acceptance_rate")
if s.api_retry_multiplier < 1 or s.private_retry_multiplier < 1:
raise ValueError("retry multipliers must be at least 1")
api_attempts = s.monthly_requests * s.api_retry_multiplier
private_attempts = s.monthly_requests * s.private_retry_multiplier
api_token_cost = (
api_attempts
* (
s.input_tokens_per_request * s.api_input_per_million
+ s.output_tokens_per_request * s.api_output_per_million
)
/ 1_000_000
)
api_total = api_token_cost + s.api_extra_monthly
private_total = (
s.private_fixed_monthly
+ private_attempts * s.private_variable_per_request
)
api_accepted = s.monthly_requests * s.api_acceptance_rate
private_accepted = s.monthly_requests * s.private_acceptance_rate
return {
"api_monthly_cost": api_total,
"private_monthly_cost": private_total,
"api_cost_per_accepted_outcome": api_total / api_accepted,
"private_cost_per_accepted_outcome": private_total / private_accepted,
}
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("scenario", help="Path to a JSON scenario")
args = parser.parse_args()
with open(args.scenario, encoding="utf-8") as handle:
scenario = Scenario(**json.load(handle))
print(json.dumps({
"assumptions": asdict(scenario),
"results": evaluate(scenario),
}, indent=2))
if __name__ == "__main__":
main()
把假设保存为独立文件:
{
"monthly_requests": 1000000,
"input_tokens_per_request": 800,
"output_tokens_per_request": 200,
"api_input_per_million": 1.0,
"api_output_per_million": 4.0,
"api_extra_monthly": 500.0,
"private_fixed_monthly": 3500.0,
"private_variable_per_request": 0.0002,
"api_acceptance_rate": 0.92,
"private_acceptance_rate": 0.88,
"api_retry_multiplier": 1.03,
"private_retry_multiplier": 1.08
}
执行 python inference_cost.py scenario.json,然后每次只改变一个假设。示例数字只用于演示输入结构,实际决策必须替换为当前合同、发票、基准与验收结果。需求、Token 构成、有效利用率、验收率、重试、人员、能耗、汇率和必要副本数都应提供低位、基准与高位场景。
所有降本手段都要经过质量门禁
不同成本杠杆改变的是系统不同部分,不能共享一个固定节省比例。
Prompt Cache 与 KV Cache
Prompt Cache 可按供应商规则减少重复输入处理;推理服务中的 KV Cache可减少符合条件的注意力状态重复计算;语义缓存则按语义复用已有回答。三者机制不同,身份、新鲜度、隔离与失效风险也不同。
需要测量可缓存请求比例、命中率、读写费用、错误复用、过期复用、延迟、存储、失效工作和质量。语义缓存生产指南进一步说明授权与误命中控制。
批处理与调度
连续批处理可以在 Slot 释放后调度新请求,提高已交付产能;供应商离线批处理则可能采用另一种商务费率。两者都可能增加排队或取消复杂度,因此应测量 TTFT、ITL、端到端延迟、完成率和 Goodput,而不是只引用峰值 Token/s。
量化与模型压缩
模型量化可以降低权重显存,并可能提高吞吐,但结果取决于 Kernel 支持、校准、上下文、硬件和任务质量。必须测试准确模型产物与运行时,并把验收损失或回退工作计入结果成本。模型量化指南说明这些边界。
上下文选择与输出控制
删除无关上下文、约束输出长度可能减少计费或计算 Token。与此同时,要验证引用覆盖、指令保留、拒答、Schema 有效性和回答质量。导致更多重试的短 Prompt 反而可能抬高总成本。
把支出对账到应用事件
成本可观测性应关联账单、运行时与结果证据,同时避免保留不必要的敏感内容。
event_id
request_id
workload_class
tenant_id_hash
model_and_revision
route_and_fallback_reason
input_output_cache_and_tool_units
queue_ttft_itl_and_e2e
retry_and_attempt_count
quality_gate_version
accepted_outcome
billed_cost
allocated_runtime_cost
每个周期需要对齐三组总量:
- 供应商用量与供应商发票;
- 运行时分摊与基础设施、平台账本;
- 应用事件与已验收业务结果。
同时记录数据完整度、延迟到达事件、币种、额度与共享成本分摊。租户 ID 经过哈希,并不代表所有 Trace 都可以安全保留;Prompt、密钥、个人数据、工具 Payload 和生成内容都应根据明确的保留目的脱敏。
决策门禁与常见失败
成本变更只有同时通过核算、质量、服务与回滚门禁,才具备上线条件。
- 建立基线:固定代表性轨迹、验收 Rubric、SLO、模型身份与带日期成本账本。
- 容量测试:扫描请求速率、并发、上下文、输出长度与突发性,报告 Goodput 与失败,不只报告峰值吞吐。
- 质量测试:比较任务切片、误验收、升级、恢复、安全与人工复核。
- 敏感性测试:改变需求、利用率、副本、价格、人员、能耗、重试率与验收率。
- 发布门禁:设置预算、质量与 SLO 阈值,明确负责人、回滚触发器和回退容量。
- 上线对账:将预测与发票、基础设施账本及已验收结果比较。
常见失败包括:比较不同模型质量、用平均流量规划突发容量、把公开标价当成真实发票成本、把峰值吞吐当成有效产能、漏掉失败工作,以及未审计日志、更新、备份与操作人员就宣称本地执行天然隐私。
常见问题
如何计算 AI 推理成本?
先确定成本边界与统计周期,再建立带日期的用量账本,分摊供应商费用或运行时 TCO,加入重试、失败、复核、可观测和共享服务,最后除以已验收结果。单 Token 成本应保留为诊断子指标。
什么时候自部署比 API 便宜?
不存在统一请求量或 Token 阈值。只有在相同质量、SLO、可靠性与风险契约下,自部署的完整分摊单次验收结果成本更低时,结论才成立。流量形状、副本、利用率、硬件价格与人员投入都可能改变结果。
小模型一定能降低推理成本吗?
不一定。小模型需要在明确任务切片中验证,还要计入分类器错误、误验收、升级、回退、首次尝试浪费、维护和安全。不能从参数量直接推断适用性。
GPU 利用率越高就一定越便宜吗?
不一定。高活动率可能同时伴随排队、延迟超标或输出未通过验收。经济效率取决于每一元已配置成本交付多少满足 SLO 的已验收工作,而活动率与显存指标用于解释产能为什么有效或无效。
应该在长期文章中维护供应商价格表吗?
准确费率应放在带日期的账本或生成报告中。文章只保留计费维度、来源 URL 与更新方法。供应商更换模型、缓存规则、地域、折扣或工具计价后,决策方法仍可复用。
参考资料
- FinOps Unit Economics
- FOCUS 规范
- OpenAI API 定价
- Anthropic API 定价
- Gemini API 定价
- vLLM Serving Benchmark
- vLLM 生产指标
- NIST AI 风险管理框架