☰
LiteLLM:开源大模型网关,统一多模型接入与成本管控
2026/10/21 15:28:11 网站建设 项目流程

很多做AI应用的同学,早期都在代码里硬编码各家大模型API的地址和密钥,一个应用接了三四个供应商,每个供应商的请求格式还不一样,代码里全是兼容层和if-else。等到团队协作、成本统计、模型切换的需求一起来,整个调用链就彻底乱套了。litellm(全称Light LLM Engine)最初给我的印象是一个“统一格式转换库”,但真正上手之后你会发现,它能做的远不止格式换算——把它当网关用,才是这个项目最大的价值。

简单说,litellm是一个开源的大模型网关(LLM Gateway),本身以Python包的形式提供,同时也内置了一个高性能代理服务器。应用层几乎不需要改造代码,只要把API地址指向litellm,它就能把请求统一转发给几十乃至上百家不同的模型服务商,并在这个过程中完成模型路由、负载均衡、密钥托管、预算限制、日志追踪等一系列事。它适配了OpenAI SDK的调用风格,也就是说你原有的SDK用法基本不用动,改个base_url就能接上。

这篇内容我会从实际落地角度,把litellm的设计思路、部署方式、配置技巧和踩坑记录完整展开,适合正在做LLM应用开发、想统一管理多个模型供应商的团队,也适合想给个人项目加一层“模型路由层”的独立开发者。

1. 这个工具到底解决什么问题

1.1 从多供应商接入的真实困境说起

做过AI应用的人应该都有体会:一个正经产品不太可能只绑定一家模型厂商。原因很现实:单点故障风险、价格波动、不同模型在不同场景下表现差异大。比如客服机器人用便宜的小模型跑分类,复杂推理才调用大模型;再比如某些地区访问海外模型延迟高,得切到国内厂商的替代模型。这时候你就面临几个绕不开的问题:

  • 每家厂商的请求格式不同,接口路径不同,SDK也不通用,代码里得有多个client分别维护。
  • 每个厂商的密钥散落在代码、配置文件、环境变量里,团队成员谁都在用,无法控制权限和用途。
  • 每个月结算成本时,各家平台各出一份账单,你要手动去核对每条调用到底花了多少钱、是谁调用的。
  • 换模型要动代码,发版,测试,耗时又容易出错。

这些问题单独看都不致命,但叠加起来会随着业务增长迅速失控。我之前见过一个项目,代码里光是处理供应商格式兼容的逻辑就有上千行,每次加新模型都要改一遍主流程,上线前还要专门联调一整天。

litellm对这个痛点的解法很直接:它把“模型API”这一层抽象出来做一个标准入口,所有上游模型都映射成统一的调用格式,应用只需要跟litellm说话,剩下的兼容、转发、统计全部交给网关处理。

1.2 litellm的定位与核心思路

先理解一个关键点:litellm本质上扮演的是“协议翻译器+请求调度器”的角色。它把不同供应商的API协议统一转换成OpenAI风格的调用格式,同时把OpenAI风格的输入请求转换成目标厂商需要的真实请求格式。这个思路和数据库中间的访问层很像,只不过它针对的是模型服务。

litellm一共有两种使用形态:

  • 作为Python库:在代码里直接import litellm,用litellm.completion(messages=...)统一调用各家模型。这个形态适合写脚本、做实验,节省的是格式转换的工作量。
  • 作为代理服务器:启动litellm --config config.yaml,暴露一个http://localhost:4000的OpenAI兼容端点,应用把base_url指过去就行。这个形态适合生产环境,你能得到完整的路由、限流、预算、日志能力。

实际项目中,99%的团队最后都会选择代理服务器形态,因为它彻底做到了“应用无感”——应用根本不知道后端到底接了几家模型,也不会被供应商SDK升级牵着走。后面我整个实操也围绕代理这种形态展开。

2. 核心功能拆解与设计逻辑

2.1 一个入口接入所有供应商

litellm对供应商的接入方式是“配置驱动”,不是“代码驱动”。你不需要为每个厂商写调用逻辑,只需要在config.yaml里声明模型列表,网关就能自动识别并转发。

配置结构大致是这样的:

model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: claude-3 litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: os.environ/ANTHROPIC_API_KEY

这里有一个很容易忽略的设计:model_name是你在应用层使用的逻辑名字,litellm_params.model是网关真正转发给上游时用的完整模型标识。通过这个映射,应用永远只认gpt-4o、claude-3这种简单的逻辑名,即使你后台把claude-3换成某国内厂商的模型,应用层一行代码都不用动。

实际支持范围很广,常见的海外几个头部模型、国内各大厂商、开源模型托管的托管平台,还有本地用vLLM、Ollama部署的自建模型,都能接入。你甚至可以把同一个逻辑名映射到多个上游不同厂商的模型上,这就引出了下一节的路由能力。

2.2 模型路由与故障转移是如何工作的

如果你只想做统一接入,一个反向代理就够了。litellm真正加分的地方在于,它支持把一次请求动态分发给多个上游模型,这背后的逻辑是“网关层做高可用”。

核心配置是给一个model_name配置多个上游,比如:

model_list: - model_name: my-completion-model litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: my-completion-model litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: os.environ/ANTHROPIC_API_KEY

此时网关收到逻辑名my-completion-model的请求,会在两个供应商之间做选择。默认的策略是简单轮询(round-robin),也可以配置成加权轮询(weighted round-robin),甚至可以按照自定义规则路由。

这种设计解决的实际问题非常典型:

  • 主模型限流了,请求自动切换到备选模型,不需要应用自己捕获异常再重试。
  • 主模型服务宕机,网关自动把流量切到其他可用供应商,用户几乎无感知。
  • 两个同级别模型按比例分流做A/B测试,灰度验证新模型效果。
  • 按上下文长度分模型,小请求走便宜模型,大请求走长上下文模型。

2.3 密钥治理与成本控制

很多团队最开始把密钥直接写在应用代码里,只图方便。可一旦密钥在日志、聊天记录、代码仓库里泄露,后果非常严重。litellm的密钥管理把这块补上了:

  • 上游密钥统一托管在网关环境变量或配置中,应用层完全接触不到真实上游密钥。
  • 网关可以生成“虚拟密钥”(virtual key),每个应用、每个团队成员都用独立虚拟密钥。
  • 虚拟密钥可以单独设定预算上限、速率限制、允许访问的模型范围。
  • 管理员可以在网关上随时吊销某个虚拟密钥,不需要去上游平台修改密钥。

成本控制这一块是litellm特别实用的功能。你可以给某个密钥设定max_budget,比如1美元,一旦这个密钥累计消耗超过这个数值,网关直接拒绝后续请求。这个消耗金额不是估算的,网关会根据实际使用的token数量和上游定价表实时计算。同时它支持按天、按周、按月设置重置周期,方便做周期性预算控制。

2.4 可观测性与日志追溯

网关除了做代理转发,还有一个天然优势:所有请求都经过同一个点,日志和监控数据非常集中。litellm默认会把每次请求的模型、时间、token用量、成本、延迟、响应状态记录下来,支持入库到PostgreSQL等数据库,也支持把日志推送到Prometheus做指标监控。

这对团队的意义很大。我有一次排查线上问题,用户反馈某个供应商的模型回答质量时好时坏。通过网关日志拉出近一天该模型的请求分布,发现其中相当比例被路由到了另一个备用模型上,因为备用模型成本低、权重配得高。说白了不是模型出问题,是路由权重策略导致部分请求走了“劣质但便宜”的线路。没有网关日志去回溯,这类问题会反复排查不出来。

3. 从零部署一套可用网关

3.1 安装与启动基本形态

litellm的代理支持Docker部署,也支持直接用pip安装后命令行启动。我建议团队项目优先用Docker,干净、可移植、升级方便。演示项目或者本机调试,用pip就够了。

安装命令很简单:

pip install 'litellm[proxy]'

装好之后,先准备一个最小的config.yaml,我习惯把上游密钥放在环境变量里,而不是直接写进配置文件,这样配置文件可以安全地提交到代码仓库:

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

启动代理:

export OPENAI_API_KEY=sk-xxxx litellm --config config.yaml --port 4000

看到类似Uvicorn running on http://0.0.0.0:4000的输出就说明起来了。默认端口是4000,不冲突,也容易记住。

如果你的环境不允许多个服务同时监听端口,也可以只用在代码库方式。但代理方式的优势太大了,我后面所有演示都基于代理模式。

3.2 编写config.yaml的主干配置

配置文件的完整结构比刚才那个最小示例要更丰满,我平时起步会配置这些块:

model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ.OPENAI_API_KEY - model_name: gpt-4o-mini litellm_params: model: openai/gpt-4o-mini api_key: os.environ.OPENAI_API_KEY litellm_settings: drop_params: true general_settings: database_url: os.environ.DATABASE_URL

我解释下为什么建议设置里带上这个drop_params。不同供应商支持的参数不完全一致,比如某厂商的请求不接受frequency_penalty之类的参数,默认情况下网关遇到这种不一致会直接报错。打开drop_params后,网关会忽略目标模型不支持的参数,保证请求能成功发出去。这个开关很适合“一个逻辑名映射多个供应商”的场景,因为不同厂商的能力差异确实大。

database_url这里先提一下,它是成本追踪和虚拟密钥功能的基础。如果不配置,网关默认会把日志存在内存里,重启就丢了,密钥管理功能也无法使用。所以生产环境建议从一开始就配置PostgreSQL。

3.3 用OpenAI SDK接入网关

启动网关后,开发者的接入方式基本就是改base_url。以Python的OpenAI SDK为例:

from openai import OpenAI client = OpenAI( api_key="sk-1234", # 这里填litellm生成的虚拟密钥 base_url="http://localhost:4000/v1" ) response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "你好,介绍一下你自己"}], stream=True, ) for chunk in response: print(chunk.choices[0].delta.content or "", end="")

这里有个细节:配置里model_list中的model_name是什么,SDK的model参数就填什么,而不是填上游完整模型标识。很多第一次用的人容易踩坑,在SDK里填openai/gpt-4o这种带前缀的名字,结果网关找不到对应模型。

其他语言也是一样的逻辑,Node.js、Java、Go的OpenAI SDK都支持自定义base_url,改一下就能接。如果团队里已经有现成的SDK使用代码,迁移成本基本为零。

4. 关键实操:路由、预算与权限的进阶配置

4.1 路由策略与权重配置实战

我最开始用litellm只当它是反向代理,后来研究路由功能,发现这东西潜力很大。配置方式是在model_list里给同一个model_name挂多个上游,然后用routing_strategy指定策略。

litellm支持的路由策略主要有:

策略配置值适用场景
简单轮询round-robin流量均分,适合无差别负载分担
加权轮询weighted-round-robin按比例A/B测试,或优先便宜模型
基于延迟latency-based-routing优先选响应快的供应商
基于TTFBttfb-latency-based-routing优先选首字返回快的
成本优先cost-based-routing默认先选最便宜的可用模型

举个例子,我有个业务模型,平时想多用成本较低的供应商A,但又不能让它完全打死供应商B,因为B的复杂推理效果确实更好。我用加权轮询来配:

model_list: - model_name: shared-model litellm_params: model: vendor-a/shared-model api_key: os.environ.VENDOR_A_API_KEY model_info: id: vendor-a-shared-model - model_name: shared-model litellm_params: model: vendor-b/shared-model api_key: os.environ.VENDOR_B_API_KEY model_info: id: vendor-b-shared-model router_settings: routing_strategy: weighted-round-robin model_group_alias: shared-model: [vendor-a-shared-model, vendor-b-shared-model]

注意这个配置结构:router_settings里的model_group_alias把两个上游模型归入一个“模型组”,并给每个模型分配权重。默认权重是相等的,你可以在model_info里加上weight: 30这样的字段来调节分发比例。经过这种配置,同一个逻辑名shared-model发出的请求会按照30:70之类的比例分发到两个供应商。

这里要特别提醒一下,如果路由目标的上游模型来自不同类型的供应商——比如一个OpenAI兼容、一个Anthropic协议——网关会自动做协议转换,所以应用层依然无感。但不同模型的能力边界是不同的,路由策略不能只考虑成本和延迟,还要考虑任务类型。最好是按任务性质拆成多个model_name,再在每个逻辑名下做路由。

4.2 预算限制与虚拟密钥配置

虚拟密钥是litellm里我觉得最实用的一个设计,尤其适合团队协作。它的理念类似“给每个成员一张子卡”:你上游的根密钥只有网关管理员掌握,团队成员拿到的都是网关头生成的虚拟密钥,使用范围、额度、速率全部受控。

创建虚拟密钥需要先连上数据库,然后可以通过管理端API操作:

curl --location 'http://localhost:4000/key/generate' \ --header 'Authorization: Bearer sk-1234' \ --header 'Content-Type: application/json' \ --data '{ "models": ["gpt-4o", "gpt-4o-mini"], "max_budget": 10, "budget_duration": "30d", "max_parallel_requests": 10 }'

这个接口会返回一个类似sk-abc123...的虚拟密钥,把这段密钥交给对应成员配置到自己的环境里。它有两个核心约束:

  • max_budget: 10表示这张密钥的总消费上限是10美元。
  • budget_duration: 30d表示这个额度以30天为周期重置。
  • max_parallel_requests限制并发的请求数量,防止某个成员写死循环脚本把额度烧光。

这样做还有一个额外好处:当有人滥用、密钥泄露,你只需要吊销他的虚拟密钥,根本不需要去上游平台重新生成根密钥,也不影响其他人的使用。

4.3 与团队现有系统的集成模式

litellm在部署位置上通常处在“内网 -> 模型供应商”的中间层。常见的有两种形态:

  • 网关部署在服务集群内部,作为应用容器旁边的一个独立服务,应用通过内部域名访问。
  • 网关作为企业内部的统一模型接入平台,不同业务线的应用都通过它调用模型,由平台管理者统一管控预算和模型准入。

第二种形态下,litellm相当于整个公司调用大模型的“总入口”。业务方不需要关心每个模型在哪个平台、密钥是什么、怎么计费,只需要在平台上申请一个虚拟密钥、选定可用模型,代码里配置base_url就能用。

我见过一个团队就是这样运作的:算法部门统一维护litellm网关,其他业务团队提交申请后就拿到各自的虚拟密钥,接入期间业务方一行模型SDK代码都没写过。而且因为所有流量都过网关,管理层能直接看到各团队每月的模型消费报表,预算管理和成本分摊变得非常透明。

5. 常见问题与排查实录

5.1 请求超时与重试策略:按模型类型区分处理

实际线上跑起来之后,超时是最常见的问题。原因在于不同供应商的响应速度差异巨大,尤其是需要长推理的模型,耗时可能超过60秒,但很多HTTP客户端默认超时只有10到30秒。这时候请求不是没到,而是“还没回来就被客户端放弃了”。

litellm支持在配置里设置时间阈值,并对超时请求做重试。建议是:常规聊天模型设30秒到50秒,带推理扩展开的长推理模型要放宽到100秒以上。同时,启用重试配置,避免因网络抖动丢请求。但重试次数不宜过多,因为有些供应商对同一个请求重复提交是会计费的,一两次即可。

5.2 模型名映射导致的404或400错误

之前说过,SDK里的model参数要填config里的model_name,这是实践中最容易踩的坑。另外一个相关坑是填了带前缀的完整标识,比如某供应商的模型完整名称是vendor-b/shared-model,你直接填到SDK的model参数里,网关会在model_list中找不到对应条目,返回404。

如果你在日志里看到No model found for: xxx这类报错,优先检查:配置文件里model_name是不是这个名字,SDK传的model参数是否完全一致。这个排查路径基本能解决九成以上“找不到模型”的问题。

5.3 成本统计不准的纠正方法

成本统计依赖上游定价表。如果你用的是某种自定义部署模型、本地模型或未收录模型,网关可能没有它的价格数据,日志里cost可能就是0,或者因为单位错配出现偏差。你需要在配置里手动补充价格信息:

model_info: cost_per_token: 0.000002 output_cost_per_token: 0.000006

cost_per_token是输入token单价,output_cost_per_token是输出token单价,单位是美元/token。这块看着简单,但很多自定义部署的团队容易忽略,结果预算功能形同虚设。

5.4 流式响应和并发连接的处理

litellm对流式响应(streaming)支持得比较完整,OpenAI SDK的stream参数可以直接用。但在高并发场景下,如果发现网关响应变慢或者日志出现连接超时,需要考虑给网关前面加一层负载均衡,让多个litellm实例一起扛流量。

这里有个容易漏掉的细节:litellm的虚拟密钥和预算记录依赖数据库,如果多个实例跑在同一套PostgreSQL上,高并发下的锁竞争可能拖慢请求处理。建议实例数量起来之后,保持数据库配置合理,并定期清理过期日志,避免日志表无限膨胀影响查询和写入性能。

5.5 一些容易被忽略的细节

我在使用过程中还整理了几个容易被忽略但影响很大的细节:

  • 配置文件改动后要重启网关才能生效,没有热加载机制。
  • 如果你的应用使用异步客户端,要确认网关服务自身有足够的线程池处理并发长连接,必要时调整启动参数。
  • 上游供应商密钥到期前,建议提前在环境变量中更换,否则线上会突然大面积报错且不好定位。
  • 日志库会自动记录完整的prompt和响应内容,涉及敏感数据时建议关闭完整日志或做脱敏处理,避免合规风险。

比如脱敏这一点,有些团队刚开始不重视,直到有一次排查问题时发现员工提问内容全部明文存在日志里,才意识到风险。litellm支持配置turn_off_message_logging,开启后日志只记录token用量和元数据,不记录具体消息内容,这个在涉及用户隐私的场景下非常关键。

最后再补一个我自己上手时真正体会到的好处:litellm把“模型接入”这件事彻底从应用代码里剥离出来了。以前每接一个供应商,都要写一段适配代码、安排一次联调、出一版新代码;现在加模型只是改一下config.yaml,然后重启网关,应用层连感知都没有。这个开发模式的转变,带来的效率提升是很明显的。如果你正被各种模型API的差异化搞得焦头烂额,认真研究一下litellm的网关形态,大概率能找到一条更省心的路。

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

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

立即咨询