跳到主要内容

你的 AI 账单只是一个未标记的行项目:当 Token 拒绝被标记时的 FinOps

· 阅读需 11 分钟
Tian Pan
Software Engineer

财务在月底打开发票。一个供应商。一个数字。它比上个月大,而且下个月还会更大。然后他们提出了唯一重要的问题 —— 这是哪个功能花的钱? —— 房间里没人能回答。

这是在生产环境中运行 AI 的一种隐蔽失败模式。并不是说账单数额巨大;如果价值匹配,数额大也没关系。失败之处在于账单是无法归因的。它作为一个单一的费用项出现 —— OpenAI、Anthropic、Bedrock、Azure —— 没有任何财务部门真正需要的维度:没有按功能、按团队、按客户,也没有按成功的任务进行拆分。你能看到总额在上升。但你看不出 原因,而当发票寄到时,原本可以解释它的请求上下文早已消失了。

这之所以会让优秀的工程团队措手不及,是因为他们已经为云服务解决过一次成本归因问题了。每个 EC2 实例、每个 S3 存储桶、每个托管数据库都是一个带有 ARN 且可以标记的 资源team:paymentsenv:prodservice: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 — 防止测试环境的支出混入你的生产单位经济数据中。
加载中…
References:Let's stay in touch and Follow me for more thoughts and updates