1. 先从“换模型像搬家”说起为什么我围着一层网关转前阵子接了一个内部AI小项目需求本身不复杂让业务方用一个接口同时能用上几款不同的大模型还要能自动容灾、记录花费。一开始想着很简单各家模型商不都提供了Python SDK吗挨个对接就是了。真正动手才发现问题根本不在于“会不会用SDK”而在于“每次想换或者加一个模型都要动代码”。今天写的那套请求体是messages数组、max_tokens这种字段明天换一家字段变成了system独立传递、超额参数必须删除。你以为只是字段名差异实际上各家对角色定义、上下文长度计算、流式返回格式、错误码语义都有自己的理解。等你终于把三家的逻辑都用if-else串起来产品又说要加本地模型你看着满屏分支心态直接崩掉。LiteLLM解决的就是这个“接口碎片化”问题。它本身是一个开源的大模型网关对外暴露一套OpenAI兼容的API格式对内通过配置把请求转发给不同的模型供应商或者本地的Ollama、vLLM等推理服务。说白了它把“换模型要改代码”这件事变成了“改一行配置文件”。这篇文章我会把LiteLLM从原理到实际配置完整过一遍内容包括它的请求转发链路、最小可用的代理搭建、多模型路由与降级、预算和并发控制、以及我实际使用中踩到的一些边界问题。适合正在做AI应用、需要对接多家模型的开发者参考尤其是那种“模型随时可能被替换/增加”的团队。2. 核心原理拆解一次请求从入站到出站的完整路径2.1 为什么要把OpenAI格式当成“通用语”LiteLLM最值得称道的设计是它把OpenAI的Chat Completions接口当成了“通用语言”。客户端发过来的请求、以及代理返回的响应通通都是这种格式。而真正发送给各家模型商的请求由代理内部完成“翻译”。你可能会问为什么偏偏选OpenAI格式因为目前市面上大多数模型供应商要么原生兼容OpenAI格式要么提供了兼容层。你的代码如果本来就用OpenAI SDK写的换模型时只需要改base_url指向LiteLLM代理剩下的几乎不用动。这就是LiteLLM能做到“改配置即可切换供应商”的基础。从使用者的感受来看LiteLLM很像一个数据库中间件业务侧不需要关心背后是MySQL还是PostgreSQL统一走SQL中间件负责方言转换、连接管理、读写分离。你的应用不需要关心背后是GPT类模型还是Claude类模型还是本地模型统一走/v1/chat/completionsLiteLLM负责供应商适配、转发、重试和降级。2.2 一次请求从进入代理到返回客户端的完整过程我自己在排查问题的时候习惯把一次请求拆成六个环节去理解客户端构造一个标准的OpenAI请求体POST到LiteLLM的/v1/chat/completions带着业务模型名比如chat-smart。LiteLLM根据路由配置选出本轮请求要转发到哪个真实模型比如“chat-smart”这个逻辑名背后可能绑定了三个真实供应商。代理把OpenAI格式的参数转换成目标模型真正的API格式。转换过程中可能发生参数裁剪后面会专门讲。代理把真实请求发到目标模型API等待响应。目标模型的响应被转回OpenAI格式返回给客户端。流式场景下则保持SSE流式转发。代理记录本次调用的模型、tokens、耗时和费用写入日志或监控后端。理解这条链路很重要因为后面所有配置——路由策略、重试、fallback、限流——都是在这条链路的某个环节上做文章。比如重试发生在第4步fallback发生在第3步之后发现上游报错时预算检查发生在第2步决定模型之前。知道这些之后你不会再把LiteLLM想成一个简单的“请求转发器”。它是一个有状态、有策略、有观测能力的中间层。下面我直接进入实操先把最小代理跑起来再逐步叠加复杂能力。3. 三分钟跑通一个本地代理最小可用配置实操3.1 安装与环境检查LiteLLM本质上是Python包安装前建议确认Python版本在3.8以上。我自己一直用3.10没遇到兼容问题。安装命令如下pip install litellm[proxy]注意这里装了proxy额外依赖因为纯LiteLLM库只是SDK真正要跑代理服务必须安装这个扩展。如果你是在国内网络环境建议顺手把pip源切到镜像源否则安装过程可能比较慢。装完后验证一下litellm --version正常会打印出版本号。到这里环境就绪不需要额外启动数据库一个最小的代理可以直接跑在内存配置上。3.2 写一个最小config文件并启动LiteLLM代理的入口是config.yaml。这个文件核心内容就两部分model_list定义哪些逻辑模型可用、对应转发到哪里litellm_settings定义一些全局行为。我先写一个最简单的配置model_list: - model_name: chat-smart litellm_params: model: openai/gpt-4o api_key: os.environ[OPENAI_API_KEY]配置里的model_name是对外暴露的名字客户端请求时用的是它litellm_params下的model是真实转发目标必须带供应商前缀比如openai/gpt-4o、anthropic/claude-3-5-sonnet、ollama/llama3.1:8b。不带前缀的话LiteLLM会默认当成OpenAI系的模型去处理这是一个非常容易踩的坑。启动命令也简单litellm --config config.yaml --port 4000看到类似Uvicorn running on http://localhost:4000的日志就算启动成功。建议第一次跑的时候加上--detailed_debug这样能看到完整的请求日志方便确认转发链路。3.3 用curl和OpenAI客户端分别验证最小代理起来后先用curl直接打一发请求确认链路通不通curl http://localhost:4000/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-any-key \ -d { model: chat-smart, messages: [{role: user, content: 用一句话介绍你自己}], temperature: 0.7 }注意默认情况下LiteLLM代理并不校验API Key请求头里的Authorization随便填一个值就行。如果你在它前面套了Nginx之类的入口真实鉴权可以放在那一层做如果想让LiteLLM自己管理虚拟Key后面第5章会讲。再用OpenAI SDK验证一下兼容性。这段代码基本就是官方OpenAI SDK的原样用法唯一区别是改了base_urlfrom openai import OpenAI client OpenAI( base_urlhttp://localhost:4000/v1, api_keysk-any-key ) resp client.chat.completions.create( modelchat-smart, messages[{role: user, content: 你好请介绍一下LiteLLM}], temperature0.7 ) print(resp.choices[0].message.content)如果你在跑这段代码前一直在折腾各家原生SDK此时应该能感受到那种“终于不用再学第七套SDK”的轻松感。到这里最小闭环已经打通。接下来我们在这个基础上做多供应商混跑。4. 多供应商路由的真正玩法优先级、负载与自动降级4.1 用config统一管理多家模型单模型接入只是开胃菜。LiteLLM真正的优势在于多个真实模型可以共享同一个逻辑名。我曾经在同一个chat-smart名下绑定了三个不同来源的模型某闭源大模型、另一家的旗舰模型、本地部署的开源模型。配置大概长这样model_list: - model_name: chat-smart litellm_params: model: openai/gpt-4o api_key: os.environ[MODEL_A_KEY] priority: 1 - model_name: chat-smart litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: os.environ[MODEL_B_KEY] priority: 2 - model_name: chat-smart litellm_params: model: ollama/llama3.1:8b api_base: http://localhost:11434 priority: 3 - model_name: chat-fast litellm_params: model: openai/gpt-4o-mini api_key: os.environ[MODEL_A_KEY]这里有两个关键点。第一同一个model_name可以出现多次LiteLLM会把它们视为同一逻辑模型下的多个候选。客户端始终只请求chat-smart至于具体打到哪个真实模型完全由路由策略决定。第二priority字段是我自己惯用的写法。优先级数字越小代表越优先。正常情况下流量会优先打给gpt-4o如果它报错或超时才会自动降级到Claude最后才是本地Ollama。这套机制让“核心模型不可用”不再等于“整个功能不可用”。4.2 路由策略从随机分配到用量感知LiteLLM的路由策略不仅限于简单优先级。官方内置了好几种策略我实际用过的三个策略名行为特点适合场景默认简单轮询在候选模型间均匀分发多个等价位模型承担流量优先级排序尽量打给优先级最高的模型主备模型场景用量感知路由根据历史消耗和剩余配额动态分配多模型预算紧张、需要省钱时配置方式是在router_settings下面指定routing_strategyrouter_settings: routing_strategy: usage-based-routing-v2我实际对比过默认策略在“两个模型价格相同”时很省心流量分配得很均匀。但一旦涉及预算控制建议换成用量感知的策略它会在每次请求前估算剩余配额把流量往更宽裕的模型上导。仅凭这一条我就避免了好几次“月初就跑光预算”的尴尬。无论选哪种策略有一点注意路由粒度按请求维度不按会话维度。也就是说同一个用户的同一段会话不同请求可能打到不同模型上。如果你的产品强依赖“同一个会话始终由同一个模型回答”需要在应用层额外记录会话与模型的绑定关系或者干脆给关键场景单独分配一个逻辑模型名。4.3 重试、超时与fallback把故障处理交给配置我早期犯过一个错误只配了路由没配兜底。结果某天主模型供应商限流代理直接抛错给客户端业务方还以为我把服务搞挂了。后来我把重试和fallback补上情况立刻好转。retry相关配置写在litellm_settings下litellm_settings: num_retries: 3 request_timeout: 60num_retries控制单个模型失败后的重试次数request_timeout是单次请求超时时间。如果重试后依然失败就会触发fallback逻辑。模型级的fallback配置写在具体模型的litellm_params里面- model_name: chat-smart litellm_params: model: openai/gpt-4o api_key: os.environ[MODEL_A_KEY] fallbacks: [anthropic/claude-3-5-sonnet-20241022]这个配置的含义是如果gpt-4o连续重试后仍失败就把本次请求转发给Claude模型。注意fallback列表里可以写多个LiteLLM会按顺序逐个尝试直到有一个成功。这里有个经验fallback别把本地Ollama放在前面因为它响应速度通常比商业API慢一旦商业API抖动流量全压到本地延迟会让你怀疑人生。兜底模型应该选“质量略低但可用性最高”的那个。另外重试次数不是越高越好高并发下会把请求积压在代理层反而拖垮整个服务。我一个生产环境通常设2到3次超时设为30到60秒能覆盖绝大多数瞬时故障。5. 预算、并发与可观测性让网关替你管账5.1 给Key和模型设置消费上限对多模型团队来说控制成本往往比功能开发更让人头大。LiteLLM提供了几个层面的预算能力我用得最多的是模型级预算和Key级预算。模型级预算保护的是“某个模型每月最多花多少钱”model_list: - model_name: chat-smart litellm_params: model: openai/gpt-4o api_key: os.environ[MODEL_A_KEY] model_max_budget: 200当这个模型累计花费超过200美元LiteLLM会拒绝后续请求并使用fallback。这一条我在生产环境开过作用非常直接。Key级预算更细。你在代理启动后调用它的Key管理接口生成一个虚拟Key并为这个Key指定消费上限curl http://localhost:4000/key/generate \ -H Content-Type: application/json \ -d { max_budget: 50, models: [chat-smart] }返回结果里会有一个key字段把它分给具体业务方他们用这个Key请求时消费就会单独记账花完50美元自动失效。这样每个项目的成本分摊就变得非常干净月底直接看面板就能出对账数据。5.2 并发控制与限流预算控住之后第二个容易出问题的是并发。曾经有一天某个业务方的定时任务突然把并发请求拉满直接把上游限流触发了一轮fallback风暴最终表现是接口大面积变慢。那次之后给代理加了并发限制litellm_settings: max_parallel_requests: 50这个值控制在同一时间点允许进入转发层的请求总数。超出的请求不是丢弃而是排队等待。这个数并不是越大越好需要结合上游模型供应商的速率限制和自身服务能力来调。我目前的经验是先设一个保守值压测时逐步上调观察P99延迟的变化找到拐点后往回退一点。另外提一句LiteLLM的并发控制是进程内的。如果你用Docker至少起了三四个副本每个副本各管各的配额全局并发数其实是“单副本限制 × 副本数”。要做到严格的全局限流需要配合外部的Redis等状态存储配置复杂不少。中小规模项目如果单副本够用其实不必急着上多副本。5.3 定位问题先打开Debug日志很多入门的开发者遇到问题习惯去看客户端报错但LiteLLM的问题往往发生在代理内部。排查的第一件事就是打开详细日志litellm --config config.yaml --port 4000 --detailed_debug开了之后控制台会打印每个请求的内部流转信息从哪个路由策略选出的模型、实际转发到哪个供应商、上游返回的原始错误是什么。有一回我遇到一个问题部分请求很快返回部分请求卡满60秒超时。客户端看都一个样只有打开Debug日志才发现超时的请求全被路由到了本地Ollama。原因是当时我在测试用量感知路由它认为商业模型配额快不够了主动把流量切到了本地。数据看起来是合理的但业务上不可接受。后来我在router_settings里把本地的权重调低问题就消失了。这类问题不看日志根本无从下手。所以我的建议是无论代理多稳定Debug日志开关一定要留着一个随时能打开的通道别只靠客户端那点错误信息猜。6. 选型视角LiteLLM该不该进你的技术栈6.1 适合用与不适合用的场景LiteLLM不是我见过的唯一大模型网关但它确实是开源方案里上手门槛最低的一个。不过它也不是万能药我自己画了一条很清楚的分界线。如果你的项目同时满足下面三个条件需要对接两个以上模型供应商、需要控制整体成本、需要给多个内部项目统一发放API Key那LiteLLM能帮你省非常多的事情。反过来如果你的项目单一模型、单供应商只是写个脚本跑一遍就算完那么直接调官方SDK反而更合适。加网关意味着多一层部署、多一层故障点、多一份运维成本这些在小项目里都是净负担。还有一种场景要慎重对首字延迟极其敏感的聊天应用。请求每经过一个代理层都会多消耗几毫秒甚至几十毫秒。如果你们的核心竞争力就是“响应最快”那在任何中间件面前都要犹豫一下。LiteLLM本身更多是牺牲可忽略的延迟换取可维护性和容灾能力。6.2 配置与集成中容易踩的几个边界问题几个实际使用中很容易让人困惑的地方一次说清楚。第一model字段的供应商前缀必须写对。写openai/gpt-4o和只写gpt-4o是两个意思前者明确了路由到OpenAI兼容接口后者会被默认当OpenAI处理。如果接的是Azure、Anthropic等一定要记得把前缀带上。第二参数兼容性问题。各模型家的参数集合不一样有些模型不支持logprobs、presence_penalty这类高级参数。如果你统一在客户端传了LiteLLM在转发时默认会做参数过滤。给litellm_settings加上drop_params: true会让不在目标模型支持列表里的参数自动丢弃而不是报错。这个开关建议在混合接入开源本地模型时务必打开因为开源模型的参数支持范围往往更窄。第三流式输出的一致性。streamTrue的请求走的是SSE流式返回LiteLLM会把上游的流内容重新包装成OpenAI格式再转发给客户端。大多数情况没问题但有个细节不同供应商的usage统计方式不同有的在流结束时推送token数有的不推送。如果客户端依赖流式响应里的usage字段做统计建议以代理侧记录的用量为准。LiteLLM在日志里会记录每个请求的token数你可以从那边拉数据做后续计费。第四虚拟Key并不是默认生成的。在配置里没显式管理Key时任何字符串都能通过代理。生产环境如果直接暴露给外部网络一定记得在Key管理界面生成真实虚拟Key接上数据库做持久化并关闭“免鉴权”模式。6.3 我的一点判断标准用了一段时间之后我慢慢形成了一个很朴素的判断标准如果团队的瓶颈在“灵活接模型”LiteLLM适合如果瓶颈在“极致性能”它不合适。这句话听起来像废话但我见过太多团队在项目初期就疯狂追求极致链路结果花了一两周在性能优化上产品却因为模型切换太慢迟迟没上线。对我来说大部分AI应用的瓶颈根本不在网关这几毫秒延迟而在“能不能快速试出最合适的模型配合”。LiteLLM让我在半天之内就能给业务方开一套多模型入口后面发现某个模型效果不好改一行配置重新reload就能换掉这种“试错效率”才是真实的开发价值。当然它也在一直迭代配置项更新很快。我的建议是每次升级版本后先在你的预发环境跑一遍现有配置因为有些字段在版本间会调整或废弃。最后分享一个我自己的小习惯所有模型配置的改动我都用Git管理配置文件里不写任何明文Key全部走环境变量。每次改动后写清楚原因比如“新增本地模型作为三级兜底”“调低某供应商权重”。这样出了问题翻历史记录比翻聊天记录靠谱一万倍。