litellm 做 Agent 成本监控:3 个账单维度实战

上个月我们一个 Agent 跑批任务,月底财务把账单拍在桌上:这个月的模型调用费是上个月的 3 倍。问题是我们根本说不清楚钱花在了哪一步。Agent 不像普通接口调用,它一个任务会拆成几十次 LLM 调用,横跨多个模型和工具,最后只拿到一张按总量的聚合账单。

本文用一个可复用的 litellm 成本监控方案,把账单按任务、模型、工具三个维度拆开,代码可以直接抄。

一、为什么普通账单不够用

云厂商给的用量报表通常只有「总 token 数 × 单价」,最多到「按模型聚合」。但排查成本真正的难点在更细的粒度。

比如同一个 Agent,写代码的步骤和做检索的步骤走的模型不一样,前者用贵的高能力模型,后者用便宜的小模型,总量上看不出问题,拆开才发现检索步骤因为 prompt 没收敛,被反复重试了十几次(来源:内部 Agent 调用日志复盘)。

另一个常见误区是把「请求数」当「成本」。一次流式长文本生成可能消耗一次请求的几十倍 token,只看 QPS 完全误导。所以监控的第一原则:用 token 而不是次数作为计费单位,并且把每一步归属到具体任务(来源:litellm 官方成本追踪文档)。

二、用 litellm 的 callback 钩住每次调用

litellm 在每次 completion / acompletion 调用结束后都会触发注册的 callback,回调里能拿到 model、usage、response_cost、kwargs 等字段。我们写一个自定义 callback,把每次调用的成本累加到内存字典,并按三个维度打标签。

python 复制代码
import litellm
from litellm import completion, acompletion
from collections import defaultdict
import time

# 三个维度的累加器
ledger = {
    "by_task": defaultdict(float),   # 按任务 id
    "by_model": defaultdict(float),  # 按模型名
    "by_tool": defaultdict(float),   # 按工具名
}

class CostTracker:
    def __init__(self):
        self.total = 0.0

    def _tag(self, kwargs):
        # 从 metadata 里取我们注入的标签
        meta = (kwargs.get("litellm_params") or {}).get("metadata") or {}
        return (
            meta.get("task_id", "unknown"),
            meta.get("model_key", kwargs.get("model", "unknown")),
            meta.get("tool", "unknown"),
        )

    async def async_log_success_event(self, kwargs, response_obj, start_time, end_time):
        cost = response_obj.response_cost if hasattr(response_obj, "response_cost") else 0.0
        if not cost:
            # 厂商没返回成本时,用本地价目表兜底
            cost = litellm.completion_cost(completion_response=response_obj) or 0.0
        t, m, tool = self._tag(kwargs)
        ledger["by_task"][t] += cost
        ledger["by_model"][m] += cost
        ledger["by_tool"][tool] += cost
        self.total += cost

tracker = CostTracker()
litellm.callbacks = [tracker]

调用时在 metadata 里注入标签,这样后续才能归因:

python 复制代码
await acompletion(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "检索用户订单"}],
    metadata={"task_id": "order_query_8821", "tool": "retriever", "model_key": "gpt-4o-mini"},
)

三、三个维度分别解决什么问题

维度一:按任务。 这是最容易被忽略也最有价值的一维。一个业务流往往由多个子任务拼成,按任务聚合后,你能直接回答「这个客户的一次对话花了多少钱」。我们接入后第一周就发现,有两类任务占了总成本的 60%,优化它们比笼统压价有效得多(来源:生产环境接入后首周统计)。

维度二:按模型。 用来检查「该用小模型的地方有没有误用大模型」。比如意图识别这种轻活,本该走 4o-mini,结果因为默认配置走了 4o,单价差出 15 倍。按模型聚合能一眼定位这类错配。

维度三:按工具。 工具调用是 Agent 成本黑洞的重灾区,尤其是带检索、带代码执行的步骤。某次我们发现一个工具因为报错重试机制没设上限,单任务被调用了 40 多次,成本是直接原因的 40 倍。按工具聚合后,这类异常会立刻从平均值里跳出来。

四、工程取舍与踩坑

第一个坑:litellm 的内置价目表不是全的,尤其自部署模型(vLLM、本地推理)没有官方价格。

解决办法是在 litellm.register_model 里手动填 input_cost_per_token 和 output_cost_per_token,否则 response_cost 恒为 0,监控直接失效(来源:litellm 自定义模型定价文档)。

第二个坑:流式响应要显式传 stream_options={"include_usage": True},否则 usage 只在最后一个 chunk 返回,callback 拿不到 token 数。非流式不受影响,但生产基本都用流式,这一行很容易漏。

第三个坑:重试会重复计费。Agent 框架自带的 retry 不改 metadata,两次重试会被记成同一个任务的两次独立调用,看起来成本翻倍。建议重试时复用同一个 task_id,这样累加逻辑天然合并,但要在日志里单独标记重试次数,避免掩盖质量问题。

第四个坑:跨模型对比要用「等效输出 token」而不是「原始 token」。不同模型的 tokenizer 不同,同样一句话 token 数能差 20%,直接比单价会误判。我们统一折算成字符数再算单位成本,结论才稳(来源:多模型 tokenizer 对比测试)。

五、辩证:监控本身也要讲成本

不是所有调用都值得精细监控。内部测试、一次性脚本、低频后台任务,上全套标签反而增加开发负担。我们的做法是只对「生产环境 + 高频 + 多步骤」的 Agent 开三维监控,其余只记总量。另一个要警惕的是把监控数据当 KPI 滥用,为了压低成本强行砍模型档次,可能让任务成功率掉得更狠。成本监控的目标是定位异常,不是替业务做取舍。

六、小结与后续

把上面的 CostTracker 跑起来后,建议先观察两周,重点看「任务维度的 Top 5 成本贡献者」和「工具维度的重试倍数」。通常这两张表就能指出 80% 的优化空间。后续可以接一个定时任务,把 ledger 落库并画趋势图,从「事后对账」升级成「实时告警」。

互动思考题:

你现在的 Agent 账单是怎么监控的?

是只看了云厂商的总量报表,还是已经能拆到任务级?

遇到过哪些看起来正常、拆开才发现贵得离谱的步骤?

欢迎在评论区聊聊你的踩坑。

数据与事件来源:litellm 官方成本追踪与自定义模型定价文档、内部 Agent 调用日志复盘(2026 年生产环境统计)、多模型 tokenizer 对比测试、云厂商用量报表字段说明。成本口径已与云厂商用量报表交叉核对,单价以官方价目表为准。

相关推荐
Mr.D学长1 小时前
毕业设计项目 基于python的答题卡识别评分系统
python·毕业设计·毕设
云和数据.ChenGuang1 小时前
LangChain 实战指南:从入门到构建智能应用
开发语言·人工智能·python·langchain
青少儿编程课堂1 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会C/C++考级:拓扑排序课程表排课解析
c++·python·算法·bfs·信息学竞赛
const_qiu1 小时前
第三章 04:3.6 基础调用链的构建
开发语言·python
向上的车轮1 小时前
Python 大数据处理不慢:Polars + DuckDB + Arrow 实战指南
开发语言·python
羞儿1 小时前
Cordis 内核:五概念、生命周期与事件
llm·agent·harness·cordis 内核
一缕82年的清风1 小时前
生产级多智能体协作避坑:死锁防范与确定性状态机实战
agent
lucas_AI1 小时前
Librarian Agents:别等提问了再翻原文——先训练一个「图书管理员」把长文档收拾好
agent
程序员小孔.1 小时前
基于 SpringBoot + UniApp + Vue 的家政服务系统设计与实现
前端·数据库·spring boot·python·docker·微信小程序