如果你的后端接口里躺着一堆来自不同大模型厂商的SDK每个厂商的鉴权方式、请求字段、超时时间甚至报错格式都不一样每接入一个新模型就要多写几百行适配代码——那你大概率会喜欢 litellm 这个名字。它不是一个花哨的 RAG 框架也不是又一个 Chat Bot 壳子而是一个把“接多个大模型”这件事尽可能收敛成“接一个统一接口”的开源代理网关。这个定位听起来简单实际用下来你会发现它把路由、重试、回退、缓存、成本统计、密钥托管全部揉进了同一个代理层解决的是生产环境里反复踩的那些脏活累活。我最初接触 litellm 是因为项目里同时接了多家模型服务有的返回 JSON 不稳定有的在高峰期频繁限流有的账单完全对不上号。改了两版代码之后我决定把调用入口彻底收口。这里把我从安装到落地的整个实操过程、踩坑记录和调优心得都整理出来给同样被“多模型集成”折磨过的朋友一个可以照着做的参考。1. litellm 解决的到底是什么问题1.1 多模型接入的后端混乱现场做过实际 LLM 应用的人都会经历这样一个过程先按某一家厂商的 SDK 调通了一个模型跑得很开心。紧接着业务方说“这个模型在中文场景下表现一般能不能换一家”于是你兴冲冲打开另一家的文档发现它的 Python SDK 是另一套写法鉴权方式从 Header 里的静态 Key 变成了动态签名请求体里字段名都不一样连流式输出的解析逻辑都要重写。如果再叠加一点真实世界的混乱某个上游接口突然改了超时时间某个新模型试运行阶段需要灰度一部分流量还有财务要求把每笔调用费用分摊到不同项目组——你的调用层就会迅速变成一个又大又脆的“胶水层”。每一处新改动都可能牵连出一连串的兼容问题。表面上是“多接几家的烦恼”本质上是你需要一层“协议翻译 统一控制面”。1.2 litellm 的核心思路一个格式换掉一切litellm 的核心思路并不复杂先把市面上主流的模型调用统一转成同一套“OpenAI 风格的请求/响应格式”然后在这套统一格式之上加路由、回退、限流、缓存、成本计算这些横切能力。换句话说litellm 是一层反向代理客户端只需要按照一套标准格式发请求litellm 负责把请求翻译成目标模型供应商的格式再把供应商返回的结果统一翻译回来。这套设计最聪明的地方在于它“向上统一向下适配”。向上你的业务代码永远只面对一个熟悉的标准接口向下litellm 维护了一大堆供应商适配器各家 API 的差异被隔离在适配层里你不需要关心对方的请求体应该怎么写。这一点和数据库中间件的思路很像客户端只跟代理说话代理才去跟你背后的各种数据源打交道。代价是你需要多维护一个代理服务但这个代价对比一套被各家 SDK 绑架的调用层小得太多。2. 环境准备与快速上手2.1 安装与最小启动litellm 的安装很直白用 pip 直接装就行建议装带 proxy 依赖的版本这样内置的代理服务和配置解析才能一起用上pip install litellm[proxy]装完之后你既可以把 litellm 作为 SDK 在自己的 Python 代码里直接调用也可以把它作为一个独立的 HTTP 代理跑起来。我最推荐的落地方式是后者因为代理模式可以让团队里所有语言的服务共用一套模型网关不需要每人装一套 Python 包。先给一个最小可用的配置文件config.yamlmodel_list: - model_name: my-main-model litellm_params: model: provider-x/llm-v2 api_key: os.environ/PROVIDER_X_KEY这里的provider-x是一个占位符实际使用时替换成你自己的供应商标识provider-x/llm-v2代表“哪一家供应商的哪个模型”。环境变量PROVIDER_X_KEY用来存放对应的密钥好处是密钥不会直接出现在配置文件里。然后用一条命令启动litellm --config config.yaml --port 4000启动之后代理默认服务在 4000 端口。用 curl 测一下curl -X POST http://localhost:4000/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-any-key \ -d { model: my-main-model, messages: [{role: user, content: 你好介绍一下你自己}] }只要看到正常的 chat completion 返回说明这个最小网关已经通了。初次跑通这个流程并不需要理解内部原理但建议你保留这个最小配置做后续实验的底子因为后续所有高级能力都是在这个基础上加字段。2.2 Python SDK 直接调用除了代理模式litellm 还提供了 Python SDK适合不想起服务、只在脚本里用的情况。最基本的调用方式是这样的import litellm response litellm.completion( modelprovider-x/llm-v2, messages[ {role: system, content: 你是一个乐于助人的助手}, {role: user, content: 把这句话翻译成英文} ], api_key你的密钥, ) print(response.choices[0].message.content)这里有个常见误解有的朋友以为model参数里的斜杠前面是“模型分组”其实它在 litellm 里的含义是“供应商/模型名”。如果你在代理模式下定义了model_list那么业务代码里传的是你自定义的model_name比如上面配置的my-main-model实际请求会由网关自动映射到provider-x/llm-v2。使用 SDK 时还可以通过环境变量来指定供应商的密钥比如设置一个通用的关键字LITELLM_API_KEY或者按供应商习惯定义环境变量名。如果你不希望密钥出现在代码里强烈建议走代理模式把密钥管理全交给网关。3. 核心功能拆解路由、回退与高可用策略3.1 模型路由与多供应商配置当你需要同时接入多个供应商的多个模型并在不同模型之间做流量分配时model_list就是核心阵地。它支持在同一名称下配置多组litellm_params每个参数里都可以指定不同的 model、api_key、api_base甚至可以设置请求权重。我们来看一个两个供应商的高可用配置例子model_list: - model_name: fallback-model litellm_params: model: provider-a/chat-turbo api_key: os.environ/PROVIDER_A_KEY model_info: mode: completion supports_function_calling: true - model_name: fallback-model litellm_params: model: provider-b/general-70b api_key: os.environ/PROVIDER_B_KEY model_info: mode: completion supports_function_calling: true同一个model_name挂两个不同的模型之后litellm 在收到fallback-model请求时会按照某种路由策略选择一个上游模型。默认情况下它会做简单的负载均衡你也可以通过routing_strategy配置更多策略例如基于最低延迟或者基于最低成本来选择路由。路由策略选择背后有一个很实际的考量如果你更在意省钱可以配置优先选择单价更低的模型如果你更在意响应速度就按最近一段时间的平均延迟排序。当然延迟排序需要更大的请求样本才能稳定不要在流量很小时对延迟策略抱有太高期望。3.2 fallback 回退机制路由和回退经常会混淆。路由是在一个模型名称后面挂着多个实际模型在“正常情况”下选择其中一个回退则是在“已经选中的那个模型”请求失败之后自动去试备选模型。回退机制是你应对上游限流、过载、悄悄变更模型的保底手段。配置回退稍微绕一点它是在主请求配置里声明备选列表。例如model_list: - model_name: main-vllm litellm_params: model: provider-a/ultra-1 api_key: os.environ/PROVIDER_A_KEY fallbacks: - model: provider-b/reliable-1 api_key: os.environ/PROVIDER_B_KEY - model: provider-c/base-plus api_key: os.environ/PROVIDER_C_KEY这样当provider-a/ultra-1抛出错误或者触发限流时litellm 会自动尝试provider-b/reliable-1如果再失败再尝试provider-c/base-plus。这里要注意几个细节首先回退是在“主请求失败”后触发的因此每次回退都会增加一次上游调用的耗时。如果主模型大概率已经超时建议配合下面会讲到的请求超时配置避免一个请求卡半天。其次回退不能无限级联一般配两到三个备选就够了。最后回退是按“请求失败”来触发的业务逻辑上的“答案不对”它不会感知比如模型返回了格式正确但是内容错误的 JSONlitellm 不会因为你判断结果不符合预期而自动切换模型。3.3 重试与限流设置litellm 内置了默认重试逻辑但默认值往往不适合生产。你需要根据上游模型的稳定性来显式配置litellm_settings: num_retries: 3 request_timeout: 30 retry_after: 2num_retries是最多重试次数retry_after是两次重试之间的基础等待秒数litellm 会按照指数退避的方法叠加延迟避免在限流期间频繁冲击上游。request_timeout是最重要的一个参数它决定了单个请求等待上游响应的上限。我在最初上线时踩过一个很痛的坑没有设置超时时间恰好上游供应商某个节点进入半死状态请求一直挂起不返回导致后端线程池被占满所有普通请求跟着遭殃。后来把request_timeout调到 30 秒并配合重试整体稳定性立刻提升一个量级。这里给一个可选的经验值对大部分对话模型来说非流式响应 5 到 10 秒属正常超过 20 秒基本可以判定异常长文档、复杂推理任务可放宽到 60 秒但最好不要无脑放宽因为超时保护本身就是防线。4. 缓存、成本与安全生产级能力的隐形加分项4.1 响应缓存与语义缓存缓存是 litellm 一个容易被低估的功能。对有大量相似查询请求的业务场景比如客服知识库问答如果问题命中频繁一次完整的模型调用耗时可能好几秒而缓存命中时可以直接返回历史结果延迟降到毫秒级。litellm 的缓存建立在 Redis 上需要在配置里连接 Redislitellm_settings: cache: true cache_params: type: redis host: localhost port: 6379 ttl: 3600这里的ttl是缓存过期时间单位为秒。还有一个容易被忽略的细节litellm 的缓存默认是针对“完全相同请求”的精确缓存它不会对请求做语义层面的近似匹配。也就是说你把“介绍下你们公司”和“请介绍你们公司”分别发过来它们不会命中同一条缓存。如果你需要语义缓存需要结合向量检索在网关前面再加一层逻辑。在决定开启缓存之前请想清楚业务场景。对话类应用如果开了缓存用户重复提问时会拿不到模型的新回答体验会很奇怪。适用于缓存的反而是那种“相同输入对应确定输出”的场景比如代码生成模板、固定格式的文档总结。4.2 成本追踪与用量统计如果你经历过一个月的模型账单出来后才发现某个项目组烧了几千块的痛苦就会明白成本追踪为什么是刚需。litellm 内置了一个成本计算模块里面维护了一份常见供应商模型的单价表每次调用结束后它会根据 token 消耗和模型单价自动算出这笔请求的价格并记录到内部数据库中。要让成本计算准确需要在配置里为每个模型挂上完整的model_infomodel_info: mode: chat input_cost_per_token: 0.000003 output_cost_per_token: 0.000014价格字段的单位是“美元/token”。这个配置虽然繁琐但对成本敏感的项目非常关键。如果你不想手工填价格litellm 也提供成本查询接口通过/spend相关接口可以按 API Key、用户、团队来查看汇总消费。生产环境里我通常每隔一小时把消费记录同步到内部报表系统方便财务和项目负责人实时观测。这里给新接触的朋友一个忠告不要让成本追踪变成事后的摆设一定要从第一次上线就把模型级别的单价配全否则后面的历史数据是没有办法补算准确的。4.3 密钥管理与团队协作另一个让我坚定选择 litellm 代理模式的原因是它的虚拟密钥体系。在微服务架构里如果每个服务都要各自持有供应商的真实密钥一旦某个服务被拖库回滚成本非常高。litellm 的做法是在上游供应商密钥之上再发一层虚拟密钥业务侧拿到的是一把只能访问 litellm 网关的钥匙litellm 自己保管真实上游密钥。虚拟密钥还支持预算、速率限制和过期时间。你可以给不同业务线、不同环境甚至不同开发人员分配不同的虚拟密钥然后设置各自的每秒请求上限和消费总额。比如测试环境的密钥每月预算 50 美元某个内部工具密钥每秒最多 2 次请求超出后直接拒绝。还有一个容易踩的坑是密钥泄露。虚拟密钥虽然好但它本质上仍是你内部系统的通行证一旦泄露攻击者至少能消耗你的上游预算。所以建议在网关前面再套一层网络访问控制或者配合 API 网关限制来源 IP把虚拟密钥当作“隔离层”而不是“保险箱”。5. 生产部署与容器化5.1 用 Docker 把代理跑起来代理模式天然适合容器化因为它的配置文件和密钥都可以通过环境变量注入应用本身无状态。如果不想自己构建镜像litellm 官方提供了现成的镜像但生产环境我更推荐用 Dockerfile 把配置和依赖锁住FROM python:3.11-slim WORKDIR /app RUN pip install litellm[proxy] COPY config.yaml /app/config.yaml ENV LITELLM_CONFIG_FILE_PATH/app/config.yaml EXPOSE 4000 CMD [litellm, --config, /app/config.yaml]构建镜像时注意不要把真实密钥写进 Dockerfile 或镜像层里。正确做法是运行时通过环境变量注入比如在 docker compose 里引用宿主机环境变量services: litellm-proxy: build: . ports: - 4000:4000 env_file: - .env.production environment: - LITELLM_CONFIG_FILE_PATH/app/config.yaml restart: unless-stopped单独把代理服务跑起来的最大好处是业务服务不再需要安装 Python SDK只要发 HTTP 请求就好了。你的 Java、Go、Node.js 后端都能通过标准 HTTP 调用同一个网关技术栈之间的模型调用差异被彻底抹平。5.2 配置管理与热加载配置文件的变更在代理服务里是家常便饭新增模型、调整权重、改缓存策略都是日常操作。最简单的做法是改完配置后重启容器但这会导致瞬时连接断裂不适合有持续流量的场景。litellm 提供了配置热加载的能力但需要配合自动轮询。你可以把config.yaml挂载到容器里然后设置轮询周期general_settings: poll_interval: 30配置更新后最多 30 秒内代理会自动重载新的模型列表和规则。这个机制在生产里非常实用比如业务方临时要灰度一个新模型你只需要修改配置文件并推送网关就会自动生效不需要重启。不过热加载也有坑如果你在运行时动态创建过虚拟密钥或临时修改过路由这些动态状态可能不会完全跟着配置文件热加载。我一般把配置文件看作“基础资产”动态状态看作“临时补丁”基础变更靠热加载临时调整就走管理接口避免两种方式互相覆盖。5.3 可观测性接入模型网关一旦成为所有服务的必经之路它的健康状态就直接决定了整个系统的可用性。litellm 内置了几个非常实用的健康检查接口/health/liveliness用于进程级存活检查/health/readiness用于检查它是否已经加载好模型列表/health/available可以检查具体模型的上游健康状态。我建议在 Kubernetes 的探针里同时使用存活和就绪探针避免把流量打到一个已经加载失败的代理上。此外litellm 还暴露了/metrics端点输出 Prometheus 格式的监控指标包括请求总数、失败次数、耗时分布和 token 消耗。你可以把这些指标接入现有的监控体系再配合告警规则去兜底。这里分享一个我调监控阈值的经验与其盯着 CPU 和内存不如直接盯“上游错误比例”和“请求耗时 P99”。上游出问题时最明显的就是 P99 上涨和 429 错误比例飙升。把这两条配上告警比任何基础设施监控都能更快地暴露模型供应商的问题。6. 常见问题与排查技巧实录6.1 高频故障速查表把我在实际使用中经常遇到的问题整理成一张表方便快速定位。现象常见原因解决思路请求返回 401 鉴权失败上游密钥配错或虚拟密钥到期检查model_list中对应模型的 api_key 是否正确检查虚拟密钥状态请求返回 429 限流上游限流或虚拟密钥速率限制开启回退机制调整num_retries抬高虚拟密钥每秒请求限制返回 timeout 错误request_timeout设置过小适当调大超时检查上游服务是否半死模型列表加载失败config.yaml 里模型名拼写错误用litellm --config config.yaml --test做配置检查缓存命中率低开启的是精确缓存请求有一点差异即不命中评估是否升级语义缓存或用规范化预处理请求文本上下文超长错误请求 token 超过上游模型最大限制在网关侧配置max_tokens约束或者做消息截断table 里最后一条“上下文超长”是最常见的非网络类错误它往往不是配置问题而是业务侧没有控制输入长度。litellm 不会自动帮你截断超长上下文所以需要你在业务代码里做好长度约束或者通过 prompt 精简策略来控制。6.2 延迟和稳定性调优心得第一个心得是“不要迷信开箱即用的默认值”。litellm 的默认设置能让小流量服务快速跑起来但在生产大流量下一定要针对模型供应商的实际情况调整超时、重试和并发连接数。我试过不调超时直接接一个平时响应 1 秒的高性能模型结果一次上游毛刺就把大量请求拖到 30 秒以上整个服务被拖垮。后来把超时收到 5 秒加上两轮快速重试那些毛刺很快就被过滤掉了。第二个心得是回退列表的顺序要按“能力从强到弱、价格从高到低”排列。很多时候业务希望主模型是最好用的备选模型是便宜快速的。但要注意备选模型的能力如果和主模型差距过大回退后可能返回低质量结果业务侧又没有做校验就会把降级后的结果直接呈现给用户。我在生产环境对模型回退结果做了简单的质量提示把“该结果由备选模型生成”透传到前端避免用户疑惑。第三个心得是连接复用。litellm 代理在跨供应商调用时会维护连接如果业务侧每次请求都新建 TCP 连接代理本身容易成为瓶颈。建议在业务侧使用连接池保持长连接复用同时在 litellm 这一侧关注默认的并发连接数必要时调整系统文件描述符上限。最后一个心得是关于密钥轮换。上游供应商密钥一旦泄露或者到期你需要快速轮换。litellm 的虚拟密钥并不能自动感知上游密钥的变化你要在配置中更新环境变量或者通过管理接口刷新。生产上我会给密钥设置一到两个月的轮换周期并且把轮换动作脚本化避免手动操作漏掉某个 model 条目。用了这阵子 litellm我最深的体会是模型网关的价值不在于省掉那些“多写几百行适配代码”而在于它把你从“每一家供应商的差异”中解放出来让你把注意力放在业务本身。后来每次业务需要接入新模型我的操作变成了“往配置里加一条记录、热加载、跑通回归”以前的焦虑和手忙脚乱基本消失了。如果你也正在被多模型集成折磨建议先跑通最小代理把路由、回退、成本这三件事做起来剩下的能力等踩到对应坑的时候再逐个打开也不迟。