
多模型接入这件事几乎每个做过 AI 应用的人都会碰到同一个坎今天要接模型 A明天业务又要接模型 B后天客户说能不能把某个模型换成 C。每个平台的 SDK 不一样鉴权方式不一样计费口径也不一样。最开始我还能靠封装几个函数硬撑等到服务要上线、多个团队都要用同一套模型能力时才发现自己维护的不是接口而是一堆越来越乱的补丁。后来我开始用 litellm才慢慢把这类问题理顺。简单说litellm 是一个开源的模型调用网关它把几十种模型服务商的 API 统一成一套接口同时把密钥管理、重试、限流、预算控制、负载均衡这些生产环境躲不掉的事情变成一份可维护的配置文件。这篇文章我会从为什么需要它、核心能力、快速上手、生产配置、排障经验到性能优化完整梳理一遍适合正在接触多模型调用、想给团队搭建统一 AI 入口的开发者参考。1. 多模型接入这件事为什么值得单独做一个网关1.1 我最早是怎么被多模型调用折腾的早先做一个内部 AI 工具时我负责把几个主流的模型服务商都接进同一个功能里。第一版代码长得很“直白”每个服务商写一个 adapter每个 adapter 里处理各自的请求格式、超时时间、错误码还有各自的 api_key。接口倒是调通了但后面每次加模型都要重写一段逻辑改功能时要同步改所有 adapter。最痛苦的是线上报错不同服务商的错误返回完全不一样有的用 HTTP 400有的用 500有的错误信息藏在几层 JSON 里定位一个问题要来回翻日志。后来团队决定不只接模型还要控制成本和访问权限。需求一下子从“能调通”变成了“不同部门用不同模型、每月有预算上限、超了要告警、失败要自动重试”。如果这些全部自己写等于从零造一个流量网关。这件事的复杂度远高于“封装 SDK”我很快意识到需要一个专门的中间层来承接。1.2 litellm 到底是什么litellm 从名字也能猜出大概一个用于大模型调用的中间件。它对外提供一套和主流大模型 API 风格兼容的接口你只要按照这个统一规范发请求它会把请求转发到你配置的后端模型服务商再把响应转回来。模型切换只是改配置不需要改业务代码。我平时主要用到它的三层能力。第一层是统一编程接口包括 Python SDK 和 HTTP 网关第二层是网关能力比如多模型路由、负载均衡、fallback、重试、限流、预算第三层是管理能力比如虚拟密钥、用户和团队划分、日志和成本监控。这些叠加起来它就不再是一个“API 转换器”而是一个可以长期维护的模型接入平台。1.3 什么场景真正值得引入 litellm并不是所有项目都需要上网关。如果只是本地写脚本、做 Demo直接调官方 SDK 反而更省事。但出现下面这些情况时我建议尽早把它加进来业务代码里同时引用了多个服务商 SDK改功能要动多处。同一个模型要提供给多个应用或团队但不想把密钥分发出去。需要限制调用成本要求按项目、按用户做配额。需要一个统一的日志和监控入口方便排查线上问题。想让模型在多个后端之间自动切换比如某些地域访问某个服务商更稳定或者某家服务商临时故障时自动换到另一家。如果你现在的项目已经出现以上迹象搭一个 litellm 网关的成本会比想象中低很多通常一个下午就能跑通原型。2. litellm 的核心能力和选型拆解2.1 统一格式把不同 SDK 的差异挡在外面litellm 最核心的设计是让调用方只关心一套消息格式。比如 chat 模型都用messages[{role: user, content: ...}]这样的结构embedding 模型都统一传input字段。它对后端做转换返回结构也尽量保持一致。这样业务侧可以固定使用一套协议底层接的是哪家服务商对调用方透明。我在使用中会把 litellm 理解成一个“前端路由 后端适配”的组合。前端负责接收统一请求后端负责对接各家平台的真实接口。接口格式、超时时间、鉴权字段、错误处理都在 litellm 内部消化掉。业务侧只需要记住一个 API 地址和一对密钥其他细节不用管。2.2 模型路由和负载均衡它可以当“模型选择器”用这是我在生产环境中使用最多的功能。litellm 允许你在配置里定义一组模型列表并给它们起别名。调用方用的是别名litellm 根据别名和后端可用情况决定真正请求哪家模型。具体负载均衡策略也有几种可选。常见的有轮流分配、基于延迟的最低延迟优先、基于使用量的负载均衡。比如两个后端模型能力差不多我想尽量让延迟更低的服务多承担流量就可以使用延迟优先策略。这种方式比自己在代码里写 if-else 判断要可靠得多因为 litellm 会持续收集端点健康信息和响应延迟。2.3 预算、密钥与权限管理很多团队接入模型时最担心的是密钥泄露和被乱调用。litellm 在这方面天然适合做统一入口平台侧只暴露网关地址后端服务商的密钥只存在网关配置里。业务方拿到的是一把虚拟密钥可以限制这把钥匙属于哪个用户、哪个团队、能用哪些模型、每月花多少钱。我实际使用中会把虚拟密钥和团队绑定。比如运营团队只能用某几个模型研发测试环境用另一批密钥每个密钥单独设预算。超预算后网关直接返回配额超限错误后端不会产生额外的费用。这个能力如果自己实现涉及数据库、鉴权、计费核算工作量不小。2.4 为什么不自己写一个网关我在设计初期也想过自己封装一个简单的网关。做法无非是 Flask 起一个服务转发请求到后端再记录日志。但做着做着就会发现问题重试策略要考虑哪些错误码可以重试限流要考虑每分钟请求数和 token 数负载均衡要持续探测后端状态预算扣费要考虑输入输出 token 的计费差异这些还只是基础设施部分。litellm 把这些问题都沉淀成了配置项和内置逻辑而且社区迭代频繁。我自己的团队选择直接基于它搭建而不是重复造轮子。当然如果你有非常特殊的定制需求比如需要对接内部自研的鉴权系统litellm 也提供了扩展点可以在它基础上做二次开发。3. 30分钟跑通一套自己的模型网关3.1 安装 litellm 与基础准备先说明一下我用的版本会持续更新所以下面的命令你在执行前最好对照官方文档确认。基础依赖是 Python 3.8 以上。安装方式推荐用 pippip install litellm[proxy]这里proxy是额外依赖项包含运行 HTTP 网关需要的组件。如果你只用 Python SDK 做统一调用不打算启动网关服务可以只装litellm本身。我在最开始只装了基础包后来发现要用管理接口和虚拟密钥才补装完整依赖。装好后可以通过命令行确认版本litellm --version另外准备一份后端模型服务商的 API 密钥。这一步不要直接把密钥写进业务代码而是准备放到 litellm 的配置里。3.2 写一份最小可用的 config.yamllitellm 的核心配置是一个 YAML 文件。我习惯把所有的模型路由和策略都放在这里方便走版本管理。最简单的配置只需要列出模型列表model_list: - model_name: unified-chat litellm_params: model: provider-a/model-a api_key: os.environ/PROVIDER_A_KEY这里的model_name是暴露给调用方的别名litellm_params.model是实际请求后端时的模型标识格式一般是“服务商名/模型名”。密钥可以通过环境变量引用避免明文写进仓库。启动时加载环境变量文件就行。如果你想支持多个后端可以在model_list里多加几项同一个别名可以对应多个后端。比如model_list: - model_name: unified-chat litellm_params: model: provider-a/model-a api_key: os.environ/PROVIDER_A_KEY - model_name: unified-chat litellm_params: model: provider-b/model-b api_key: os.environ/PROVIDER_B_KEY这样一个别名unified-chat后面挂了两个真实模型litellm 会在它们之间做负载均衡。调用方完全无感。3.3 启动网关并验证连通性启动命令很简单litellm --config config.yaml --port 4000启动后litellm 会提供一个 OpenAI 兼容的接口监听在本地 4000 端口。先别急着写业务代码可以用命令行验证一下模型列表是否加载成功。我习惯先访问健康检查接口和一个模型的列表接口curl http://localhost:4000/health/liveliness curl http://localhost:4000/v1/models如果你设置了 master key这些请求需要带请求头。master key 可以在配置或启动参数里指定比如litellm --config config.yaml --port 4000 --master_key sk-local-test-key设了 master key 之后访问/v1/models时就要带上curl http://localhost:4000/v1/models \ -H Authorization: Bearer sk-local-test-key3.4 用代码发起第一次对话请求验证网关没问题后就可以用常用的大模型 SDK 来调用它了只需要修改 base_url 指向自己的网关。比如业务侧原本用的是平台方 SDK现在把地址替换成http://localhost:4000同时用 litellm 下发的虚拟密钥或 master key 替换原来的密钥。下面是一个用 Python 调用的最小示例这里我用litellm自己的 Python SDK更直观import os import litellm os.environ[LITELLM_MASTER_KEY] sk-local-test-key response litellm.completion( modelunified-chat, messages[ {role: user, content: 你好请用一句话介绍你自己} ], api_basehttp://localhost:4000, ) print(response.choices[0].message.content)注意这里model参数填的是配置里的模型别名unified-chat而不是后端真实模型名。如果请求成功说明网关已经把请求路由到了某个配置的后端服务商。之后你要测试另一个后端只需要重新调整配置或路由规则不需要改代码。4. 生产环境如何配置路由、预算与重试4.1 模型路由别名的设计思路生产环境里我建议把别名设计成“业务语义”而不是“模型名称”。比如不要直接叫model-a而是叫fast-chat、high-quality-chat、embedding-general这类名字。这样业务方只关心用途不关心底层具体接的是哪个模型后面替换模型时不会影响业务。例如model_list: - model_name: fast-chat litellm_params: model: provider-a/fast-model - model_name: high-quality-chat litellm_params: model: provider-b/quality-model - model_name: embedding-general litellm_params: model: provider-c/embedding-model调用方需要“快速聊天”时用fast-chat需要“高质量回答”时用high-quality-chat。如果某天发现 provider-b 的模型效果不好直接改配置把high-quality-chat指向另一个模型业务方无感知。我实际改配置的时候只需要重启网关或触发配置重新加载省掉了所有下游应用的改造。4.2 配置 fallback 与负载均衡生产环境里模型服务商偶尔会抖动或者某个模型因为限流开始大量返回错误。litellm 支持 fallback 配置当主模型失败时自动尝试备用模型。在配置里可以这样定义router_settings: fallbacks: fast-chat: - provider-b/backup-model这里的意思是当fast-chat默认后端不可用时路由会转向provider-b/backup-model。当然你要确保备用模型也在 model_list 里配置过。负载均衡方面litellm 支持多种策略。我常用的是usage-based-routing它会优先选择之前调用量较低的后端尽量让多个后端分担压力。还有latency-based-routing优先选当前延迟最低的后端适合对响应速度敏感的场景。配置项在router_settings.routing_strategy里设置。选型时最重要的判断标准是你的瓶颈是成本、延迟还是可用性。如果只追求可用性建议用带 fallback 的轮询如果追求体验可以优先延迟策略。4.3 重试策略与超时设置默认情况下litellm 会针对某些瞬时错误自动重试但生产环境里你最好显式定义自己的策略避免重试风暴。我在项目中会针对不同错误的 HTTP 状态码设置不同行为网络超时类错误可以重试一两次而鉴权失败、请求参数错误这类问题不应该重试。相关配置项大致包括重试次数、超时时间、冷却时间。比如我希望同一个请求最多重试 2 次单次请求超时 30 秒后端连续失败后进入 60 秒冷却可以写router_settings: retry_policy: max_num_retries: 2 timeout: 30 cooldown: 60这里有一个很容易踩的坑重试次数不是越多越好。如果三个后端都故障每个请求都重试 3 次网关会瞬间发出大量请求导致后端限流更严重。我一般把重试次数控制在 1~2 次并配合冷却时间让故障后端有恢复的时间。4.4 预算和速率限制的生产配置预算控制是 litellm 很有价值的功能。配置项支持按密钥设置 max_budget也可以按模型、按团队、按用户设置。比如某个测试团队一个月只能用 50 美元超了就不允许调用general_settings: master_key: sk-master-key database_url: postgresql://...密钥层面的预算可以通过管理接口创建虚拟密钥时指定也可以用配置预定义。生产环境我强烈建议接一个数据库比如 PostgreSQL 或 Redis用来持久化密钥信息、预算扣费和日志数据。如果只用内存网关一重启预算和密钥数据就丢了这在线上是没法接受的。速率限制也很有用主要体现在每分钟请求数和每分钟 token 数两个维度。比如限制某个应用每分钟最多 100 次请求防止测试脚本把成本打爆。具体规则可以在 litellm 配置的max_parallel_requests、max_tokens_per_minute等参数里做全局或按密钥的限制。我的原则是宁可先给一个保守的配额发现问题再放开也不要一开始放开导致月底账单吓人。4.5 密钥管理与团队权限划分密钥管理这块我在项目里把密钥分成了几类。第一类是全局限流密钥给内部运维和调试用第二类是团队密钥每个团队有自己的预算和模型白名单第三类是用户级密钥给具体应用或个人脚本使用。这样权限边界很清楚谁用了多少成本也能追踪到人。在 litellm 中创建虚拟密钥可以通过管理接口完成。大致流程是先用 master key 请求一个创建密钥的接口传入用户、团队、预算和允许的模型列表然后获得一把sk-开头的虚拟密钥。这把密钥可以替代真实服务商密钥在业务代码中使用。我比较喜欢它的一个点是需要撤销某个应用的访问权限时在网关里把对应的虚拟密钥删掉就行不需要去后端服务商那里轮换真实的密钥。5. 上线后踩过的坑观测手段与排查清单5.1 怎么确认请求到底走到了哪里多模型网关最大的问题是“黑盒”——业务侧发请求给网关网关转发给后端如果出错了到底是哪一段出了问题我自己的排查习惯是先看 litellm 的日志再看健康检查接口最后看后端平台的调用记录。litellm 的日志里会记录每次请求的模型、密钥、用户、延迟、token 消耗、成功失败状态。我通常把日志级别调到 INFO生产环境用结构化日志收集。如果需要深入看某个请求的完整链路可以用 Request ID 去检索日志。很多问题其实在日志里都能看到答案比如某个模型被限流、某个 API key 已经到期、某个后端 URL 配置错误。5.2 常见问题速查表为了方便排障我把平时经常遇到的问题整理成一个速查表。这里的错误信息我用的是常见场景的描述不同版本可能有细微差异但排查思路是一样的。现象可能原因处理方式请求返回 401master key 或虚拟密钥错误检查请求头 Authorization 是否带对返回模型不存在别名未在 model_list 定义或模型名拼写错误检查 config.yaml确认 model_name返回 context length exceeded实际请求 token 超出后端模型上限精简上下文或改用支持更长上下文的模型请求超时后端模型响应慢或超时时间过短调整 timeout 参数检查后端负载连续报错 429触发限流或预算上限检查预算用量看是否需要扩容或调限流某个后端故障但网关仍发流量给它未配置健康检查或冷却时间不够配置 fallback、冷却时间观察后端恢复情况排查的顺序我建议是先看是不是配置问题再看是不是密钥权限问题最后才怀疑后端服务商。因为大部分线上问题都是配置没同步、密钥没配好导致的。5.3 我几次比较典型的线上踩坑经历第一次比较深刻的坑是预算设置过于严格。我在测试环境给某个应用设了很低的月预算结果同事一跑批量任务网关立刻拒绝请求。当时以为是后端出问题查了很久才发现是预算透支。从那以后我学到一个习惯预算可以设告警线但不要把告警线当成硬拒绝线尤其测试环境否则排查成本反而更高。第二个坑是重试参数设置过大。我在一次压力测试时把重试次数调到了 4结果后端因为限流开始返回 429网关不断重试把限流打得更严重最终形成恶性循环。后面我把重试次数下调并给每个后端加了冷却时间情况立刻缓解。重试的本质是应对抖动不是掩盖故障这个度要把握好。第三个坑是使用内存模式做生产部署。一开始我觉得项目规模不大不需要数据库结果一次重启把所有虚拟密钥和预算数据全清掉了。之后我老老实实加了 PostgreSQL把所有状态持久化。这个经验也分享给准备上线的朋友即使团队小也要在第一天就把状态存储想清楚。6. 性能优化与后续扩展思路6.1 提升吞吐量的几个实测建议litellm 本身是 Python 写的网关如果单位时间请求量很大单实例的性能可能会成为瓶颈。先不用急着做复杂架构优化我建议从下面几件事开始开启流式输出。大部分聊天场景用streamTrue能明显降低首 token 延迟用户体验好很多。使用异步调用。litellm 支持 async 接口配合asyncio.gather可以做并发请求。我在内部测试中把一批独立请求从串行改成并发后整体耗时下降非常明显。缓存同一类结果。如果业务中大量请求是重复问题可以开启缓存比如同一段消息在短时间内直接返回缓存结果减少后端调用。连接池调优。保持与后端服务商的连接复用减少 TLS 握手开销。如果单实例确实不够litellm 也支持水平扩展。网关无状态部分可以放在多个实例后面用负载均衡器分发状态数据统一存放在数据库和 Redis 中。Redis 在缓存速率限制、预算计数和语义缓存方面很有帮助。6.2 从网关到内部模型平台的演进litellm 做网关只是第一步。我实际项目中把它当成一个基础底座在其周边陆续接入了模型效果评测、数据集管理、灰度发布。比如新模型上线时先用某个团队密钥绑定新模型灰度跑一段时间观察日志里的延迟和错误率稳定后再切换主路由。这些能力 litellm 本身不一定全部提供但它暴露的 API 和管理接口很适合被上层系统调用。如果后续想做得更完整还可以接入提示词模板管理、多环境隔离、审计日志分析等。我看到很多团队会基于 litellm 再做一个对内的模型管理后台让非技术同事也能自助申请密钥、查看用量。这种演进路径比一开始就自研一套模型平台要平滑得多。7. 几点个人体会最后聊一点我自己的使用感受。litellm 最让我满意的地方不是它帮我省了多少行代码而是把“模型切换”变成了一件不需要发版的事。以前的流程是业务改了需求我改代码测试排队上线。现在的流程是改一份 YAML重载配置完事。这类体验带来的开发效率提升比想象中更明显。当然它也不是银弹。如果你的团队只有一两个模型、调用量很小直接用官方 SDK 完全足够。但一旦你发现自己开始维护三四个 SDK、五六把密钥并且还要跟不同团队解释“为什么这个模型调用方式不一样”那这就是一个信号你需要的不是更多封装而是一个统一入口。我建议可以从最小配置开始先把一个聊天模型跑通再逐步加负载均衡、预算、密钥管理。不要一上来就把所有功能都配置齐全否则排障的时候容易被一堆配置项绕晕。跑通之后你会慢慢发现这套东西真正的价值所在。