☰
大模型多供应商接入不再难:用litellm构建统一API网关
2026/10/13 18:48:55 网站建设 项目流程

多家大模型服务商的接口风格不统一,每次新增一家供应商就要改一批业务代码,这种日子我过了大半年。后来被逼着做统一接入层,才真正把litellm这个项目用起来。它不是某个大厂的商业方案,而是一个开源的轻量级工具库,既能当 SDK 嵌入业务系统,也能当作独立代理服务统一分发模型请求。对靠 API 做产品的团队来说,这个项目最值钱的地方在于:把几十家模型服务商的差异全部收敛到一个标准接口后面,业务侧只需要维护一个客户端配置,模型商怎么换、参数怎么变,都由它去消化。

如果你也在做 LLM 相关应用,被多供应商接入、费用统计、负载均衡这些问题烦过,这篇文章值得花十分钟看完。里面没有任何广告,全部是我自己实际试过的接入流程、配置参数和排坑记录,也包含一些网上文档没写清楚的取舍逻辑。

1. 为什么同一套业务代码要对接八家模型服务商

1.1 多供应商调用需求是怎么来的

早期我参与的项目只接了一家模型服务商,SDK 固定、接口固定,上线跑得很顺。到了下半年产品要支持更多场景,同一个功能在有些场景下需要更快的响应,在另一些场景下追求更低成本,于是名单从一家扩展到多家。问题随之而来:每家供应商的请求格式不一样,鉴权方式不一样,错误码定义也不一样,连模型名称都各叫各的。

当时业务服务里开始出现大量if (provider equals xxx)的分支,每个分支里塞一套独立的 HTTP 调用逻辑。模型供应商增加一个,分支就多一套,代码量指数上升。更要命的是,上游供应商修改了响应字段,我需要逐个接口排查,测试成本非常高。产品迭代节奏因此被拖慢,连带着线上问题的定位也变困难。

这种情况下最合理的做法,不是继续往下堆分支,而是在业务层和模型服务商之间增加一个统一的接入层。业务层只需要面对一种接口协议,剩下的鉴权、格式化、转发、重试全部交给接入层处理。litellm能替代自己写的这套接入层,并且比我预想的考虑得全面很多。

1.2 统一接入层要解决的四类问题

归纳下来,业务侧真正需要统一层解决的是四类问题:

  • 接口协议统一:不管后端请求的是哪种风格的服务商接口,统一层对外只暴露一种调用方式,参数命名、返回结构保持一致。
  • 鉴权信息收敛:不同服务商的 API 密钥不再散落在各个业务服务里,而是集中配置在接入层,权限回收、密钥轮换都在一处完成。
  • 成本与用量可观测:每个请求用了哪个模型、消耗了多少 Token、花了多少钱,都要有统一口径的记录,否则月底对账完全靠猜。
  • 故障转移与负载均衡:某一家服务商超时或限流时,接入层能把请求自动切换到备用的服务商,而不是让业务端自己处理异常。

这四个问题,litellm都有对应的能力。它最擅长的就是把不同模型服务商的请求格式转换成统一的内部表示,再转成目标服务商的格式发出。业务端拿到的是一个标准响应对象,不管背后实际请求的是哪家,解析逻辑都一样。

1.3 为什么不是自己写一个 Request 中转模块

很多人第一反应是自己写一个中转模块,把几家服务商的请求转发逻辑包一层。我也这么写过,写完之后才感受到维护成本比想象中高太多:每家服务商的 SDK 版本在更新、接口字段在变动、新模型不断出现,同一模型在不同供应商那里的名字还不一样,自己维护一个适配层,相当于给自己请了一份全职工作。

开源项目的优势是社区已经把大量适配工作做完了,支持的供应商列表越来越长,模型映射表也在持续更新。你只需要升级依赖,就能获得新的适配能力。自己写的模块做不到这种同步速度,尤其在模型服务商快速迭代的现阶段,跟进成本极高。

2. litellm 到底帮你管了哪些事

2.1 它既不是 SDK 也不是纯网关

我最开始对litellm的认知有些偏差,以为它只是一个类似统一 SDK 的 Python 库,后来发现它还自带一个高性能代理服务,可以独立运行。换句话说,它同时提供两种使用方式:嵌入式模式和代理模式。

嵌入式模式适合业务服务直接调用,Python 代码里引入包后,使用统一接口发请求,适合单体应用或 Python 技术栈的团队。代理模式则是把它启动为一个独立服务,业务端通过 HTTP 接口访问,适合多语言团队、多个服务共用一个接入层的场景。

这两种模式不是互斥的,甚至可以配合使用。比如让代理承担统一的鉴权和费用记录,业务服务则通过标准 OpenAI SDK 风格接口去调用代理。能让现有代码几乎零改动迁移,这种兼容性设计是它比较讨喜的地方。

2.2 请求转换和模型映射的价值

真正花功夫的部分是请求转换层。不同服务商的系统提示词格式、模型名称、温度参数上限、Token 计算方式各不相同,litellm内部维护了一套模型映射表,可以把统一的请求参数翻译成每个服务商能理解的格式。

以模型名称为例,同一类能力在不同供应商那里可能叫 A、B、C 三个名字,你在业务代码里只需要写一个内部的通用名,由litellm映射到实际供应商的模型。如果有一天你决定把所有请求切换到一个新的供应商,业务代码不需要改动,只需要修改接入层的映射配置。

2.3 返回結果结构化处理

不同服务商的返回结构差异很大,有的直接返回文本,有的返回带思考链的结构,有的把拒绝原因放在一个独立字段里。litellm会把它们统一成大家都熟悉的风格,比如补全内容字段、Token 使用量字段、结束原因字段。

我实际感受是,这种结构化处理在日志分析和成本核算时特别省事。之前自己做转发层,每个供应商的 Token 统计字段都不一样,统计费用还得写一堆兼容代码。用统一结构之后,一行代码就能把每次请求的 Token 消耗和费用归档到数据库。

3. 先跑通嵌入式调用再考虑部署网关

3.1 安装和最小可用实例

建议从嵌入式模式开始,先把litellm跑通,理解它的请求模型之后,再上代理模式。安装很简单,使用 Python 的依赖管理工具即可,推荐创建独立的虚拟环境,避免污染全局 Python 环境。

python -m venv llm_env source llm_env/bin/activate pip install litellm

最小调用代码如下,把服务商密钥配置到环境变量后,直接指定模型名称发起请求:

import os import litellm os.environ["PROVIDER_A_API_KEY"] = "你的密钥" response = litellm.completion( model="provider-a/model-name", messages=[{"role": "user", "content": "你好,请介绍一下你自己"}] ) print(response["choices"][0]["message"]["content"])

这里比较关键的是model参数的写法,格式是服务商名称/模型名称。litellm会解析出服务商前缀,然后按对应的鉴权方式、接口协议去调用。如果你不写服务商前缀,它还会尝试从已配置的密钥环境变量中自动推断,但建议在代码里写清楚,避免歧义。

3.2 消息格式转换带来的参数兼容问题

很多从某一家服务商直接迁移过来的项目,总以为消息格式是通用的,实际并非如此。有的服务商把系统消息单独放一个字段,有的要求所有消息走同一个列表,有的不支持某些角色类型。litellm会做转换,但是转换过程中可能丢一些非标准字段。

如果你用到了某家服务商特有的参数,比如某个特定的采样开关,需要确认它在统一参数中是否有映射。litellm的 实现中提供了extra_body或自定义参数的透传能力,必要时应使用这个能力把这些特殊字段传给后端。该透传时就透传,不要硬套统一模型,否则特殊参数会被静默丢弃。

3.3 异步调用和流式输出

实际业务中同步调用撑不住高并发场景,需要在上线前改用异步和流式。

import asyncio import litellm async def stream_chat(): response = await litellm.acompletion( model="provider-a/model-name", messages=[{"role": "user", "content": "用流式方式输出一段文字"}], stream=True ) async for chunk in response: delta = chunk["choices"][0]["delta"].get("content") if delta: print(delta, end="") asyncio.run(stream_chat())

注意流式响应的结构可能因服务商而异,但在统一层内它会尽量收敛成一致的增量块格式。实际项目里,如果出现首字延迟过高,问题往往不在统一层,而在后端服务商的流式响应速度,排查时要分清楚责任边界。

4. 把代理网关部署到生产环境的细节

4.1 为什么最终选择了代理模式

嵌入式模式验证完能力之后,我最后把生产环境的接入层改成了独立代理服务。原因有三点:

  • 业务服务由多个团队维护,技术栈不完全一致,统一用 HTTP 调用比强迫所有团队引入同一个 SDK 更现实。
  • 密钥和预算策略需要集中管控,放在业务代码里容易被无意间泄露到日志。
  • 上游服务商如果发生变化,只需要维护代理的配置,不需要要求各业务团队重新发版。

代理服务的部署形态很简单,它是基于 Python Web 框架实现的,可直接用进程管理器或者容器方式托管。我这边是使用容器方式部署的,一个实例承载了所有模型请求的中转。

4.2 基本启动配置

启动代理前需要准备一份配置文件,用于声明要从哪些服务商请求、模型如何对应、费用如何记录。配置格式是 YAML,看起来直观。

model_list: - model_name: text-sm litellm_params: model: provider-a/model-a-mini api_key: os.environ/PROVIDER_A_API_KEY model_info: max_tokens: 4096 - model_name: text-large litellm_params: model: provider-b/model-b-pro model_info: max_tokens: 8192

启动命令:

litellm --config config.yaml --port 4000

启动后,业务侧可以通过兼容接口访问代理。只要请求中的model字段填的是配置里的text-sm或text-large,代理就会按配置转发到对应的真实模型服务商,响应格式和原版一致。这个设计大大降低了业务方的迁移成本,之前用标准接口的项目,只需要修改 base_url 就能切换过来。

4.3 环境变量注入密钥的安全做法

千万不要把密钥直接写进 YAML 文件提交到代码仓库。实践中的安全做法是配置中引用环境变量,密钥由发布系统注入,仓库里只保留占位符。具体写法是在api_key字段填os.environ/变量名,代理启动时会从环境变量读取。

在配置管理方面,至少要把以下信息分开管理:模型列表属于代码配置,密钥属于敏感配置,费用预算属于运行时配置。三者混在一起是事故发生的高发原因。

4.4 网关层面的权限校验

代理如果不做任何校验,相当于把你的模型资源开放给外网,风险极大。我见过有人把代理端口暴露到公网,被刷了几百块钱费用才发现。最少要在代理前面加一层带密钥的鉴权,比如要求所有请求携带一个统一的访问令牌,代理校验通过后才允许转发。

更细的做法是按业务线划分不同令牌,每个令牌绑定不同的模型访问范围和预算上限。这样某个业务线泄露了令牌,损失可以被限制在最小范围内。

5. 预算控制、负载均衡与失败重试的配置思路

5.1 预算策略从前端限制做起

模型调用费用不像普通服务器账单那么直观,它跟请求量、输入长度、输出长度强相关,同一个模型不同时段价格还可能不同。如果不做限制,线上一个 bug 可能导致无数个循环请求,费用快速上升。

litellm支持设置预算上限,可以按团队、按密钥、按照用户维度限制。我常用的配置是给每个业务线分配一个最大消费额度,接近上限时开始告警,达到上限时直接拒绝新请求,并返回一个自定义错误信息。

router_settings: budget_budget_duration: 30d max_budget: 1000

配置说明:这里的max_budget是按美元计价的硬上限,budget_budget_duration是滚动周期。建议初始阶段先设置一个偏保守的额度,运行一段时间之后根据实际用量再放宽。

5.2 负载均衡路由算法

当同一个模型逻辑被映射到多个供应商时,代理可以把请求分配到不同供应商上。比如保证高可用,主供应商故障时切换备用;或者追求成本均衡,按预设比例把流量分散到不同服务商。

配置示例:

router_settings: routing_strategy: simple-shuffle

更高级的路由可以通过权重配置实现,把routing_strategy换成带权重的策略。需要强调的是,路由策略要配合健康检查机制使用,否则会把请求持续转发给一个已经不健康的供应商,导致大量超时。

我在生产环境把主用和备用供应商设置了不同的优先级,并开启了自动重试。某个供应商连续返回限流错误时,代理自动将请求转发到备用供应商。这一配置上线后,某次主供应商大面积故障期间,业务几乎无感知。

5.3 重试次数和退避策略怎么调

重试机制是统一接入层最有价值的能力之一,但也是最容易配错的地方。核心问题不是要不要重试,而是重试策略是否符合被调用服务商的实际限流逻辑。

我踩过的坑是:重试次数设得太大,退避间隔又太短,高负载时段把限流推得更严重。后来把重试次数降到三次,并采用指数退避加抖动,等待时间从 1 秒开始递增,效果明显改善。

配置里的相关参数通常包括max_retries、timeout和退避系数。线上建议至少留 30 秒的总等待时间,既不影响用户体感,又给后端留出恢复窗口。

5.4 费用记录与对账

代理模式的另一个好处是统一记录了所有请求的 Token 消耗和费用信息。这些数据默认存储在本地数据库中,也可以配置为导出到外部监控系统。

我每周会对一次账,把代理记录的总费用和各供应商后台的费用明细做比对。刚开始总有小差异,原因是各家统计工具的统计口径不同,对输入输出 Token 的定义有细微差别。后来统一以代理记录为准,供应商后台数据只做参考,差异在合理范围内即可,不需要追求完全一致。

6. 集成过程中容易踩的坑与排查方法

6.1 模型名称写错导致连带失败

最普遍的错误是模型名称不规范。一种是忘了写服务商前缀,另一种是模型名称中的版本号不对。这两类错误通常在调用时才会暴露,表现为 404 或模型不存在错误。

排查方法很简单,看代理的日志,里面会记录最终发给目标服务商的模型名和接口地址。先用最小调用脚本逐家验证,确认每家都能独立连通,再接入统一层,不要一上来就调代理。

6.2 超时时间设置不当引发雪崩

模型生成本身耗时较长,尤其在输出很长时,单次请求可能几十秒才返回。如果给代理配了太短的超时时间,它会把正常的慢请求当作失败,触发重试逻辑,导致服务商并发翻倍,然后又反过来加剧耗时。

处理方式:不要把全局超时设成统一的固定值,而要根据模型复杂度单独配置。比如轻量模型 30 秒,大模型 120 秒。配置允许为不同模型设置不同超时时间,灵活度很高。

6.3 本地存储爆满和日志轮转问题

代理有一段运行时间之后会出现本地数据库文件快速增长的情况。原因是每个请求的详细数据都会被落盘,在流量大的时候数据量相当可观。

我没有特意去关闭日志,而是做了两件事:一是把历史请求的保留周期缩短,二是在系统层面配置日志轮转。如果模型调用量特别大,建议把请求记录接入外部数据存储,避免本地磁盘成为瓶颈。

6.4 某家供应商密钥失效后的可视化

供应商密钥有有效期,密钥失效时如果代理仍继续尝试调用,会返回鉴权错误,而且可能多次重试浪费延迟。这个问题不是一次性配置就能解决的,需要在监控里把鉴权错误单独分类,设置明确的告警规则。

我在实际过程中专门建立了一个错误码映射表,把各家服务商返回的鉴权错误统一映射为同一个错误码。这样无论是哪家供应商密钥失效,业务团队都能从日志里一眼识别,不会因为各家报错词汇不同而误判。

7. 和技术团队自研封装相比,怎么决策

7.1 开发成本和长期维护对比

自研封装的初始成本看起来不高,就是一个 HTTP 转发函数加几张映射表。但长期维护成本会逐渐超过使用开源方案的成本。原因在于模型服务商更新频繁,每次接口调整都要跟上。个人维护时,这块工作的持续性很难保证。

用litellm之后,这部分升级工作由开源社区承担,你只需要在合适时机升级版本。升级可能出现不兼容情况,但概率总体可控,风险远低于完全自己维护。

7.2 可扩展性是不是短板

开源项目也存在定制空间不足的问题,这是所有开源方案的通病。如果你有一些非常特殊的内部需求,比如需要和内部权限系统深度打通,或者需要对响应做精细的后处理,可能需要在代理外面再包一层服务,或者基于它的回调机制做二次开发。

实际项目里我们做了两件事:一是通过预调用来实现内部权限校验,二是在代理外部增加一个薄薄的定制层,专门处理那些需要结合内部业务逻辑的场景。这样既保留了开源方案的能力,又满足了定制要求。

7.3 决策建议落地经验

我的建议是,如果团队只有一个模型服务商,后续也暂时没有增加的计划,直接用官方 SDK 即可,完全不需要引入统一接入层。一旦规划中的服务商数量大于两个,或者已经在两个以上间切换过,立即引入统一接入层,越早成本越低。

不过有一点要清醒:litellm并不能解决模型能力本身的问题。它只是把调用过程变得标准化,让业务代码不必跟着服务商一起变。模型选型、成本评估、效果调优这些工作,仍然需要业务团队自己做判断。

8. 写在最后的扩展用法与个人体会

8.1 从统一调用层开始逐步搭建内部 LLM 平台

几个月的实际使用让我体会到,litellm适合作为内部大模型平台的底座。业务团队把它当作一个标准的模型入口,所有模型请求从这一个口子进出。后续接新的供应商时,业务侧完全无感,模型团队只需要更新映射配置和验证效果。

往这个方向上扩展,还能接上更丰富的模型管理能力。比如为不同的业务场景提供不同的模型别名,为不同类型的调用设置不同的优先级,再配合监控系统做 SLA 分析,整个内部 LLM 平台就能从"能调用"进化成"能治理"。

这个思路适合任何规模在增长、模型调用开始变得复杂的团队,不管是从零起步,还是已经有一个自研转发层想迁移,都可以参考。

8.2 我的几点经验总结

如果不是一开始就理解了嵌入式模式和代理模式的区别,我大概会在部署架构上走不少弯路。建议先小范围用嵌入式模式做概念验证,确认统一接口能满足业务需求后,再上代理模式,这个过程会比较平稳。

配置代理的服务名、超时、预算时,不要追求一步到位。先保守,再逐步调整。线上环境永远按最小的可运行集开始,加上完整的监控告警,再逐步完善策略,这是我多次踩坑之后得到的经验。

最后,无论选用哪种方式,密钥管理都必须放在第一位。我对接过的项目里面,因为密钥泄露导致费用异常的,比模型调用异常多出好几倍。接入任何统一层之前,先把安全边界画清楚。

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

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

立即咨询