# LLM 的 FinOps —— 单位经济学与多租户归因

> 传统 FinOps 在 LLM 开销上失灵。成本是 token 交易，不是资源在线时长。tag 对不上 —— 一次 API 调用是一笔交易，不是一项资产。工程决策（prompt 设计、上下文窗口、输出长度）就是财务决策。2026 年的操作手册有三个归因维度，第一天就要埋点：按用户（`user_id`）用于席位定价和扩张，按任务（`task_id` + `route`）用于产品面成本和优先级，按租户（`tenant_id`）用于单位经济学和续约。四个 token 层 —— prompt、工具、记忆、响应 —— 一个桶藏住了开销。多租户产品的执行阶梯：按租户限流（2-3x 预期峰值，清晰的 429 + retry-after）；每日花费上限（1.5-3x 合同上限；触发限流收紧 + 告警）；花费 z-score > 4 时的 kill switch（自动暂停 + 呼叫 on-call）。归因模式：打标聚合、遥测拼接（trace-ID → 账单；准确率最高）、采样外推、基于模型的分摊、事件溯源、实时流。单位指标：每解决一次查询的成本、每生成一个产物的成本 —— 不是 $/M token。回溯打标总会漏；在请求创建时埋点。

**类型：** Learn
**语言：** Python（标准库，一个带 kill switch 的玩具级成本归因模拟器）
**前置要求：** 阶段 17 · 13（可观测性）、阶段 17 · 14（缓存）
**预计时间：** ~60 分钟

## 学习目标

- 解释为什么传统 FinOps（tag + 分档）在 LLM 开销上失灵，并说出三个新的归因维度。
- 列举四个 token 层（prompt、工具、记忆、响应），以及为什么单桶计费藏住成本。
- 为一个多租户产品设计一条执行阶梯（限流 → 花费上限 → kill switch）。
- 挑一个单位指标（每解决查询/产物的成本）而不是 $/M token。

## 问题背景

你的账单写着 $40,000。你不知道：
- 哪个租户花的。
- 哪个产品特性驱动的。
- 有没有哪个个人用户在滥用。
- 元凶是 prompt 膨胀、工具调用，还是记忆放大。

供应商侧的打标聚合对云资源（EC2、S3）有用，因为 tag 会传播到账单行项。LLM API 调用不自动打标 —— 你得在调用点盖上 user/task/tenant 并一路带下去。回溯归因总会漏掉边缘情况。

## 核心概念

### 三个归因维度

**按用户**（`user_id`）：谁在花多少。驱动席位定价、扩张对话，识别重度用户。

**按任务**（`task_id` + `route`）：哪个产品面花多少。驱动特性优先级、砍掉昂贵特性的决策。

**按租户**（`tenant_id`）：哪个客户盈利。驱动单位经济学、续约定价、分档阈值。

第一天就在调用点把三个都埋上。回溯总是更糟。

### 四个 token 层

| 层 | 例子 | 占总量典型比例 |
|-------|---------|---------------------|
| Prompt | 系统 + 用户输入 | 40-60% |
| 工具 | 喂回来的工具调用结果 | 20-40%（agent 工作负载） |
| 记忆 | 之前的对话 / 检索到的文档 | 10-30% |
| 响应 | 模型输出 | 10-30% |

把四个一起装桶会让优化变盲。在你的归因 schema 里把它们拆开。

### 执行阶梯

1. **限流** 按租户。2-3x 预期峰值。返回带 `Retry-After` 的 429。租户感到摩擦；不会有意外账单。

2. **每日花费上限** 按租户。1.5-3x 合同上限。触发：收紧限流 + 告警客户成功团队。

3. **kill switch** 在花费 z-score 相对租户基线 > 4 时。自动暂停租户；呼叫 on-call；升级到运维 + CS。

### 归因模式

- **打标聚合**：盖元数据 header；之后聚合。简单；粗糙。
- **遥测拼接**：经 trace ID 把 trace 拼到账单。准确率最高。成熟团队的做法。
- **采样 + 外推**：采样 5-10%，乘起来。对粗略开销划算；漏尾部。
- **基于模型的分摊**：用回归推断成本驱动因素。给没 tag 的遗留数据用。
- **事件溯源**：把成本作为流里的事件（Kafka / Kinesis）。实时。
- **实时流**：仪表盘亚秒级更新。

### 每 X 成本是单位指标

$/M token 是供应商话术。产品指标：

- 每解决一张支持工单的成本。
- 每生成一篇文章的成本。
- 每成功完成一次 agent 任务的成本。
- 每用户会话分钟的成本。

把成本绑到一个产品结果上。否则优化没有锚。

### 成本归因 trace 的形状

```
trace_id: abc123
  user_id: u_42
  tenant_id: t_7
  task_id: task_classify_doc
  route: model_haiku
  layers:
    prompt_tokens: 1800
    tool_tokens: 600
    memory_tokens: 400
    response_tokens: 150
  cost_usd: 0.0135
  cached_input: true
  batch: false
```

每次调用都发出。存进数据湖。按维度聚合。阶段 17 · 13 的可观测性栈就是这东西住的地方。

### 叠加节省的栈

栈：缓存 + batch + 路由 + 网关。四个全上：
- 缓存 L2（阶段 17 · 14）：输入便宜约 10 倍。
- Batch（阶段 17 · 15）：5 折。
- 路由到便宜模型（阶段 17 · 16）：降本 60%。
- 网关效率（阶段 17 · 19）：冗余 + 重试。

最佳情况叠加：约为朴素基线的 5-10%。大多数团队只用上 2-3 根杠杆；很少有人四个全叠。

### 你该记住的数字

- 归因维度：按用户、按任务、按租户。
- 四个 token 层：prompt、工具、记忆、响应。
- kill switch：花费 z-score > 4。
- 单位指标：每解决查询的成本，不是 $/M token。
- 叠加优化：可能做到基线的约 5-10%。

## 实际使用

`code/main.py` 用三档执行阶梯模拟一个多租户 LLM 服务。注入一个滥用租户并演示 kill switch 触发。

## 拿去用

这一课产出 `outputs/skill-finops-plan.md`。给定产品和规模，设计归因 schema 和执行阶梯。

## 练习

1. 跑 `code/main.py`。kill switch 在什么 z-score 触发？你怎么挑阈值？
2. 设计一个按租户、按任务的成本仪表盘。你先建的 5 个视图是什么？
3. 你最大的租户单位经济学为负。提出三个干预措施，按客户影响排序。
4. 给一个支持产品算每解决工单成本：每张工单 300 万 token、每天约 800 张工单、GPT-5 缓存费率。
5. 论证回溯打标究竟能不能行。它什么时候可接受？

## 关键术语

| 术语 | 大家嘴上怎么说 | 它实际是什么 |
|------|----------------|------------------------|
| 按用户归因 | "用户级成本" | 每次调用盖上 `user_id` |
| 按任务归因 | "特性成本" | `task_id` + `route` 标识产品面 |
| 按租户归因 | "客户成本" | `tenant_id`；驱动单位经济学 |
| 四个 token 层 | "成本层" | prompt + 工具 + 记忆 + 响应 |
| 限流 | "429 守卫" | 在网关执行的按租户上限 |
| 每日花费上限 | "每日上限" | 带告警的租户级预算 |
| Kill switch | "自动暂停" | 花费 z-score > 4 触发自动挂起 |
| 每解决成本 | "产品单位指标" | 成本绑到产品结果，不是 token |
| 遥测拼接 | "trace 到账单" | 准确率最高的归因模式 |
| 叠加优化 | "缓存+batch+路由+网关" | 叠加节省到基线的约 5-10% |

## 延伸阅读

- [FinOps Foundation — FinOps for AI Overview](https://www.finops.org/wg/finops-for-ai-overview/)
- [FinOps School — Cost per Unit 2026 Guide](https://finopsschool.com/blog/cost-per-unit/)
- [Digital Applied — LLM Agent Cost Attribution 2026](https://www.digitalapplied.com/blog/llm-agent-cost-attribution-guide-production-2026)
- [PointFive — Managed LLMs in Azure OpenAI](https://www.pointfive.co/blog/finops-for-ai-economics-of-managed-llms-in-azure-open-ai)
