做后端或者搞 AI 应用开发的,这两年大概率都被一件事折腾过:不同大模型厂商的 API 格式不统一、鉴权方式不一样、SDK 各写各的,想在项目里接多家模型做容灾或对比,代码里全是 if-else 适配层。今天要聊的 litellm,就是专门解决这一摊子事的开源方案。它本质上是一个统一的模型调用网关,用一套 OpenAI 风格的接口去对接上百家主流模型服务商和本地推理框架,同时还把负载均衡、失败重试、成本配额、日志追踪这些生产环境刚需的能力全部收编了。
这篇文章不是项目文档的翻译,而是从我实际使用的角度出发,把 litellm 是什么、为什么值得用、怎么快速落地、生产环境还要注意哪些坑,一条龙讲清楚。无论你是刚接触 LLM 开发的初学者,还是在团队里负责 AI 基础设施的工程师,这篇文章都适合你。
1. 项目定位与整体设计思路
1.1 它是“模型网关”,不是又一个 SDK
第一次看到 litellm 的人,很容易把它归类成“又一个封装各家 API 的 Python 库”。这么理解不算错,但格局小了。litellm 的核心价值在于它把自己定位成模型网关:你的业务代码只跟它通信,它替你跟真实的大模型服务商通信。
这个角色转换非常关键。SDK 是嵌在你的代码里的,逃不掉升级、兼容、多版本维护的问题;网关是独立部署的服务,你的代码只需要认准一个接口地址。以后想换模型服务商、想加新的模型、想调整路由策略,改的是网关配置,业务代码一行不用动。类似生活中你家的路由器:电脑手机不需要知道外网运营商怎么接线,只要连上路由器,网络通了就行。litellm 就充当了 AI 调用这层“路由器”。
从数据流看,litellm 做的事情非常清晰:接收客户端请求,解析请求里的 model 字段,根据配置好的路由策略和模型映射关系,决定把请求转发给哪个上游服务商,等上游返回结果后再统一封装成标准格式回给客户端。这中间它还能插一脚做重试、限流、预算检查和日志记录。
1.2 为什么需要这样一个中间层
很多人会有疑问:自己写个 util 函数封装一下各家 API 不行吗?非要部署一个服务?说实话,如果只是个人项目接两三个模型,自己封装确实够了。但一旦到了团队协作、生产环境、多模型多场景并行的时候,自研方案的维护成本会指数级上升。
我见过好几个团队踩过这些坑:同学 A 负责接厂商甲的接口,封装了一套函数;同学 B 负责接厂商乙的接口,又封装了一套函数;两套代码风格迥异,请求参数命名还不一致。到了后来要用厂商丙的新模型时,发现要同时改三套代码。更要命的是,不同厂商的限流策略不一样,失败重试逻辑也不一样,谁都不敢乱动别人的代码。litellm 把这些共性能力全部收拢到网关层,业务侧只需要面对一个标准接口,接口语义不变,底层随便换。这就是网关模式在 AI 场景下最大的价值:隔离变化、收敛复杂度。
另外,LLM 调用天然有容灾需求。单一厂商的模型服务可能出现限流、故障、或者临时下架。有 litellm 在中间做多路转发和自动 fallback,业务侧不会感知到这些抖动,稳定性一下子就上来了。这在用大模型做核心链路的生产系统里,属于刚需中的刚需。
2. 核心功能拆解与上手要点
2.1 统一接口:一套代码接入所有模型
litellm 最基础的能力就是把各家模型的请求和响应都转成 Chat Completions 风格。这意味着你在代码里只需要使用统一的消息格式(messages 列表,包含 role 和 content),不需要关心上游是哪个厂商、参数命名有何差异。
举个例子,你在 litellm 网关里配置了 A、B、C 三家服务商的模型,业务代码发请求时只需要指向 litellm 的地址,model 字段写上你配置好的模型别名(比如 gpt-4o 或者 claude-sonnet),litellm 会自动解析并转发到真实地址。返回结果也是统一结构:choices、usage 这些字段的位置和含义完全一致。
这个统一接口的细节含金量很高。比如有的服务商返回的 usage 里包含 prompt_tokens,有的叫 input_tokens,有的甚至不返回 prompt 明细。litellm 会在内部做归一化,统一映射成 completion_tokens、prompt_tokens、total_tokens 三个标准字段。做成本统计和用量分析的时候,不用再对着不同厂商的字段名做清洗,省了很多事。
刚接触的朋友建议这么理解:litellm 把“各家有各家的方言”翻译成了“大家都听得懂的普通话”。业务代码这部电话机,只需要安装一个普通话模块,剩下的方言翻译交给网关就好了。
2.2 模型路由与负载均衡
litellm 的负载均衡不是简单的轮询,它支持多种路由策略。最常用的配置是 weight-based routing:给同一模型的多个上游部署配置不同的权重,网关按权重比例分发请求。
model_list: - model_name: my-chat-model litellm_params: model: provider-a/model-name api_key: os.environ/PROVIDER_A_KEY weight: 7 - model_name: my-chat-model litellm_params: model: provider-b/model-name api_key: os.environ/PROVIDER_B_KEY weight: 3这样配置的效果是:同一个逻辑模型 my-chat-model,70% 流量走厂商 A,30% 走厂商 B。如果厂商 A 出现故障或限流,litellm 会自动把失败请求转发到厂商 B,业务侧几乎无感。
还有更细的策略,比如基于延迟的最低延迟优先策略,比如基于预算的优先使用便宜模型策略。我曾经在某个模拟项目中给不同渠道配置过不同的预算阈值,让 litellm 在预算低的时候自动切换到更便宜的模型上,相当于做了一个成本自适应兜底。这个思路对个人开发者控制 API 账单特别实用。
2.3 失败重试与优雅降级
LLM 接口的失败率比你想象中高。原因很复杂:上游限流、网络波动、请求体太大触发超时、模型临时过载。litellm 里有比较完善的重试机制,可以从两个维度配置:重试次数和重试条件。
general_settings: retry_policy: retry_on_timeout: true retry_on_rate_limit: true max_num_retries: 3 min_timeout: 10这里说几个实际经验。第一,重试要考虑上游的限流恢复时间,盲目快速重试只会加重限流。litellm 对限流错误会默认采用指数退避,第一次等 1 秒、第二次等 2 秒、第三次等 4 秒,实测下来比固定间隔重试的效果好很多。第二,最好把重试次数设成 2 到 3 次,再多的话,请求延迟会叠加得很明显,用户侧体验会很差。第三,超时配置要看业务场景:流式输出场景超时时间可以放宽到 60 秒甚至更久,非流式的短请求压到 15 秒以内就够了。
2.4 多租户管理与预算控制
如果你们团队有多个人或数个业务线共用同一个网关,litellm 的多租户能力就很有用了。可以给不同团队分配不同的虚拟密钥,每个密钥绑定各自的模型访问范围、速率限制和预算上限。
简单理解就是:给每个虚拟密钥发一张“饭卡”,这张卡只能在特定窗口打特定菜,每天额度是多少钱,用完了就禁刷。比起直接把上游服务商的 key 暴露给所有人,这种虚拟密钥的管理方式在安全性和成本控制上都让人放心很多。
2.4.1 实际配置一个虚拟密钥
curl -X POST "http://localhost:4000/key/generate" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ -d '{ "models": ["my-chat-model"], "max_budget": 10, "user": "team-a" }'上面这段是生成一个只允许访问 my-chat-model、预算上限 10 美元、归属 team-a 的虚拟密钥。实际使用的时候,把这个返回的 key 配给你的应用,应用调用 litellm 时带上它,网关侧就能做到精确的计量与控费。
我在实践中特别喜欢这个预算控制,因为大模型 API 账单经常有滞后,很多时候月底收到账单才发现超支了。有了 litellm 的这种实时预算检查,请求发出前就会校验余额,超额直接拒绝,从源头堵住了费用失控的问题。
2.5 日志追踪与可观测性
litellm 默认提供详细的请求日志,可以记录每一次调用的模型、token 用量、耗时、成功失败状态、花费金额。这些数据对排查问题太关键了。
尤其是“用户说响应太慢”这种事,没有日志你只能瞎猜。有了 litellm 的日志面板,我几分钟内就能看到是网络延迟大、模型本身生成慢、还是在排队等待重试。它把链路耗时拆出来了,问题定位效率成倍提升。
日志有两种查看方式:控制台输出和自带的 UI 面板。部署在服务器上的话还可以接入 Prometheus 做指标采集,这些在 litellm 的文档里都有对应配置。
3. 实操过程:从安装到完成第一次调用
3.1 安装 litellm
安装方式非常友好,直接用 Python 包管理工具安装即可。推荐装在有 Python 3.8 以上环境的机器上,最好是独立的虚拟环境,避免依赖冲突。
python -m venv litellm-env source litellm-env/bin/activate pip install "litellm[proxy]"注意这里我装的是带 proxy 扩展的版本。litellm 有两种使用形态:作为 Python 库直接调用,或者作为独立代理服务部署。生产环境强烈建议用 proxy 形态,因为负载均衡、虚拟密钥、多租户这些高级能力都在 proxy 模式下才完整可用。
3.2 最小化配置启动代理服务
准备一个配置文件 config.yaml:
model_list: - model_name: my-chat-model litellm_params: model: provider-a/model-name api_key: os.environ/PROVIDER_A_KEY然后启动服务:
litellm --config config.yaml --port 4000看到类似 "Proxy Server started" 的日志就成功了。此时 litellm 已经在本地 4000 端口监听请求。
需要注意,上面的配置里 api_key 用了 os.environ/PROVIDER_A_KEY 这种写法,也就是从环境变量里读密钥。这是一种好习惯,避免把密钥硬编码进配置文件。实际运行时,记得先把这个环境变量导出:
export PROVIDER_A_KEY="你的上游密钥"3.3 用统一接口完成第一次模型调用
服务起来了,怎么测呢?最简单的方式是用 curl 直接打接口:
curl http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ -d '{ "model": "my-chat-model", "messages": [{"role": "user", "content": "你好,请用一句话介绍你自己"}], "temperature": 0.7 }'等几秒钟,你会看到模型返回的标准格式结果。这里 Authorization 里的 sk-1234 是 litellm 默认的 master key,可以在配置里通过 environment 变量修改,生产环境千万别用默认值。
如果不想用 curl,直接用主流的 OpenAI SDK 也行,只要把 base_url 改成 litellm 的地址、api_key 改成 master key 就行。这是 litellm 接口兼容性的另外一个体现:市面上几乎所有为 OpenAI 风格接口写的代码,字面意义上只需要改两行配置就能切换到 litellm。
3.4 配置落盘与热更新
配置文件写好后,每次改了配置不需要重启整个服务。litellm 支持运行时动态更新配置,一种方式是调用管理接口动态增删模型,另一种方式是把 litellm 挂在配置管理中心上做 watch。前者更轻量,适合临时加一个模型调试;后者适合生产环境在多个节点上同步配置。
我日常调试常用动态管理接口,比如新拿到的某个服务商试用 key,我希望立刻在网关上测试一下:
curl -X POST "http://localhost:4000/model/new" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ -d '{ "model_name": "test-model", "litellm_params": { "model": "provider-x/test-model", "api_key": "临时密钥" } }'加完立刻生效,不用重启,非常适合验证新模型效果。不过这个方法适合开发和测试阶段,如果加上去的模型有问题,记得用完就删,不然会产生脏配置。
3.5 部署上生产环境再补两句
本地验证通过之后,部署到生产环境有几个地方必须注意。
第一,启动进程用 systemd 或 docker 都行,但确保进程能开机自启和异常退出自动重启。我习惯用 docker compose 管理,日志和日志轮转都好处理。第二,litellm 默认端口 4000,业务侧访问时建议套一层内网负载均衡器,不要把网关直接暴露到公网。第三,进程配置好优雅退出,因为正在处理的请求可能需要几秒到几十秒,直接 kill 会导致上游已经生成的内容白白浪费。
生产环境的启动命令,额外推荐加上日志落盘参数:
litellm --config config.yaml --port 4000 --log-file /var/log/litellm.log日志单独落盘对事后追问题太重要了。
4. 常见问题与排查技巧实录
4.1 报错:模型不存在 或 404
如果你配置的模型名称没有在 model_list 里声明,litellm 会拒绝请求。这类报错最常见的原因是配置文件的模型名和请求时的 model 字段没对上。
排查思路:先看配置,确认 model_name;再看请求,确认 body 里的 model。两边不一致就会出现 404。还有一种情况是你在管理接口动态加了模型,但没加成功,比如密钥权限不足,用管理接口新增模型时必须用 master key 而不是虚拟密钥。
4.2 报错:上游认证失败
litellm 把上游密钥配置错了,或者环境变量没注入成功,都会导致认证失败。此时 litellm 的日志和响应里会透出上游状态码,比如 401。
处理建议:先手动用 curl 测一遍上游接口,确认上游密钥本身是有效的;再检查 litellm 配置里的 api_key 是否拼对,环境变量是否在 litellm 进程里生效。如果 litellm 是通过 docker 部署的,别忘了检查环境变量确实传进了容器。
4.3 报错:上下文长度超限
这个报错信息通常很直接,就是请求的 tokens 总数超过了模型的窗口大小。litellm 默认不会自动裁剪上下文,但支持配置 context window 检查和 fallback 模型。
有几种处理方式:第一,在业务侧做上下文裁剪,把 messages 里过长的部分截断;第二,在 litellm 配置里给同一个 model_name 配一个支持更长窗口的 fallback 模型,比如标准模型处理不了就自动切到长上下文模型;第三,启用 litellm 上下文管理工具,它会按配置策略修剪消息列表。我个人建议第三条慎用,自动裁剪可能丢掉关键信息,最好还是代码侧先保证 context 长度在合理范围。
4.4 响应速度不稳定,时快时慢
出现这种问题大家第一反应是上游不稳定,但 litellm 的日志能帮你把问题掰开揉碎。
- 如果日志显示 spend 时间很长,说明上游生成本身慢,可能需要换模型或降低 max_tokens;
- 如果日志显示重试次数多,说明上游在报错或限流,可以检查是否是流量分配不均;
- 如果日志显示排队时间长,可能是 litellm 本身的并发处理能力到瓶颈了,考虑加副本。
我踩过的一个典型坑是:给某个模型配了多个上游实例,但其中一个实例的延迟特别高,导致整体平均响应被拖慢。后来我开启最低延迟策略,把慢实例自动排除出去,效果立竿见影。这类路由策略问题在 litellm 的配置里改一行就能生效,建议多试几种方案找到适合自己场景的。
4.5 虚拟密钥突然失效
虚拟密钥有预算上限和过期时间。如果你的密钥设置了 max_budget,一旦花费到限额,后续请求会直接 401。这个设计是为了防止费用失控,不是 bug。
处理办法有两个方向:一是提高这个密钥的预算,适合业务确实需要更多额度的情况;二是给密钥配置定期重置预算,适合按月配额制的团队。litellm 也支持在管理面板里查看每个密钥的实时花费情况,方便追踪到底是谁在用、用了多少。
4.6 常见问题速查表
| 现象 | 可能原因 | 快速处理 |
|---|---|---|
| 请求返回 404 | model 名称与配置不一致 | 检查 model_list 配置 |
| 返回 401 | 上游密钥错误或虚拟密钥失效 | 测上游密钥、看预算是否耗尽 |
| 上下文超限 | messages 太长超出模型窗口 | 业务侧裁剪上下文或配置长窗口 fallback |
| 响应慢 | 上游生成慢或路由策略不优 | 开最低延迟策略,检查重试次数 |
| 日志里 spend 过多 | 某个密钥或模型用量大 | 用预算控制,按团队拆密钥 |
| 启动失败 | 配置语法或环境变量缺失 | 用 yaml 校验工具检查配置 |
5. 进阶实践与避坑心得
5.1 流式输出场景下的稳定性
大模型应用里流式输出太常见了,打字机效果谁用谁知道。litellm 对流式接口支持得也不错,但有几个细节要格外注意。
首先是超时时间。流式输出可能持续十几秒甚至几十秒,默认的 10 秒超时肯定不够,一定要在配置或代码里把 timeout 调大。其次是断流问题,网络抖动可能导致流中断,litellm 的重试机制对流式请求的处理和非流式不完全一样,最好在业务代码里对流中断做一层兜底。
我的建议是生产环境的流式请求至少加一个“首次 token 到达时间”监控,如果超过 10 秒还没收到第一个 token,大概率是上游出问题了,这时候可以考虑提示用户稍后再试,而不是无限等待。
5.2 成本控制还可以更细
litellm 的预算管理已经有模有样,但我建议你在此基础上再细化两层。
第一层是按业务场景分密钥。比如聊天机器人用一个密钥、内容总结用另一个密钥,两个业务线的预算互相隔离,哪个超支了一眼就能看出来。第二层是按天设置限额。litellm 的预算可以按总预算设置,实测下来配合日志一起用,成本追踪效果好很多。
分享一个我用过的模拟场景:某日活动量比平时大了 5 倍,设置的日预算在下午就触发了拦截。还好密钥做了日额度限制,避免了因为活动流量异常导致账单爆炸。这类兜底设计在业务不可控的流量场景下非常重要。
5.3 多实例部署时的配置同步
如果你们的请求量很大,litellm 单实例撑不住,就需要多实例部署。多实例部署面临一个问题:配置如何同步?虚拟密钥数据如何共享?
litellm 官方推荐用数据库存储配置与密钥数据,这样所有实例共享同一份数据,虚拟密钥在哪个实例上都能验证通过。具体到操作层面,需要给 litellm 配一个 PostgreSQL 数据库连接,同时数据库实例最好也做成高可用。配置管理上,尽量把模型清单维护在数据库里,少依赖本地配置文件。
这部分的复杂度会比单实例高不少,我建议业务量没到瓶颈之前先别急着上多实例,把单实例吃透再扩展也不迟。
5.4 定期巡检与配置治理
用了一段时间后,配置清单里往往积累了不少已经停用的模型和废弃的密钥。建议每月做一次巡检:把模型列表拉出来逐个测试,还用的留着,不用的删掉;把虚拟密钥按团队拉出来核对,离职同学或废弃系统的密钥及时吊销。
巡检这事听起来简单,实际操作中容易犯拖延症。我的经验是固定在每个月的某一天做“模型健康检查”,利用 litellm 的管理接口批量发一个最简单的请求,把不通的模型筛选出来逐个处理。整个过程半小时左右,换来的是配置清单的干净和生产环境的稳定,很划算。
5.5 补充几个容易忽略的细节
litellm 对模型重命名这事值得多说一句:model_name 是一个逻辑名字,只存在于 litellm 网关内部,跟上游厂商真实的模型 ID 是两个概念。起名的时候最好用业务维度,比如 chat-main、chat-cheap、embedding-main。别直接用上游的模型 ID 当 model_name,不然以后换厂商要全局改请求里的 model 字段,又回到原来的老路了。
另外日志里记录的花费是估算值。litellm 是根据 token 用量和配置的单价算出来的,如果上游价格变动了,记得及时更新配置里的价格参数,不然成本统计会失准。
最后再说一下管理接口的鉴权。master key 就是 litellm 的超管密钥,能新增模型、生成虚拟密钥、查看全量日志,一定要妥善保管。生产环境建议定期轮换 master key,同时确保管理接口不暴露在公网。安全上的一个疏忽可能导致整个模型资源被人薅羊毛,这点再怎么强调都不为过。
litellm 这套东西,前前后后我在多个项目里用了将近一年,最大的感受是:它把“多模型接入”这件原本琐碎、重复、容易出错的事,真正收敛成了一个标准化操作。新模型上线不再是改代码发版,而是改一行配置,业务侧甚至无感知。后续如果你准备引入新的模型服务商、做模型容灾、或者在团队里统一 LLM 调用入口,litellm 是一个值得优先考虑的基础设施选项。