财务在月底打开发票。一个供应商。一个数字。它比上个月大,而且下个月还会更大。然后他们提出了唯一重要的问题 —— 这是哪个功能花的钱? —— 房间里没人能回答。
这是在生产环境中运行 AI 的一种隐蔽失败模式。并不是说账单数额巨大;如果价值匹配,数额大也没关系。失败之处在于账单是无法归因的。它作为一个单一的费用项出现 —— OpenAI、Anthropic、Bedrock、Azure —— 没有任何财务部门真正需要的维度:没有按功能、按团队、按客户,也没有按成功的任务进行拆分。你能看到总额在上升。但你看不出 原因,而当发票寄到时,原本可以解释它的请求上下文早已消失了。
这之所以会让优秀的工程团队措手不及,是因为他们已经为云服务解决过一次成本归因问题了。每个 EC2 实例、每个 S3 存储桶、每个托管数据库都是一个带有 ARN 且可以标记的 资源。team:payments、env:prod、service:checkout —— 只要加上这些标签,成本和使用情况报告就会自动进行切分。十年来的 FinOps 工具都基于这种模式:成本挂载在可标记的资产上,而分配只是在已有标签基础上的下游报告问题。
LLM API 调用从根本上打破了这一假设。它不是一种资产。它是一次 交易 (transaction) —— 一个返回 Token 后即消失的无状态请求。没有资源 ID 可以标记,没有长期存在的东西可以贴标签。供应商按 API 密钥和时间向你计费,并汇总成一个总额。无论调用瞬间存在什么样的业务上下文 —— 哪个用户、哪个功能、哪个客户、哪个智能体 (agent) 运行 —— 除非 你 在调用那一刻、在请求离开你的进程之前将其放入其中,否则这些信息都不会出现在账单数据中。
为什么 Token 支出难以适配现有的标签
结构性问题在于上下文存在于错误的地方。你的 LLM 调用发生在函数深处,而这些函数根本不知道它们正在为哪个业务动作服务。一个 summarize() 辅助函数不知道它是被文档搜索功能还是邮件助手调用的。一个检索步骤不知道它正在处理三个调用栈之前的哪个客户请求。Token 成本产生在栈底,而其意义则存在于栈顶。
云端标记之所以奏效,是因为意义和资源是同一个对象 —— 你标记了数据库,针对它的每一次查询都会自动继承该归因。LLM 调用则相反。花钱的东西(请求)和解释成本的东西(业务意图)被整个调用栈隔离开来,除非你显式地将其透传下去,否则没有任何东西能携带这个意图。
这就是为什么两种显而易见的退路都令人失望。供应商原生归因 —— 项目范围的密钥、工作区使用情况 API、按密钥的成本细目 —— 确实存在且值得开启,但它的粒度止于密钥级别。你得到的是“这个密钥花了 4 万美元”,而不是“注册流程花了 4 万美元,主要花在一个企业租户的超大文档上”。而且你不可能在不陷入密钥管理泥潭的情况下,为每个功能、每个租户、每个环境都创建一个密钥。追溯性日志解析 则更糟。一旦请求完成,你的日志只会显示一个不透明的模型调用:供应商、模型、Token 数量。路由它的功能、触发它的用户、它所属的智能体运行 —— 这些上下文在调用时存在于内存中,事后根本无法从日志行中恢复。重建过程缓慢、有损,并且总是漏掉你最关心的那些特定情况,例如横跨数十次调用的漫长智能体追踪 (agentic traces)。
只有在请求创建时就附带标签,归因才是真实的。没有“事后”这一说。
你实际需要埋点的内容
解决方法并不光鲜:在每个模型调用处附加业务元数据,并将其透传到每一个环节。从业者们已经达成共识,建议在每个请求中携带以下一组核心字段:
feature — 产品功能界面(聊天、摘要、agent_research)。这是财务和产品部门最先想要的维度。
customer_id (已哈希) — 在 B2B 中实现按租户的单位经济分析和利润保护。
user_id — 隔离那些拉高平均成本的重度账户。
agent_run_id — 将多步执行分组,这样失控的循环会显示为一个昂贵的追踪,而不是五十个看起来很便宜的调用。
prompt_version — 固定模板,这样成本回归可以追溯到导致成本上升的修改。
deployment — 防止测试环境的支出混入你的生产单位经济数据中。
有两条实现路径可以携带这些信息,而无需将每个函数签名都变成元数据传递员。第一种是 LLM 网关或代理 —— 如 LiteLLM、Portkey、Helicone 等 —— 所有模型请求都通过它进行路由。作为一个统一的收口点,它可以在一处对每次调用进行计价、标记、记录和预算检查,你只需将元数据作为请求头注入,而无需在应用程序代码中层层传递。第二种是通过 OpenTelemetry 进行 追踪上下文传播 (trace-context propagation):在 HTTP 边界启动的追踪已经携带了 user_id 和 session_id,在该追踪内部创建的任何 LLM span 都会自动继承它们,而不需要每个中间函数手动向下传递。大多数成熟的方案会同时使用两者 —— 网关用于执行和权威计价,追踪则用于网关请求头无法看到的深度调用图上下文。
有一个会计细节比看起来更重要。不要将 Token 简化为一个单一的输入/输出桶。提示词缓存读取 (prompt-cached reads)、缓存创建写入、补全 Token 和工具 Token 的成本差异巨大,将它们混为一谈会掩盖资金流向。如果你按全额输入价格计算缓存读取,一个缓存密集型的工作负载看起来会异常昂贵;而一个工具密集型的智能体看起来很便宜,直到你注意到那些没人统计的工具 Token。在包含元数据的同一追踪中按类别拆分 Token 数量,否则你按功能计算出的数据将会是“极其自信的错误”。
财务需要的指标,而非供应商给你的指标
供应商提供给你的是单 token 成本。这是公司里最没用的数字。工程部门以外的人没人能根据“我们每个 token 花了 $0.000003”采取行动,甚至在工程部门内部,它也无法告诉你某个功能是否值得运行。
能改变决策的指标是单元经济效益 (unit economics) —— 即支出除以业务产出:
- 每个已解决工单的成本(针对支持代理):现在你可以将其与人工处理相同工单的成本进行比较,关于“我们是否应该发布这个功能”的对话就有了一个实际的数字。
- 每个活跃用户的成本(针对助手功能):将其与你收取的费用交叉对比,你就能知道该功能是拥有正毛利率,还是在你最大的客户身上悄无声息地亏本。
- 每个成功任务的成本:将支出除以评估 (eval) 结果。这个指标能捕捉到昂贵的失败:一个因重试消耗数千个 token 但仍未完成任务的智能体,其单次尝试的成本很高,而单次成功的成本则是无限大。
- 每个智能体运行的成本:追踪中位数和 p99。中位数告诉你正常情况;p99 则是失控循环和重试风暴发生的地方,正是这些情况导致账单爆炸。
如果没有请求时归因 (request-time attribution),这些指标都无法计算。这就是核心所在。单 token 成本之所以是你免费获得的指标,恰恰是因为它不承载任何业务意义;而有意义的指标正是那些你必须进行埋点 (instrument) 才能获取的指标。
不知情的真实代价
这里的失败不在于超支,而在于一份无法归因的账单对你决策的影响。
没有归因,每一次优化都是在瞎猜。你无法判断该优化哪个功能,因为你不知道哪个功能昂贵。你无法设定团队预算,因为你无法衡量每个团队的支出。你无法针对“总结功能的单次请求成本一夜之间翻了三倍”发出告警,因为你从未计算过单次请求成本。你就像在驾驶一架唯一的仪表是剩余总燃料量的飞机 —— 你知道自己在消耗燃料,却不知道花在了哪里。
而且,它还会削弱那些真正起作用的 AI 功能的商业逻辑 (business case)。当 CFO 看到一个持续攀升且没有明细的大额数字时,理性的反应是对整个支出项产生怀疑 —— 包括那个产出价值远超成本的隐藏功能。归因能让你为胜出者辩护。“这个智能体解决每个工单的成本是 1.80,而人工处理需要14”,这句话能保护预算。“上个季度 AI 花了我们 40 万美元”,这句话则会让项目被砍掉。
供应商不会为你解决这个问题。这不符合他们的利益,也不在他们的数据模型中 —— 他们按密钥和时间计费,因为那是他们能看到的,而归因支出所需的业务上下文永远不会离开你的程序。归因是你的埋点问题,而且窗口期很短:元数据必须在调用发生的瞬间附加,否则就永远消失了。
在账单变得惊人之前就开始
陷阱在于,当账单还很小时,归因看起来是可选的。没人会为一个每月支出 200 美元的功能去做成本归因埋点。然后功能奏效了,用量增长,另外三个功能也使用了相同的密钥,账单跨过了财务部门开始质询的门槛 —— 此时,你已经有了数月无法归因的支出,且无法追溯。
在发布时就进行归因埋点,而不是在账单让你感到肉疼时。前期的成本很低 —— 每次调用附加一个元数据字典,通过网关或链路追踪 (trace) 来承载 —— 而事后则是不可弥补的。在调用点标记每一次调用。按类别统计 token,而不是混在一起。按功能、按客户、按成功结果汇总支出。在需要之前就构建好按租户和按功能的视图,因为另一种选择是向你的 CFO 解释,为什么账本上增长最快的支出项也是你最不了解的一项。一年后仍能运行 AI 的团队,是那些能够立即回答“哪个功能花了这笔钱”而无需打开发票的团队。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部