- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 账单来了,却没人知道谁花了多少
- 硬预算为什么是最后的手段
- 把暴走防护与治理分开的两层结构
- 单次增量的大小几乎就是设计的全部
- 路由要去的不是最便宜的模型,而是能把活干完的最便宜的模型
- 真正主导成本的不是模型单价,而是上下文
- 缓存不是免费的
- 搬到自己组织里的最小配置
- 参考资料
账单来了,却没人知道谁花了多少
把编码智能体放给团队用上两个月左右,通常都会开始同一段对话。账单比上个月涨了三倍,而没有人能解释这些钱是从哪里来的。工具有三种,各自用不同的账号调用不同的模型,用量则散落在各家厂商的控制台里。
在这种状态下最常见的应对,是给每个人设一个额度。而这多半会失败。撞到额度的人在工作中途被卡住,开一张工单,然后等着有人来批。省下的钱,还不如被打断的工作时间贵。
硬预算为什么是最后的手段
Databricks 在 2026 年 8 月 7 日发布的 Managing AI Coding Costs at Scale,在采访了多家公司之后这样写道:在他们聊过的所有公司里,硬预算都只被当作最后的手段来用。
原因在成本结构里。编码智能体的开销不是正态分布,而是长尾。大多数工程师用得很普通,少数人会跑大活儿。而那少数几件大活儿,通常正是最有价值的工作 —— 大规模重构、老旧服务的迁移、故障原因追踪,都是人来做要花好几天的事。按平均值划线,被砍掉的恰恰就是这些工作。
额度的第二个问题是没有学习效果。被卡住的人并不会明白自己为什么用得多,只会知道自己被卡住了。下个月他还用同样的方式,然后在同一个地方再被卡一次。
于是方向变了。与其禁止使用,不如把花了多少变得可见,并且要继续用就确认一次。
把暴走防护与治理分开的两层结构
同一家公司在 2026 年 7 月 28 日发出的 How Databricks manages its own coding agent spend 里,这套设计写得很具体。预算被分成了两层。
日预算是一条定得很低的暴走防护线。目的不是省钱,而是事故检测。它要在一天之内抓住陷入死循环的智能体、配置错误的批处理任务这类东西。用量接近 90% 时会有 Slack 通知,一个按钮就能让本人把自己的额度往上抬一档。这种自助批准没有次数限制。
月预算的性质完全不同。它被定得高到大多数工程师一辈子也碰不到,要往上调需要管理者批准,而且上调会带一个期限 —— 1 个月、3 个月、6 个月 —— 到期自动回落。档位也不细密,大致就是 2 倍、5 倍、事实上无限制这么粗。粗糙是刻意的,只有这样,批准这件事才会变成真正的讨论,而不是走个形式。
单次增量的大小几乎就是设计的全部
在这个结构里,最需要用心确定的值不是上限,而是增量。按原文的说法,增量的大小是这样定的:一位按月度预算均匀使用的工程师,一次通知都不会看到。
而且当管理者上调月度预算时,日额度和增量会按比例一起变大。不这么做,拿到大项目批准的人就会整天只顾着按自助批准按钮,暴走防护线也就失去了意义。
"""网关预算判定:上限有两个,实效上限只有一个。"""
from dataclasses import dataclass
@dataclass
class BudgetPolicy:
monthly_max: float # 只能由管理者批准才上调的上限
runaway_increment: float # 一次自助批准所打开的幅度
def effective_limit(self, month_to_date: float) -> float:
"""当月累计 + 一次增量,但不得超过月度上限。"""
return min(month_to_date + self.runaway_increment, self.monthly_max)
def decide(self, month_to_date: float, today: float, today_limit: float):
limit = self.effective_limit(month_to_date)
if month_to_date + today >= self.monthly_max:
return "block", "已达月度上限 - 需要管理者批准"
if today >= today_limit:
return "self_ack", "按一次确认按钮即可继续"
if today >= today_limit * 0.9:
return "notify", f"今日剩余 {round(today_limit - today, 2)} 单位"
return "allow", ""
# 月度上限留得宽裕,每日增量取得很小的组合
policy = BudgetPolicy(monthly_max=1000.0, runaway_increment=40.0)
for mtd, today, day_limit in [(120, 10, 40), (120, 37, 40), (120, 41, 40), (990, 15, 40)]:
print(mtd, today, policy.decide(mtd, today, day_limit))
这段代码做的事很简单,但组织的全部政策都装在里面。什么是拦截、什么是确认、什么是沉默,四行就定下来了。不用去看散落各处的仪表盘,评审这一个函数就够了。
路由要去的不是最便宜的模型,而是能把活干完的最便宜的模型
第二个轴是路由。Databricks 表示,其内部网关的智能路由在结果与最高质量模型大体相当的前提下,把平均任务成本降低了 30% 以上。
需要注意的是,这和「用便宜模型吧」不是一回事。它是逐请求判断哪个模型最便宜且能把这件事干完,判断错了就会带来重试,反而更贵。所以路由器在上线前后必须把质量指标和重试率一起看。只看成本的话,永远都像是改善了。
同一篇文章里还有一个决定:不在公司内部开放顶级模型,理由是相较上一个版本的质量提升未能得到确认。不用最新的模型也是一种选择,这一点在这里很重要。
真正主导成本的不是模型单价,而是上下文
第三个轴是最大的一个。把原文的说法搬过来:在昂贵的推理真正执行的那一刻,用户最初敲下的那句话在进入系统的数据里只占可以忽略的比例,成本由上下文主导。
智能体一次调用所装载的,是系统提示词、工具定义、文件片段、检索结果,以及此前所有轮次的历史。用户敲的那一行,相比之下就是舍入误差。所以把上下文砍掉一半,通常比换到单价便宜一半的模型效果更大。
Databricks 写道,通过调整 harness 和缓存配置,生成的 token 数量减少了将近 50%。关键在于,这个数字是在没有更换模型的情况下拿到的。
缓存不是免费的
关于缓存,有一句话说得很准确:写缓存是要花钱的,而读缓存会大幅降低每次推理的成本。
这两件事同时成立,在实务中经常被忘掉。在前缀频繁变化的配置里打开缓存,你会一直付写入成本,却等不到命中。所以在打开缓存之前要确认的不是命中率,而是前缀的稳定性。如果系统提示词和工具定义每次请求的顺序都不一样,或者混进了时间戳,命中率在结构上就升不上去。
检查并不难。从真实流量里抽 100 条请求,把要缓存的前缀打成哈希打印出来即可。如果出现了 90 个不同的哈希,那么在这套配置下缓存只会增加成本。仅仅把工具列表的排序固定下来,再把动态插入的当前时间和会话标识挪到前缀后面,哈希种类就掉到个位数的情况很常见。
搬到自己组织里的最小配置
这套设计不必原样复制,但顺序值得遵守。
| 顺序 | 要做的事 | 不做的后果 |
|---|---|---|
| 1 | 把所有智能体流量汇聚到一个网关 | 之后所有的数字都是局部统计 |
| 2 | 把用量归属到人和任务 | 永远不知道谁把钱花在了什么上 |
| 3 | 加上一条低的日常暴走防护线和自助批准按钮 | 事故没法在一天之内抓住 |
| 4 | 先固定前缀,把缓存命中率提上来 | 换了模型,额外开销原封不动 |
| 5 | 然后再考虑路由和更换模型 | 把质量下降误读成成本改善 |
Databricks 的文章披露,在公司内部改动预算结构之前,每月有 500 到 1,000 名工程师撞到额度。那是数百张工单,以及同样数量的被打断的工作会话。这意味着成本管理的成败,不能只看账单降了多少,还要看在降低的过程中动用了多少次人手。
参考资料
- Managing AI Coding Costs at Scale — Databricks, 2026-08-07 —— 四种技法、路由节省 30% 以上、生成 token 减少 50%、缓存写入成本的提及,都出自这篇文章。
- How Databricks manages its own coding agent spend with Unity AI Gateway Budgets — Databricks, 2026-07-28 —— 两层预算、自助批准、增量按比例扩大,以及每月 500 到 1,000 人撞到额度的情况,都出现在这里。
- 一些媒体摘要里流传着「用这些技法最多节省 90%」的说法,但我在 Databricks 原文中能够确认的数值就是上面写的那些,而且原文自己也说明,表格里整理的节省幅度是基于非正式问卷的方向性数字。90% 这个数字在原文中无法确认。
- 正文中的预算判定代码,是我按原文所述规则实现的,其中的数字是示例。