直接回答

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 租金除以峰值吞吐。

text
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 之前,必须先定义验收规则。

text
cost_per_accepted_outcome =
  (供应商成本
   + 私有运行时成本
   + 端侧成本
   + 重试与回退成本
   + 人工复核成本
   + 运营分摊成本)
  / 已验收结果数

已验收结果必须通过可测量的工作负载契约。例如:客服工单解决后未再次打开、代码改动通过测试与 Review、抽取结果匹配标注字段、Agent 在未产生越权副作用的前提下完成动作。

高风险工作流中,成本必须服从发布门禁。NIST AI 风险管理框架提供了可信与风险管理结构。它不规定推理成本公式,但支持把有效性、安全、隐私、安全防护、透明度和责任保留在决策中,避免为了降本直接删除这些约束。

flowchart LR A["代表性请求轨迹"] --> B["候选路由"] B --> C["质量与安全评测"] C --> D["延迟与可靠性 SLO"] D --> E["已验收结果"] C -->|失败| F["回退、重试或人工复核"] D -->|失败| F F --> G["归因失败成本"] E --> H["单次验收结果成本"] G --> H

把小模型与路由作为完整系统评估

只有完整路由仍然达标时,小模型才真正降低成本。参数量不是质量契约,窄基准上的胜出也不能证明可以全面替代更大模型。

每个任务切片至少测量:

  • 首次验收率与误验收率;
  • 升级率与升级原因;
  • 回退延迟与回退成功率;
  • 回退前已经消耗的 Token 与算力;
  • 工具调用 Schema 有效率与副作用正确性;
  • 拒答、策略与授权行为;
  • 模型包、评测与维护成本。

设 p_small_accept 为小模型路由正确验收的请求比例,p_escalate 为升级到更强模型的比例,p_false_accept 为错误验收比例,则预期成本可先写成:

text
expected_route_cost =
    小模型路由成本
  + p_escalate * 回退成本
  + p_false_accept * 修复与风险成本

这条公式仍必须受质量门禁约束:即使预期支出更低,只要误验收率或安全预算超标就不能上线。还应把确定性规则作为候选方案。分类、校验、检索或模板可能比生成模型成本更低,失败方式也更容易预测。

运行可复现的敏感性模型

敏感性模型应同时输出假设与结果,确保评审者可以复现盈亏点。下面的脚本比较 API 月成本与私有运行时完整分摊 TCO,并计算单次验收结果成本。它把费率和性能作为输入,不在代码中固化供应商价格或基准结论。

python
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()

把假设保存为独立文件:

json
{
  "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 反而可能抬高总成本。

把支出对账到应用事件

成本可观测性应关联账单、运行时与结果证据,同时避免保留不必要的敏感内容。

text
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

每个周期需要对齐三组总量:

  1. 供应商用量与供应商发票;
  2. 运行时分摊与基础设施、平台账本;
  3. 应用事件与已验收业务结果。

同时记录数据完整度、延迟到达事件、币种、额度与共享成本分摊。租户 ID 经过哈希,并不代表所有 Trace 都可以安全保留;Prompt、密钥、个人数据、工具 Payload 和生成内容都应根据明确的保留目的脱敏。

决策门禁与常见失败

成本变更只有同时通过核算、质量、服务与回滚门禁,才具备上线条件。

  1. 建立基线:固定代表性轨迹、验收 Rubric、SLO、模型身份与带日期成本账本。
  2. 容量测试:扫描请求速率、并发、上下文、输出长度与突发性,报告 Goodput 与失败,不只报告峰值吞吐。
  3. 质量测试:比较任务切片、误验收、升级、恢复、安全与人工复核。
  4. 敏感性测试:改变需求、利用率、副本、价格、人员、能耗、重试率与验收率。
  5. 发布门禁:设置预算、质量与 SLO 阈值,明确负责人、回滚触发器和回退容量。
  6. 上线对账:将预测与发票、基础设施账本及已验收结果比较。

常见失败包括:比较不同模型质量、用平均流量规划突发容量、把公开标价当成真实发票成本、把峰值吞吐当成有效产能、漏掉失败工作,以及未审计日志、更新、备份与操作人员就宣称本地执行天然隐私。

常见问题

如何计算 AI 推理成本?

先确定成本边界与统计周期,再建立带日期的用量账本,分摊供应商费用或运行时 TCO,加入重试、失败、复核、可观测和共享服务,最后除以已验收结果。单 Token 成本应保留为诊断子指标。

什么时候自部署比 API 便宜?

不存在统一请求量或 Token 阈值。只有在相同质量、SLO、可靠性与风险契约下,自部署的完整分摊单次验收结果成本更低时,结论才成立。流量形状、副本、利用率、硬件价格与人员投入都可能改变结果。

小模型一定能降低推理成本吗?

不一定。小模型需要在明确任务切片中验证,还要计入分类器错误、误验收、升级、回退、首次尝试浪费、维护和安全。不能从参数量直接推断适用性。

GPU 利用率越高就一定越便宜吗?

不一定。高活动率可能同时伴随排队、延迟超标或输出未通过验收。经济效率取决于每一元已配置成本交付多少满足 SLO 的已验收工作,而活动率与显存指标用于解释产能为什么有效或无效。

应该在长期文章中维护供应商价格表吗?

准确费率应放在带日期的账本或生成报告中。文章只保留计费维度、来源 URL 与更新方法。供应商更换模型、缓存规则、地域、折扣或工具计价后,决策方法仍可复用。

参考资料

相关资源