☰
Litellm实战:统一多LLM API网关的部署与排坑指南
2026/10/13 8:32:30 网站建设 项目流程

如果手头同时接入三五家 LLM 服务商,你会很快发现一件事:真正麻烦的不是模型能力,而是 API 格式。A 家用这种报文,B 家用那种结构,错误码也各说各话,今天需求要换模型,明天就得改一版配套代码。Litellm 就是在这种背景下经常出现在我技术选型清单里的方案——它是一个开源的 LLM API 网关,把主流模型服务商的接口统一成一套 OpenAI 兼容风格,同时把密钥、预算、限流、日志这些和模型能力无关的脏活也一并接管。这篇文章想把我自己从安装配置到实际排坑的过程完整写下来,给正在考虑统一模型接入的团队或个人开发者一个可参考的落地样本。

1. 为什么需要 Litellm:一个 API 网关解决了什么问题

1.1 多模型调用的真实痛点

先说一个场景。你负责的 AI 应用最开始只接了一家模型提供商的接口,代码很简单:一个请求,一个 JSON 响应。后来因为效果、成本、可用性等原因,需要把同样的问题同时发给另一家模型服务商做对比,甚至还要支持自建的开源模型服务。这时候麻烦来了:每家接口的鉴权方式不一样,有的用 Bearer Token,有的要求特殊 Header;请求体结构不完全一致,有的叫 prompt,有的叫 messages;返回内容也不一样,从响应里提取出来的字段千奇百怪。更别说 Token 计费字段、错误码体系的差异。为了切换模型,你可以在代码里堆一堆 if-else,但这样的代码维护成本极高,每加一家供应商,就要把分支逻辑再捋一遍。而且真实密钥往往会出现在环境变量文件、Git 提交历史甚至前端代码里,一旦泄露,损失根本控制不住。

再说成本。同一个功能,每家的定价、Token 统计方式都不一样,如果调用散落在各段代码里,月底想拉一个“这个项目到底花了多少钱”的报表,几乎不可能。就算勉强汇总,因为各家返回的 token 数含义不同,估算出的数字也很难对齐。这些问题叠加起来,已经不再是“忍一忍就能过去”的麻烦,而是直接影响到项目能不能规模化上线的阻碍。

1.2 Litellm 的核心定位:LLM 网关/代理

Litellm 的基本形态是一个本地或服务器上的代理进程。你的应用不再直接请求各家模型提供商的端点,而是先把请求发给 Litellm,由 Litellm 根据配置去解析、转换、转发,再把上游结果返回。这个过程对客户端来说是透明的——你只需要把 base_url 改成本地 Litellm 的地址,然后沿用熟悉的 OpenAI 兼容接口。

一个大白话类比:Litellm 就像公司里的前台。访客(你的应用)不需要知道每个部门(各家模型)的具体座位,只要把需求告诉前台,前台负责带路、登记身份证(鉴权)、记下访问时间(日志),还能帮你拦截超预算的访客。配置好的 Litellm 可以完成这些事情:

  • 统一模型调用协议,把不同提供商的参数翻译成客户端能用的格式;
  • 模型路由与负载均衡,同名逻辑模型对应多个真实模型;
  • 密钥托管,所有真实密钥存在服务端;
  • 配额管理、预算控制、速率限制;
  • 全量调用日志和成本估算。

这样一个代理层把“业务代码”和“模型供应商”彻底解耦。前端应用不需要知道今天用的是哪家模型,也不需要关心真实 key 放在哪里,Litellm 在中间既做了协议翻译,又做了安全闸门。这个定位,是它区别于普通 SDK 封装库的核心所在。

2. 核心功能拆解:从接入、路由到成本控制

2.1 统一模型接入与协议转换

Litellm 支持接入几乎市面上主流的 LLM API,闭源的、开源的、通过兼容层自部署的,基本都能在配置文件里声明后使用。你不用为每家写适配层,因为 Litellm 的源码里已经内置了几十种 provider 的协议转换逻辑。对于输入参数,有的模型要求 temperature 取值范围不一样,有的要求新版 messages 结构,Litellm 在转发前会做一次归一化;对于返回结果,它会把各家响应格式统一成标准结构,这样应用侧拿到的永远是同一套 JSON 字段。

具体配置上,你需要定义一个逻辑模型名(model_name)和一个或多个真实模型映射。参考最小示例:

model_list: - model_name: my-virtual-model litellm_params: model: provider-name/real-model-name api_key: ${REAL_API_KEY}

其中provider-name是 Litellm 内部注册的 provider 标识,某个厂商就对应某个固定前缀;real-model-name是该厂商下具体的模型版本。${...}是环境变量引用,目的是避免密钥直接写在文件里。请求时,客户端只要填model: my-virtual-model,Litellm 就会根据这个 model_name 在 model_list 里找到真实映射,然后完成协议转换。这就是统一接入的核心逻辑:客户端只认识逻辑名,真实厂商信息全部隐藏在代理层。

2.2 路由、重试与故障转移

大多数时候我们需要的并不是简单的一对一映射,而是同一个逻辑模型背后对应多个物理上游:主供应商不可用时切备用,或者按优先级滚动。Litellm 天然支持这种设计,你只需要在 model_list 里重复使用同一个 model_name,配置不同的真实模型即可。

model_list: - model_name: production-model litellm_params: model: provider1/flagship-model api_key: ${PROVIDER1_API_KEY} - model_name: production-model litellm_params: model: provider2/backup-model api_key: ${PROVIDER2_API_KEY} litellm_settings: fallbacks: production-model: - provider2/backup-model

请求命中production-model时,Litellm 会把流量在 provider1 和 provider2 之间做负载均衡;当 provider1 返回特定的错误(比如限流、超时、5xx)时,自动把请求转到 provider2。这里有几个细节容易踩坑:fallback 并不是所有错误都触发,默认只在网络错误、429、500 等场景触发,有些业务错误如上下文长度超限就不会;如果你希望只要主模型请求失败就无条件切换,需要显式配置。另外,超时和重试次数可以分别设置request_timeout和num_retries,控制异常时的等待体验。

这套机制最大的价值,是让我可以把“换供应商”变成一次配置变更,而不是一次代码发布。线上模型挂了,运维改 YAML、重启配置就行,应用服务完全没有感知。对于模型稳定性要求高的业务,这是很实用的降级手段。

2.3 密钥管理与权限控制

如果在一个二三十人的团队里,每个开发手上都拿着真实厂商密钥,风险其实非常高。Litellm 提供了虚拟 key 的概念:真实 key 只在服务端配置中存在,客户端和开发者用的是 Litellm 生成的虚拟 key。虚拟 key 可以绑定一个或多个逻辑模型,可以设置速率、预算和过期时间。

具体使用方式:通过管理接口创建虚拟 key 后,客户端把它作为 Authorization Bearer Token 传到 Litellm。Litellm 先校验虚拟 key 是否有效、是否超预算,再取出对应的真实 key 去上游请求。这样真实 key 永远不会出现在客户端的配置、日志和 CI 环境里。某些团队甚至会让前端直接使用短期虚拟 key,即便被截获,损失也控制在有限范围内。

虚拟 key 的存储可以是内存或数据库。生产环境我建议使用外部数据库来持久化,否则重启后 key 全部失效,会引发线上事故。权限控制也可以做得很细:某把 key 只能访问model-a,另一把 key 能访问model-b和model-c;某把 key 的日预算是 100 元,超了自动拒绝。这对于多部门共用一台代理非常有用。

2.4 预算、速率限制与并发控制

速率限制是保护上游账号和自身服务的必要手段。Litellm 可以在全局、每个 key 或每个模型级别设置 rpm(每分钟请求数)、tpm(每分钟 Token 数)、max_parallel_requests(并发请求上限)。

简单算一下:如果上游账号给到的 tpm 是 100000,平均每分钟请求量约 60 个,那么每个请求平均不能超过 1667 个 Token。假设实际请求平均 2000 Token,就需要限制 rpm 为 50。Litellm 内部有基于令牌桶的限流器,超过限制的请求会被拒绝(429),也可以配置为等待。对于多实例部署,需要把限流状态放到 Redis 里才能全局生效,否则每个实例各自计数,总并发会超出预期。

预算控制也很有用。你可以设置max_budget,当累计成本达到阈值后该 key 自动禁用。Litellm 通过记录每次调用的输入/输出 Token 数,结合模型单价来估算成本。注意,这只是估算,最终请以实际账单为准。对于个人项目,这个功能可以防止模型调用失控。

2.5 观测性与调用日志

做 AI 应用的人都知道,模型调用是一个“黑盒”,如果不记录,出了问题根本无从查起。Litellm 默认会记录每次请求的元数据,包括:时间戳、请求模型、实际模型、prompt 和响应摘要(可配置)、Token 数、估算成本、延迟、错误码。这些日志会写入数据库,也可以通过 REST API 查询。

我比较常用的管理接口有这些:

  • /health/liveliness:生存检查;
  • /spend/logs:获取最近的调用日志;
  • /spend/keys:按虚拟 key 统计开销;
  • /model/info:查看当前模型配置。

如果和监控系统对接,Litellm 也支持把指标暴露成标准监控格式,方便大家接入已有的告警体系。有日志之后,至少可以回答三个问题:某个功能为什么慢?这个月花了多少钱?哪条 prompt 重复调用次数最多?这些是后面做成本优化的直接依据。

3. 实战部署:5 分钟跑通一个 Litellm 代理

3.1 环境准备与安装

开始之前,先确认本机有 Python 3.9 及以上版本,并建议用虚拟环境,避免污染全局环境。虚拟环境是 Python 项目的基本礼仪,既然 Litellm 本身是 Python 写的,用虚拟环境管理依赖最省心。

python -m venv litellm-env source litellm-env/bin/activate pip install -U "litellm[proxy]"

这个安装命令会装好代理所需的全部依赖,包括 FastAPI、uvicorn 等。安装完成后先别急着启动,因为 Litellm 没有配置文件时虽然能起一个默认服务,但默认配置里没有你关心的模型映射,后续还是要重新写配置,不如一开始就把配置问题处理干净。

3.2 编写最小配置文件

我建议把配置放在项目根目录下,命名成config.yaml,方便后续用--config指定路径。先给一个最简配置,方便理解核心结构:

model_list: - model_name: my-model litellm_params: model: provider-example/flagship api_key: ${FLAGSHIP_API_KEY} - model_name: my-model litellm_params: model: provider-example/backup api_key: ${BACKUP_API_KEY} litellm_settings: drop_params: true num_retries: 2 request_timeout: 30 general_settings: master_key: sk-master-123456 database_url: sqlite:///litellm.db

解释一下几个关键字段:model的格式为provider/具体模型,如果 provider 是你自己托管的服务,还可以追加api_base参数指向本地端点。drop_params: true很关键,因为不同的上游对参数兼容度不同,比如某个备用模型不支持logit_bias,开启这个参数后 Litellm 会在转发前把它自动删掉,而不是强传导致报错。num_retries和request_timeout控制请求容错,master_key是你的管理唯一 key,后续创建虚拟 key 和管理接口都靠它。如果省略master_key,首次启动时会随机生成一个并打印在日志里,实际使用中很容易丢掉,所以建议显式配置。

3.3 启动代理并测试

先导出真实密钥环境变量,再启动:

export FLAGSHIP_API_KEY="你的真实供应商密钥" export BACKUP_API_KEY="你的备用供应商密钥" litellm --config config.yaml --port 8000 --host 0.0.0.0

启动日志里如果出现 “Uvicorn running on http://0.0.0.0:8000” 就说明代理已经起来了。先用健康检查接口确认:

curl http://localhost:8000/health/liveliness

正常会返回{"status":"ok"}之类的 JSON。然后可以试一下模型列表接口:

curl http://localhost:8000/v1/models -H "Authorization: Bearer sk-master-123456"

这里会列出你在 config 里声明的逻辑模型名。注意 API 请求必须带 Authorization 头,即使只是管理接口,如果你不传,可能返回 401。看到模型列表出现,说明配置已经被正确加载。

3.4 用兼容方式发起第一次聊天补全

不用纠结是否安装了某个特定 SDK,直接用 requests 库演示也能把过程拆得很清楚:

import requests url = "http://localhost:8000/v1/chat/completions" headers = { "Authorization": "Bearer sk-master-123456", "Content-Type": "application/json", } payload = { "model": "my-model", "messages": [ {"role": "user", "content": "用一句话介绍你自己"} ], "temperature": 0.7 } r = requests.post(url, headers=headers, json=payload, timeout=60) print(r.status_code) print(r.json())

如果一切正常,响应里的结构和你直接请求某厂商的接口一致,区别是数据经 Litellm 统一过。只要 base_url 指向 Litellm,市面上所有兼容 OpenAI 接口的客户端库,比如常见的链式框架、Agent 框架,都可以无缝切换。这里要特别提醒:如果使用 master_key 作为客户端调用 key,其实不太推荐。生产环境应该创建一把专用虚拟 key,并且只分配它需要的模型权限,这样可以避免不同业务之间互相影响。

4. 常见问题与排查技巧实录

4.1 请求返回 401 Unauthorized

通常是因为客户端没带有效的虚拟 key。如果你没有创建虚拟 key,那么只有用general_settings.master_key才能通过。另一个容易被忽略的点是:在没有设置 master_key 的情况下首次启动,Litellm 会把一个随机生成的 master key 打印在日志里,很多人没看到,导致后面请求全被拒绝。解决办法是重启时显式指定,或者从日志里找到那串随机 key。

补充一个我踩过的坑:如果只设置了 master_key,但请求的模型还需要特定的虚拟 key 来绑定路由,光用 master_key 可能无法触发某些 per-model 的限流配置。建议通过管理接口创建虚拟 key,并把虚拟 key 绑定到对应模型,这样权限和限流都更清晰。

4.2 模型提示 Model Not Found 或 404

百分之九十五的情况是客户端请求的 model 名和 config.yml 里的model_name不一致。注意:不是让你填真实模型名,而是填逻辑名。如果你在 config 里定义的是my-model,请求里就不能写provider-example/flagship。排查时先curl /v1/models看看当前实际暴露了哪些模型名,再检查请求 body 里的 model 字段。

另外,如果使用model: provider/specific-model格式时,provider 前缀写错也会导致不可见。可以用litellm --config config.yaml --test之类的命令去测试配置,它会实际调一次上游,验证模型 ID 是否有效。这个方法比反复重启代理试错要快得多。

4.3 fallback 不生效

当你配置了多个相同 model_name 的模型,但请求总是打到第一个时,先确认是否给该 model_name 配置了fallbacks。如果没有,Litellm 只会做负载均衡,不会自动切换。就算配置了,fallback 也不会对某些错误触发,比如上下文超长的 400、参数校验错误,这类问题切到备用模型也没用,所以不要误以为 fallback 能解决所有失败场景。

另一个常见问题是:两个上游虽然属于同一个逻辑模型名,但备用模型不支持某些参数,导致 fallback 后仍然报错。配合drop_params: true基本上可以规避大部分参数兼容问题。如果还有特殊参数需要透传,可以在 litellm_params 里用额外的字段声明。

4.4 Token 统计和成本估算与账单对不上

Litellm 的成本计算依赖它对输入、输出 Token 的统计。如果 API 请求里没有显式设置max_tokens,或者上游返回值里不包含 Token 信息,估算就会不准,导致后台看到的成本和厂商账单有差异。这个问题无法完全消除,只能通过以下方式减少:确保请求里显式传入max_tokens,并开启 Litellm 的预算管理参数;定期拉取/spend/logs和厂商控制台账单做交叉比对;把成本估算当作趋势参考,而不是精确财务数字。

我自己就遇到过后台显示一个项目消耗了 300 元,但厂商账单只有 280 元的情况,误差主要来自某些请求的重试被重复计算。后来我核查了日志,发现num_retries会让同一条请求被尝试多次,每次尝试都会单独记一条成本,但最后成功的那条可能才真正计费。所以如果有重试需求,建议在成本报表里按 request_id 去重。

4.5 启动时报错 require redis

如果你在配置里使用了 Redis 相关的 cache 或 rate limit 设置,但 Redis 没有启动,Litellm 启动时会报错。本地跑最小 demo,建议先用 sqlite 加内存模式,能省很多麻烦。等需要多实例时再引入 Redis,到时候把实例地址和密码配好即可。

一个小经验:即使没有 Redis,Litellm 也可以跑得很稳,但限流和缓存功能就无法跨实例生效。如果你只有单实例,内存模式足够;如果你部署了多个副本,一定要把 Redis 和数据库都配置好,否则状态不同步,虚拟 key 和预算会出现漂移。

4.6 并发低、请求排队严重

从三个方向排查:上游供应商的账号速率、Litellm 自身的并发参数(max_parallel_requests)、Redis 限流是否成为瓶颈。不要把上游的 tpm 调得过高以免触发封禁。Litellm 是异步的,但在单进程模式下,缓慢的外部 HTTP 请求也会占用连接,建议使用多 worker 启动(如 uvicorn workers 4),并配合外部数据库和 Redis。

如果真的从日志里看到大量 429,多半是上游账号限流,而不是 Litellm 的问题。此时应该考虑加一个队列层,或者降低单 key 的 rpm,让流量更平滑。很多人一遇到性能问题就怪代理代理慢,其实打开--detailed_debug看时间消耗分布就会发现,大部分时间都在等上游响应。

4.7 快速排障技巧

开启详细日志:启动时加--detailed_debug,日志里会打印每个请求的决策链路,包括 fallback 判断、缓存命中、成本估算。如果线上不方便重启,也可以动态修改日志级别。下面这张表是我常用的故障排查速查表:

现象可能原因优先排查点
401虚拟 key 缺失或失效检查 Authorization 头;重新创建 key
404模型名不一致查看 /v1/models 确认逻辑名
429触发限流或上游限流检查 rpm/tpm 配置;查看上游日志
fallback 不切换未配置 fallbacks 或错误类型不匹配核对 config 和错误码
成本偏差重试计费重复按 request_id 去重统计
启动报错Redis/数据库未就绪检查外部依赖连接

5. 进阶玩法与最佳实践

5.1 多实例高可用部署

Litellm 本身只是一个无状态代理,状态都放在外部数据库和 Redis 中,所以可以水平扩展多个实例。典型部署方式是:每个实例共享同一个 PostgreSQL 数据库和 Redis;前面用负载均衡器分发流量;实例用 Docker 或 systemd 管理;master_key 和虚拟 key 都存数据库,实例之间状态一致。这样部署后,单台机器故障不影响整体服务。

我实际测试过两个实例同时服务,由负载均衡器轮询,虚拟 key 依然是同一个,限流和预算也能全局生效。这里有一个需要注意的点:如果使用 sqlite,多个实例访问同一个文件会锁库,绝对不可取。所以要保证多实例,至少要把database_url换成 PostgreSQL 一类的服务端数据库。

5.2 统一入口打通 RAG 和 Agent 应用

很多团队会用常见的链式框架写 RAG。如果不做统一网关,每个 Agent 实例都直接对接不同模型,维护成本会很高。把 Litellm 放在中间,应用侧只认一个入口。比如检索增强想用厂家 A 的推理模型,另一个团队想用厂家 B 的模型,只要在 Litellm 配置不同的逻辑模型名即可,各业务照着逻辑名调用。

这样带来另一个好处:切换模型时不用重新发布应用。业务今天用模型 m1,明天效果好想试 m2,改一个配置变量就能灰度,应用代码完全不用动。对于快速迭代的 AI 团队来说,这种灵活性非常值钱。

5.3 用缓存和阶梯模型把成本降下来

Litellm 自带缓存功能,可以把相同请求的响应缓存到 Redis,适用于回复固定或重复率高的场景。配置一个缓存参数后,几乎相同的提问会在代理层直接命中,不再消耗上游 Token。我见过一些客服知识库类应用,重复问题占比高达四成,缓存一旦打开,成本能肉眼可见地下降。

还可以利用 fallback 把高优先级流量走贵模型,把低优先级流量切到便宜模型。例如,实时客服用旗舰模型,离线批量分析用便宜模型,通过不同的 key 或模型名隔离,这样总成本能降不少。配合预算告警,当某 key 费用接近阈值时,自动禁用或切换,防止失控。

5.4 多团队隔离与权限审计

大型团队最怕的是互相干扰。Litellm 的虚拟 key 可以按团队分配:团队 A 的 key 只能访问chat-model-a和embedding-model-a;团队 B 的 key 只有chat-model-b权限;每个团队的 key 设置独立预算和速率。这样做的好处是,一方面避免某个团队误用高配额导致其他团队被限流,另一方面月底可以做成本分摊。

我还习惯每周通过/spend/keys接口拉一篇报表,按团队、按模型汇总,写得清楚,管理者心里有数。如果某个月某个团队的费用异常,也能很快定位到具体模型和具体 key,而不是全公司一起背锅。

最后说一点我自己的体会。Litellm 并非只能部署在大型系统里,哪怕只是一个三五人的小项目,只要你同时接触两个以上的模型服务商,它就值得一台低配服务器。我最初只是抱着试试的心态接入,后来真正让我留下的倒不是省了多少代码,而是它把密钥和预算管住了,让我敢把模型能力放开给团队其他人用。踩过的坑主要是配置项太多,所以我的建议很直白:别一开始就追求把所有功能都打开,先用最简配置跑通一次真实调用,再逐步加路由、加限流、加数据库。如果你已经体会过多模型切换的酸爽,应该能明白这套方案的价值在哪。

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

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

立即咨询