隔一段时间不跟一遍生态,就会发现自己有点跟不上。LLM应用开发最近火到什么程度?光是切换模型这一步,就能让人烦到怀疑人生。今天聊的这个项目,叫litellm,一句话说清楚:它是一个开源的LLM网关,也叫统一代理层,用一套API格式把市面上主流大模型服务商的接口全部包起来。简单讲,你的业务代码不用再为不同模型写不同的调法,直接走litellm这一个口子,后端是接通的还是通义、是本地部署的模型,还是别家闭源的接口,对上层调用者完全透明。
很多团队一开始觉得用不着这种中间层,结果项目一跑起来就发现,模型A效果不好想切模型B,结果B的请求参数格式完全不一样;再往后又发现几个人共用几个API Key,月底账单对不上;再往后想限个流、给不同部门分配额度,发现根本没有现成的机制。这些问题litellm都能管,而且它本身是个开源项目,不是封闭的商业平台,部署在自己服务器上,数据内容不经过第三方中间链路。
这篇文章我会从实际使用的角度,把它的核心设计拆开来看,再给出完整的部署步骤、配置示例和排错经验,适合正在做AI应用开发的后端工程师、想给团队搭一套模型治理基础设施的技术负责人,以及那些被多模型切换折磨过的独立开发者。
1. 为什么需要一个LLM代理层
1.1 多模型接口的接入痛点
先看一个具体场景。你的应用要同时接入多家模型服务:一个用于日常闲聊,先上A家的通用大模型;一个用于专业写作,试试B家的长文本模型;再部署一个本地的开源模型处理敏感数据。每个服务商的SDK风格都不同,有的用messages数组,有的用prompt字符串,有的流式返回的字段叫delta,有的叫choices,还有的干脆把所有输出包在一个JSON字符串里。
我见过不少团队的第一版集成方案是写一个LLMClient接口,每个服务商写一个实现类。一开始只有两家还好,第三家接入时,就要处理超时配置、重试策略、错误码映射、流式解析、模型名称映射、计费格式转换……这套代码越写越厚,最终变成项目里最难维护的一块。
而且这种紧耦合带来的问题不止是代码层面。业务方想从A模型切到B模型,光靠发版已经不够,还得同步修改配置中心、重启服务、刷掉缓存。如果还牵扯到上游依赖的接口协议,那一次切换基本等于一次小型重构。
1.2 litellm 的定位与优势
litellm做的事情就是一个转换层:它对外暴露一个标准的OpenAI兼容接口,同时把所有常见服务商的原生接口翻译成这个标准格式。你只需要按OpenAI的ChatCompletion方式调用,剩下的内容、鉴权、重试、流式协议全部交给litellm处理。
部署完成之后,你的业务代码里再也不会直接出现某个具体服务商的SDK,最多维护一份模型到服务的映射配置。想要切换模型,改配置文件或者重新指定model参数就行,业务代码一行都不用动。
除了接口统一之外,litellm还自带几个对生产环境很重要的能力:
- 预算管理:为每个Key、每个用户、每个团队设置额度上限。
- 限流控制:按请求数或Token数做速率限制,防止单个应用把配额打爆。
- 负载均衡:同一模型配置多个上游Key,自动分配请求,实现故障转移。
- 日志追踪:记录每一次请求的模型、Token消耗、延迟和费用,方便对账。
- 多租户管理:多个团队共享同一代理,各自用完各自的预算。
这些能力不是额外插件,而是代理层本身的一部分,所以接入成本非常低。
1.3 什么时候你不需要它
也必须说清楚:不是所有项目都适合引入这层代理。如果你的应用只调用一家模型服务,并且没有切换模型的可能性,也没有多人共享Key、预算管理、日志审计的需求,那litellm属于过度设计。每多一层就多一个故障点,这个判断要尊重实际情况。
适合用的场景一般至少占一到两条:多模型并存、多人/多应用共享API成本、需要做精细的配额管控、需要对模型调用做审计留痕。如果你的近期规划里还没有这些东西,那先别急着上代理层,把业务跑通更重要。
2. 核心功能拆解:它到底做了什么
2.1 统一API格式与转换机制
litellm的核心是建立在OpenAI的接口规范上的。为什么偏偏选OpenAI格式,而不是另创一套?因为OpenAI的ChatCompletion接口已经被大量开源工具和框架默认支持,各种Agent框架、向量库插件、IDE插件默认就能对接它。litellm顺势而为,把OpenAI接口作为中间格式,兼容成本最小。
它的转换层工作方式可以理解为一张映射表:把目标服务商的请求参数结构,翻译成OpenAI的messages、model、temperature、max_tokens等字段;再把目标服务商的响应结构,翻译成OpenAI统一的choices、message、finish_reason结构。流式场景下,SSE数据格式也会被转换,客户端解析逻辑完全不需要区分背后是哪个模型。
这种设计直接带来了一个好处:你的业务服务里只需要维护OpenAI SDK一种依赖,换模型、换服务商只是改一个model字符串的事。
2.2 预算、限流与权限控制
预算管理是litellm特别好用也最容易被忽视的功能。很多开发团队拿到API Key就开始写代码,月底账单出来才发现某个测试脚本烧了几百美元,这种例子我见过不止一次。
litellm支持在代理层设置多级预算:
- 全局预算:整个网关的总花费上限。
- Key级预算:某个虚拟Key的最大花费,超过后直接拒绝请求并返回429或自定义错误。
- 用户级预算:按用户ID维度管控,适合面向C端的产品。
- 团队级预算:按团队维度分配资源。
限流方面,litellm可以让每个虚拟Key在一分钟、一小时、一天内最多处理多少请求或消耗多少Token。配置很灵活,max_parallel_requests控制并发,tpm_limit和rpm_limit控制每分钟的Token和请求数。
权限控制体现在虚拟Key体系上。你可以为不同的业务线创建不同的Key,并给每个Key绑定允许访问的模型列表。比如A应用只能用基础对话模型,B应用才能用高成本的长文本模型,从源头卡住滥用。
2.3 智能路由与负载均衡
这是litellm在生产环境里真正值钱的部分。当你在同一个模型下配置了多个上游服务商的API Key时,litellm默认会轮询转发,请求被均匀分散到各个Key上。
更进阶的做法是配置routing_strategy。它支持几种策略:
simple-shift:简单轮询。usage-based-routing:基于每个Key当前配额消耗的实时状态路由,尽量让配额充足的Key多承担请求。latency-based-routing:优先选择历史延迟更低的Key。least-busy:选择当前并发请求数最少的Key。
多Key轮询不只是为了提高可用性,还承担了配额管理的职责。假设你订阅了某个服务商的两个档位,一个基础档一个高级档,希望优先耗完基础档的额度,再走高级档,那可以把基础档的Key权重配高一些,或者直接用usage-based-routing让它自适应分配。
另外值得一提的还有故障转移。某个上游Key如果返回401、403或者429,litellm可以自动把这次请求转发到下一个可用Key上,对客户端无感知。这个机制在某个服务商突发故障或者单个Key被限流时特别管用。
2.4 日志记录与可观测性
凡是涉及钱的系统,没有日志就是瞎子。litellm内置了请求日志表,每一条请求都会记录模型名、虚拟Key标识、用户标识、请求时间、延迟、Token用量、预估费用。
它还支持把日志写到传统数据存储里,比如PostgreSQL、MySQL,甚至S3、GCS这类对象存储。你也可以接监控工具,通过Prometheus暴露指标,在Grafana上画看板,实时观察整条链路的调用量和费用走势。
我现在维护的一套系统就是每天凌晨跑一个统计任务,把litellm日志表按团队维度和模型维度做汇总,输出到成本报表里。财务那边再也不用月底看账单猜,每一个模型调用花了多少钱都能追溯到具体应用和具体Key。
3. 从零部署一套代理服务
3.1 环境准备与安装
litellm是个Python项目,安装方式很常规。我建议在部署前先确认机器有没有满足条件的Python版本,我自己用的是Python 3.11,跑起来很稳。然后直接执行安装:
pip install 'litellm[proxy]'这里安装的是带代理服务的版本,和纯SDK版本不同。如果只想用Python库,装litellm本体就够了,但我们现在要搭代理层,所以装[proxy]扩展。
装完之后验证一下版本:
litellm --version这个命令会输出当前版本号,看到版本信息出来就说明装好了。
安装过程依赖的包比较多,如果是国内网络环境,可能需要给pip配置镜像源,否则下载会非常慢。这个不是litellm的问题,是Python生态的老问题。
3.2 准备模型凭证
准备凭证的意思是,在启动代理之前,得让litellm知道你有哪些上游API Key可以用。有两种方式:
第一种是放在环境变量里。litellm对主流服务商都有固定的环境变量命名规则,比如某个服务商的Key对应的环境变量名就非常直观,一般是服务商名加_API_KEY的格式。启动前把Key注入环境变量即可,官方文档可以直接查到每个服务商对应的变量名。
第二种是写在配置文件的model_list里,这种方式更可控,也便于版本化维护。每个模型条目里写明model_name(对外暴露的模型名)和litellm_params(实际调用的模型名和API Key)。
我当前的配置长这样:
model_list: - model_name: gpt-demo litellm_params: model: gpt-xxx api_key: sk-xxx - model_name: claude-demo litellm_params: model: claude-xxx api_key: sk-xxx - model_name: local-model litellm_params: model: openai/本地模型服务地址 api_base: http://localhost:8000/v1配置里model_name是对接业务方时使用的名字,业务代码只认这个名字。litellm_params.model填的是上游真实模型名。api_base用于自建服务或网关,比如本地用vLLM部署的开源模型,就指到对应的服务地址上。
3.3 编写核心配置文件
litellm支持通过命令行参数直接启动,但生产环境建议用一个YAML配置文件把所有配置归拢起来。下面是一个我在测试环境用的基础配置,注释都写得比较清楚:
model_list: - model_name: gpt-demo litellm_params: model: gpt-xxx api_key: sk-xxx litellm_settings: drop_params: true set_verbose: false num_retries: 3 request_timeout: 30 retry_after: 0.5 general_settings: master_key: sk-your-master-key database_url: postgresql://user:pass@localhost:5432/litellm otel: false几个关键参数解释一下:
drop_params:当传入的参数对某个上游模型不支持时,直接丢弃而不是报错。这个开关很实用,因为不同模型对参数的宽容度不一样。num_retries:请求失败后的重试次数。我一般设成3,太多容易把上游接口打得更忙。request_timeout:上游请求超时时间。注意这个值要结合模型实际响应速度来设,不能拍脑袋。master_key:代理服务的总管理Key。所有向litellm发起的请求都要带上这个Key,它是代理层权限体系的根。database_url:可选但强烈推荐。接上数据库之后,预算、配额、日志这些能力才能启用。
如果一开始不想接数据库,也可以本地起一个SQLite来用。先让日志和预算功能跑通,之后再迁移到PostgreSQL。
3.4 启动服务并验证
配置写好后,启动代理服务只需要一条命令:
litellm --config ./config.yaml --port 4000服务起来之后,验证接口是否正常。litellm兼容OpenAI格式,直接用一个请求试一下:
curl http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-your-master-key" \ -d '{ "model": "gpt-demo", "messages": [{"role": "user", "content": "你好"}] }'返回正常的choices结构,就说明代理链路已经通了。在这之后,你的业务代码里所有指向某个上游服务商Base URL的地方,全部换成http://你的服务器地址:4000即可。
3.5 客户端SDK接入
接入方式兼容OpenAI官方SDK,所以代码改动很小。用Python举例:
from openai import OpenAI client = OpenAI( base_url="http://你的服务器地址:4000/v1", api_key="sk-your-master-key" ) resp = client.chat.completions.create( model="gpt-demo", messages=[{"role": "user", "content": "你好"}] ) print(resp.choices[0].message.content)如果你用的是Node.js的官方SDK,配置也差不多,把baseURL指到litellm的地址就行。业务代码的感知只是换了一个端点,其他都不用改。
这里容易踩一个坑:litellm管理端也会占用/路径的路由,你如果直接用浏览器打开http://服务器地址:4000,看到的是管理后台或者健康检查的提示。/v1/chat/completions才是真正的API入口,别搞混。
4. 我踩过的坑与排查实录
4.1 请求一直超时,但不是代理的问题
有一次我部署到一台新机器上,代理服务已经起来了,curl测试时一直报timeout。一开始以为是配置问题,反复修改request_timeout和num_retries都没有效果。
后来检查发现,那台机器所在的安全组没有放行上游服务商的出口IP,代理服务本地的4000端口确实开着,但出站请求被网络策略拦了。这个排查走了不少弯路,因为litellm的日志里只显示上游连接超时,完全没有提示是网络策略导致的。
遇到超时问题,先分三步排查:第一步确认上游服务商接口能不能直接访问通;第二步确认代理容器或进程所在的机器有没有出站限制;第三步再怀疑配置。顺序反了会很浪费时间。
4.2 模型名对不上导致404
litellm里最经典的报错是请求返回404,响应里的错误信息是"model not found"。这个问题的原因几乎永远是业务请求里写的model和你model_list里定义的model_name不一致。
有一次排查某团队的问题,他们代码里写的是gpt-4,但配置文件里暴露的模型名是gpt-demo,两边自己说自己的,代理层自然不认识。这类问题不是litellm的bug,而是定义不统一导致的。
一个习惯是:尽快把模型名配置版本化,并给不同的业务环境用不同的前缀区分。比如prod-gpt-chat和test-gpt-chat,一目了然,从根源上减少沟通误解。
4.3 预算清零后服务异常但不报错
预算功能上线后,某个测试环境的模型突然大量返回空内容,去日志里看又没有任何错误。仔细查才发现,是给这个环境配置的预算已经用完了,litellm默认策略是直接拦截请求,而客户端那边把拦截响应当成了正常响应处理。
这个问题的教训是:代理端的拦截响应和模型正常响应都应该有清晰的状态标志,客户端拿到响应时不能只取content字段就完事,还要检查HTTP状态码。另外,测试环境的预算不要设得太死,不然你根本分不清是模型坏了还是配额用完了。
4.4 并发高时出现排队和雪崩
有段时间某个模型服务的响应延迟突然变得很高,litellm日志里看到大量请求排队的迹象。后来发现是上游某个Key的并发限制很低,而我配置的max_parallel_requests没有针对这个Key设置,导致请求全部拥堵在一起。
litellm有专门的超时和并发保护参数。当你给某个上游Key配置了rpm_limit或tpm_limit,同时设置了max_parallel_requests之后,超出并发限制的请求会进入等待队列,而不是直接打给上游。这个机制保护了上游服务,也让客户端不至于被瞬时熔断。
但反过来也说明,并发配置一定要基于上游服务商的实际限制来定,不要拍脑袋。最好先在测试环境压一轮,把真实的极限摸出来,再加一点余量作为兜底。
5. 生产环境落地建议
5.1 单机部署还是集群部署
很多团队一开始都是单机部署litellm,因为它的性能开销很小,一个2核4G的小实例就能支撑几百个并发请求的转发和转换。如果只是给团队内几十个人做接入,单机完全够用。
但一旦服务于线上业务,单机就成了单点。litellm本身是无状态的,所有状态都放在PostgreSQL或者Redis里,所以部署多个实例做负载均衡非常容易。我推荐的生产形态是:前置一个负载均衡器,后面挂两个或三个litellm实例,共享同一个数据库。这样可以做到一个实例挂了,另一个自动接管请求。
还有一个要注意的点:litellm的并发和性能还取决于上游模型的响应时间。模型响应长,连接被占用的时间就长,同样内存下可承载的并发请求数就少。这个和请求量是两回事,评估容量时不要只看QPS。
5.2 密钥管理与安全
litellm的master_key是最高权限凭证,谁拿到它谁就能创建新的虚拟Key、修改预算配置。一旦泄露,等于整个模型网关的钥匙交了出去。
我的做法是:
- 不在代码仓库里保存
master_key,而是通过环境变量注入。 - 每个业务线使用独立的虚拟Key,不要共用主Key。
- 定期轮换虚拟Key,并把不再使用的Key删除。
- 开启数据库审计功能,留痕每一次Key创建和修改操作。
如果部署在云环境,还可以配合云厂商的密钥管理服务,把主Key放到加密存储里,应用服务启动时再从那里读取,而不是写死在配置文件。
5.3 成本治理与多团队协作
litellm在多团队协作模式下的价值十分突出。每个团队一个虚拟Key,每个Key绑定自己的模型白名单和预算上限。这样一来,成本责任直接落到使用方,你再不用去追着问“这个月为什么花了这么多”。
我自己的团队里还固定了一个成本巡检的节奏:每周看一次按Key和模型维度的汇总,发现异常增长的条目就顺着日志追下去,看看是哪个应用、哪个用户在调用。很多失控的花费其实并不是恶意滥用,而是某个测试脚本忘了关定时任务。有了日志,五分钟就能定位到问题。
如果要接企业内部的统一认证体系,litellm也支持对接自定义鉴权,可以在请求到达代理层之前做一次用户身份校验。这部分的配置稍微复杂一些,但值得花时间做,尤其当你面向多个外部业务方开放模型能力的时候。
5.4 扩展玩法:从代理到内部模型平台
litellm用熟了之后,你会发现自己不知不觉在做一件比“接口代理”更大的事:你在搭一个内部模型接入平台。
比如说,你可以在代理层统一记录每次请求的反馈数据,沉淀成一份内部模型评估集。哪个模型在某个业务上面表现好,不再靠主观感受,而是看真实调用的延迟、Token成本和用户反馈。再比如说,你可以把不同模型的测试通道统一暴露给产品同学,让他们自己对比效果,而不是每次都要找你改代码。
这个方向听起来有点远,但它确实是litellm这类统一网关最终会带你去的地方。基础设施准备好了,上层能力的叠加就是水到渠成的事。
根据我个人的经验,litellm最让人舒服的一点是:它没有把一个复杂问题变得更复杂,而是用一个几乎无感的转换层,把后续所有模型的接入、切换、治理问题都收拢到了统一出口。你只需要花一下午把基础配置跑通,接下来就能看着它稳定地替你挡掉一大批鸡毛蒜皮的杂事。如果你正被多模型集成、Key管理、成本对账这些事折磨,花点时间认真把litellm搭起来,不亏。