☰
LiteLLM 统一接入多家大模型:LLM API网关部署与生产实践
2026/10/13 5:06:16 网站建设 项目流程

做 AI 应用后端的人,大概率都遇到过这个场景:上午刚接完 OpenAI 的接口,下午产品又提需求说要支持 Anthropic 的模型;再过两天,客户要求换成 Azure 的部署实例,或者试用一下开源模型的兼容端点。每家 API 都有自己的鉴权方式、报文结构、错误码,SDK 也各写各的。你只能被迫维护一层又一层适配代码,越堆越多。我最早处理这个问题的方式很粗暴:写一个内部中转服务,把各家 API 的差异“捂”在自己的工具函数里。直到后来用了 LiteLLM,才意识到这类问题其实有更省心的解法。

LiteLLM 是一个开源的 LLM API 网关 / 统一代理层,核心能力是让你用一套接口、一套 SDK、一套鉴权逻辑去调用市面上主流的大模型服务商,同时还能做负载均衡、故障回退、预算控制、密钥管理和调用观测。它不是某个模型本身的封装,而是站在你业务系统和各家模型 API 之间的“中间层”。这个定位决定了它适合的场景非常集中:后端服务、平台型产品、需要给多个内部团队开放模型能力的中小型公司,以及那些今天换模型、明天换供应商、后天又要做成本分摊的开发者。

这篇文章我会从原理讲到实操,再用生产环境踩过的坑来收尾。内容偏工程向,但我也尽量把关键概念解释得直白一些,方便新手把整个逻辑串起来。

1. LiteLLM 到底是什么?为什么这类工具会冒出来

1.1 一个代理层解决“模型碎片化”问题

先看最原始的矛盾。OpenAI 的 Chat Completions 接口和 Anthropic 的 Messages 接口看起来都是在“发消息、拿返回”,但实际请求体差异很大:模型名写法不同、系统提示词的位置不同、工具调用的结构不同、流式输出的数据格式也不完全相同。更别提各家对 JSON 模式、视觉输入、结构化输出的支持等级参差不齐。

业务系统如果直接接这些 API,代码里就会长满 if-else。今天判断“如果是 OpenAI 就走 OpenAI SDK”,明天判断“如果是 Claude 就走 Anthropic SDK”。这种逻辑一旦多了,就会开始出现奇怪的 bug:同一个 prompt 在 A 模型上没问题,在 B 模型上因为字段结构问题频频报错。你很难抽象出一个统一的接口层,因为每一家 SDK 的“个性”太强了。

LiteLLM 做的事情,简单说就是把这些差异吞掉。它对外提供一套和 OpenAI SDK 兼容的接口格式,对内再把你的请求翻译成各家模型真正需要的样子。你的业务代码永远只针对一个接口地址做调用,至于后面是 Azure 还是 Bedrock,是开源模型还是商业模型,由代理层自己判断。

这个思路很像后端开发里的 API 网关:客户端不直接面对微服务集群里的每个节点,而是先经过一层网关联动路由、鉴权、限流和监控。LiteLLM 对你的大模型调用做的正是这件事。

1.2 它和“直接调各家 SDK”的本质区别

很多人一开始会问:我直接调官方 SDK 不是更简单吗?模型能力是官方给的,参数文档也是官方的,何必中间多一层代理?

这个问题本身没错,但它前提是“你只服务一个模型供应商、只服务一个业务方、不需要做任何成本管控”。一旦你的系统需要面对多个供应商,直接调官方 SDK 的维护成本会迅速上升。举个例子:你给客户 A 开了 Anthropic 的模型,给客户 B 开了 OpenAI 的模型,两个客户都要通过同一套后台去调用,那你如何统一计费?如何限制某个客户不能调用贵模型?如何做到模型出了故障自动切换到备用模型?这些能力官方 SDK 通通不提供,你得自己写。

LiteLLM 的价值就在于把这些“业务工程问题”提到代理层统一解决。它在技术上并不复杂,但设计目标很明确:让你不必为每家供应商各写一套调用逻辑,也不必为了“多租户成本分摊”去另起炉灶。对比之下,官方 SDK 更像是“把某个 API 封装好给你用”,而 LiteLLM 是“把一群 API 变成一个可运营的系统”。

1.3 这套思路适合谁,不适合谁

以我接触过的项目来看,最适用的人群有三类:

  • 做 SaaS 平台,需要让外部用户通过统一的接入密钥调用不同模型。
  • 公司内部有多个算法团队、后端团队,每个人申请模型密钥都要走审批,领导还希望看每个团队花了多少钱。
  • 业务需要多模型轮询或回退,比如主模型挂了自动切备用,或者某些请求分给便宜的模型处理。

不适合的情况也有。比如你只需要固定调一个模型,没有任何成本管控需求,那么上 LiteLLM 完全是多此一举,直接写 SDK 半小时就搞定。又比如你在边缘设备或资源受限环境内跑,不希望中间再塞一个 Python 服务,那直接用轻量 SDK 也更合适。LiteLLM 的定位非常明确:它解决的是“多模型、多租户、可观测”的组织级问题,而不是“帮我少写几行调用代码”的个人便利问题。

2. 核心功能拆解:这些能力决定了它值不值得引入

2.1 统一格式转换与模型路由

LiteLLM 最底层的功能是格式转换。你发一个 OpenAI 风格的请求体过来,它会根据你声明的模型提供商,把消息内容重新组装成对应 API 的格式。这个过程对使用者透明:你不需要知道 Claude 的 system prompt 要单独放一个字段,也不需要担心 Gemini 的 roles 和 OpenAI 不完全一致。

模型路由主要靠 config 文件里的model_list来实现。每一个条目定义一个对外暴露的模型名(model_name),并映射到某个真实模型的调用参数(litellm_params)。调用方只需要记住“这个系统里叫gpt-4o-mini的模型”,不需要关心它背后是从 OpenAI 调、从 Azure 调,还是经过某个兼容协议转发到自建模型服务。

这里有个容易混淆的点:如果你不写model_list,直接用model: "openai/gpt-4o-mini",LiteLLM 也能工作,它会根据前缀猜测该走哪家供应商。但生产环境建议把所有模型显式声明在配置里,因为这样你才能控制路由权重、给它绑定密钥、加预算限制,出了问题也能一眼看清配置。

2.2 负载均衡、重试与回退

这是 LiteLLM 的第二个核心价值。同一个对外模型名可以配置多个上游实例,比如你在 OpenAI 和 Azure 都部署了同一个模型,LiteLLM 会在它们之间分配请求。分配策略支持简单的轮询,也支持自定义权重——比如某个供应商稳定性高,就给它的权重调大一些。

重试机制也比较实用。当上游返回 429 限流、5xx 错误或者超时的时候,LiteLLM 可以自动重试。它知道哪个供应商现在大概率不可用,会优先把请求切到其他实例。更高级的用法是配置fallbacks:主模型失败时,整个请求自动转发给备用模型。这个功能做客服机器人、做稳定性要求高的服务时非常有用。你不需要在业务代码里写一堆 try-catch 再手动切模型,代理层会把失败请求消化掉。

但我要提醒一点:回退机制虽然省心,不是没有任何副作用。备用模型能力和主模型不一定是完全对齐的,同一个 prompt 可能会得到不同风格的结果。业务上如果要保证“非某个模型不可”,那建议别配 fallback,宁可失败也要透明;如果只是追求“别让用户看到报错”,那 fallback 就很香。

2.3 预算控制、限流与密钥管理

我见过很多团队用 LiteLLM,最大的诉求反而是成本管控。AI 应用最怕一件事情:某个测试脚本忘了关循环,一夜之间把预算烧光。官方控制台虽然有 usage 页面,但那是整个账号的,你没法针对某个业务线、某个客户做独立限制。

LiteLLM 的解决方案是引入“虚拟密钥”概念。管理员有一个 Master Key,然后通过这个 Master Key 创建一堆子密钥。每个子密钥可以设置:

  • 允许调用的模型范围。
  • 单个请求上限、每分钟请求次数上限、每分钟 token 上限。
  • 总预算额度,比如“这个密钥一个月只能花 50 块钱”。
  • 过期时间,到点自动失效。

子密钥分发给不同团队,谁花了多少钱一目了然。这比直接给每个人发官方密钥安全得多,哪怕某个子密钥泄漏了,也不会影响到主账号,还能立刻吊销。按我的经验,只要系统开始有“第三方接入”的需求,虚拟密钥这个功能基本是刚需。

2.4 观测、日志与缓存

大模型应用和传统接口有个很大区别:调用结果不是事务性的,你很难用数据库状态去判断一次调用成功没成功。因此观测就显得格外重要。LiteLLM 内置了日志回调机制,可以把每次调用的模型、token 消耗、延迟、错误信息统一转发到你自己的日志系统或者可观测平台。

它还支持缓存配置。如果业务里有大量重复请求——比如多个用户问同一个知识库问题——缓存命中之后就可以省掉一次真实模型调用。缓存支持内存、Redis,也有语义缓存选项,能将相似问题映射到同一个答案。这个功能对降低成本很显著,但对一致性要求高的场景需要谨慎,模型输出本来就不是确定性的,缓存可能让用户觉得“系统不会变”。

3. 从零搭建一套 LiteLLM 网关:部署与配置实操

3.1 配置文件到底怎么写

LiteLLM 的核心配置是一个 YAML 文件,里面主要包含model_list、litellm_settings、general_settings这几个大块。我先把一个最小可用的示例贴出来,之后逐个解释。

model_list: - model_name: gpt-4o-mini litellm_params: model: openai/gpt-4o-mini api_key: os.environ/OPENAI_API_KEY - model_name: claude-3-5-sonnet litellm_params: model: anthropic/claude-3-5-sonnet api_key: os.environ/ANTHROPIC_API_KEY - model_name: mixed-azure-openai litellm_params: model: azure/gpt-4o-mini api_key: os.environ/AZURE_API_KEY api_base: os.environ/AZURE_API_BASE litellm_settings: drop_params: true request_timeout: 60 general_settings: master_key: sk-your-master-key-change-me database_url: os.environ/DATABASE_URL

第一眼看上去,model_name和下面litellm_params.model的关系最容易搞混。model_name是对外暴露的名字,你的业务代码请求时用的就是它;litellm_params.model是真正上游模型标识。带openai/、anthropic/、azure/这类前缀,是为了告诉 LiteLLM 应该用哪套协议去解析这个上游模型。如果你在litellm_params.api_key里直接写明文密钥也可以,但用os.environ/XXX的方式读取环境变量更安全,避免配置文件被推送到 Git 里泄露。

这里有一个常见误区:drop_params: true表示“当某个上游模型不支持传入的某些参数时,自动丢弃而不是报错”。例如 OpenAI 可能接受response_format,但某些兼容端点不支持,drop 掉之后请求还能继续。这个开关很实用,但也会掩盖掉一些你想保留的行为,所以我建议只在确实有多模型混用需求时开启。

3.2 Docker 部署与启动流程

我个人最推荐的部署方式是 Docker Compose,原因很简单:LiteLLM 的依赖比较多,直接 pip 装容易把系统环境搞乱,而容器化之后升级、回滚、扩副本都很方便。

先准备一个最简单的docker-compose.yml:

version: "3.9" services: litellm: image: ghcr.io/berriai/litellm:main-latest container_name: litellm ports: - "4000:4000" volumes: - ./config.yaml:/app/config.yaml environment: - OPENAI_API_KEY=${OPENAI_API_KEY} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - DATABASE_URL=${DATABASE_URL} command: ["--config", "/app/config.yaml", "--port", "4000", "--num_workers", "4"]

启动命令其实就是一个docker compose up -d。启动完成后,默认会监听 4000 端口。然后你可以直接发一个请求测试:

curl http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-your-master-key-change-me" \ -d '{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "你好,请用一句话介绍自己"}] }'

这个接口路径和 OpenAI 的规范基本一致,/v1/chat/completions、/v1/models这些都能直接用。如果你的业务代码用的就是 OpenAI SDK,那把base_url指过来即可,模型名换成配置里声明的model_name。

--num_workers这个参数值得认真调。默认数值可能比较小,而在高并发场景下,worker 数量不够会表现为“延迟忽高忽低”或者“CPU 明明没跑满但请求就是上不去”。但我也不建议无限加大,worker 太多会带来额外的内存开销,通常和 CPU 核数保持一个合适比例比较稳妥。

3.3 虚拟密钥、多租户和数据库配置

要让虚拟密钥功能真正跑起来,你需要接一个数据库。LiteLLM 支持 PostgreSQL、MySQL 等常见数据库,推荐直接用 PostgreSQL 实例。配置里写上database_url后,启动时它会自动建表。

创建虚拟密钥的请求长这样:

curl http://localhost:4000/key/generate \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-your-master-key-change-me" \ -d '{ "models": ["gpt-4o-mini", "claude-3-5-sonnet"], "max_budget": 50, "budget_duration": "30d", "max_parallel_requests": 10 }'

请求成功后会返回一个key字符串,或者你直接在/ui管理界面上创建也可以。这个 key 分给某个团队之后,它的所有调用都会计入预算。max_parallel_requests限制并发,防止某一个调用方把网关打满。

实际使用中,我认为一个比较好的组织方式是:每个业务线或每个客户一套 key,模型白名单控制在它真正会用到的模型上。这样做的好处是,即使某个 key 泄露,你能快速定位到影响范围,并且可以把损失限定在单个租户内,而不是整个平台挂掉。

3.4 用 OpenAI SDK 接入的完整示例

部署好网关之后,业务侧接入只需要改两处:base_url和api_key。下面是一个 Python 示例:

from openai import OpenAI client = OpenAI( base_url="http://localhost:4000/v1", api_key="sk-your-virtual-key", ) resp = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": "讲个段子"}], temperature=0.7, ) print(resp.choices[0].message.content)

Node.js、Java 这些语言也都一样,只要是 OpenAISDK 兼容的客户端,改一下 base_url 就能接入。这也是 LiteLLM 一个很聪明的设计:它没有自定义一套全新协议,而是选择兼容已有生态,这样迁移成本极低。很多团队从直连 OpenAI 迁到网关,改动量只有环境变量里的几百字符。

有一点要强调:当你在代码里传model="gpt-4o-mini"时,它指的是你在 LiteLLM 配置里定义的名字,而不是 OpenAI 官方模型名。如果你通过 LiteLLM 调用官方模型但配置里没声明,也可以用model="openai/gpt-4o-mini"这种带前缀的形式直接传,LiteLLM 会按前缀去匹配供应商。

4. 生产环境踩坑记录:这些问题我排查了一整晚

4.1 流式输出延迟或直接不返回

我刚把 LiteLLM 部署好时,第一个遇到的大坑就是流式调用。业务端用stream=True请求,LiteLLM 也把响应流式返回,但某些模型就是偶尔卡住,表现为前端收到一句半句就停住,直到超时。

排查了很久后发现,问题出在request_timeout和上游模型本身的输出节奏上。流式模式下,如果第一个 token 等了很久才到,或者两个 token 之间间隔较长,LiteLLM 默认的超时策略可能会误判为超时。后来我把request_timeout调大,并且给流式请求单独做配置,情况就好很多。另一个原因是上游模型本身延迟高,LLM 首 token 时间普遍比普通 HTTP 接口长,不能拿传统 API 的超时标准来套。

4.2 预算数据不刷新,显示一直不准

虚拟密钥控制预算量其实分两个阶段:请求进入时先做一次“预检查”,请求结束后再异步上报实际 token 消耗。如果你在数据库里看成本数据,可能会有延迟。尤其在高并发下,异步任务的积压可能让某个 key 的实际消费额看起来很低,但后面突然跳变。

遇到这个问题的正确做法,不是去改数据库,而是提高后台处理任务的并发能力,并且确认部署了足够多的 worker。LiteLLM 文档里对这类任务队列也有说明。总之,预算功能能做“事后结算”和“事前拦截”的双重保障,但如果你只依赖它做实时强管控,需要把上报延迟考虑进去。

4.3 权重路由不生效:请求总是打到同一个上游

配置了多个上游实例、也配置了权重后,我一度发现所有请求还是被打到第一台上游。后来细看才发现,问题在于我配置了某种“会话亲和性”策略。在很多网关里,如果开启了基于用户或会话的粘滞路由,同一个调用方会一直被路由到同一个实例,这是故意的,而不是 bug。

如果业务不要求“同一用户必须走同一模型实例”,那这类亲和策略最好关掉,否则负载均衡形同虚设。另外还要检查一个点:如果上游实例的模型名完全相同,LiteLLM 默认情况下可能会把它们当成一个模型做轮询,但前提是配置里确实写了多条litellm_params,而不是写在了同一条里。

4.4 模型参数传不过去,报“不支持该参数”

这是多模型网关最容易出现的兼容性问题。OpenAI 支持response_format、tools、seed这些参数,但转成其他厂家模型时,LiteLLM 必须决定怎么处理参数。有些参数它实现了转换,有些参数它直接不支持。当你在请求里带了一个 LiteLLM 无法映射的参数时,默认行为是报错。

我当时用drop_params: true解决了大部分问题,但也引出了新问题:某些希望严格的校验场景里,参数被静默丢弃后,模型输出质量明显下降。现在我的习惯是分模型写配置:支持度高的大模型不开 drop,兼容性差的小模型才开。这不是标准答案,但更符合实际业务需要。

4.5 连续请求导致内存涨个不停

有一次生产环境跑了一周后,容器内存越涨越高。起初以为是内存泄漏,后来在日志里发现,我打开了过多的日志回调,而回调里又把完整请求体、响应体都塞到了消息队列里。请求吞吐一高,队列消费不过来,内存就上去了。

解决思路很简单:生产环境只保留必要字段,比如 token 数、延迟、模型名、状态码,不要记录完整 prompt 和响应。一方面是内存开销,另一方面也是隐私安全考虑。大模型应用最忌讳把用户输入原封不动写进日志,出了问题责任很大。

5. 和其他方案对比:什么时候不一定选 LiteLLM

5.1 自研网关 vs 现成代理

很多团队会纠结要不要干脆自研一个统一调用层。如果你们的核心人力很充足,自研确实能最大化贴合业务。但自研的隐性成本往往被低估:格式转换规则要自己维护,各家 API 更新了你得跟着改,重试、限流、成本统计等一堆“周边功能”都要自己造轮子。除非团队有持续投入,否则做到后面很容易变成一个没人敢动的“祖传模块”。

LiteLLM 这类现成方案的最大优点,是社区和版本迭代帮你在追各家 API 变动。你不需要关心 Anthropic 最近改了某个响应字段,只要升级版本即可。缺点则是它本身的配置体系也有学习成本,而且更新过快,某些参数在不同版本里行为不完全一致,升级前需要仔细看 changelog。

5.2 托管型统一 API 服务 vs 自托管网关

现在市面上也有一些托管的统一模型 API 服务,直接把各家模型聚合在一个域名后面。这类服务上手极快,不需要部署,也有完善的计费体系。如果你不想维护任何基础设施,只想一个 key 调用所有模型,那托管服务是更好的选择。

代价是请求会经过第三方的中转链路,延迟和稳定性受制于人。另外,模型输入输出也会暴露给中转方,企业内部如果对数据隐私有严格要求,那这一条基本一票否决。自托管 LiteLLM 虽然要维护服务器,但数据链路完全在自己手里,合规上更可控。

5.3 什么时候可以直接放弃它

如果你只是在自己电脑上跑实验,偶尔换模型写个 Demo,那装一个 LiteLLM 纯属给自己增加负担。对于没有多模型、多租户、成本管控需求的项目,直接用官方 SDK 是最干净的做法。另外,如果团队的主要技术栈不在 Python,也不想额外维护一个 Python 服务,那 LiteLLM 的引入成本就要重新评估。虽然它对外暴露了标准 HTTP 接口,你最终只需要 HTTP 调用,但运维层面还是多了一个服务要管理,这点要想清楚。

6. 一些值得留意的配置细节和运维经验

6.1 环境变量和密钥管理

LiteLLM 的配置里可以用os.environ/XXX引用环境变量。实际运维时,我会把这些环境变量放到容器编排工具里统一管理,而不是塞进 YAML。尤其注意master_key绝对不要用默认值,很多公开示例里的默认 key 一旦暴露,任何人都能访问你的网关。部署完成后第一件事,就是改掉默认 master key,并请确认它没有出现在公网可访问的页面里。

6.2 关闭遥测选项

LiteLLM 默认会收集一些匿名使用数据,用于改进项目。如果公司内部对数据外发有严格限制,部署时最好主动关闭。配置里有个telemetry相关设置,或者直接设环境变量LITELLM_TELEMETRY=False。我建议在内部部署时一律关掉,省得后面被安全部门问起来说不清楚。

6.3 UI 调试和健康检查

LiteLLM 自带一个简单的管理后台,可以看模型列表、密钥列表、调用日志。生产环境我会让/health接入监控系统,同时定期看一下/model/info,确认配置的每个模型是否健康。曾有一次 Azure 的密钥过期了,但/health仍然返回正常,直到调用量上升才暴露问题。所以不要只依赖健康检查,要多看模型状态。

6.4 升级版本前先看兼容性变更

这个项目迭代速度很快,社区版发布频繁。我从一个旧版本升级到新版本时,遇到过配置文件格式不兼容的情况:原来model_name对应的字段要改,某些默认行为也变了。建议在测试环境完整跑一遍回归,把请求、回退、预算校验三块重点测一下,再上生产。

我个人现在的习惯是:把所有配置代码化、版本化。config.yaml 放到配置仓库里,升级前 diff 配置差异,这样即使行为变了,也能快速定位是哪项配置导致。

最后再分享一点我的使用体感

用了 LiteLLM 大半年,最大的体会是:它的核心价值不在“省事”,而在于把模型调用从“代码问题”变成了“配置问题”。以前换模型要改代码、发版、重新部署,现在只需要在配置里加一个模型条目,然后调一下路由权重。业务团队和基础设施团队的协作方式也变了,算法团队不再关心密钥和网关细节,而平台团队能清楚地看到每个模型、每个租户的成本结构。

如果你正准备上 LiteLLM,我的建议是先别追求功能齐备,而是从最小配置开始:一个模型、两个 key、一张成本报表。把基础链路跑通,再把多模型回退、预算控制、缓存逐个加进去。你会发现,当模型成为可配置的资源之后,整个系统的灵活性强很多。当然,它也不是万能的,自治性和稳定性之间永远需要权衡。但至少在“多模型统一接入”这件事上,LiteLLM 现阶段是我用过的综合成本最低的方案。

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

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

立即咨询