把乱七八糟的模型调用统一收口是每个做了半年以上 AI 应用的人迟早要面对的事。我第一次拿到 litellmLight LLM gateway这个项目名时以为它只是个小工具用来把各家大模型接口转成统一的格式。后来发现我错了它解决的问题远比“格式转换”广得多模型路由、负载均衡、虚拟 Key、预算管控、日志追踪全都包了。如果你正在做多模型接入、想给团队一个统一的模型网关或者只是想把几个模型服务商串到一个接口后面这篇东西应该能帮你少走不少弯路。1. 项目定位与整体思路拆解1.1 多模型接入的真实痛点做 AI 应用的人应该都经历过这种场景项目一开始只接了某一家大模型服务商的对话接口代码里直接写死client XxxClient(api_key...)调complete()完事。后来需求变了要么是另一家的模型质量更好要么是本地要部署开源模型做私有化要么是同一个模型在不同服务商手里的价格不一样需要切换麻烦就来了。每个服务商的接口风格不同有的用/v1/chat/completions有的用/v1/messages有的走 gRPC参数也不同有的叫temperature有的叫top_k返回结构更不一样有的在choices[0].message.content有的在content[0].text。这意味着每接入一家新模型都要写一套适配逻辑还要处理鉴权方式、错误码、限流策略的差异。业务代码被这些东西塞得越来越脏模型切换一次就得改好几个文件还得重新测试一遍。我见过不少项目就是在这种状态下跑起来的表面看是“接入了很多模型”实际上每接一个都快把研发逼疯。LiteLLM 最早戳中的就是这件事。1.2 LiteLLM 的核心思路不做适配器做网关LiteLLM 的解法不是再写一个 SDK 让几家用而是把所有模型服务商接到一个代理后面对外只暴露一层统一接口。这层接口长什么样就是目前大模型服务商里最通用的 Chat Completions 风格POST /v1/chat/completions请求体是{model, messages, temperature...}返回体是{choices, usage}。客户端发过来的请求先进代理代理根据“模型名”找到对应的上游配置把请求翻译成上游服务商能理解的格式再把上游返回结果统一翻译回标准结构原样返回给客户端。业务方只需要把base_url指向这个代理代码几乎不用改就能访问到代理后面挂的所有模型。这个思路跟 Nginx 做负载均衡很像客户端永远只认一个入口入口背后怎么分发、转发给谁由网关决定。这个设计带来的直接好处是模型切换从“改代码 重新发布”变成了“改服务端配置”。同一套代码今天调用模型 A明天想换模型 B不用动业务逻辑只要改网关配的模型映射关系就行。1.3 适合谁来用解决什么问题我个人把使用者分成三类。第一类是个人开发者和独立开发者主要在多个模型之间横跳做对比测试或者在 application 里不想写死某一家厂商想保留随时切换的余地。这种情况用轻量模式就够了一条命令把代理跑起来所有上游 Key 都放在配置文件或环境变量里本机调试很舒服。第二类是中小型团队需要给多个人分不同的 API Key控制每个人的消费额度还要能看到每个 Key 调了哪些模型、花了多少钱。这种场景下 LiteLLM 的虚拟 Key、预算限制、用量日志正好能顶上。第三类是偏中大型的服务端团队要把大模型网关嵌入现有基础设施对接内部监控、权限体系还要做多活容灾、负载均衡和审计日志。这类需求可以把它作为网关层配合数据库、消息队列等外部组件一起用。不要一上来就想着把全套功能都用上。它的学习曲线不算陡但功能面很宽踩坑点也多你需要搞清楚自己在哪一层。2. 核心功能拆解网关到底干了几件事2.1 统一接口层一个协议访问全部模型LiteLLM 对外提供的核心接口就是上面说的 Chat Completions 风格。你在客户端用标准方式构建请求设置model字段为“代理里的模型名”消息内容照常填剩下的交给代理。代理内部维护着一张很大的映射表把各家模型服务商的协议都翻译成了这一套标准。除了文本对话Embedding、图像生成、音频转写、重排序等常见的模型能力也有对应端点只是使用频率低一些。最让我觉得省事的是它对本地模型的支持。很多人既用云上大模型又想在本地起一个开源模型做私有化场景LiteLLM 对本地模型运行时也做了适配。你在配置里把模型写成本地模型运行时的名字代理就通过对应的协议去调用本地服务对外仍然是标准接口。业务代码完全不用关心上游到底是云上服务还是本地进程。标准化的意义可能在一个人写 demo 时感受不到到了团队协作的时候才会体现新同事接手项目不需要熟悉每个服务商的 SDK只需要知道“调统一网关填模型名”上手成本低一大截。2.2 模型路由与负载均衡如果你以为 LiteLLM 只是“翻译官”那就把它看小了。它的另一个重头戏是模型路由。一个常见的需求同一个模型名买了多个服务商的渠道或者同一个服务商下多个 Key希望请求自动分发哪个能用用哪个。LiteLLM 支持在模型名下配置多个上游地址网关按权重轮询哪个上游挂了、超时了就自动把请求转到下一个可用的上游。这里面还能做同一模型不同版本的温切换比如模型版本升级前先拿小流量试一下稳了再全量切。更实际的功能是“降级策略”。比如你的配置里主模型是某头部服务商的最大号模型备选是另一个服务商的同级别模型再往下还可以退到开源模型。当主模型调用失败、限流或者超时的时候路由会自动按优先级往下找。对于生产环境来说这种容灾能力比“接口统一”重要得多。需要注意路由是建立在“同一个模型名在逻辑上可以互相替代”的前提下。如果主模型和备选模型能力差异过大自动降级很可能返回质量不稳的结果。所以最好把“互为备份”限定在能力接近的模型之间。2.3 虚拟密钥、预算与限流这个功能官方叫 Virtual Keys我愿称之为“给下游发子 Key 的工具”。企业内部不可能所有人都共用你的服务商总 Key一方面是额度没法统计另一方面一旦泄露就得全部重置。虚拟 Key 的逻辑是你给每个成员、每个项目颁发一个sk-开头的虚拟 Key这个 Key 只能打到你自己的代理上代理再拿配置里的真实上游 Key 去请求服务商。这样一来真实 Key 永远只存在服务端环境变量或配置文件里客户端接触不到。配合虚拟 Key 的是一套预算控制。你可以给某个 Key 设一个总额上限比如 20 美元也可以按天、按周、按月设滚动预算。一旦使用量超过上限这个 Key 的请求就直接被拒掉。这对于控制内部滥用、给客户做计量计费非常有价值。同一套体系里还带了限流控制比如某个 Key 每分钟最多多少次请求、每秒钟最多并发多少。团队里经常有人写了个死循环脚本把额度跑光有了这个限制至少不会把整条链路打爆。2.4 可观测性与成本追踪不看日志就谈不上管理。LiteLLM 默认会在内存里记录每次请求的 token 用量和花费如果配置了数据库就会落盘写入 Spend Logs按虚拟 Key、模型、用户维度去统计。每次请求用了多少输入 token、多少输出 token、按上游价格算下来花了多少钱都能查出来。日志在本地跑一跑看不出什么但一上生产就会变成刚需。月底要对账、要做成本分摊、要分析哪个模型成本最高、哪个 Key 消耗异常都靠这套数据。如果接上了外部日志服务还可以做调用链追踪和报警。有一点要提前知道如果只是内存日志代理一重启数据就没了。生产环境一定要接数据库持久化否则审计需求来了就抓瞎。我见过有人直接拿 SQLite 顶着用了一段时间结果数据量一大查询明显变慢后来还是切到了独立数据库。3. 实操部署与基础配置3.1 本地快速启动一条命令把代理拉起来先看最简单的用法。装好 Python 环境后直接pip install litellm[proxy]安装然后执行litellm --model openai/gpt-4o --port 4000注意这里openai/gpt-4o的含义是“使用某服务商兼容协议访问 gpt-4o 模型”环境变量里需要配上对应的真实 API Key。跑起来以后代理默认监听 4000 端口。你在任何 OpenAI 风格的客户端里把base_url改成http://localhost:4000/v1传递api_key可以随便填一个非空值就能调 gpt-4o。这种方式适合临时调试也适合个人电脑上做验证。但要注意命令行直接挂单个模型说明文档里那些路由、预算功能通通没有它真的就只是一个翻译代理。如果你装了 Docker还可以用镜像直接跑配置文件挂载进去就行适合部署到服务器之前先本地验证。3.2 config.yaml 的核心配置拆解真实使用中所有配置都写在一个 YAML 文件里启动时指定litellm --config config.yaml --port 4000下面是一个最基础但完整的配置文件我加了解释model_list: - model_name: my-gpt4 litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY model_info: max_tokens: 4096 - model_name: my-claude litellm_params: model: anthropic/claude-sonnet-4 api_key: os.environ/ANTHROPIC_API_KEY model_info: max_tokens: 8192 litellm_settings: drop_params: true set_verbose: false general_settings: master_key: sk-your-master-key-here逐个字段看。model_list是核心每个条目定义了一个“对外模型名”model_name客户端请求里写的 model 就是这个值。litellm_params里指定真实上游模型和真实 Keyapi_key用os.environ/引用环境变量避免把 Key 写死在文件里。model_info建议写上 max_tokens很多自动路由和上下文截断逻辑要依赖它。litellm_settings里我重点说drop_params。不同上游支持的参数不一样有的支持logprobs有的不支持。默认情况下代理会把请求参数原样透传给上游如果上游不认就报错。开了drop_params: true代理会先过滤掉上游不支持的参数再发能少掉很多报错。general_settings里最重要的一项是master_key。启动代理后你访问/models等接口会看到代理的模型列表和管理接口如果不设master_key这些接口裸奔在外网别人扫到你的端口就能看到你的网关配置非常危险。设了 master_key 后访问管理端点都要带上这个 Key。只写上这些就能跑通基础代理了。但绝大多数人不会只用单个模型下面会讲到多模型路由配置。3.3 项目集成客户端只要改两个地方接代理不需要引入任何新的 SDK因为对外就是标准接口。拿最常用的 Python 客户端举例from openai import OpenAI client OpenAI( base_urlhttp://localhost:4000/v1, api_keysk-anything ) resp client.chat.completions.create( modelmy-gpt4, messages[{role: user, content: 你好}] ) print(resp.choices[0].message.content)和原来唯一的区别就是多传了一个base_url。api_key这里其实随便填因为代理会用自己的 Key 去调上游你的客户端真正使用的是代理的地址和服务。如果你用的是 LangChain类似的思路在 ChatOpenAI 里指定 base_url 就行from langchain_openai import ChatOpenAI llm ChatOpenAI( base_urlhttp://localhost:4000/v1, api_keysk-anything, modelmy-gpt4 )之所以大家都顺着这套风格来接是因为 Chat Completions 实际上已经成了行业事实标准。绕过标准自己搞一套工具链就断了。3.4 生产部署建议别一股脑压在一个进程里本地调试没问题之后上生产需要考虑几件事。第一代理本身要扩容。最简单的做法是在它前面加一个负载均衡层后面挂多个代理实例每个实例同一份配置。代理实例之间如果不共享数据库虚拟 Key 的用量统计可能会有延迟日志也可能分散。所以生产环境一个基本原则是数据库必须共享。第二配置管理要重视。config.yaml建议放在 Git 仓库里走版本管理真实 Key 一律通过环境变量注入。这样换人、迁移环境的时候配置文件可以直接复用Key 不会因为换台机器就丢了。第三健康检查。代理能不能正常调上游不只是“进程活着”就行。你的负载均衡器最好能定期调用代理的某个健康检查端点确认它背后的模型通道是可用的而不是只测 TCP 通不通。第四超时和重试要提前设计好。上游大模型接口响应本身就慢动辄几十秒代理的默认超时可能不够用。后面我还会详细说。4. 进阶玩法与真实场景经验4.1 高可用与容灾多模型互为备份这是生产环境里最值得花时间配的一段。先看一个配置例子model_list: - model_name: main-llm litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: main-llm litellm_params: model: anthropic/claude-sonnet-4 api_key: os.environ/ANTHROPIC_API_KEY - model_name: main-llm-lite litellm_params: model: openai/gpt-4o-mini api_key: os.environ/OPENAI_API_KEY这里我给三个条目起了同一个对外模型名main-llm。客户端请求main-llm时代理会在这两个上游之间做负载均衡第一个不行就到第二个。这比在代码里手写 “try A except B” 干净太多了。实际效果怎么样我遇到过某上游服务商整体抽风返回 5xx 持续了十几分钟。如果代码直连上游这十几分钟业务就是不可用。走了网关之后代理自动把流量切到备选上游用户侧几乎没感知。事后复盘网关日志里能看到大量失败重试记录但那已经是“事后”了当时服务没断。要多说一句不要盲目配置太多备选。备选的模型如果能力参差不齐降级后的输出质量可能让用户明显不满。我一般建议主备之间能力差距不要太大最忌讳把一个大模型工作流的主模型降级成一个轻量小模型效果差到没法用。4.2 企业内部权限管控落地给团队搭一个网关常见的目标是“让大家都能用模型但不准乱用”。虚拟 Key 是这里面的核心。流程是这样的管理员在配置里设好所有真实上游 Key启动网关后通过管理端点生成虚拟 Key。生成时可以指定绑定某个 user_id方便追踪是谁在调用设置预算上限比如总共 50 美元限定可以访问哪些模型组比如只能访问轻量模型不能访问旗舰大模型然后把虚拟 Key 发给对应成员。成员在代码里把api_key填成这个虚拟 Keybase_url指向代理。管理员随时可以在服务端撤销某个 Key不需要重启代理也不需要去上游服务商后台重置 Key。这套机制落地以后有个很实际的作用成本分摊。团队内部按项目维度发 Key月底数据库里的 Spend Logs 一查每个项目消耗了多少 token、多少钱清清楚楚。我见过有的团队月底对账全靠手工翻聊天记录那个酸爽谁做谁知道。4.3 与现有服务体系的链路打通网关就是个服务完全可以融进现有的可观测体系里。LiteLLM 支持自定义回调你可以写一个回调函数在每次请求结束后把成功/失败、耗时、token 用量、成本这些数据推给内部监控平台。我之前在一个项目里接了一套内部看板把 spend logs 和请求延迟都汇总上去。原来想着“大模型调用黑盒延迟高一点也没办法”后来发现同一个模型不同时段的表现差异很大有的渠道晚高峰明显变慢。有了数据之后就把晚高峰流量尽量路由到另一个渠道平均延迟肉眼可见地降下来了。另一个打通的点是统一鉴权。网关前面再挂一层内部认证服务让所有模型请求都经过你现有的登录鉴权这样模型能力就变成了一个内部 API 服务而不是一个“谁拿到 Key 就能用”的裸接口。5. 踩坑记录与排查速查表5.1 模型名映射错误404 和 Invalid Model这是新手最容易踩的坑。客户端传的 model 名必须等于config.yaml里model_name的值而不是上游真实模型名。比如你配了model_name: my-gpt4但客户端调用时写model: gpt-4o代理会告诉你找不到这个模型。排查思路很简单先看代理日志看请求进来时匹配到了哪个配置项或者在客户端先调/models接口确认代理里到底有哪些模型名。这个接口默认会返回配置里的所有模型列表比对着看一眼就知道是不是名字写错了。5.2 上下文超限与参数透传问题大模型对上下文长度有硬限制。你把 3 万字塞给一个上下文窗口很小的模型上游会直接报错。有的团队就遇到这种情况同样的代码换个模型就莫名报错查了半天发现是新的模型窗口小了。处理方式有两个层面。一是配置model_info.max_tokens让路由和上层逻辑有依据不至于把过长的内容发给一个根本装不下的模型二是在业务层做内容截断或摘要压缩从源头控制输入长度。网关能帮你路由但管不了业务语义上的内容长度。参数透传的问题前面提过如果遇到“某个参数上游不支持”的报错先在litellm_settings里开drop_params: true。如果你在同一个代理里挂了多个上游强烈建议开启否则同一个请求在这个模型能跑、换那个模型就报错排查起来非常烦。5.3 上游限流与重试策略服务商 API 有 Rate Limit 很正常。你配置了多个上游 Key某个 Key 达到了每分钟调用上限返回 429。代理默认有重试机制但如果你的业务是高并发还是建议自己控制一下并发量别把所有流量都压到一个 Key 上。我和朋友就闹过笑话为了跑压测脚本里开了 50 个并发结果上游直接开始疯狂限流代理日志刷屏自己还一脸懵。后来在网关里把每个 Key 的并发限制调小了又在客户端加了指数退避重试才稳住。5.4 代理实例的并发与性能代理是有性能开销的虽然它本身只是转发和协议转换但 Python 服务在多并发下的表现也受限于进程模型。如果你发现代理 CPU 占用不高、但并发上不去多半是单实例瓶颈要么后面多挂实例要么调大 Uvicorn 的 worker 数。还要注意连接池。上游连接不能每来一个请求就新建一条 TCP否则延迟和资源消耗都很难看。我看过有人的代理明明配置没问题但请求慢得离谱排查到最后发现每次请求都重新建立上游连接。正确的做法是让代理连接复用同时给上游服务商调大响应超时。5.5 日志与预算数据不准确预算统计不准确最常见的原因是用了内存模式并且多实例部署。多个实例各自记各自的账总量当然对不上。另一个常见原因是页面缓存预算查出来是昨天的数其实是统计延迟不是丢数据。真正要查账时直接查数据库里的 Spend Logs 表按 Key、按模型 group by 一下原始数据都在。发现明显异常比如某个 Key 消费暴增优先看这个 Key 关联的日志是不是有重试风暴——上游一直报错代理一直重试token 使用量就在那里白白消耗。重试策略一定要设最大次数别让它无限重试。写到最后分享一个我的实操体会我自己的项目里LiteLLM 已经稳定跑了大半年。最开始我只把它当接口转换器后来慢慢把虚拟 Key、预算、多模型容灾都用起来了现在团队内部所有模型调用都走这层网关已经没人再在业务代码里直接写死上游 Key 和地址了。如果你准备在自己的项目里引入它我的建议是先别追求大而全。第一步挑一个你最常用的模型通过代理转发客户端只改base_url。跑通之后再加第二个模型配一个负载均衡或者降级策略。等这条链路稳了再考虑虚拟 Key 和预算管控。每步都验证好了再走下一步比一次配全套功能后出问题四处找原因效率高得多。最后再提醒一个小技巧配置文件的变更最好都能记录到版本管理里模型切换、参数调整都有迹可循。模型通道出问题的时候你能快速知道“上一次改动是什么时候、是谁改的”这份历史记录能帮你省下大量排查时间。
阅读完成 · 觉得有帮助?