搞大模型应用这一年多,我最大的感受就是:AI 时代最不缺的就是模型,最缺的是一个能把这些模型都管起来的中间层。每次项目里要接一个新模型,都得重新读一遍文档、改一遍代码、调一遍鉴权,光这些重复劳动就能耗掉半天。所以当身边几个做 AI 应用的朋友不约而同提到 litellm 这个开源项目时,我决定认真把它研究透。
litellm 是一个开源的 LLM API 网关,简单说,它把所有主流大模型提供商的接口统一成 OpenAI 的格式,你只需要写一份代码,就能调用包括 OpenAI、Anthropic、各类国产模型、开源社区模型在内的一大堆模型服务。同时它还内置了密钥管理、成本追踪、速率限制、模型负载均衡这些生产环境必需的能力。如果你的项目需要接入多个模型,或者你正在给团队搭一套统一的 AI 服务入口,这篇文章刚好适合你。
1. 为什么需要这样一层 API 网关
1.1 多模型接入的碎片化之痛
先说说我在实际项目里遇到的真实情况。刚开始做 AI 应用的时候,我直接在后端代码里调用模型的 SDK。一开始只接了一个模型,感觉还挺简单,但后来业务需要对比不同模型的回答效果,就得同时接两三个模型。这时候问题就暴露出来了,每个提供商的接口风格完全不一样,请求体结构不同、认证方式不同、错误码含义不同,甚至超时设置和重试逻辑都得单独处理。
有一回我需要把其中一个模型从服务 A 切换到服务 B,结果改完代码,测试环境跑通了,一上生产就出问题。原因是服务 B 的流式响应处理方式和服务 A 不太一样,我原来的流式解析代码直接失效。那一次上线折腾了快一天,加了不少临时判断逻辑才糊弄过去。这件事让我意识到,如果业务代码里到处散落着各个模型提供商的 SDK,那每次模型升级、切换、新增,都是一次冒险。
1.2 网关层和直连模式的本质区别
直连模式就是业务代码直接和每一个模型提供商通信,这种模式在小规模试验阶段没有问题,但一旦进入团队协作、多人共用、多环境部署,短板就非常明显。每个开发者都要配置自己的密钥,密钥管理混乱不说,成本也没法统一核算,出了限流问题更是不知道是哪段代码触发的。
litellm 做的事情,是在业务代码和模型提供商之间加了一层统一代理。所有请求先打到 litellm,再由 litellm 转发到真正的模型服务商。业务代码只和 litellm 通信,litellm 就是一个标准化的转换器。你可以把它理解成一个万能插座转换头,各个国家的电器插头(不同模型提供商的 SDK)都能插到这个转换头上,而你的业务代码只需要适配一种插座规格(OpenAI 兼容格式)。
这个设计最大的价值在于,模型选择从代码里的硬编码变成了配置里的一个参数。业务代码根本不需要知道背后到底是哪个模型在提供服务,只需要发一个请求说"我要用这个模型",至于这个模型在哪里部署、用哪个 API 地址、密钥是什么,全部由 litellm 在配置层搞定。
2. 核心能力逐项拆解
2.1 统一接口标准,一份代码跑所有模型
litellm 最基础也是最核心的能力,就是把所有模型的调用接口统一成 OpenAI 的 chat/completions 格式。这意味着你的业务代码只要是按 OpenAI 的规范写的,比如用 openai 的 Python SDK 或者直接发 HTTP 请求,那它就能通过 litellm 访问背后所有的模型。
这么做的好处非常直接。我团队里几个后端同学过去写 AI 功能,总要先问一句"这个模型是什么 SDK",现在不用问了,统一写 OpenAI 格式的代码,模型相关的差异全被 litellm 挡在最外层。而且 litellm 还支持模型名映射,你可以给每个模型起一个项目内部的别名。比如"模型A"对应某个大参数模型,"模型B"对应一个性价比更高的小模型,业务代码里永远只写这两个别名,后面想换掉模型A的实际提供方,改动配置就行,代码一行都不用动。
统一格式这件事,做起来比听起来复杂。不同的模型提供商有各自的参数体系,有的叫 max_tokens,有的叫 max_new_tokens,有的 temperature 取值范围是 0 到 1,有的则是 0 到 2。litellm 需要在请求转发时把这些参数做翻译转换,同时在响应回传时把各种不同的响应结构统一成 OpenAI 的样子。只有真正做过聚合层研发的人才知道,这其中的边界情况多得让人头皮发麻,好在 litellm 把这些细节都处理掉了。
2.2 密钥托管与安全管控
模型 API 的密钥管理是生产环境里最容易被忽略、又最容易出问题的地方。在很多团队里,密钥直接写在代码里、放在环境变量里,甚至被不小心提交到代码仓库里。一旦泄露,就是实打实的成本损失。litellm 通过虚拟密钥机制来规避这个问题。
你可以把真实的模型提供商密钥存在 litellm 服务端,然后为每个开发者、每个项目、甚至每个环境生成一个单独的虚拟密钥。业务请求用的是虚拟密钥,litellm 在转发请求时才把它替换成真实密钥。这样一来,真实密钥只存在于 litellm 的配置里,其他开发者根本接触不到。更实用的是,虚拟密钥可以单独设速率限制、设预算上限、设过期时间。给实习生发一个密钥,预算设个 50 块,跑完了就自动熔断,不用天天盯账。
另外,litellm 支持设置主密钥(master key),所有管理和查询接口都需要主密钥或具有相应权限的虚拟密钥才能访问。这套权限模型虽然称不上复杂,但已经能把"谁在用模型""每个应用花了多少钱""每个密钥还能不能用"这些问题管理得明明白白。说实话,我见过不少业务量不小的团队,连这种最基础的管控都没有。
2.3 成本追踪与用量分析
模型调用的成本追踪是我非常喜欢的一个功能。之前和几个用其他网关方案的朋友聊天,他们最头疼的就是月末核算成本:每个项目跑了多少 token、累计花了多少钱,只能靠猜,完全没有准确数据。litellm 自带的用量记录功能解决了这个问题。
服务端会记录每一个请求的模型、token 用量、延迟、成本估算,以及这个请求用的是哪把虚拟密钥。通过管理后台或者查询接口,你可以按虚拟密钥、按团队、按模型维度去统计消耗。这套数据的用处很大,不光能用来做内部成本分摊,还能用来做模型选型分析。比如你同时接了两个能力相近的模型,跑一段时间后看数据就知道哪个更省钱、延迟更低,选型决策就有了依据,不再靠感觉。
成本追踪还能配合预算限制做主动管控。给某把虚拟密钥设置月度预算,当累计成本超过阈值时,litellm 会自动拒绝新的请求。这在内部工具、测试环境、面向外部用户的场景里都非常好用,相当于给成本上了一道保险。
2.4 负载均衡、重试与降级处理
单个模型服务商总会有不稳定的时候,限流、超时、5xx 错误,在规模化调用场景下几乎是每天都会遇到的事情。litellm 内置的重试和降级机制,让我们不用在业务代码里做一堆异常处理。
你可以配置多组模型,当主模型出现特定类型错误时,litellm 自动把请求转发到备用模型。比如主模型是海外某个服务商,偶尔网络不稳定,那就配一个国内模型作为降级方案。更实用的场景是:同一个模型同时配置多个提供方,比如同样一个开源模型,既可以通过某个托管服务商调用,也可以调用本地部署的实例,litellm 会在它们之间做负载均衡。当一个提供方超时或出错时,请求就会自动切换,整个过程业务侧是无感知的。
重试策略也有讲究。litellm 支持配置重试次数、重试间隔、退避系数。简单说,第一次请求失败后,它会等一小段时间重试,如果还失败,等待时间会逐步加长,避免所有请求同时重试把服务商打爆。这种机制在流量高峰期的稳定性保障上,效果非常明显,我见过不少直连模式的项目在模型服务商抖动时就瘫痪,而加了 litellm 之后依然能保持较高的成功率。
3. 本地部署与核心配置实操
3.1 最快的启动路径
litellm 是一个 Python 项目,可以通过 pip 直接安装。如果你只是想快速试用,这是最简单的方式。
pip install 'litellm[proxy]'安装完成后,可以通过命令行直接启动:
litellm --model gpt-4o --port 4000这样会启动一个监听 4000 端口的代理服务,并且把你配置的模型注册进来。但这种方式只适合临时测试,生产环境的配置要复杂得多。litellm 支持通过配置文件来定义模型、密钥、参数,更贴近真实使用。
litellm --config config.yaml --port 4000配置文件是 YAML 格式,里面定义了你需要接入的模型列表、模型对应的提供商、真实的 API 密钥位置,以及各种全局参数。我用下来的经验是,从配置文件启动才是正确打开方式,一切可配置、可版本管理、可审计。
3.2 配置文件的核心模块解析
litellm 的配置文件里,最关键的是两个部分:模型列表配置和通用参数配置。
先看一个最简配置示例:
model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: claude-3-5-sonnet litellm_params: model: anthropic/claude-3-5-sonnet api_key: os.environ/ANTHROPIC_API_KEYmodel_list 是模型注册表。每一个条目包含两个字段:model_name 是这个模型对外提供的名字,litellm_params 是转发请求时真正用的参数。在 litellm_params 里,model 字段的格式是"提供商/模型名",后面可以跟对应的 api_key。api_key 不建议直接写在配置文件里,而是用 os.environ/XXX 这种形式引用环境变量,这样配置文件可以提交到代码仓库,密钥还留在服务器环境里。
除了基本的模型注册,litellm_params 还支持很多粒度更细的参数,比如设置请求超时时间、请求重试次数、指定使用某个模型的具体版本。之前我们遇到过一个问题,同一个模型在提供商侧升级了新版本,结果业务表现和之前不一样了。后来在配置里固定了模型版本号,才避免了这种"悄悄变化"带来的麻烦。
全局参数部分,比较常用的是数据库连接和主密钥设置。litellm 把请求日志、成本数据都存在数据库里,默认使用 SQLite,但生产环境建议用 PostgreSQL,后续展开说。
3.3 用 curl 和 Python 快速验证服务
启动 litellm 之后,怎么确认它真的能转发请求?最简单的方法是用 curl 直接请求它的接口。
curl http://localhost:4000/v1/chat/completions \ -H "Authorization: Bearer sk-1234" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "messages": [{"role": "user", "content": "你好,请介绍一下自己"}] }'注意这里的 model 字段,值对应的是 config.yaml 里 model_list 中的 model_name,而不是模型提供商的真实模型 ID。litellm 会按这个名字找到对应的转发配置。如果一切正常,返回的 JSON 结构和直接调用 OpenAI 是一样的。
Python 侧的调用更是无缝,直接用 openai 的 SDK,把 base_url 指向 litellm 的地址就行:
from openai import OpenAI client = OpenAI( base_url="http://localhost:4000/v1", api_key="sk-1234" ) resp = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "你好"}] ) print(resp.choices[0].message.content)很多开发者第一次用的时候会惊讶于这个代码的普通,没有特殊的库、没有特殊的封装,就是最标准的 OpenAI SDK 用法。这正是 litellm 想要的效果:学习成本趋近于零。
3.4 数据库与生产参数选择
litellm 服务端的数据库配置是很多人容易忽略的部分。默认情况下,litellm 会使用 SQLite 存储数据,这在本地实验、并发量不高的时候没有大问题。但我建议只要服务会持续运行、有多个开发者同时使用,就直接切换到 PostgreSQL。原因是 SQLite 在多个进程同时写入时容易出锁问题,而 litellm 的请求日志、成本数据是高频写入的。PostgreSQL 能更好地支撑这种并发场景,也更方便后续做数据分析和对接监控系统。
数据库连接通过 DATABASE_URL 环境变量配置:
export DATABASE_URL="postgresql://user:password@localhost:5432/litellm"启动时加上主密钥参数:
litellm --config config.yaml --port 4000 --master_key sk-litellm-master-xxx主密钥很重要,所有管理类接口都需要它来鉴权。生产环境里一定要把主密钥放在安全的地方,不要出现在 shell 历史里,更不要提交到代码库。
4. Docker 部署与生产环境落地
4.1 容器化部署的几个关键步骤
如果你们团队的基础设施是 Kubernetes 或者 Compose 那一套,那 litellm 的 Docker 部署方式更合适。litellm 官方维护了 Docker 镜像,拉取后通过环境变量和挂载文件来配置。
最简单的启动方式:
docker run -d \ --name litellm \ -p 4000:4000 \ -v $(pwd)/config.yaml:/app/config.yaml \ -e DATABASE_URL="postgresql://user:password@pg-host:5432/litellm" \ ghcr.io/berriai/litellm:main-latest \ --config /app/config.yaml \ --master_key sk-litellm-master-xxx这里做了两件比较关键的事:把本地的 config.yaml 挂载到容器内,避免把配置写死在镜像里;通过环境变量传入数据库连接,数据库放在容器外部。这样做的好处是,镜像本身是通用的,配置文件和环境变量随时可以调整,不用重新构建镜像。
在 Kubernetes 里部署,思路一般是 Deployment 加 Service,配置用 ConfigMap 挂载,密钥放在 Secret 里。litellm 本身是无状态服务,状态都在数据库里,所以扩缩容很轻松,压测发现单实例扛不住时,直接加副本即可。
4.2 生产环境的几个必配项
生产环境比本地环境多出来的要求,主要是三件事:持久化、可观测性和高可用。
持久化方面,前面提到的 PostgreSQL 是核心,所有的用量数据、日志数据都在里面。别省这一步,直接用 SQLite 的话,服务一重启、数据一多,就会开始出现各种奇怪问题。
可观测性方面,litellm 支持通过配置把请求日志同步到 Prometheus,具体做法是在配置文件里开启 prometheus 相关配置,然后在 Prometheus 里抓取 litellm 暴露的 /metrics 接口。这样模型的请求量、错误率、延迟都能进监控大盘,出了问题能第一时间发现。我有一次排查线上模型响应变慢的问题,就是靠监控数据定位到是某个模型提供商的某个节点异常,而不是我们的服务出了问题。
高可用方面,litellm 的多实例部署要留意 Prometheus 指标统计的特殊性。因为 litellm 的指标是按实例记录的,每个实例记录自己的请求量,所以如果开了多个副本,需要在 Prometheus 里配置聚合查询,按服务名去 sum,不然看到的指标是分片的。这条我踩过坑,日志看着正常,指标对不上,后来发现就是聚合维度有问题。
5. 常见问题与排查技巧实录
5.1 高频报错速查表
| 报错现象 | 可能原因 | 解决思路 |
|---|---|---|
| 401 Unauthorized | 虚拟密钥错误、主密钥未设置 | 检查 Authorization 头里的 key 是否在 litellm 中有效 |
| 404 Model Not Found | model 名称未在 model_list 注册 | 检查配置里的 model_name 是否和请求一致 |
| 429 Too Many Requests | 触发了速率限制或预算上限 | 查看虚拟密钥的限制配置,或检查服务商侧配额 |
| BadRequest 参数不兼容 | 某些参数不被目标模型支持 | 在 litellm_params 里固定该模型兼容的参数 |
| 502 Bad Gateway | 模型服务商接口异常 | 检查服务商状态,配置备用模型降级 |
我在实际排查中发现,很多报错并不是 litellm 本身的问题,只是错误信息经过了 litellm 的包装,看起来像它的锅。比如 404 Model Not Found,十次里有八次是配置里的 model_name 写错了,或者是请求里传了完整的真实模型 ID,但没有经过映射。解决方式是先确认请求里传的名字和 config.yaml 里 model_list 定义的 model_name 完全一致。
5.2 排障的正确姿势
litellm 的日志信息量很大,但前提是你知道怎么读。启动时加上 --debug 参数会输出更详细的日志,每次转发的链路中,日志里会标明请求命中哪个模型配置、实际转发到哪个服务商、用了多长时间、返回了什么错误。排查问题的时候,先别急着看业务代码,先打开 litellm 的日志看请求有没有正常进来、转发到了哪里、目标服务商返回了什么。
另外,litellm 提供了一个 /health 健康检查接口,可以快速确认服务本身是否存活。结合数据库的请求记录,基本能定位大部分问题。我自己的排查习惯是:先确认 litellm 进程活着,再确认配置的模型能通过 /v1/models 接口查到,然后手动发一个 curl 请求看原始返回。这三个步骤能覆盖大部分"模型突然不好用了"的情况。
还有一个常用的小技巧:配置文件的语法错误会导致 litellm 启动失败,但报错信息有时候比较隐晦。我建议改完配置文件后,先本地用一个小脚本启动服务,确认能够启动再应用到生产环境。别小看这一步,我有一次在 YAML 里缩进错了,生产环境服务的健康检查挂了半天才发现是配置文件的问题。
5.3 反馈慢、超时类问题的定位
如果请求总是超时或者延迟很高,不要第一反应去调 litellm 的重试参数。先用 curl 绕过 litellm,直接请求模型提供商的原始接口,对比一下延迟。如果直连也慢,那问题出在模型服务商侧;如果直连很快、通过 litellm 就慢,那再检查 litellm 所在服务器的网络环境、DNS 解析、以及是否走了代理。
另外,litellm 的数据库写入也可能成为瓶颈。它的请求日志是同步写的,如果数据库响应变慢,会连带拖累请求的响应时间。我在压测时遇到过这个坑,并发量拉上去之后,数据库写入排队,接口响应时间明显增加。解决方法是给数据库加索引、或者把日志采样调低,减少不必要的写入压力。
结束语
用 litellm 当团队统一的模型网关,是我在 AI 应用工程化过程中非常正确的决定。它最打动我的不是某一个功能多强大,而是它把工程化需要考虑的问题集中到了一个地方:密钥安全、成本核算、模型切换、异常降级,都有对应的解决方案。哪怕你只是一个人开发,不需要团队协作,用它来管理多个模型的密钥和成本,也能省下不少精力。
最后分享一个小经验:刚开始用 litellm 的时候,别急着把所有模型都配上去,先挑两个常用的模型跑通核心链路,把密钥管理、成本记录这些基础能力用起来,等稳定了再逐步扩展。配置越多,排查问题的范围就越大,一步一个脚印反而更快。后面如果你的场景需要更深度的定制,litellm 也提供了丰富的回调机制,可以在请求的各个阶段注入自己的逻辑,那就是另一个层面的玩法了。