1. 从一条response_cost=None日志说起
如果你正在用 LiteLLM 做多模型网关,大概率见过这条报错:
LiteLLM:ERROR: litellm_logging.py:1265 - Model=internlm2 not found in completion cost map. Setting 'response_cost' to None它的意思很直白:LiteLLM 内置的model_cost字典里没有internlm2这个模型名,所以它算不出这次请求花了多少钱,只能把response_cost置为None。结果就是——请求能通,但计费字段是空的,/global/spend/keys里看不到这条消耗,LiteLLM_SpendLogs表里也查不到有效 spend。
这就是 LiteLLM 计费模型处理的核心矛盾:它内置了一张成本表,但你的模型名不一定在里面。LiteLLM 的计费逻辑集中在litellm/cost_calculator.py,日志钩子在litellm_core_utils/litellm_logging.py,只要模型名匹配不上completion_cost_map,计费链路就断了。
这篇面向需要统一管理多模型计费与 Key 的开发者,给出两件事:一是用 TaoToken 统一 Key/API 通道把模型名收敛到可控范围,二是给出一份可直接复制的config.toml配置骨架,并演示一次计费模型请求的验证动作,确认计费字段与模型映射正确返回。适合已经在跑 LiteLLM Proxy、但被自定义模型计费卡住的同学。
2. TaoToken 前置:统一 Key 与模型映射
LiteLLM 的计费依赖模型名到价格的映射,而模型名又依赖上游 provider。如果每个 provider 各接一套 Key、各写一套模型名,model_cost永远补不完。TaoToken 在这里的作用是提供一个统一的 API 通道,把上游模型收敛成一套 OpenAI 兼容接口,你只需要在 LiteLLM 里维护一份模型映射。
先拿到统一 Key。访问控制台创建:
https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite创建后在 API Keys 页面复制 Key:
https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewriteAPI 基地址统一用:
https://taotoken.net/api注意这里不加 UTM 参数,它是给程序调用的。Key 形如sk-xxxx,后面 LiteLLM 的api_key字段就填它。
模型名怎么定?建议在 TaoToken 侧先确认可用模型清单,再决定 LiteLLM 里的model_name。你可以用模型对话页面手动发一条请求,确认模型 ID 拼写:
https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite这一步很关键。LiteLLM 的计费匹配是字符串精确匹配,internlm2和internlm-2在它眼里是两个模型,前者匹配不上就None。所以模型名必须在 TaoToken 和 LiteLLM 两侧保持一致。
3. config.toml 配置骨架:可复制片段
LiteLLM Proxy 支持config.yaml,也支持config.toml。下面这份骨架按「统一通道 + 自定义计费」组织,你可以直接改 Key 和模型名。
3.1 基础模型列表与统一通道
[general_settings] master_key = "sk-your-litellm-master-key" database_url = "postgresql://user:pass@localhost:5432/litellm" [model_list.internlm2] model_name = "internlm2" litellm_params = { model = "openai/internlm2", api_base = "https://taotoken.net/api", api_key = "sk-your-taotoken-key" } [model_list.qwen-plus] model_name = "qwen-plus" litellm_params = { model = "openai/qwen-plus", api_base = "https://taotoken.net/api", api_key = "sk-your-taotoken-key" }这里model = "openai/xxx"是让 LiteLLM 走 OpenAI 兼容协议,api_base指向 TaoToken 统一通道。model_name是你在 LiteLLM 里对外暴露的名字,也是计费匹配用的名字。
3.2 自定义计费:补上缺失的成本映射
LiteLLM 允许通过model_cost覆盖或新增成本项。单位是「每 token 美元」,注意是 token 不是千 token,写错会差三个数量级。
[model_cost.internlm2] input_cost_per_token = 0.0000005 output_cost_per_token = 0.0000015 [model_cost.qwen-plus] input_cost_per_token = 0.0000004 output_cost_per_token = 0.0000012如果你不想在 TOML 里硬编码,也可以在 LiteLLM 的 UI 里配置自定义计费模型,效果等价,请求进来后会走你定义的费率。
3.3 计费落库与回调
[litellm_settings] success_callback = ["postgres"] failure_callback = ["postgres"]postgres回调会把每次请求的 spend 写入LiteLLM_SpendLogs,这是后面查MonthlyGlobalSpendPerKey视图的数据源。如果你要接外部计费系统,可以换成自定义 callback,但内置模式已经够用。
4. 验证请求:确认计费字段与模型映射
配置写完,启动 Proxy:
litellm --config ./config.toml --port 40004.1 发一次计费模型请求
curl -X POST 'http://localhost:4000/v1/chat/completions' \ --header 'Authorization: Bearer sk-your-litellm-master-key' \ --header 'Content-Type: application/json' \ --data '{ "model": "internlm2", "messages": [{"role": "user", "content": "你好,测试计费"}] }'返回体里除了choices,重点看usage:
{ "usage": { "prompt_tokens": 8, "completion_tokens": 12, "total_tokens": 20 } }4.2 查 Key 维度计费
curl 'http://localhost:4000/global/spend/keys?limit=5' \ --header 'Authorization: Bearer sk-your-litellm-master-key' \ --header 'Content-Type: application/json'正常返回应该能看到total_spend不再是 0:
[ { "api_key": "4a232c5264640946b61ec32fb3304278af1a34cc26482066aa66e250cddde75e", "key_alias": "internlm2", "key_name": "sk-...ZeoQ", "total_spend": 28.4 } ]如果total_spend还是 0,回到日志看有没有response_cost=None,说明model_cost没匹配上。
4.3 直接查库确认
select * from "MonthlyGlobalSpendPerKey" a join "LiteLLM_VerificationToken" b on a.api_key = b.token;MonthlyGlobalSpendPerKey是个视图,定义大致是:
CREATE VIEW "MonthlyGlobalSpendPerKey" AS SELECT date("LiteLLM_SpendLogs"."startTime") AS date, sum("LiteLLM_SpendLogs".spend) AS spend, "LiteLLM_SpendLogs".api_key FROM "LiteLLM_SpendLogs" WHERE "LiteLLM_SpendLogs"."startTime" >= (CURRENT_DATE - '30 days'::interval) GROUP BY (date("LiteLLM_SpendLogs"."startTime")), "LiteLLM_SpendLogs".api_key;还有LiteLLM_VerificationTokenView可以关联 team、budget 等信息,它基于LiteLLM_VerificationToken表左连LiteLLM_TeamTable。这两个视图是排查计费归属的主要入口。
5. 本篇常见错排查
5.1response_cost=None反复出现
最常见原因是model_name和model_cost的键不一致。LiteLLM 用model_name去查成本表,你写internlm2却在model_cost里写internlm-2,就匹配不上。统一命名即可。
5.2 计费金额明显偏大或偏小
检查input_cost_per_token的单位。LiteLLM 用的是每 token,不是每千 token。如果你按「每千 token 0.5 元」填成0.5,实际会放大 1000 倍。正确写法是0.0000005这种量级。
5.3 请求通了但LiteLLM_SpendLogs没数据
先确认success_callback里有没有postgres,再确认database_url能连上。回调写库失败不会阻断请求,所以现象是「请求正常、计费为空」。看 Proxy 启动日志里有没有数据库连接报错。
5.4 特定 Key 的统计查不到
/global/spend/keys只返回有 spend 记录的 Key。如果某个 Key 从没成功计费过,它不会出现在列表里。先用该 Key 发一次请求,再查。
5.5 模型映射对了但上游 404
api_base要写https://taotoken.net/api,不要带/v1后缀,LiteLLM 会自己拼/v1/chat/completions。多写一层路径会 404。
6. 继续接入与长期编码
计费链路跑通后,下一步是把 Key 管理和模型映射固化下来。如果你还在排障阶段,建议先把 API Keys 和接入文档过一遍,确认 Key 权限和通道地址:
https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite想先验证某个模型名和计费字段是否对得上,用模型对话页面手动发一条最快:
https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite如果你要把 LiteLLM 长期挂在编码 Agent 或自动化流程后面,Key 会频繁调用、模型会经常切换,这时候用 Coding Plan 把通道和额度固定下来更省心:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite我自己的做法是:config.toml里只保留model_name和model_cost两份清单,新增模型时两边同时加,加完立刻用/global/spend/keys验证一次total_spend有没有涨。涨了就说明计费字段和模型映射都对上了,没涨就回去看日志里的response_cost。这套动作重复几次,比事后翻数据库快得多。