☰
litellm 实战:构建统一多模型调用网关
2026/10/14 8:52:44 网站建设 项目流程

多模型接入这件事,几乎每个做过 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 以上。安装方式推荐用 pip:

pip install "litellm[proxy]"

这里proxy是额外依赖项,包含运行 HTTP 网关需要的组件。如果你只用 Python SDK 做统一调用,不打算启动网关服务,可以只装litellm本身。我在最开始只装了基础包,后来发现要用管理接口和虚拟密钥,才补装完整依赖。装好后可以通过命令行确认版本:

litellm --version

另外准备一份后端模型服务商的 API 密钥。这一步不要直接把密钥写进业务代码,而是准备放到 litellm 的配置里。

3.2 写一份最小可用的 config.yaml

litellm 的核心配置是一个 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-key"

3.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( model="unified-chat", messages=[ {"role": "user", "content": "你好,请用一句话介绍你自己"} ], api_base="http://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 写的网关,如果单位时间请求量很大,单实例的性能可能会成为瓶颈。先不用急着做复杂架构优化,我建议从下面几件事开始:

  • 开启流式输出。大部分聊天场景用stream=True能明显降低首 token 延迟,用户体验好很多。
  • 使用异步调用。litellm 支持 async 接口,配合asyncio.gather可以做并发请求。我在内部测试中,把一批独立请求从串行改成并发后,整体耗时下降非常明显。
  • 缓存同一类结果。如果业务中大量请求是重复问题,可以开启缓存,比如同一段消息在短时间内直接返回缓存结果,减少后端调用。
  • 连接池调优。保持与后端服务商的连接复用,减少 TLS 握手开销。

如果单实例确实不够,litellm 也支持水平扩展。网关无状态部分可以放在多个实例后面,用负载均衡器分发,状态数据统一存放在数据库和 Redis 中。Redis 在缓存速率限制、预算计数和语义缓存方面很有帮助。

6.2 从网关到内部模型平台的演进

litellm 做网关只是第一步。我实际项目中把它当成一个基础底座,在其周边陆续接入了模型效果评测、数据集管理、灰度发布。比如新模型上线时,先用某个团队密钥绑定新模型灰度跑一段时间,观察日志里的延迟和错误率,稳定后再切换主路由。这些能力 litellm 本身不一定全部提供,但它暴露的 API 和管理接口很适合被上层系统调用。

如果后续想做得更完整,还可以接入提示词模板管理、多环境隔离、审计日志分析等。我看到很多团队会基于 litellm 再做一个对内的模型管理后台,让非技术同事也能自助申请密钥、查看用量。这种演进路径比一开始就自研一套模型平台要平滑得多。

7. 几点个人体会

最后聊一点我自己的使用感受。litellm 最让我满意的地方,不是它帮我省了多少行代码,而是把“模型切换”变成了一件不需要发版的事。以前的流程是:业务改了需求,我改代码,测试,排队上线。现在的流程是:改一份 YAML,重载配置,完事。这类体验带来的开发效率提升,比想象中更明显。

当然,它也不是银弹。如果你的团队只有一两个模型、调用量很小,直接用官方 SDK 完全足够。但一旦你发现自己开始维护三四个 SDK、五六把密钥,并且还要跟不同团队解释“为什么这个模型调用方式不一样”,那这就是一个信号:你需要的不是更多封装,而是一个统一入口。

我建议可以从最小配置开始,先把一个聊天模型跑通,再逐步加负载均衡、预算、密钥管理。不要一上来就把所有功能都配置齐全,否则排障的时候容易被一堆配置项绕晕。跑通之后,你会慢慢发现这套东西真正的价值所在。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询