☰
用LiteLLM统一管理多模型API:从网关配置到预算控制实战
2026/10/13 5:24:09 网站建设 项目流程

聊一个最近在内部工具链里出镜率很高的项目:LiteLLM。简单说,它是一套开源的 LLM API 网关/代理,核心能力是把 OpenAI、Anthropic、Azure OpenAI、各类国产模型、本地部署模型全部收拢到一个 OpenAI 兼容接口后面,然后由它统一转发、计费、限流、做 Key 管理和日志。之所以想写它,是我发现自己前后给三拨团队搭过类似的“模型路由层”,前两次都是自己手搓,第三次才换成 LiteLLM,结果后面维护成本直接少了一个量级。如果你正在处理“多个大模型供应商、多把 API Key、业务代码里散落一堆 SDK”的问题,这篇文章应该能帮你省掉不少弯路。

这个项目的定位很明确:它不是模型训练框架,也不是模型评测工具,而是一个“站在业务代码和模型供应商之间的代理层”。适合谁来用?后端工程师、平台/工具链开发者、小团队的技术负责人,只要你不想在业务代码里反复改供应商切换逻辑,LiteLLM 就值得试试。下面我按自己从安装到落地排查的真实路径来拆。

1. “多模型直连”的混乱现场,为什么需要网关层

1.1 没有代理层时,代码里会发生什么

假设你的项目要同时用 OpenAI 的 GPT 系列和一个国产大模型。最直观的写法是引入两家 SDK,然后写两套请求函数:

import openai from some_national_sdk import ChatClient openai_client = openai.OpenAI(api_key="sk-xxx") national_client = ChatClient(api_key="sk-yyy") def chat_gpt(messages, model="gpt-4o"): resp = openai_client.chat.completions.create(model=model, messages=messages) return resp.choices[0].message.content def chat_national(messages, model="glm-4"): resp = national_client.chat.completions.create(model=model, messages=messages) return resp.choices[0].message.content

刚开始没什么问题。但两周后需求就来了:模型要统一走 Azure OpenAI、供应商要加一个、某一家的模型要按团队限额、要统计每个部门花了多少钱、要记录每次请求的 token 数。这时候你会发现自己陷入了几个麻烦。

第一,各家 SDK 的模型名、参数、返回结构差异很大,业务逻辑被两家 SDK 的细节牢牢绑死。第二,API Key 直接散落在代码和配置里,发给谁都不放心。第三,账单分散在好几个平台,月底想算一笔总账,得先人工导出再对表。第四,改一次供应商就要改业务代码,发版周期跟着变长。这还只是用了两家,如果五家呢?

最讽刺的是,这些问题其实都不是业务问题,它们全是“接入层”的基础设施问题。可它们偏偏在每一个团队里反复出现。所以就有了一个朴素的思路:在业务代码和模型供应商之间,塞一个“模型网关”,所有下游细节都收敛到它身上。

1.2 加代理层,而不是改业务代码

代理层的核心价值,一句话说就是“把不稳定的下游和稳定的上游隔离开”。业务代码只认一个 OpenAI 兼容接口,供应商怎么换、Key 怎么轮换、限流怎么做、费用怎么统计,那都是网关的事。

我后来总结过这三个模型网关的硬性标准:

  • 接口兼容性要强,最好是 OpenAI 的接口风格,因为团队里随便拉个人都会用。
  • 配置驱动,换模型、调参数尽量不写死代码。
  • 可观测性要好,能清楚看到每次请求花的 token、费用、成功失败状态。

LiteLLM 在这三点上做得相当平衡。它本身就是一个 Python 服务,你用pip install 'litellm[proxy]'装起来后,跑起来就是一个本地 API 服务,默认端口是 4000,接口风格直接对齐 OpenAI 的/chat/completions、/embeddings、/models。业务端只需要把base_url改成http://your-gateway:4000,其余几乎不用动。

1.3 LiteLLM 在同类方案里为什么值得优先看

现在类似的工具不算少,比如 One API、new-api 这类,也有商业的网关产品。LiteLLM 的优势主要有三个。一是纯粹,它本身是命令行工具加 Python SDK,没有绑死管理后台,想接自己的运维体系很容易。二是配置灵活,config.yaml里可以定义模型列表、供应商参数、重试策略、预算规则,几乎全量能力都通过配置暴露出来。三是生态兼容面广,主流的 OpenAI 兼容服务、Anthropic 风格接口、Azure OpenAI 的资源模式,它都支持。

当然它不是没有缺点。管理后台默认比较朴素,不像商业化网关那样有一大堆图表;文档有时候更新得比功能慢,一些新特性需要自己去翻源码或者 issues。但对于自己搭内网工具链来说,这些完全不是阻碍。

2. 动手前必须先搞懂的基础概念

2.1 三个关键名词:代理服务、模型别名、供应商路由

上手 LiteLLM 之前,有三个概念必须先整明白,否则配置起来会一脸懵。

第一个叫 Proxy Server,也就是你最终跑起来的那个 HTTP 服务。它本身不产模型,只负责接收请求、按规则路由到真实供应商、再把响应吐回来。你可以把它理解成一个“模型交换机”,业务侧连接的永远是这个交换机。

第二个叫模型别名(model_name)。在 LiteLLM 的配置里,model_name是“你给业务方看的名字”,而真实的供应商模型名写在model字段里。比如你可以在配置里写model_name: gpt-4o,真实model: openai/gpt-4o-2024-11-20,也可以写model_name: my-assistant,真实model: anthropic/claude-3-5-sonnet-20241022。这一步解决了所有团队都会遇到的痛点:业务环境不跟着上游命名走。

第三个叫供应商路由。LiteLLM 内部通过模型名前缀识别供应商,openai/、anthropic/、azure/、bedrock/、ollama/等。如果你只有一个本地 Ollama 模型,配置里就要写ollama/llama3.1,后面接真实请求时它会去http://localhost:11434找 Ollama 服务。

刚入门的人最容易在这里卡住:直接拿供应商模型名当作model_name用,然后发现请求 404。记住,在 LiteLLM 的世界里,model_name是个逻辑标识,你可以随便起名,重点是把映射关系配对。

2.2 config.yaml 里到底该写什么

LiteLLM 的配置采用 YAML 格式,三个核心区块很常用:model_list、litellm_settings、general_settings。

model_list是模型路由表,必填。每条至少包含model_name和litellm_params,后者里面必须有model这个键,表示真实模型标识。还可以附加api_key、api_base、temperature等默认参数。

litellm_settings是通用参数区,比如设置drop_params、request_timeout、num_retries、fallbacks这些。我的经验是,超时和重试放这里全局调,比在每条模型里重复写要省事。

general_settings是一些服务级设置,比如master_key(代理自己的访问密钥)、database_url(PostgreSQL 连接串,用于持久化日志和预算数据)、otlp或prometheus相关开关。

2.3 一个最小配置实例解析

先看一个能跑通的最小配置,我建议新手从这里起步:

model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: sk-your-openai-key general_settings: master_key: sk-litellm-master-key

这个配置表示:业务方只要用model=gpt-4o调用你的代理,代理就会去请求 OpenAI 的真实gpt-4o,并且代理自身要求请求头里带Authorization: Bearer sk-litellm-master-key。

你把这文件保存为config.yaml,然后执行:

litellm --config config.yaml --port 4000

服务起来后,本地就多了一个 OpenAI 兼容服务。如果你这时候用原来的 OpenAI SDK 去调,只是把base_url换成http://localhost:4000,行为上几乎感觉不到变化。这就是我能想到的最平滑引入方式。

3. 从零跑通统一接口的完整实操

3.1 安装与启动:一次装到位

官方推荐用虚拟环境跑,因为 LiteLLM 依赖的包挺多,直接装进全局环境容易和项目现有依赖打架。我个人用的是 uv,不过用 pip 也一样:

python -m venv .venv source .venv/bin/activate pip install 'litellm[proxy]'

这里提醒一句:装[proxy]扩展非常关键。如果只装litellm,你拿到的是 SDK 而不会有litellm命令的 proxy 入口。第一次装的时候我就吃过这个亏,命令行敲litellm --config ...直接提示找不到命令,后来才发现要装 proxy 扩展。

启动写法也值得单独说。直接litellm --config config.yaml会让服务走默认端口 4000,但我在实践中更喜欢固定端口并开详细日志:

litellm --config config.yaml --port 4000 --detailed_debug

--detailed_debug只建议排查问题的时候开,平时别开,日志量太大。

3.2 让现有 OpenAI SDK 直接指向代理

代理跑起来后,模拟业务端的调用。我强烈建议用一个最简单的 Python 脚本来验证通路,别一上来就接生产代码:

from openai import OpenAI client = OpenAI( api_key="sk-litellm-master-key", # 注意这里是 master_key base_url="http://localhost:4000/v1" # 注意结尾的 /v1 ) resp = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "你好,请回复:ok"}], ) print(resp.choices[0].message.content)

这里最容易踩的坑是base_url的路径。OpenAI SDK 会默认在 base_url 后面拼/chat/completions,所以如果你的 base_url 写了http://localhost:4000,实际请求可能变成http://localhost:4000/chat/completions,但 LiteLLM 的 OpenAI 兼容路径其实是/v1/chat/completions。我第一次测试时直接 404,后来把 base_url 改成http://localhost:4000/v1才通。官方文档也一直强调这个细节。

3.3 多模型路由、负载均衡与兜底策略

单模型跑通只是开胃菜,网关的价值在多模型场景才真正体现。下面是我常用的一套多模型配置:

model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: claude litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: os.environ/ANTHROPIC_API_KEY - model_name: local-llm litellm_params: model: ollama/llama3.1 api_base: http://localhost:11434 litellm_settings: request_timeout: 60 num_retries: 2

这里有一个非常实用的配置细节:api_key可以写成os.environ/变量名的形式,让 LiteLLM 从环境变量里读 Key。好处是敏感信息不进 YAML,方便直接把配置文件放版本库。

负载均衡怎么配?同一个model_name下面写多条litellm_params记录即可:

model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY1 - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY2

LiteLLM 会自动在这些记录间做轮询,两个 Key 轮流被使用。这招在供应商单 Key 限流时极其有效。我实测过,在同样请求频率下,双 Key 轮询能把 429 的概率大幅压低。

兜底策略也很有用。所谓 fallback,就是 A 模型失败时自动转 B 模型。可以在litellm_settings里加:

litellm_settings: fallbacks: [ {"gpt-4o": ["claude"]} ]

意思是gpt-4o请求失败时,自动改走claude。这个功能在生产环境很救命,尤其是某些供应商晚上高峰期随机返回 5xx 的时候。

3.4 重试、超时与参数透传的实测心得

关于重试和超时,我在实际使用中的体会是:不要盲目加大num_retries。LiteLLM 默认在某些场景下会对 429、5xx 做重试,如果配得太大,上游一旦开始抖动,你的代理层会瞬间堆积大量请求,反而放大问题。我一般把num_retries保持在 2 到 3,超时控制在 60 到 120 秒之间,因为大模型流式响应本身耗时就不短。

另一个值得说的点是参数透传。业务端请求里带的temperature、max_tokens、top_p这些参数,LiteLLM 默认会原样传给上游。但如果业务侧总是传一些当前模型不支持的最新参数,上游就会报错。解决办法是在litellm_settings里开drop_params: true,让 LiteLLM 自动丢弃当前模型不支持的参数而不是直接把错误抛回业务端。这个开关我建议所有团队都打开,它能吞掉一大类“同一个业务参数换模型就报错”的兼容性问题。

4. Key 管理、预算控制与团队协作:网关如何管钱

4.1 虚拟 Key 机制:别再把上游 Key 撒给所有人

LiteLLM 有一个很核心的能力:虚拟 Key。它的工作方式是这样的:你在代理里创建一把虚拟 Key(比如sk-1234),这把 Key 和真实的上游 Key 完全无关。业务方调代理时,用的是虚拟 Key;代理内部拿着虚拟 Key 去映射真实上游 Key,再请求供应商。这样上游真实 Key 永远保存在代理服务这一侧,不会进入业务环境。

创建虚拟 Key 有几种方式,最常用的是调用 LiteLLM 自己的接口。假设代理服务跑在本机 4000 端口,用master_key调:

curl -X POST "http://localhost:4000/key/generate" \ -H "Authorization: Bearer sk-litellm-master-key" \ -H "Content-Type: application/json" \ -d '{ "models": ["gpt-4o"], "max_budget": 20, "budget_duration": "30d" }'

返回里会带一把key,这就是给业务方用的虚拟 Key。它的好处很多:可以随时吊销、可以限制可用模型、可以设置预算上限。团队里再也不用有人问“谁手里有 OpenAI Key”。

4.2 预算、限流与团队配额怎么设

预算控制是网关最实用的部分之一。我通常会按团队或者项目建 Key,然后给每个 Key 设置独立的max_budget。上面的命令里,max_budget: 20表示这张 Key 最多花 20 美元,budget_duration: 30d表示这个额度是 30 天周期,到期自动重置。

还可以设置每分钟的请求速率限制:

curl -X POST "http://localhost:4000/key/generate" \ -H "Authorization: Bearer sk-litellm-master-key" \ -H "Content-Type: application/json" \ -d '{ "models": ["gpt-4o"], "max_budget": 50, "budget_duration": "30d", "rpm_limit": 60, "tpm_limit": 100000 }'

rpm_limit是每分钟请求数,tpm_limit是每分钟 token 数。我踩过的一个坑是:只设置了max_budget,没设rpm_limit,某个定时任务在高峰期瞬间打出大量请求,差点把月度预算几分钟内烧穿。所以强烈建议任何面向自动化任务发放的虚拟 Key,至少把rpm_limit配上。

4.3 费用统计与日志:月底再也不用自己对表

预算控制只是前菜,真正让我觉得“早就该用网关”的时刻是查账。没有网关的时候,月底要跑三四个平台的后台导出账单。有了 LiteLLM 之后,每条请求的 token 消耗、成本估计、模型名、请求状态都打到日志里,还能直接查询。

查询某张 Key 的消费记录:

curl -X GET "http://localhost:4000/spend/logs?key=sk-1234" \ -H "Authorization: Bearer sk-litellm-master-key"

如果要持久化这些日志,官方推荐接 PostgreSQL。在general_settings里配好database_url,重启后日志和预算数据都会落库。我实测下来,如果只是临时用,SQLite 也能顶一阵子,但一旦多台机器或者要查复杂费用报表,还是尽早切 PostgreSQL,否则后面数据量上来迁移很痛苦。

这里要特别提醒一个坑:预算扣费的准确性依赖数据库记录。如果你服务只用内存跑,Key 的剩余额度在重启后会复位,可能造成“明明没超预算,却被拒绝服务”的情况。所以凡是涉及预算、团队配额的生产部署,数据库必须配好。

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

5.1 请求返回 404、模型不存在

这个是我遇到频率最高的问题。业务端报model not found或Unknown model时,百分之八十是model_name没对上。你在请求里传的模型名,必须和config.yaml中model_list里的model_name完全一致,而不是真实供应商模型名。

排查套路很简单:先看model_list里的model_name是什么,再对比请求里的model字段,最后看代理启动日志里有没有模型映射异常。也可以用:

curl -X GET "http://localhost:4000/model/info" \ -H "Authorization: Bearer sk-litellm-master-key"

这条命令会返回代理当前注册的所有模型名,是排查模型映射问题的第一利器。

5.2 请求一直超时或 502

分几种情况。如果所有模型都超时,先查代理服务本身到外网的连通性,再查 DNS 解析。如果只有某个供应商超时,那大概率是上游接口地址问题。用国内服务器部署时,这个问题尤其容易被忽略:一些海外模型接口的延迟和稳定性完全取决于网络链路,代理层能做的就是调大超时、开重试,但链路质量本身代理解决不了。

另外,很多模型供应商官方要求 SSL 证书验证。如果你的代理跑在内网环境,且上游接口用的证书不被系统信任,可以在litellm_params里对特定模型设置ssl_verify: false。注意,这只建议在自己能控制可信链的内网用,公网环境别轻易关验证,安全更重要。

5.3 上游 Key 一直报鉴权失败

这个问题通常是环境变量没被加载。配置里写了os.environ/OPENAI_API_KEY,但启动服务的进程里没有这个环境变量。排查方法很简单,在终端里先echo $OPENAI_API_KEY确认有没有值,没有就先 export,或者写进.env文件再用--config启动时加载。

还有一个细节:如果同时在litellm_params和系统环境变量都配置了 Key,LiteLLM 优先读取litellm_params里的值。这会导致你改了环境变量,但请求还在用旧 Key,误以为设置没生效。

5.4 上游频繁 429,代理服务跟着抖

429 通常是触发了供应商的速率限制。除了前面说的多 Key 负载均衡,另一个实用技巧是在代理里开启智能重试。LiteLLM 本身支持按Retry-After头等待后重试。还有一种思路是给模型配置更低的并发上限,从源头削峰:

litellm_settings: max_parallel_requests: 20

这个参数控制代理层同时处理多少个请求,超过的直接排队或返回 429。我在内部工具里设成 20 之后,上游 429 明显少了,而且代价只是排队等待时间变长,而不是失败率上升。

5.5 日志、指标接入不成功

生产部署时,团队通常希望把代理的指标接到现有监控。LiteLLM 提供 Prometheus 端点/metrics,你只需要在general_settings里打开:

general_settings: master_key: sk-litellm-master-key otel: true

然后用 Prometheus 抓取http://localhost:4000/metrics即可。需要注意的是,打开otel: true后会有额外的可观测性依赖,如果你的环境里没搭好相关后端,可能会在启动时报错。可以先不开,等监控体系真正需要再补。

一些实战后的个人体会

LiteLLM 真正改变我工作习惯的地方,不是省掉了那几行切换供应商的代码,而是让“模型资源”变成了一种可管理、可计量、可分配的东西。以前模型是被硬编码在各个业务服务里的,现在它是一个统一入口,后面接什么模型,业务方根本不需要感知。从搭建第一天起,我就在配置里把所有模型都起成稳定的逻辑别名,之后上游模型迭代升级,我只改网关配置,业务代码一行不动。

最后分享一个很实用的小技巧:如果你把多个供应商的“同能力模型”都映射到同一个model_name下,业务代码里只写一个模型名,网关自动做负载均衡和故障转移,这种感觉非常爽。但这套玩法要想稳,前提是先把日志、预算、超时这些基础配置搭扎实。我的建议是:别想着一步到位,先从一台模型一个 Key 跑通最小链路开始,再逐步加模型、加负载、加预算。基础设施这东西,稳比花哨重要得多。

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

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

立即咨询