如果你对接过两家以上不同的大模型服务应该很熟悉这种烦躁感A 家的 SDK 有自己的鉴权方式参数命名跟你习惯的完全不同B 家的流式返回格式又跟 A 家差了一截C 家甚至没有现成 SDK只能自己拼 HTTP 请求。我在给内部某知识库助手做多模型接入的时候就被这种碎片化折磨了一段时间。后来在代码层和各个模型之间加了一个 litellm 统一网关才把这些问题真正压下去。这篇就聊聊它是什么、能解决什么、怎么落地以及我在实际使用中踩过的坑。litellm 本质上是一个大模型调用代理层屏蔽掉不同模型服务商之间的 API 差异对外提供一套统一的 OpenAI 格式接口。你只需要按 OpenAI SDK 的写法去调用它由它负责把请求转发到背后真实的模型服务商再把返回结果转换成统一格式交给你。适合对接多个模型、需要统一管控成本和密钥、或者想给团队提供一个稳定模型接入点的场景。如果你只是本地调一个模型玩那不需要它但一旦你或你的团队要同时面对三四个模型供应商它就是很实用的基础组件。1. 为什么要在大模型和业务之间加一层统一网关1.1 先看痛点直连各家 SDK 有多烦先说一个很直观的场景。你有一个内部问答助手最初只接了一家模型服务商代码里直接用对方 SDK 写业务逻辑一切都很顺畅。过了一阵子你想对比一下另一家的效果于是引入第二个供应商。麻烦开始出现两家的temperature参数取值范围不一样max_tokens命名不同返回内容里 token 用量的字段位置也不同而流式输出的数据结构完全是两套东西。我实际遇到的情况是同一个业务函数里为了兼容两家供应商到处写if provider A这种分支。刚开始只有两三家还能忍后来还接了本地部署的模型服务不同服务的输入输出差异越来越大业务代码开始变成一堆补丁叠补丁改一个需求要同时改两三个分支。更头疼的是密钥管理每个服务商的 API key 散落在不同环境变量里新同事入职要交接半天图形化的成本统计更是一个都没有。其实最底层的问题不是哪家 SDK 不好而是你让业务代码同时耦合了太多上游协议。这时候就需要一层东西把这些差异挡在外面。1.2 litellm 的思路把多样性挡在网关后面litellm 的做法很直接它自己作为代理服务跑起来业务代码永远只跟它对话。它对外暴露的接口是 OpenAI 格式即/chat/completions、/embeddings这类标准端点入参结构也是大家最熟悉的messages列表加模型名。在网关内部它负责把这份统一格式的请求翻译成目标服务商能理解的协议再发送出去。这种设计有一个特别实用的点业务侧接入成本极低。团队里任何一个人只要会写 OpenAI 客户端就天然会调用 litellm 网关。如果明天要把模型 A 换成模型 B业务代码几乎不用动只需要在网关配置里改一下模型映射关系把原本指向 A 的模型别名指到 B 上就行。我跟同事开玩笑说它就像是给各个大模型 API 加了一个万能转换头你只要认准一个插口后面插什么电器都行。另一个好处是审计和管控的集中化。所有请求都会经过网关所以谁在什么时候用了什么模型、消耗了多少 token、花了多少钱都能在网关这一层统一拿到。这比让每个业务线各自去服务商后台查账单要清晰得多。1.3 什么情况下才值得上 litellm说实话并不是所有项目都适合引入 litellm。如果你只是一个个人小项目就调某一个固定模型那直接用官方 SDK 反而更轻多一层网关就是多一个需要部署和维护的组件没必要。但当出现以下任一情况时就值得认真考虑了团队内多人需要共用模型资源你需要在多个供应商之间做效果对比和切换你想按项目或按部门控制模型使用预算你有多个后端服务都要接大模型不希望每个服务都重复实现一套鉴权和重试逻辑。我自己是从个人脚本接入开始用的后来因为内部项目要开放给多个业务方调用才正式把它当独立服务部署起来相当于给团队提供一个统一的模型入口。2. litellm 的核心功能拆开讲2.1 统一请求格式与参数映射litellm 最基础的能力就是把不同服务的请求参数映射成统一的 OpenAI 风格。比如你调chat/completions传一个messages列表里面有role和content这是大家都熟悉的写法。网关收到后会根据你配置的目标模型将temperature、top_p、停止词等参数转换成对应供应商的字段。需要注意的一点是不同模型服务商对参数的实现程度不一样。有的模型支持frequency_penalty有的不支持有的对temperature的合法范围定义不同。litellm 的处理方式通常是把不支持的参数忽略或降级而不是报错。这既是优点也是坑如果你特别依赖某个模型独有参数最好先去查一下 litellm 的文档确认映射规则不然可能出现“网关显示调用成功但实际效果跟预期不同”的情况。日常开发中我在业务侧维护一个模型别名常量表代码里只引别名。比如fast-chat指代某个速度快的模型big-reasoning指代能力更强的模型。哪天要升级模型能力我就只改网关配置业务服务不需要重新发布。这个看着很不起眼的操作真到跨部门协作的时候能省掉很多沟通成本。2.2 多密钥、预算与租户隔离密钥管理是 litellm 很强的一块。网关本身有一个master key所有管理端请求都靠它。在这个主密钥之下可以创建很多个虚拟 key每个虚拟 key 可以绑定不同的预算上限、限流速率和使用权限。比如 A 组同学拿一把只能访问某个模型的 key每月最多花 200 块B 组同学拿另一把 key可以访问另外几个模型。这种设计解决了团队协作里一个很现实的管控问题过去大家共用一个服务商的 API key出了异常消耗很难定位是谁的锅。换成虚拟 key 之后每把 key 都有独立 IDlitellm 后台能看到每个虚拟 key 的调用量和累计成本。出了突发情况可以立刻查到是哪个 key 在大量调用甚至可以随时吊销某个 key 而不影响其他人。预算控制也不是一刀切的“超了就停”。litellm 支持设置预算告警阈值到了 80% 就发通知到 100% 再限制或停用。我们内部某个业务线就是这样配的模型异常消耗再也没出现过月底爆账单的情况。如果你准备给多业务方提供服务这组功能基本是刚需。2.3 负载均衡、重试与故障转移除了统一接口litellm 在稳定性方面也做了不少事情。它支持同一个模型配置多个 API key网关会在这些 key 之间做轮转或按负载分发变相突破单个 key 的速率限制。比如某个厂商的 API 允许每分钟 600 次请求但你的应用高峰期会瞬时打很高就可以在配置里多放几个 keylitellm 自动分摊流量。更让我觉得实用的是故障转移机制。你可以配置一个主模型和几个 fallback 模型当主模型返回错误、超时或触发限流时网关会自动把请求转到备用模型上。这一点在生产环境里价值很大就算某个供应商临时故障你的业务用户也不会直接感知到服务不可用最多是响应稍微慢一点。我实际测试过 fallback 的效果主模型连续报错时网关会在几百毫秒内切到备用模型整体请求失败率显著下降。当然 fallback 也不是万能的比如主模型和备用模型的响应风格差异可能很大对内容质量要求高的场景最好不要让 fallback 模型处理得那么“无感”宁可提示用户稍后重试。2.4 成本追踪与用量观测litellm 的成本追踪是我愿意长期使用它的重要原因之一。它会根据请求的输入输出 token 数和模型费率自动统计出每一次调用的估算成本。在它的管理页面上可以按模型、按虚拟 key、按时间段去看成本曲线。这些数据也能通过回调集成到企业内部监控系统。它内部维护了一张模型价格表你接入的模型如果不在表里也可以手动在配置里指定按 Token 计费的价格。对用自部署模型或特殊模型的团队来说这个功能很实用成本数据依然能汇总到同一个体系里。我在做月度成本复盘时基本就是从 litellm 后台导出一份用量明细按项目归类汇总比对着各家服务商账单去梳理省力太多了。3. 从零落地部署、配置与第一个真实请求3.1 快速把一个代理服务跑起来litellm 提供两种使用方式一种是直接在 Python 脚本里 import当作一个 SDK 调用统一的completion()方法另一种是启动一个独立代理服务在本地或服务器上常驻运行。如果只是自己写脚本用第一种就够了如果想让团队共用建议用第二种。我的实践是直接用 Docker 部署它包好了运行环境省掉很多折腾。核心就一个命令的思路我用 docker-compose 管理。一个最小化的配置大概是这样的services: litellm: image: ghcr.io/berriai/litellm:main-latest ports: - 4000:4000 volumes: - ./config.yaml:/app/config.yaml command: [--config, /app/config.yaml, --port, 4000]启动前只需要准备一个config.yaml配置文件。启动后访问/health/liveliness和/health/readiness两个端点就可以确认服务是否健康。我第一次启动时连健康检查都没看直接就去调接口结果等了一会儿才发现服务没起来白费了不少排查时间。所以如果你们也准备上这个建议先跑通健康检查再继续往下走。3.2 配置一个真实的模型接入config 文件是 litellm 的配置中心。一个最简的模型接入配置长这样model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: claude-flash litellm_params: model: anthropic/claude-3-5-sonnet api_key: os.environ/ANTHROPIC_API_KEY这里有一个很关键的细节model_name是业务侧看到的名字litellm_params里的model才是网关真正路由的标识格式通常是“供应商名/实际模型名”。我第一次用的时候把model_name和model都写成了同一个名字结果网关在路由时判断错了供应商报了一堆莫名其妙的错误。后来才明白这两个字段是有分工的。启动服务后用 curl 简单测一下curl http://localhost:4000/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-1234 \ -d { model: gpt-4o, messages: [{role: user, content: 你好}] }如果返回正常的choices结构说明网关已经打通。这里返回的 JSON 结构和官方 API 几乎一样业务方直接按熟悉的格式解析即可。3.3 用 OpenAI SDK 调用网关网关跑通之后接入方拿到手的体验就是“它就是一个兼容接口”所以很多现成工具也能直接复用到 litellm 上。比如一段原本调用官方 SDK 的代码只需改三个东西base_url、api_key、model其余逻辑原封不动。我用 Python 示意一下from openai import OpenAI client OpenAI( base_urlhttp://your-server:4000/v1, api_keysk-your-virtual-key, ) resp client.chat.completions.create( modelgpt-4o, messages[{role: user, content: 介绍一下桂林}], ) print(resp.choices[0].message.content)这里配置文件中模型名是gpt-4o在业务侧它不一定真的指代官方那个同名模型。它可能被映射到另一个厂商的模型或是在多个供应商之间做了负载均衡。这个透明的映射关系就是网关的核心价值之一。还有一个非常实际的好处由于外部接口格式统一你之前写好的提示词模板、工具调用逻辑、后处理代码在切换模型时基本不需要改动。换模型从“改代码发版”变成了“改网关配置然后告诉同事新别名”这个体验的差别经历过的人都懂。3.4 负载均衡和 fallback 的配置细节负载均衡和故障转移的配置都在同一个 config 文件里。同模型多 key 轮转可以这样写model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY_1 model_info: supports_parallel_function_calling: true - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY_2网关会在两个 key 之间轮换。如果同时配置了多个不同的model_name可以通过路由规则把请求分配。故障转移则是在router_settings里配置fallbacks比如router_settings: fallbacks: - gpt-4o: - claude-flash意思是当gpt-4o这个模型不可用时自动尝试claude-flash。需要提醒的是fallback 模型和主模型的能力差距可能不小生产环境建议只在主模型临时不可用或限流时做兜底而不是日常把流量导过去。另外 fallback 会带来一次额外的调用尝试超时时间的配置要留足不然业务平台已经等不及给你断了网关还在尝试备用模型这个体验反而更差。4. 生产环境会遇到的坑和排查思路4.1 常见报错速查表用久了我发现litellm 的报错大多集中在配置、鉴权和流式处理三类。整理一个速查表方便遇到问题时先对号入座。现象通常原因处理建议404 模型不存在请求里的 model 名在配置中没写或model_name与路由标识混淆检查 config 里的model_name和实际请求值是否一致401 鉴权失败虚拟 key 未创建或已禁用通过管理接口生成新 key确认Authorization头正确429 限流或预算超限虚拟 key 的 RPM/TPM 到顶或预算用尽提高限流配置或检查预算报表定位消耗来源502/504 上游请求失败上游模型服务超时或不可用检查上游供应商状态同时看 fallback 配了没有流式请求中 SQL 报错使用某些异步客户端时连接处理不当确保上游客户端关闭了 keep-alive 或正确释放连接有一个报错我印象比较深业务侧用异步 HTTP 客户端调用网关请求量一上来就出现大量连接错误。排查了很久才发现是客户端连接池设置太小压力全部压在 TCP 连接建立上。这跟 litellm 本身关系不大但提醒我一个经验网关稳定不等于链路稳定客户端侧的连接池、超时、重试策略都要一起调。4.2 从上游和下游两个方向排查litellm 最常见的排查路径其实是分两侧的一是看“网关拿到请求后有没有正确发到上游”二是看“下游业务是否真的收到了预期的响应”。我在排查一个问题时一般先看日志里有没有完整的请求转发记录确认网关收到了请求、目标模型是哪个、响应状态码是多少。litellm 的日志会打印出每次请求的模型标识和耗时但没有业务上下文的话你还需要在业务侧记录一个 request id两端对起来查。这个看起来很简单但遇到线上问题时能省下一个小时。后来我习惯在业务侧把request_id透传到日志里再结合网关日志去定位定位速度明显快很多。还有个很隐蔽的问题不同厂商流式返回的内容格式差异。流式响应里通常会带一堆delta但有些供应商的delta字段在不同阶段会缺字段有些供应商会把工具调用放在delta的特殊子字段里。litellm 一般会做适配但如果你在业务侧直接处理原始流式对象还是要按统一的 OpenAI 结构去写不要依赖某个供应商的特殊字段。4.3 容易被忽略的性能与成本细节有几个细节我建议每个准备把 litellm 接进生产环境的人都注意一下。第一个是流式请求的 token 统计。如果你用stream: true默认情况下响应里可能没有完整的 usage 信息导致成本统计出现缺口。解决办法是在发起请求时同时传stream_options: {include_usage: true}这样流式响应的最后一段会带上用量。这个字段最初我经常忘直到月底对账发现成本数据少了一块才翻日志找到原因。第二个是 embedding 模型的维度一致性。如果你同时接入了多个供应商的向量模型它们的输出维度大概率不一样。业务库里如果已经有一部分向量是按旧的维度生成的切换模型后新旧向量无法直接比较这个问题在检索场景里很容易被忽视好在 litellm 能帮你统一入口但它不负责帮你统一向量维度这需要业务侧自己做兼容。第三个是超时和重试的配合。litellm 网关层有重试配置业务侧不要同时做太多层重试不然一个上游慢请求会被放大很多倍拖垮整个链路。最初我们为了“稳定”做了三层重试结果上游一抖动网关下面的数据库和下游服务全被打爆。后来把重试收敛到网关一层并把超时时间调整为分段模式链路才算稳定下来。4.4 一个小技巧把模型调用日志接入内部监控litellm 支持通过回调把日志推送到你已有的监控系统。对这个能力我想多强调一下它的价值因为它不只是“方便查看日志”。我们内部实际做的是把每次调用的模型名、虚拟 key、耗时、token 用量、估算成本统一推到内部的可观测平台再按业务线做实时看板。这样成本趋势、异常调用、限流情况都能及时看到我印象中第一次把看板做出来的时候主管直接拿它来做每周汇报数据源比从各家后台手动导出数据靠谱得多。配置方式不复杂核心就是启动代理服务时指定--detailed_log或者通过配置自定义回调函数把litellm_params和响应数据组织成 JSON 推送到内部 HTTP 端点。如果你还没有监控系统也可以先让 litellm 把日志写到 JSON 文件再用日志采集器去收。关键是数据的结构化要一开始就做好至少把model、response_time、prompt_tokens、completion_tokens这几个核心字段留全。我个人在这个项目上摸索下来最大的体会是litellm 解决的远不止是代码兼容问题它把模型接入这件事从“各自为政”变成了“统一治理”。有了它之后团队新增一个模型供应商的成本已经低到几乎可以忽略而这在以前根本不敢想。如果你也刚好被多模型接入、成本失控或者密钥管理搞得头大不妨花一个下午把代理跑起来先用一个模型打通链路再慢慢把其他服务接进来。这个投入产出比我觉得是会让你觉得值的。最后再分享一个小经验配置文件的变更不要太随意建议像管理代码一样走版本管理每次改动都留记录因为模型切换导致线上行为变化的案例我见过太多次了。