如果你手上的项目已经过了“拿一个模型写个Demo”的阶段,开始同时对接多个大模型API,或者要给团队十几个人统一发放模型访问权限,那么LiteLLM真的应该进入你的技术选型清单——这是我实际用了一段时间之后的直接结论。
LiteLLM本质上是一个开源的LLM网关,它做的事情可以用一句话说清楚:把市面上主流的大模型API统一成一套OpenAI兼容的接口,你只需要学会一种调用方式,就能在OpenAI、Anthropic、Azure、本地Ollama这些后端之间自由切换,甚至可以让网关自动完成负载均衡、故障回退、成本统计和密钥管理。它适合两类人:一类是自己业务里要接多个模型的开发者,另一类是需要在团队里统一管理模型接入和成本的同学。
有些朋友可能会说,多接几个模型而已,每个厂商写一段SDK代码不就行了?如果你只是在本地脚本里试一次,确实可以。但一旦进入生产环境,你会发现事情远没有那么简单。这篇文章我会从为什么需要它讲起,带你快速跑通SDK和代理服务,然后把配置、成本、部署和踩坑这些关键点逐一拆开讲清楚。
1. 为什么需要LiteLLM:模型接入的最后一公里问题
1.1 多模型接入的现状:每家一个SDK的麻烦
先还原一个非常真实的场景。假设你们公司的AI功能一开始用的是OpenAI的GPT系列,代码写得很舒服:
from openai import OpenAI client = OpenAI() resp = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "写一段SQL"}] ) print(resp.choices[0].message.content)三个月后,业务方说Claude在代码生成上更稳,想切换过去。这时候你打开Anthropic的文档,发现它的Python SDK是这种风格:
import anthropic client = anthropic.Anthropic() resp = client.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=1024, messages=[{"role": "user", "content": "写一段SQL"}] ) print(resp.content[0].text)看似差不多,但参数名、返回结构、流式处理方式都不一样。如果再接上Azure OpenAI、AWS Bedrock、Gemini,每个厂商都有自己的鉴权方式和请求格式。业务代码里就会长出大量类似if provider == "anthropic"这样的分支。这还只是单个服务内部的情况。
更头疼的是团队协作层面。每个人手上都捏着不同平台的API Key,有人开通了GPT Plus直接拿网页版复制粘贴,有人自己注册了Claude的Key。调用的人越多,Key暴露在代码里、配置里、聊天记录里的概率就越大。月底对账的时候,你会发现根本说不清这个月的大模型费用到底花在了哪里——是测试环境跑掉的,还是某个同事调用的,还是线上请求量涨了。这就是模型接入的“最后一公里”问题:模型本身的能力差异可以先放一边,光接入和管理这一层,就够消耗大量精力。
1.2 LiteLLM的定位:一个OpenAI兼容的通用网关
LiteLLM解决的就是这个问题。它的定位可以用一张图来描述:客户端只面对一个固定的OpenAI兼容接口,LiteLLM在中间做协议转换、路由分发和统一管理。你可以把它理解成一个“插座转换头”,前面是统一的插孔,后面插什么电器它都负责适配。
原始项目里支持的模型范围非常广,常见的厂商API、云平台托管模型、本地开源的模型(比如Ollama跑起来的Llama系列)都能被纳进来。这个“统一格式”不是LiteLLM自己发明的,而是直接对齐OpenAI的接口规范。这意味着你在现有代码里只要用过OpenAI的SDK,迁移到LiteLLM几乎不需要学习成本——把OpenAI(base_url=...)指向LiteLLM的地址就行。
我自己最大的体感是,LiteLLM把“模型”和“路由策略”解耦了。举例来说,我在配置里可以同时定义三份GPT-4o的接入配置,一份走OpenAI官方,一份走Azure的部署,还有一份走某个第三方中转。对业务方来说,它们看到的都是同一个模型名,请求由LiteLLM决定到底打到哪一份配置上去。任何一份配置挂了,流量自动切换到其他配置,业务代码一行都不用改。
1.3 代理模式的关键优势:先有网关,后有治理
LiteLLM有两种用法:一个是当Python库用,直接在你自己的服务进程里调用;另一个是启动一个独立的代理服务(Proxy Server),对所有客户端暴露HTTP接口。第二种才是LiteLLM的核心价值所在。
代理模式一旦跑起来,你就有了一个全局的流量入口。所有请求都经过这个入口,所以你可以在这里做很多治理类的事情:给每个人发独立的虚拟Key、给每个Key设置预算上限、按模型维度统计调用量、在入口做失败重试和降级。这些能力如果自己从零开发,工作量不亚于做一个内部网关平台。但用LiteLLM,这些都是开箱即有的功能。
我建议你带着一个问题读下面的内容:你的业务到底是不在乎接入方式的个人项目,还是需要管控与治理的团队项目?如果是后者,代理模式基本是你的唯一选项。
2. 五分钟跑通:Python SDK与代理服务两种上手路径
2.1 安装与环境准备
LiteLLM是一个Python包,安装非常简单。我建议直接把代理相关的扩展一起装上,避免后面要用的时候再补:
pip install "litellm[proxy]"装完之后,在Python里验证一下:
import litellm print(litellm.__version__)如果你只是想在脚本里快速试一下多模型调用,到这一步就够了。但如果你要启动代理服务,还需要准备好一个主密钥(Master Key),这是LiteLLM自己用来管理代理端的凭证。先通过环境变量设置:
export LITELLM_MASTER_KEY="sk-your-master-key"主密钥很像你家里的门禁总卡,它可以创建其他子卡,也能拒绝某些区域的进入权限。代理端的管理接口(比如创建虚拟密钥、查看预算)都需要用它来鉴权。
2.2 用Python SDK直接调用多模型
先看最简单的方式——把LiteLLM当成一个增强版的SDK来用:
import litellm response = litellm.completion( model="gpt-4o", messages=[ {"role": "user", "content": "用一句话解释什么是网关"} ], temperature=0.7 ) print(response.choices[0].message.content)这段代码和OpenAI的写法几乎一致。关键区别在于model参数可以换成任意LiteLLM支持的模型标识,比如:
# 调用Claude resp = litellm.completion( model="anthropic/claude-3-5-sonnet-20241022", messages=[{"role": "user", "content": "你好"}], max_tokens=512 ) # 调用本地Ollama上的模型 resp = litellm.completion( model="ollama/llama3", messages=[{"role": "user", "content": "你好"}] )注意这里的模型名是有规律的:厂商前缀/具体模型名。LiteLLM根据前缀去匹配正确的SDK和鉴权方式。它没有很玄学的东西,就是把每个厂商的SDK封装了一层,统一返回OpenAI风格的响应结构。
异步场景用acompletion就好:
import asyncio import litellm async def main(): resp = await litellm.acompletion( model="openai/gpt-4o", messages=[{"role": "user", "content": "讲个程序员冷笑话"}] ) print(resp.choices[0].message.content) asyncio.run(main())这种直接用SDK的方式,适合在独立服务里做快速切换。它的优点是轻量,缺点是没有权限、预算、审计这些治理能力。
2.3 起一个OpenAI兼容的代理服务
代理模式的上手路径也很短。一条命令就能起一个HTTP服务:
litellm --model gpt-4o --port 8000启动之后,它会监听8000端口,并暴露一个OpenAI兼容的/v1接口。这时候你的业务代码几乎不用改,只需要修改客户端配置:
from openai import OpenAI client = OpenAI( base_url="http://localhost:8000/v1", api_key="sk-anything" ) resp = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "你好"}] ) print(resp.choices[0].message.content)api_key传什么都能过,因为本地代理默认不做Key校验。但一旦你要在服务里启用虚拟Key管理,这里就必须传LiteLLM生成的Key了。
你可以先验证一下代理的健康状态:
curl http://localhost:8000/v1/models返回的JSON里会列出当前代理能提供的模型列表。如果看到你配置的模型,说明代理已经正常连上了后端。
2.4 两种使用方式怎么选
直接SDK适合的场景:个人脚本、单一服务、不在乎治理、不想多维护一个服务。代理模式适合的场景:团队共享、多模型切换、成本控制、权限管理、统一审计。
我自己的经验是,如果一个项目只是我自己在折腾,直接SDK很爽;一旦有第二个人要用,或者要接多个环境,就立刻转代理。这就像家里装个总电闸,平时感受不到它的存在,但出问题或者要分线路的时候,你就知道它有多重要了。
3. 把网关配起来:config.yaml核心配置拆解
3.1 从命令行到配置文件
用命令行启动虽然简单,但模型一多就不够看了。LiteLLM支持通过一个config.yaml文件声明所有模型、路由、回调、预算等配置,启动时指定这个文件即可:
litellm --config config.yaml --port 8000建议一开始就把配置写成文件,因为config.yaml本身就是一个很好的配置存档,也能放进Git里做版本管理。团队里谁来改配置、改了什么都一目了然。
3.2 模型列表与参数映射
config.yaml里最重要的部分是model_list。它声明了这个代理对外提供哪些模型名,以及每个模型名实际打到哪家后端。
一个最简配置是这样的:
model_list: - model_name: my-gpt litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: my-claude litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: os.environ/ANTHROPIC_API_KEY这里有两个概念要区分:model_name是对外暴露的名字,客户端请求时必须传这个名字;litellm_params.model是LiteLLM真正调用的后端模型标识,必须带厂商前缀。
环境变量通过os.environ/变量名语法引用,好处是密钥不会直接写进配置文件。比如上面配置了os.environ/OPENAI_API_KEY,启动代理之前你要保证环境里确实存在这个变量。我踩过的一个坑就是:配置写好了,但启动代理的那个终端会话里忘了导出环境变量,结果所有请求都在鉴权阶段失败。
3.3 多实例配置与负载均衡
LiteLLM最有价值的特性之一,是同一个model_name可以映射到多个后端配置。比如我想让GPT-4o的流量分散到OpenAI官方和Azure两个渠道:
model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY model_info: mode: completion - model_name: gpt-4o litellm_params: model: azure/gpt-4o api_key: os.environ/AZURE_API_KEY api_base: https://your-resource-name.openai.azure.com model_info: mode: completion客户端始终请求gpt-4o,但LiteLLM会在两个后端之间做负载均衡。默认的路由策略是简单的随机轮询,如果你希望更智能一点,可以配置具体的路由策略。
LiteLLM支持多种路由策略,包括:
- 随机轮询:简单均匀地把请求分配下去。
- 最少连接数:优先把请求发给当前活跃请求数最少的后端。
- 基于成本/延迟的优先路由:根据后端的历史表现动态选择。
在config.yaml里通过router_settings配置:
router_settings: routing_strategy: "least-busy"我的建议是:如果几个后端能力完全一样,用随机轮询就够;如果各后端的响应速度和成本差异明显,再考虑基于延迟和成本的路由。路由策略越复杂,调优和排查的成本也越高,很多团队其实并不需要。
3.4 失败重试与模型回退
生产环境里,模型供应商服务不可用是常态。LiteLLM有两个层面的容错手段:重试和回退。
重试是同一个请求自动再发一次。通过环境变量或配置设置重试次数:
litellm_settings: num_retries: 3 request_timeout: 30注意重试要配合超时时间使用。默认超时在某些场景下偏短,如果你调用的模型生成Token比较多,建议把request_timeout调大一些。
回退是当主模型失败时,自动用另一个模型顶上。可以在代码里指定:
resp = litellm.completion( model="gpt-4o", messages=[{"role": "user", "content": "你好"}], fallbacks=[ {"gpt-4o": ["my-claude"]} ] )也可以在config.yaml里配置:
litellm_settings: fallbacks: [ {"gpt-4o": ["my-claude"]} ]我的经验是,回退策略一定要在测试环境里完整演练一遍,尤其是确认回退模型的输出格式和主模型是兼容的。如果主模型返回JSON,回退模型却返回了纯文本,你的下游解析逻辑一样会报错。
4. 成本不失控:预算、计量与监控
4.1 成本追踪的基本原理
大模型API的成本跟请求量和Token数直接挂钩。LiteLLM在代理层记录了每一次请求的输入Token、输出Token,再对照模型的价格表计算出本次调用的费用。这个价格表内置了主流模型的价格,基本不用自己维护。
成本数据默认保存在内存里,代理一重启数据就没了。要长期统计,必须配置数据库。SQLite适合本地测试,生产环境建议用PostgreSQL:
export DATABASE_URL="postgresql://user:password@host:5432/litellm"配置好之后,每次请求的成本、模型、Key、用户等信息都会写入数据库。这样月底对账就不再是拍脑袋,而是直接查表说话。
4.2 虚拟密钥与预算上限
虚拟密钥是LiteLLM代理模式里非常实用的一个功能。你可以为主密钥旗下的每个人、每个项目生成独立的Key,并限制这个Key能访问哪些模型、最多花多少钱。
生成一个预算为5美元、只能访问gpt-4o的Key:
curl -X POST http://localhost:8000/key/generate \ -H "Authorization: Bearer sk-your-master-key" \ -H "Content-Type: application/json" \ -d '{ "models": ["gpt-4o"], "max_budget": 5 }'返回结果里会有一个sk-ant-...格式的Key,把这个Key发给对应的开发者即可。他们调用代理时用这个Key:
client = OpenAI( base_url="http://localhost:8000/v1", api_key="sk-ant-xxxx" )当这个Key的累计成本达到5美元,LiteLLM会直接拒绝后续请求。这种机制特别适合控制测试环境的成本,也可以给外部合作方开一个限时限量的试用Key。
我个人的习惯是:宁可多创建几个Key,也不要复用。Key的最小粒度至少要到“人+环境+项目”,比如张三-测试环境-AI问答。真出了问题,可以单独吊销一个Key,而不会影响其他业务。
4.3 监控与回调
除了在数据库里存成本数据,LiteLLM还支持把调用成功、失败的事件推送到第三方监控平台。通过success_callback和failure_callback配置:
litellm_settings: success_callback: ["langfuse"] failure_callback: ["langfuse"]这样每次请求的输入输出、延迟、成本、模型等关键信息会被记录到Langfuse这类平台里。你在Langfuse上能看到每次请求用了哪个模型、花了多少钱、耗时多少,分析问题会直观很多。
监控一定要趁早接。等到线上出了事故才想起加日志,你会发现自己根本追溯不到当时发生了什么。我自己吃过这个亏:某个模型供应商变更了响应格式,线上报错持续了十几分钟才被业务方发现,如果当时有完整的请求日志,定位问题会快得多。
5. 生产环境部署与集成
5.1 用Docker部署代理服务
LiteLLM官方提供了Docker镜像,生产环境建议直接用容器方式部署。我常用的Docker启动方式:
docker run -d --name litellm-proxy \ -p 8000:8000 \ -e LITELLM_MASTER_KEY="sk-your-master-key" \ -e DATABASE_URL="postgresql://user:password@host:5432/litellm" \ -v $(pwd)/config.yaml:/app/config.yaml \ ghcr.io/berriai/litellm:main-latest \ --config /app/config.yaml这里有几个细节要注意。镜像版本建议锁定一个具体版本号,不要长期使用main-latest,否则哪天镜像更新了配置格式不兼容,你半夜被报警叫醒会很被动。config.yaml以卷的方式挂载进容器,本地改完配置后重启容器即可生效。
5.2 多实例部署与共享状态
代理服务的性能瓶颈通常不在LiteLLM本身,而在后端模型的速率限制。单实例的LiteLLM一般能扛住大多数中小团队的请求量。但如果你的流量确实很大,要多实例部署,那么必须保证所有实例共享同一个数据库和Redis。
多实例模式下有几个配置要点:
- 所有实例使用同一个
DATABASE_URL,这样Key、预算、成本数据是一致的。 - 使用同一个Redis实例,用于分布式限流和缓存,避免两个实例各自计费导致预算超了还在继续放行。
- 前面的负载均衡器做HTTP层转发,可以加一层Nginx或者云厂商的LB。
跨实例的成本统计如果没做好,预算控制就会失效。比如你在实例A上给某个Key设了5美元上限,但实例B不知道这个Key已经花完了,请求照样被放行。所以多实例部署的第一原则就是:数据库和缓存必须共享。
5.3 与现有AI应用集成
LiteLLM代理服务的接口是OpenAI兼容的,这意味着凡是支持自定义base_url的AI应用和框架,都能直接接入。我在实际项目中集成过的场景有这么几类:
- Python服务:改一下OpenAI SDK的
base_url即可。 - LangChain:设置环境变量
OPENAI_API_BASE指向代理地址。 - Node.js应用:使用openai npm包,同样指定baseURL。
- 内部小工具:直接curl代理的
/v1/chat/completions接口。
有一个集成时的注意事项:不要在下游代码里写死后端模型名,而是使用代理配置里的model_name。比如我们把某个场景的模型从GPT切到Claude时,只需要改config.yaml里my-gpt的后端映射,业务代码不需要知道后端已经换了。这才是网关层真正的解耦价值。
5.4 提示词管理与模型参数透传
代理还可以配置和管理提示词模板。通过/prompt/create这种管理接口,可以预先创建一批常用Prompt,后续请求直接引用。这在团队内部做提示词版本管理时非常方便,可以避免每个人在自己的代码里维护一份Prompt字符串。
需要强调的是,LiteLLM并不会把所有OpenAI的参数都拦截,像temperature、max_tokens、stream这些参数会透传给后端模型。如果你的后端模型不支持某个参数,LiteLLM会在日志里给出警告。比如Claude对max_tokens的处理和OpenAI就存在差异,配置时我建议先打开一次流式请求和一次非流式请求,确认透传参数在后端模型上的行为符合预期。
6. 踩坑记录与排查清单
6.1 常见HTTP错误速查
用LiteLLM的过程中,我积累了一个有用的排查表格。当你遇到问题,先看状态码,再按下面的清单定位:
| 状态码 | 常见原因 | 排查思路 |
|---|---|---|
| 401 Unauthorized | 虚拟Key无效、主密钥错误、后端API Key未正确加载 | 检查请求头里的Authorization,对比环境变量是否生效 |
| 404 Model Not Found | 请求的model_name没有在config.yaml的model_list里注册 | 核对model_name拼写,确认代理重启后加载了新配置 |
| 429 Too Many Requests | 触发了速率限制、预算超限或并发过高 | 查看数据库里的预算用量,确认是否达到max_budget |
| 500 Internal Error | 后端模型服务异常、配置错误、超时导致异常 | 看代理日志中的完整错误栈,确认是上游还是配置问题 |
| 503 Service Unavailable | 所有后端模型都不可用,或健康检查失败 | 检查各后端配置的API服务状态,确认回退是否生效 |
6.2 模型名和前缀的坑
LiteLLM的模型名带厂商前缀,这个规则看似简单,但出错率极高。比如OpenAI的模型写openai/gpt-4o,Azure的模型写azure/gpt-4o,Bedrock上的模型要写bedrock/anthropic.claude-3-5-sonnet-v2:0。我见过最典型的错误是把openai/前缀漏掉了,导致LiteLLM用默认的解析逻辑去猜厂商,结果请求被发到了错误的Endpoint。
排查这个问题的快速方法:直接看代理日志,启动时LiteLLM会打印当前加载的模型列表,你核对一下日志里的模型标识和你配置里写的是否一致。
6.3 流式请求与超时处理
流式响应在代理模式下同样支持,客户端直接传stream=True即可。但这里有一个隐藏问题:流式响应的超时逻辑跟非流式不一样。如果模型服务端长时间没有推送新的Token,连接可能会被中间的负载均衡器或LiteLLM掐断。
我的建议是:
- 给流式请求设置合理的
timeout参数,不建议太长。 - 在后端模型API侧,尽量开启流式输出,让首个Token尽快返回。
- 如果流式请求经常中断,优先检查网络链路,而不是怀疑LiteLLM本身。
6.4 一些实战心得
最后分享几条我在实际使用中积累的心得,谈不上多高深,但确实帮我避开了不少问题。
第一,配置文件的改动一定要通过Git管理。LiteLLM的config.yaml就是网关的全部逻辑,如果谁都能手工改服务器上的配置,出了问题你连回溯都没法回溯。让配置文件走代码评审流程,成本很低,收益很大。
第二,虚拟Key的命名和管理要规范。我建议在创建Key时把用途写在备注里,或者通过Key命名区分环境。否则几个月后你面对几十个Key,根本分不清哪个是哪个,只能全部吊销重新发。
第三,测试环境的模型回退要提前演练。我见过不止一次线上回退把请求打到一个根本不存在的模型名上,结果主模型挂了之后回退也挂了,所有请求直接失败。这个场景最好在测试环境里完整演练一次再上生产。
第四,成本数据要定期核对。LiteLLM内置的价格表虽然覆盖面很广,但新模型上线初期价格表可能没来得及更新。另外如果后端API返回的usage字段异常,成本统计就可能失真。我一般每个月抽一天,拿账单和数据库里的成本统计对一遍,基本能发现有没有模型价格没同步。
至于LiteLLM后续怎么扩展,我的体会是:先别急着把所有功能都打开,稳住“代理+虚拟Key+预算”这一套核心链路,跑通之后再逐步加监控、提示词管理、多实例。网关这种东西,越到后面越能体现出“先建规范、后有流量”的价值。等团队规模大了,你会发现它替你挡掉的很多麻烦,远比当初部署它花掉的时间值得。