☰
litellm实战:统一多模型API接入的LLM网关全解析
2026/10/13 4:46:57 网站建设 项目流程

先问个实际的问题:你现在手上是不是同时握着好几家模型厂商的 API Key,今天要用这家的大模型,明天要换另一家的,每次切换都得重新研究接口文档、调整参数格式,甚至改代码?如果你也在这个状态里,那 litellm 这个项目你应该了解一下。

litellm 是一个开源的 LLM 网关服务,简单说就是把你和各种大模型 API 之间的对接统一收口。你只需要按照一套接口标准去调用它,剩下的转发、鉴权、重试、记账这些事,它帮你处理。我最早接触这个项目是因为当时一个项目里要用到好几家的模型,代码里到处是 if-else 分支,光看都快看吐了。后来我把 litellm 接到项目里,接口统一了,密钥也收拢了,整个人轻松了不少。

这篇文章我不打算堆官方文档,而是按我自己实际落地的过程来拆:litellm 的定位、关键机制、部署步骤、以及我在生产环境里踩过的坑。适合正在做 AI 应用开发、想摆脱模型锁定的团队和个人开发者参考。

1. 先把这个项目的定位聊透

1.1 它不是一个简单的 SDK 封装

很多人第一次看 litellm,会觉得这玩意儿就是个 Python 库,把不同模型的调用封装成统一的 format。你要是只这么理解,就太小看它了。它做的其实是一个完整的网关层服务,跟 Nginx 作为反向代理的思路很像,只是它转发和处理的不是 HTTP 页面,而是大模型请求。

从这个角度去理解,litellm 的价值就非常清晰了:

  • 所有模型请求统一走一个入口,应用端不需要关心背后是哪个厂商。
  • API Key 不会散布到各个业务服务里,由 litellm 统一托管和鉴权。
  • 请求到达 litellm 后,由它做模型选择、负载分发、重试降级。
  • 生成的 token 数和成本自动记录,预算控制可以前置。

所以它解决的不仅仅是一个代码库的问题,而是一个架构层面的问题。当你的应用从一个模型扩展成多个模型、从单实例变成多实例时,没有这样一层收口,你会被各类接口差异折腾得很惨。

1.2 什么时候你该用它,什么时候别用

litellm 不是说放之四海而皆准,我用下来觉得它对两类项目特别有用:

一类是应用本身需要适配多个模型的项目。比如你这周用某家的旗舰模型,下周发现另一个开源模型部署到自己的 GPU 服务器上性价比更高,想在两者之间随意切换。这种场景下,如果业务代码直接对接原厂接口,换一次模型就要改一次代码。

另一类是团队协作项目。后端给你一把厂商 API Key,测试也要用,前端也要调,密钥散得到处都是。通过 litellm 创建虚拟密钥后,每个人拿到的都只是限定额度、限定模型的子 Key,权限可控,出了问题也好追踪。

反过来,如果你的项目只需要调用一个固定模型、对延迟要求极其严苛,或者你本身就要在嵌入式设备上直接运行推理,那中间加一层网关就是多余开销。这种场景不需要引进 litellm,直接用原厂 SDK 更省事。

2. 核心机制深度拆解

2.1 协议转换是怎么做到的

litellm 最底层的能力,是把各家厂商的请求体统一转换成它自己定义的一套标准格式。你往它那里发请求时,请求结构是标准化的,它内部再把这份标准格式映射成目标厂商需要的具体格式。这个动作看起来不复杂,但细节极其琐碎。

比如有的厂商接受的是messages数组,有的还需要额外的system字段单独处理,有的支持max_tokens这个命名,有的叫max_completion_tokens,参数名不一样,取值范围也不一样。温度的默认值、是否会输出logprobs、是否支持工具调用,这些都不同。litellm 内部维护了一张很长的模型能力表,记录了不同模型支持的参数集和默认行为,这就是它能做到"一个标准格式接所有模型"的基础。

你在配置里指定了某个模型名,litellm 就知道这个模型对应的请求限制、上下文长度、默认参数,并对请求做相应的校验和调整。这就是它能在极大模型范围内通用,而不是只支持某两三家厂商的原因。

2.2 虚拟密钥与密钥托管

很多团队把 litellm 当成密钥的统一管理入口。你在配置文件里写好自己的真实厂商 API Key,然后通过 litellm 的管理接口创建一个虚拟 Key。应用端拿到的都是虚拟 Key,而不是你真正的厂商密钥。

这个虚拟 Key 的好处是灵活。你可以给同一个模型创建多个虚拟 Key,分发到不同业务线,每个 Key 设置不同的速率限制、预算额度、可用模型列表。比如 A 业务每天最多调用 100 万 token,B 业务只能用某个特定模型,这些都能在虚拟 Key 上配置。

万一某个虚拟 Key 泄露了,或者某个业务不再需要了,你可以单独吊销这个 Key,完全不影响其他业务线,真实厂商密钥也不需要轮换。这个思路其实是参考了云计算平台主子账号的模型,在团队内部管理上很有价值。

2.3 模型路由、优先级与失败重试

litellm 内置了一个 Router,可以理解成一个智能分发器。它启用了多模型部署策略之后,就不再是简单的一对一转发,而是会根据你的配置做路由决策。

常见的配置场景是这样:你希望优先使用某家厂商的旗舰模型,它顶不住了或者响应超时,就自动切换到备用的另一个模型上。你可以给每个模型设置权重,Router 按权重分配请求;也可以设置优先级和 cooldown 时间,连续失败若干次后自动把流量切换到备用模型。

这个机制生产环境里很关键,因为单靠一个模型厂商,服务稳定性很难保证。有时候厂商那边发版抽风、限流,或者某个区域网络抖动,如果你没有这层自动降级,用户请求就直接失败了。有了 Router,至少能给你兜底,不至于请求全军覆没。

2.4 成本追踪与预算控制

大模型调用不像普通 API 那样按次计费,它按 token 计费,而 token 数是动态的。如果不做成本追踪,月底账单出来你根本说不清楚钱去哪了。litellm 把成本追踪内置到了转发链路里。

每一次请求结束,litellm 会统计请求和响应的 token 数,再结合你在配置里填的价格计算成本。你可以在多个维度看这个数据:按模型看、按 API Key 看、按用户看、按时间范围看。预算控制也可以设多层:整个代理的总预算、单个模型 Key 的预算、单次请求的最大消费上限。超出预算后,请求会被拒绝,避免失控成本。

这些功能对于那些把 AI 能力整合进产品、需要给客户提供使用量报表的开发者来说,几乎是刚需。

3. 实操部署:把 litellm 跑起来

3.1 准备工作

litellm 可以当 Python 库用,但真正要当网关用,建议直接用 Docker 部署。我自己的部署环境是一台 Linux 服务器,只暴露 litellm 的端口,厂商 API Key 都存在环境变量或配置文件里,应用端只能访问 litellm。

部署前确认好这几件事:

  • Docker 环境可用。
  • 你有哪些模型厂商的 API Key,分别是什么。
  • 业务上需要用到大模型的模型名,比如打算给客户端暴露成什么名字。

如果你暂时没有多个厂商的 Key,用一个厂商的 Key 也能先把流程跑通。配置方式是完全一样的,后面再扩其他模型只是改配置的事。

3.2 编写核心配置文件

litellm 的核心配置是一个 YAML 文件,通常叫config.yaml。这个文件里定义了模型列表、密钥、路由策略、预算等。先看一个最基础的模型配置:

model_list: - model_name: zh-model litellm_params: model: openai/zh-chat api_key: os.environ/OPENAI_API_KEY api_base: https://api.xxx.com/v1

这里的model_name是给客户端看的,客户端调用时填的是这个名字;litellm_params.model才是实际发给厂商的那一串标识。你可以把某个厂商的模型暴露成任何名字,客户端完全感知不到背后的真实模型名。

如果你有多个模型,就在model_list下继续加项。下面是一个包含两个模型的例子,一个来自某厂商的旗舰模型,一个来自某开源模型的托管服务:

model_list: - model_name: flagship-model litellm_params: model: openai/gpt-flagship api_key: os.environ/FLAGSHIP_API_KEY - model_name: fast-model litellm_params: model: anthropic/fast-model api_key: os.environ/ANTHROPIC_API_KEY

注意model字段里的前缀,openai/和anthropic/是告诉 litellm 这个请求应该按哪家的协议格式来处理。它根据这个前缀来决定内部的协议转换逻辑。

如果你还想配置负载均衡和自动重试,可以在配置下面加上 Router 相关的设置,这里先不展开,后面做基本的验证时用不到。

3.3 启动服务并验证一次调用

配置文件写好后,启动 litellm 服务:

docker run -d \ --name litellm_proxy \ -p 4000:4000 \ -v $(pwd)/config.yaml:/app/config.yaml \ -e FLAGSHIP_API_KEY=sk-xxx \ -e ANTHROPIC_API_KEY=sk-xxx \ ghcr.io/berriai/litellm:main-latest \ --config /app/config.yaml --port 4000

参数说明一下:-p 4000:4000把容器的 4000 端口映射到宿主机,-v把当前目录的 config.yaml 挂载进容器,环境变量就是你在配置文件里引用的那几把真实 Key。

启动之后,用 curl 验证一下服务是否正常:

curl http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ -d '{ "model": "flagship-model", "messages": [{"role": "user", "content": "你好,介绍一下你自己"}] }'

sk-1234是 litellm 默认的本机虚拟密钥,你在配置里开启虚拟密钥认证后,实际使用时需要创建一个属于自己的虚拟 Key,而不是用这个默认值。请求返回后,你看响应的结构,跟直接调厂商接口格式是一样的,里面包含模型返回的文本内容和 token 使用统计。

到这里,litellm 作为代理服务已经跑通了。你的应用端只需要把 base_url 指向http://localhost:4000,模型名填flagship-model,就能正常调用。

3.4 接入现有 Python 项目

litellm 设计得比较舒服的一点是,它遵循通用的 OpenAI 兼容接口规范,所以市面上大多数主流 SDK 都能直接接入。以 Python 为例,你原来写的是直接连接某个厂商的 SDK,现在改动很小:

from openai import OpenAI client = OpenAI( api_key="sk-虚拟key", base_url="http://localhost:4000" ) response = client.chat.completions.create( model="flagship-model", messages=[{"role": "user", "content": "你好"}] ) print(response.choices[0].message.content)

你注意到没有,应用层代码几乎没怎么改,只是换了一个 base_url 和 api_key,模型名换成了你自己定义的。今后如果你想把flagship-model背后的真实模型从 A 厂商切换到 B 厂商,只需要修改 litellm 的配置并重启服务,应用端一行代码都不用动。

如果是异步场景,用异步客户端指向相同地址即可,litellm 本身对异步请求处理没有问题。

4. 项目落地时绕不开的坑

4.1 响应超时导致的重试抖动

大模型接口有一个特点,就是响应时间波动大。问一个简单问题可能 1 秒就回,问一个需要长思考的问题可能要等 20 秒。如果你在 litellm 上层配置了类似 10 秒超时的策略,它到点会主动断掉,并触发重试逻辑。

这里有一个容易踩的坑:如果备用模型本身也有相同的请求,但你给两个模型设置的超时时间都是一样的,主模型超时之后切到备用模型,备用模型也很可能因为同样的问题超时。结果就是用户等了几十秒之后,看到的是一个又一个错误。

我给的建议是根据模型的实际响应特性分别设置超时和重试参数,不要用一套参数套用所有模型。另外,Router 的重试次数不宜设得太多,我一般设 1 到 2 次,多了反而容易造成请求堆积。

4.2 流式输出总是断

项目里接入聊天机器人,普遍都喜欢用流式输出,一个字一个字地蹦出来,用户体验好。但在 litellm 上刚开始接流式的时候,我经常碰到一个问题:开头能正常输出,输出到一半连接就断了。

排查下来原因有两类。一类是网络链路上的超时设置太短,尤其是通过公网访问 litellm 的场景,路由器、网关等中间设备可能断开了空闲连接。你需要在 litellm 配置里把流式响应的空闲超时调大一些,同时客户端那边也别在底层设置了不合理的读超时。

另一类是上游模型本身对流式输出的处理方式不同,有的厂商对每个 chunk 的格式定义不太一样。litellm 会在内部做格式转换,如果某个厂商格式比较特殊,它可能没法在这个版本的转换中正确解析。遇到这种情况,我建议直接升级 litellm 到最新版本,这种兼容性问题一般会在后续版本里修复。

4.3 模型名冲突导致路由不正确

有一次我给客户端暴露了一个叫chat-model的名字,同时配置了两个真实模型都对应到这个名字。我本意是想做负载均衡,但实际测试发现流量始终打到一个模型上,另一个几乎没收到请求。

查了配置和日志后发现,litellm 默认的路由策略是按顺序或按权重设置,如果权重没写对,它可能会一直命中列表里的第一项。你在配置里给多个模型指定同一个model_name时,需要明确设置路由策略和权重分配,不能指望它自动帮你均衡。

排查技巧也分享一个:litellm 自带的日志会打印每次请求命中的真实模型名,当你觉得路由不对时,先去日志里看命中情况,通常能很快定位问题。

4.4 预算超限但请求还在持续调用

预算控制是 litellm 的卖点之一,但我第一次配置时也闹过误会。我在配置里给某个 Key 设置了预算上限,心想到了上限就该停了,结果过了半天去看,还在不断调用成功。

仔细读文档才知道,litellm 的预算控制分多个层级,有的层级是按请求维度实时拦截,有的层级是按时间段统计事后阻断。如果你的配置只设置了总预算而没有设置最大单次请求预算,它不会在最开始就拦截,而是在累计超过之后才生效。

处理方式是先明确你的核心需求:如果是防止单次异常请求消耗过多 token,需要配置的是max_budget_per_request或者单次请求的max_tokens上限;如果是对某个 Key 做月度总额控制,那需要确认统计周期和触发阈值。这两者的机制不一样,不要弄混。

5. 额外想说的两个配置细节

5.1 如何管理多套环境

如果你的项目有开发环境、测试环境、生产环境,我不建议直接复制三份相同的 litellm 配置。更好的做法是把配置模板化,把模型名、预算、密钥这些差异项用环境变量替换,然后用 CI/CD 流程为不同环境生成不同的配置。

这样做的目的不是减少输入量,而是避免环境之间的参数漂移。我见过有团队在测试环境调整了某个模型的超时参数,上线时把这个参数带到了生产环境,结果生产环境的请求链路表现异常,排查很久才发现是参数不一致导致的。

litellm 官方也支持把部分配置项用环境变量注入,你要做的就是约定好每个环境该填哪些环境变量,然后把这份约定固化到部署脚本里。

5.2 日志与监控别忽视

litellm 默认会打印请求日志,但如果你打算长期维护这套代理服务,我建议还是把日志接入集中式监控平台,并针对几个关键指标配置告警:

  • 请求失败率突增,说明某个上游模型可能不稳定。
  • 平均响应延迟升高,可能是某条网络链路出了问题。
  • 某个虚拟 Key 的调用量激增,可能是业务异常或密钥泄露。

这里我不展开具体的监控平台怎么搭了,重点是想提醒你,litellm 这层网关是观测所有模型调用流量最好的位置,不要在它上面只做转发,浪费了数据价值。

6. 后续可以怎么扩展

litellm 这个项目本身迭代很快,社区也很活跃。我最近关注到的几个方向,如果你正好有需求,可以研究一下。

一个是结合向量数据库做 RAG 场景。litellm 可以配合嵌入模型做统一接入,这样不仅大语言模型走统一网关,嵌入模型也能走统一网关,整个 AI 应用的模型调用面收得更干净。

另一个是团队协作时做更细粒度的权限控制。litellm 支持设置每个虚拟 Key 能访问的模型列表、每分钟请求数限制、消费者字段,适合做多租户场景下的配额分类。如果你的产品要对不同客户提供不同的 AI 调用额度,这一层能力几乎是为这个需求准备的。

还有一个方向是把它作为公司内部模型平台上的一层入口。随着各家模型不断出新,模型能力在快速迭代,接入的模型数量会越来越多。当模型数量达到几十个的规模时,如果没有统一的入口管理,后续做模型替换、成本对比、灰度放量都会非常困难。

我个人在实际项目里体会最深的是,litellm 让我终于不用再为了换一个模型而熬夜改代码了,模型切换变成配置变更而不是代码变更,这带来的心态变化太明显了。你要是也在为多模型接入头疼,不妨按这篇文章的步骤搭一套出来试试,跑通了之后,你大概率会回头把业务代码里那些硬编码的模型调用全清一遍。

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

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

立即咨询