☰
litellm:大模型统一调用网关,轻松搞定API切换与成本管控
2026/10/13 8:24:40 网站建设 项目流程

做AI应用最烦的一件事是什么?不是模型效果不行,而是模型太多了。今天要聊的litellm,就是专门解决这件事的——一个开源的大模型统一调用网关。简单说,你在代码里写一套接口,就能无缝切换主流厂商的模型、本地部署的开源模型,甚至还能替你管密钥、做负载均衡、设预算、看用量。这篇文章我会从为什么需要它、核心功能怎么拆解、到实际部署怎么配,一步步讲清楚,最后再分享几个生产环境里容易踩的坑。

1. 为什么会出现litellm:大模型时代的第一道基础工程

1.1 被模型API碎片化支配的日常

先聊一个真实的工作场景。某天你在一家小团队做AI应用,早上用A厂商的模型写了个原型,跑通之后,领导说换B厂商的模型试试效果。你打开代码,发现要改的东西远不止“换一个模型名”这么简单:请求格式可能不一样,鉴权方式不一样,流式返回的解析方式不一样,甚至连参数名都不同。A那边叫max_tokens,B那边叫max_token,C那边叫max_tokens_to_sample。改完A的代码,还得重新写B的解析逻辑。

如果在同一个应用里同时接几个模型,代码会变得非常痛苦。每个模型一套SDK、一套错误码、一套限流逻辑,最后你写的不再是业务代码,而是一堆模型适配器。更麻烦的是,各家的调用计费方式还不一样,有的按token、有的按请求数,客户问你这个月AI花了多少钱,你算半天才算明白。

litellm解决的就是这个碎片化问题。它把各家模型API的差异处理,收敛到一个统一格式里。你在代码里只打交道一个接口,传model参数时写“厂商名/模型名”,剩下的转换、鉴权、重试、计费统计,都交给它。

1.2 它到底是个什么角色

我的理解是,litellm做的事有点像“支付网关”之于各种支付渠道:前端商家不需要关心你用的是支付宝、微信还是银行卡,后端统一走一套接口,平台帮你把各种渠道的差异消化掉。

它有两种典型用法。第一种是当成SDK/库,pip安装后直接在Python代码里调用,适合单个项目、脚本、Notebook里的快速实验。第二种是当成独立代理服务(Proxy Server)跑起来,对外提供一个兼容OpenAI格式的HTTP接口,所有应用都能通过这个网关统一访问模型。第二种才是企业落地最关心的形态,因为密钥、用量、预算、监控都集中在这层了。

一句话总结:如果你在项目里已经感觉“换一家模型要改好多地方”,或者“团队里很多人都在各自用各自的API Key,成本乱成一锅粥”,那litellm大概率对你有帮助。

2. 核心功能拆解:一个网关到底能做多少事

2.1 统一调用格式:从100个SDK变成1个

先看肉眼最直观的部分。不经litellm时,你要分别维护多个供应商的SDK;用了litellm后,代码里的请求是这个样子的:

from litellm import completion response = completion( model="provider-a/gpt-4o", messages=[ {"role": "system", "content": "你是一个资深的Python工程师。"}, {"role": "user", "content": "用三句话解释什么是闭包。"} ], temperature=0.7, )

model参数里的斜杠前面是供应商前缀,后面是模型名。这个前缀要写对,litellm才知道该走哪家供应商的鉴权和接口。比如你本地起了个Ollama模型,就写“ollama/llama3.1:8b”;用的是某云上的托管模型服务,就写对应的前缀。

那段代码的返回结构也是统一好的:一个带choices、usage等字段的CompletionResponse对象。你不需要分别处理不同家返回的结构差异。更换模型有多容易?改model参数里那个字符串就够了。

# 换一个模型,改一行 response = completion( model="provider-b/gemini-1.5-pro", # 换这里 messages=[...] )

底层的prompt格式有没有被自动改写?举个例子,某个模型走的是对话历史格式,另一个模型走的是消息列表格式,这类差异litellm会自动完成转换。你不用去背每个厂商的消息格式差异,这是直接省时间的地方。

提示:斜杠前缀不能漏。有个常见错误就是只写了“gpt-4o”没写前缀,结果litellm默认按某个约定处理,绕了一圈才反应过来。官方推荐的做法是写全“厂商/模型名”。

2.2 自动完成请求格式的输入输出转换

这里值得多聊几句,因为很多靠“调接口”混日子的朋友根本没意识到各家API的格式差异有多大。同样是“多轮对话”,有的接口是messages数组,有的要把历史记录拆成单独的字段;同样是“让模型输出JSON”,有的在请求里用response_format,有的用结构化输出,有的干脆要靠prompt约束。

litellm内部维护了一套与各厂商模型对应的转换参数配置。你传一个标准的统一参数集,它会拆分成对应服务商需要的样子;返回时又把各家的原始格式归一化成统一结构。这套转换的细节非常多,比如流式输出(stream)模式下,各家吐出来的chunk格式五花八门,litellm会统一翻译成OpenAI风格的chunk结构。这样你做流式输出时,上游应用不用改动,下面随便换模型。

在这个层面上,litellm很像一个“翻译层”:前面对着你的业务代码说统一语言,后面对着各家模型API说它们各自的语言。所谓兼容性,不是说让各厂商API长得一样,而是有一个中间人帮你做翻译。

2.3 网关模式的杀手锏:多Key管理、预算、限流与观测

SDK模式适合单点使用,但真正让团队协作和上线部署顺畅的,是代理网关模式。你只需要在某台服务器上启动一个litellm服务,把真实验证信息配置好,然后让团队所有人访问这一个地址。这样做的直接收益有四个。

第一,密钥安全。业务代码里不再需要硬编码真实密钥。开发同学只需要知道网关地址和自己的虚拟Key,就能正常访问模型。

第二,预算可控。给每个开发、每个应用、每个部门设置独立的预算上限和速率限制,超了就自动拒绝请求,月底再也不会收到爆炸的账单。

第三,统一观测。在网关这一层能看到每一次请求:谁发的、用的哪个模型、输出了多少token、响应耗时多久、是否重试、是否失败。不用再到每家后台去翻报表。

第四,高可用。同一个模型可以配多个上游渠道或多个真实Key,网关自动做负载均衡;某个渠道挂了,自动重试或降级到备用模型,对业务方透明。

2.4 成本、用量与模型表现的可观测性

线上跑了几个月后你会发现,成本、用量、模型效果这三角关系,是团队最常问的问题。“上个月那个新人的Key干了什么?”“现在按用户来看,人均token消耗是多少?”“模型A的失败率为什么比模型B高?”这些在litellm里都能直接查到。

它可以记录每一次请求的用量明细,并且提供按Key、按用户、按模型聚合的统计视图。配合后端数据库(比如PostgreSQL)存储日志,数据不会丢,随时可以做分析。对中小团队来说,这就是一个轻量级的LLM运维后台,不用再自己拼一个统计系统。

3. 实操过程:从零搭出一个可用的模型网关

3.1 安装与初始化环境

先准备环境。建议用Python 3.9以上版本建一个虚拟环境,避免依赖冲突。

python -m venv llm-gateway source llm-gateway/bin/activate pip install litellm

装完先做个冒烟测试,确认SDK能跑通。如果没有真实密钥,可以用Ollama本地模型试:

ollama pull llama3.1:8b

然后写个简单脚本:

from litellm import completion response = completion( model="ollama/llama3.1:8b", messages=[{"role": "user", "content": "用一句话介绍你自己"}], api_base="http://localhost:11434" ) print(response["choices"][0]["message"]["content"])

这里显式传了api_base,是因为本地Ollama服务地址和默认值不一致。这个细节在生产里很常见:有些供应商的兼容接口不是默认地址,你必须在请求或配置里指对它。

3.2 用config.yaml配置多供应商信息

跑通单次调用后,就该配一个正式的代理服务了。litellm的代理服务支持多种配置方式,我习惯用config.yaml来管理,因为它可以一个文件描述清楚所有模型、密钥和策略,而且能放进版本控制。

先建一个config.yaml,内容类似这样:

model_list: - model_name: my-gpt-4o litellm_params: model: provider-a/gpt-4o api_key: os.environ/PROVIDER_A_API_KEY rpm: 100 - model_name: my-claude litellm_params: model: provider-b/claude-sonnet api_key: os.environ/PROVIDER_B_API_KEY rpm: 50 - model_name: my-local-llama litellm_params: model: ollama/llama3.1:8b api_base: http://localhost:11434 litellm_settings: drop_params: true set_verbose: false general_settings: database_url: os.environ/DATABASE_URL

model_name是暴露给上层应用的“别名”,litellm_params则是这个别名背后的真实模型和参数。为什么要设计别名?因为上层业务不应该关心你到底用的哪个具体模型。某天你把某个应用从A模型切到B模型,只需改config.yaml里的映射,业务代码一行不动。这就是“模型路由”的核心思路。

3.3 启动代理服务并接入应用

启动服务:

litellm --config ./config.yaml --port 4000

看到日志里出现类似“Uvicorn running on http://0.0.0.0:4000”的信息,说明网关起来了。

接下来,在任意语言里,用OpenAI兼容SDK接入。因为litellm对外暴露的接口就是OpenAI的接口风格,所以你可以直接用openai SDK:

from openai import OpenAI client = OpenAI( api_key="sk-随便填一个虚拟key", base_url="http://你的服务器地址:4000" ) completion = client.chat.completions.create( model="my-gpt-4o", messages=[{"role": "user", "content": "你好,请介绍下你自己"}] ) print(completion.choices[0].message.content)

注意model传的是config里的别名my-gpt-4o。如果你想让业务团队只使用某些别名,就在这里做收口。

3.4 为什么第一次接入要用这种“配置+别名”的方式

很多新手一开始跳过config.yaml,直接命令行启动“litellm --model gpt-4o”,这样做确实能跑,但只适合本地试验。生产中一定要用配置,原因有几点:只有通过config,才能同时管理多个供应商的密钥;才能把每个模型的限流参数、备用渠道写清楚;才能让上层应用不用改代码就切换模型;才能让网关实例的配置是声明式、可审计、可回滚的。

这个习惯,跟写基础设施代码要“用配置而不是命令”是一个道理。命令改起来一时爽,后头维护火葬场。

4. 进阶玩法:路由策略、降级方案与成本管控

4.1 把多个真实密钥组合成一个逻辑模型

用同一个上游模型,但配多个真实密钥,是很常见的需求。这样做能突破单个账号的速率限制,也能在某个账号出问题时自动换到另一个。config里可以这样写:

model_list: - model_name: scalable-gpt-4o litellm_params: model: provider-a/gpt-4o api_key: os.environ/PROVIDER_A_KEY_1 - model_name: scalable-gpt-4o litellm_params: model: provider-a/gpt-4o api_key: os.environ/PROVIDER_A_KEY_2

两个条目用了同一个model_name“scalable-gpt-4o”,litellm会在它们之间做负载均衡。默认策略是带权重的轮询,后续你可以结合各Key的稳定性、速率限制设置更智能的权重。

4.2 设置失败次数冷却与自动重试

网关的意义不只是“翻译”,还要有容错能力。比如你的优选模型突然报错,你希望请求自动降级到备用模型。可以在config中加fallbacks:

model_list: - model_name: main-model litellm_params: model: provider-a/gpt-4o api_key: os.environ/KEY_A - model_name: backup-model litellm_params: model: provider-b/claude-sonnet api_key: os.environ/KEY_B litellm_settings: fallbacks: [{"main-model": ["backup-model"]}] num_retries: 3 request_timeout: 30 allowed_fails: 3 cooldown_time: 60

这几个参数解释一下。num_retries是同一个上游失败后的重试次数;allowed_fails是某个上游连续失败多少次后会进入冷却状态;cooldown_time是冷却时长,冷却期间新请求会直接走备用。这些参数要在“业务可用性”和“请求延迟”之间做平衡。重试太多会让用户等很久,冷却太快又会让模型切换过于频繁。建议先按“3次重试+3次失败触发冷却+60秒冷却”起步,观察线上指标后再调。

4.3 虚拟Key与预算控制

代理服务启动后,默认情况下所有人共用你配置的上游密钥。但做团队协作时,你更希望每个成员或每个应用有一个独立的虚拟Key,这样能单独统计和限流。

先用管理接口生成虚拟Key:

curl --location http://localhost:4000/key/generate \ --header "Authorization: Bearer sk-1234" \ --header "Content-Type: application/json" \ --data '{ "budget": 10, "max_parallel_requests": 5, "tpm_limit": 100000, "metadata": {"team": "algorithm", "app": "demo"} }'

这里budget字段是该Key最多能花的美元金额(实际单位以你的配置为准),max_parallel_requests限制并发请求数,tpm_limit限制每分钟token吞吐量。生成的Key要发给对应成员,并要求他们在代码中用这个虚拟Key。真正的上游密钥永不下发到业务端。

4.4 团队场景:按人和按应用核算成本

之前有次分享,有人问“预算控制会不会很粗暴,误伤正常业务?”这个问题问得好。所以litellm敢做这件事,前提是它能按粒度统计。它支持“用户”维度——你在调用时可以通过user字段传入业务里真实用户的ID或应用名,后续在网关日志里就能按这个维度看消费情况。比如你的业务里有A、B两个应用,你希望在同一个网关下分别统计它们各花了多少钱,只需在请求里带上不同的user标识,然后查询时按该字段分组。

这套能力对中大型团队特别实用:不再需要让“ChatGPT小组”和“搜索增强小组”分别去开户、分别去报销,统一走一个平台,月底看报表时直接按维度切分。

4.5 成本追踪的底层逻辑

为什么网关能算清账?核心在于它在转发前后都会记录usage字段。不管你是直接SDK调用还是走代理,它都会把该请求的prompt_tokens和completion_tokens取出来,再结合该模型对应的单价,换算成成本并落库。下面这句是配置里的说明,units的计算依旧按模型单价字段来。你可以在请求列表里看到每一次调用的token明细,这就省去了“对着各厂商后台Excel手算”的噩梦。

5. 常见问题与排查经验:实战里最容易坑人的那些事

5.1 请求报错:AuthenticationError

最常见的是认证错误。排查看几点:真实密钥是否写入环境变量并在服务器重启后正确加载;config.yaml里是否用了os.environ/XXX的写法,而不是把密钥明文写进去;宿主机环境变量是否导出成功;代理服务有没有使用你预期的那份配置文件。

有次一个小伙伴把密钥写在代码里调试没问题,一上config就报认证失败。查了半天,发现是环境变量文件加载顺序问题——服务先启动了,环境变量还没注入。务必先确认环境变量已加载,再启动litellm。

提示:千万不要把真实密钥提交到Git仓库。用os.environ方式加载,并在gitignore里忽略对应的.env文件,这是最基本的底线。

5.2 模型名报Not Found / BadRequest

这通常是“别名不存在”或“上游模型名写错”。“model=my-gpt-4o”但config里根本没有定义这个别名,立即报错;“model=provider-a/gpt-4o”但真实服务商那边没这个版本号,也会报错。排查方法是先用一个最小请求逐层拆解,先测真实上游是否能调用,再测通过网关是否能调用,最后测业务侧配置。一层层定位,而不是对着整个链路猜。

5.3 流式响应时中断或乱码

走代理做流式输出时,如果发现内容中断、报错,常见原因是超时配置过短或网络中间层有缓冲。将请求超时适当调大,确认没有引入会缓冲完整响应后再转发的组件(如某些默认开启动态缓冲的网关)。有一点要强调:litellm本身会以流式方式转发上游的chunk,但如果你外面再包了另一层代理,那层代理可能会把流式响应缓冲成整体,导致前端体验变差。排查时优先绕开无关中间层。

5.4 限流429与并发优化

上游限流是常态。一上来就疯狂并发,基本都会撞429。先检查config里的rpm/tpm是否贴近上游能承受的量级;再检查是否用了多个真实Key做负载均衡;最后看是否启动了重试和冷却。

并发连接还有一个容易忽略的地方——连接池大小。如果你用Python的请求库通过网关调模型,默认连接池比较小,高峰期TCP连接会被占满,表现为大量超时或连接被重置。可以在客户端侧调大连接池上限,或者在litellm侧调大并发worker数。具体的连接池参数不是万能的,要结合你机器CPU与内存逐步加压测。

5.5 日志里看不到请求记录

很多人配置了代理服务,也用了数据库,但在查询页面里看不到任何日志。原因大部分是数据库连接没生效,或者数据库表迁移没跑。启动时会自动建表,但如果DBA权限不够就建不了。确认database_url配置正确,确认具备对应库的写权限,确认服务启动日志中没有连接失败的警告。日志数据是后续做成本分析的基础,尽早确认链路是值得的。

6. 部署到服务器上的几个忠告

6.1 服务编排与Docker部署

代理服务本身是无状态的,迁移、扩容都容易。但如果你挂了数据库存储日志,数据库就是有状态依赖。生产上最简单的做法是用Docker容器跑服务,用托管数据库存日志。docker run一下:

docker run -d \ --name litellm-proxy \ -p 4000:4000 \ -v $(pwd)/config.yaml:/app/config.yaml \ -e DATABASE_URL=postgres://user:pass@host:5432/llm_logs \ ghcr.io/berriai/litellm:main-latest \ --config /app/config.yaml

这一步里,你只需要传环境变量进去,config挂在容器里,服务自然起在4000端口。如果团队用编排平台,也可以把同样的启动参数写进工作负载定义里。记得把4000端口的健康检查路径配置好,比如用“/health/liveliness”做存活探针。

6.2 安全加固:网关本身的访问控制

网关是对外提供模型能力的入口,绝不能裸奔。至少要做三件事:一是给管理端接口单独设置授权,不能用默认那个主Key长期跑生产;二是对请求开启速率限制,防止内部某个失控任务拖垮整层;三是把网关放在内网或边缘层,前面的鉴权交给统一的网关层处理。如果是暴露在公网,必须配HTTPS和正确的跨域策略,同时限制管理端接口只对运维网段开放。

6.3 维护习惯:配置先行、日志掌舵

我个人的习惯是,每加一个新上游模型,先改config,再针对它跑一轮前台自测,最后确认日志里有记录。更新模型版本时也是这么一套。上线后多观察“失败率”“平均TTFT(首字延迟)”“token吞吐量”这几个指标,任何一个指标出现明显恶化,都该检查是上游问题、配置问题还是业务请求问题。

7. 使用门槛与适用边界的个人体感

litellm的门槛真的不高。至少会装Python包、会写几行配置,就能把个人项目的多模型调用统一起来。但它的上限很高:路由策略、预算体系、观测平台、多环境隔离,每一点深入下去都可以做很多工程改造。我的建议是:如果你只是写个小Demo,不需要上代理模式,SDK就够;一旦你的项目要上线、有多个人接入、有成本统计需求,请尽早走到代理模式,别等服务上线再补,补的时候一定会痛。

还要多说一句,别被“支持100多家供应商”吓到,你不需要一次配齐那么多。大多数人实际用的就是那么两三家,litellm只是把“以后想换”的灵活性留给了你。核心思路是:哪怕今天只用一家,也建议通过这个统一入口去调,因为明天的事谁说得准呢。

最后一个使用上的小技巧:做模型切换时,使用别名方式(model_name)而不是真实模型名,这样未来切模型只改配置不改代码。这个操作听起来不起眼,但在真正的生产迭代里,能帮你减少一大半的返工成本。

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

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

立即咨询