最近在做 AI 应用的时候,被各家大模型 API 的差异折腾得够呛。同一个功能,OpenAI 的调用方式和 Anthropic 不一样,换到本地模型又是另一套参数,代码里到处都是 if-else 分支,维护起来非常痛苦。后来我在一个开源社区里看到有人提到 litellm,说它能把所有模型 API 统一成 OpenAI 格式,当时半信半疑。直到我实际把它接入到项目里跑通全流程,才发现这玩意儿确实能省掉一大半的对接工作。
这篇文章不是官方文档的翻译,是我自己从零开始接入、踩坑、排错之后总结出来的实战经验。我会从它到底解决什么问题讲起,再到具体怎么装、怎么配、怎么在生产环境里用起来,最后聊聊我遇到的那些坑和我的处理方式。如果你也在做多模型接入或者打算在公司里做统一的模型网关,这篇文章应该能帮你少走不少弯路。
1. 这个东西到底解决了什么问题
先说个我真实的经历。之前我维护一个内部工具,需要同时接入三家大模型的接口,每家的鉴权方式不一样、消息格式不一样、参数命名不一样,连超时重试的逻辑都得各写一套。最难受的是,产品经理某天过来说"下个版本我们想把默认模型换成另一个厂商的",我一听就知道这意味着要改底层封装、改请求构造、改错误处理,还要重新测一遍所有流式输出。这种重复劳动真的是纯内耗。
litellm 的定位就是解决这类问题。它本质上是一个大模型 API 的兼容层和网关:对外,它提供一个统一的 OpenAI 格式接口;对内,它帮你把请求翻译成各家厂商的格式。你只要按照 OpenAI 的规范写一次代码,剩下的模型切换、参数映射、错误处理、重试逻辑,全部由 litellm 替你完成。
它的核心价值可以归纳成下面几点:
- 一套代码接入 100+ 家模型提供商。从主流的几家大厂,到各种开源模型的自托管服务,基本都在支持列表里
- 支持 SDK 调用和代理服务器两种模式。SDK 适合直接嵌入代码,代理模式适合团队内统一收口 API 调用
- 自带密钥管理、成本追踪、限流、重试、缓存等生产级能力,相当于给你的 AI 调用加了一层技术中台
那它适合谁用?如果你是独立开发者,想在几个模型之间快速切换做对比实验,或者你在一个团队里负责维护公共的模型接入层,又或者你们公司要做模型网关统一管理所有业务线的 API 调用,litellm 都值得认真看看。
不过在往下走之前我要先泼一盆冷水:如果你们的业务只用一家模型的官方 API,没有任何切换需求,那其实没什么必要引入 litellm。多一层封装就意味着多一层学习成本和排查复杂度,这一点大家要心里有数。
2. 核心设计拆解:SDK 和代理两条路
我第一次看 litellm 的文档时有点懵,因为它同时提供了两种使用方式,很多人不知道该选哪个。我花了一段时间把两种都用了一遍,现在可以很清楚地跟你说它们的区别。
2.1 SDK 模式:轻量接入,适合直接嵌入
SDK 模式就是直接在 Python 代码里调用litellm.completion()来完成请求。你可以传入任意一个模型标识符,比如gpt-4o、claude-3-5-sonnet-20241022、ollama/llama3.2,litellm 会在底层解析这个标识符,自动确定对应的 API 地址、鉴权方式和请求格式。
import litellm response = litellm.completion( model="gpt-4o", messages=[{"role": "user", "content": "你好,请介绍一下你自己"}] ) print(response.choices[0].message.content)这里有个很关键的设计:模型名里包含提供商的信息。比如ollama/llama3.2中间的斜杠前缀ollama就是提供商标识,litellm 根据它来选择适配器。如果是 OpenAI 的模型,直接写gpt-4o就行,因为 OpenAI 是默认提供商。
SDK 模式最大的好处是轻,一行安装、几条调用就能跑起来。缺点也不难想到:如果多个项目都要接模型,每个项目都得配置各自的密钥环境变量,密钥管理还是散落在各处,没法统一收口。
2.2 代理模式:统一收口,适合团队协作
代理模式则是一个完整的 HTTP 服务。你启动一个 litellm proxy server,所有业务系统都把请求打到这个服务上,由它再转发到实际的大模型厂商。业务方只需要知道这个网关的地址,不需要关心背后到底是哪家模型,也不用持有各家厂商的密钥。
litellm --config config.yaml --port 4000跑起来之后,你用 OpenAI 的官方 SDK 把 base_url 指到http://localhost:4000就能正常调用:
from openai import OpenAI client = OpenAI( api_key="sk-any-string", base_url="http://localhost:4000" ) response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "你好"}] ) print(response.choices[0].message.content)注意这里我随意填了一个sk-any-string当 api_key,因为代理模式下 litellm 自己管理密钥校验,上面这个写法要配合虚拟密钥功能才安全,后面我会专门讲。
代理模式的核心优势是集中管控。所有密钥集中在服务端配置,业务方不接触真实密钥;你可以对每个接入方分配不同的虚拟密钥,做访问控制和额度限制;所有请求的日志、成本、延迟都能统一记录和分析。这是它在生产环境里最受欢迎的原因。
3. 配置与实操:从一个可用配置说起
3.1 安装与认证配置
安装比较简单,核心依赖是 Python 3.8 以上环境。我推荐用虚拟环境装,避免把系统环境搞乱。
pip install 'litellm[proxy]'安装完后需要配置厂商密钥。litellm 的密钥读取遵循一套优先级规则,会依次检查环境变量、.env文件、配置文件里的environment_variables字段。最省事的是准备一个.env文件放到项目目录下:
OPENAI_API_KEY=sk-xxxxxxxxxxx ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxx GEMINI_API_KEY=AIzaxxxxxxxxxxx这些环境变量名是 litellm 预定义好的约定,各厂商的密钥必须用对应的名字,它才能识别。如果你用的是自托管的模型服务,对应的环境变量写法可以参考官方文档,但大部分情况下就是{提供商名大写}_API_KEY这个模式。
3.2 写一个最小代理配置
代理模式的核心是一个 YAML 配置文件。下面这个配置是我在实际项目里的最小可用版本,我把模型列表精简成两家做演示:
model_list: - model_name: gpt-4o litellm_params: model: gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: claude-sonnet litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: os.environ/ANTHROPIC_API_KEY litellm_settings: drop_params: true set_verbose: false general_settings: master_key: sk-master-123456拆开解释几个关键点:
model_list是你对外暴露的模型目录。model_name是业务方调用时使用的模型别名,可以随意定义;litellm_params.model才是真正映射到厂商的具体模型标识符。这种"对外别名"和"真实模型"分离的设计非常实用,切换底层模型时业务方代码完全不用改。
drop_params: true这个参数很值得留意。不同厂商支持的参数集不同,比如有的模型不支持frequency_penalty,如果不加这个配置,传了不支持的参数请求就会直接报错。开启drop_params后,litellm 会忽略那些目标任务不支持的参数,虽然牺牲了一部分参数控制力,但兼容性会好很多。
master_key是代理服务的总管理员密钥。它的作用是保护管理接口,比如后续要调用/key/generate生成虚拟密钥、查看/spend/logs花费日志,都需要这个密钥。实际生产环境里要把它换成强随机字符串,别跟我示例里一样写好记的。
3.3 代理启动与验证流程
配置文件准备好后,启动:
litellm --config config.yaml --port 4000 --num_workers 4num_workers控制进程数,这个要根据服务器 CPU 核数和预期并发量调整。我一般先设为 CPU 核数两倍,然后再用压测数据去微调。
启动之后,可以先做个快速健康检查:
curl http://localhost:4000/health/liveliness然后模拟一个真实的 OpenAI 兼容请求:
curl http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-master-123456" \ -d '{ "model": "gpt-4o", "messages": [{"role": "user", "content": "说句话"}] }'能正常返回 JSON 响应,就说明代理已经跑通了。
4. 生产环境必须用起来的关键功能
配置跑通只是第一步。我把 litellm 放进生产环境之前,仔细研究了它的几个核心能力。这几个功能如果不掌握,那真的只是把它当成一个简单的格式转换工具在用,很浪费。
4.1 虚拟密钥:把访问权真正管起来
代理服务如果直接把 master_key 发给所有业务方,一旦有人泄露,整个网关就裸奔了。litellm 提供了虚拟密钥机制,让你可以为每个接入方单独生成密钥,并限定这个密钥能访问哪些模型、每分钟最多调用多少次、总预算多少。
curl -X POST http://localhost:4000/key/generate \ -H "Authorization: Bearer sk-master-123456" \ -H "Content-Type: application/json" \ -d '{ "models": ["gpt-4o", "claude-sonnet"], "max_budget": 100, "rpm_limit": 60, "metadata": {"team": "data-platform"} }'响应里会得到一个key字段,把它发给对应的业务方,他们拿着这个 key 请求http://localhost:4000就行。这样每个团队一把钥匙,预算和限流都隔离清楚,出问题时也能直接定位到是哪个接入方的流量异常。
4.2 模型重试与超时策略
大模型接口的稳定性说实话不算特别好,网络抖动、服务过载的情况时有发生。litellm 在代理层面统一处理重试和超时,比业务方各自做容错要省心得多。
配置方式是在litellm_settings里加:
litellm_settings: num_retries: 3 request_timeout: 600 retry_after: 0.5num_retries是重试次数,retry_after是两次重试之间的基础间隔。litellm 默认采用指数退避策略,每次重试的等待时间会递增,避免重试风暴打垮厂商接口。request_timeout要特别说一下,流式请求的总时长可能很长,如果设太短,思考时间长的模型很容易触发超时,设太长又可能导致连接长时间占用。我一般按业务场景分开处理,普通对话 60 秒,需要深度推理的场景单独建一个配置 600 秒。
4.3 成本追踪与用量统计
做技术中台的人最关心的就是成本,litellm 在这块做得比较完整。它内置了花费计算引擎,根据模型、输入输出 token 数自动计算每次调用的成本。
curl http://localhost:4000/spend/logs \ -H "Authorization: Bearer sk-master-123456"能看到每个请求的模型、token 数、预估花费、调用方等信息。代理还会在响应头里返回x-litellm-model-cost之类的字段,方便业务方实时获取成本数据。
有一点要提醒:成本计算依赖 litellm 内置的模型价格表,如果模型列表里有它不认识的型号,花费会被标记为无法估算。遇到这种情况需要手动在配置里补上价格映射。
4.4 语义缓存:省钱的利器
如果你有大量重复请求的场景(比如客服机器人频繁查询同一个常见问题),litellm 的缓存功能能省下不少预算。它支持按请求内容做精确匹配或语义相似度匹配,命中缓存就直接返回之前的结果,不再转发给模型厂商。
litellm_settings: cache: true cache_params: type: redis host: localhost port: 6379缓存后端支持本地内存和 Redis,多实例部署时务必用 Redis,否则每个实例各存一份,命中率会很低不说,还可能导致数据不一致。语义缓存需要额外配置嵌入模型来算向量相似度,这个我一般默认不开,因为嵌入计算本身也有成本,完全取决于你的请求重复率有多高。
5. 多模型路由和故障转移的玩法
litellm 还有一套路由能力,可以实现负载均衡、故障转移和区域优先级。这是它从"格式转换工具"走向"流量调度平台"的关键分层。
5.1 同一个模型挂多个密钥做负载均衡
如果你有多个厂商密钥,希望请求分摊到所有密钥上,避免单个密钥触发限流,可以这样配置:
model_list: - model_name: gpt-4o litellm_params: model: gpt-4o api_key: os.environ/OPENAI_API_KEY_1 - model_name: gpt-4o litellm_params: model: gpt-4o api_key: os.environ/OPENAI_API_KEY_2两个条目对外都是gpt-4o,litellm 会在它们之间轮询分发请求。这个场景在账号被限流时非常实用,我在做批量数据标注时就靠它把多个账号的配额都用满。
5.2 配置 fallback 降级策略
比负载均衡更常用的是故障转移。比如主模型超时或返回 5xx 错误时,自动降级到备用模型。注意这里我用了同一个模型的两个不同提供商来做演示:
router_settings: fallbacks: [ {"gpt-4o": ["claude-sonnet"]} ]含义是:当gpt-4o请求失败并重试耗尽后,自动改发到claude-sonnet。这个配置的价值在于提高整体可用性。我在一次厂商大规模故障时实测过,业务侧完全无感,因为网关自动把流量切到了另一家,整体可用性从 97% 提到了接近 99.5%。
不过 fallback 是双刃剑。两个模型的能力差异可能导致响应质量波动,而且成本结构完全不同,所以我在生产环境里只对非核心业务配置了 fallback,核心交易链路还是保持"宁可失败也不能静默切换模型"的原则。
5.3 容器化部署注意事项
大多数团队不会直接裸机跑 litellm,Docker 部署是更常见的方式。我这边提供一份经过验证的部署思路:
docker run -d \ --name litellm-proxy \ -p 4000:4000 \ -v $(pwd)/config.yaml:/app/config.yaml \ -v $(pwd)/.env:/app/.env \ --restart always \ ghcr.io/berriai/litellm:main-latest用宿主机文件挂载的方式覆盖配置,方便后续更新。这里要提醒一个坑:容器内的时区默认是 UTC,如果你要用成本报表按本地时间统计,需要在 Docker 启动参数里加上环境变量TZ=Asia/Shanghai。
生产环境建议至少跑两个副本,前面挂一层负载均衡。litellm 本身是无状态服务(缓存用 Redis 的话),多副本部署没有会话一致性问题,扩容缩容都很简单。
6. 常见问题与排查经验速查
我整理了一份我在实际使用中遇到的典型问题。这些问题在官方文档里不一定写得很直白,但我相信不少人都踩过类似的坑。
| 问题现象 | 可能原因 | 排查方法 |
|---|---|---|
调用时报model not found | 请求里的模型名在model_list里不存在 | 检查配置中对外model_name是否匹配,注意大小写 |
报错401 Unauthorized | 虚拟密钥无效或已被删除 | 用 master_key 调/key/info查看该密钥状态 |
| 请求超时频繁 | request_timeout设置太短 | 查看请求日志确认耗时分布,按 P95 调整超时 |
| 某个模型返回参数不支持 | 目标模型不支持 payload 里的某个参数 | 开启drop_params,或检查litellm_params是否多传了参数 |
| 成本记录为 0 | 模型不在 litellm 价格库中 | 手动在配置里添加该模型的价格映射 |
| 流式响应中断 | 代理层或厂商层流式处理异常 | 先直连厂商测试流式是否正常,再对比代理转发 |
| 密钥无法从环境变量读取 | 变量名不匹配 litellm 约定 | 确认环境变量名格式为{厂商大写}_API_KEY |
6.1 一个典型的流式调用问题
有段时间我们一个业务方反馈,用流式方式接 litellm 时响应总是中途断开。我排查了很久,最后发现问题是出在代理层的num_workers上。当时我开的是 8 个 worker,但每个 worker 默认的连接池大小不够,在高并发流式请求时连接被占满,新的请求坐等不到空闲连接就断了。后来通过配置文件手动调大了连接池大小,问题才解决。这种问题靠看应用日志很难发现,因为你看到的是某个连接被重置,但背后原因其实在更底层。
6.2 关于密钥管理的一点建议
虚拟密钥虽然好用,但有个细节要注意:删除密钥不会立即切断已经建立的连接,在途请求还是会正常完成。所以需要轮转密钥时,建议先创建新密钥、切换业务方配置、再删除旧密钥,而不是直接杀掉旧密钥。我因为这个操作顺序吃过亏,删得太急导致线上还有几十个请求跑在失效的密钥上。
7. 我的一些收尾心得
litellm 对我来说最大的价值不是省了那几行代码,而是它把"接入模型"这件事从"每个项目各做一遍"变成了"平台做一次,所有项目复用"。我们团队现在有五个业务模块通过它统一接模型,新模型接入的时间从原来的一到两天压缩到了半小时以内,基本上是改配置、测连通性、发布三步走。
最后分享一个小技巧。如果你想快速评估一个新模型是否值得接入,可以在代理配置里临时加一条model_name指向新的目标模型,然后指定一个测试虚拟密钥只给这一个模型权限,直接请业务方小流量试用。试用满意了再放开给全线业务,试得不满意直接删掉配置,对线上毫无影响。这种低成本试错的方式,是用熟 litellm 之后带来的额外红利。
如果你正准备给团队搭模型网关,或者还在几个模型之间犹豫不决,我建议不要急着在业务代码里写兼容层。先花一天时间把 litellm 跑通,把你的真实场景在它上面走一遍,再决定要不要深入使用。一个工具好不好用,终究还是要靠自己的实际场景来验证。