资讯动态

litellm实战指南:统一LLM网关的模型路由、成本治理与故障转移

发布时间:2026/10/14 8:59:25 来源:尧图企业网站定制
做为一名在技术社区混迹多年的开发者我最近几乎被同事和同行安利了无数遍litellm这个项目。一开始我还以为又是某个昙花一现的封装库直到自己动手在模拟项目X里把它跑起来才意识到这东西确实是刚需。简单来说litellm 是一个开源的 LLM 网关它把市面上主流的大模型 API 全部统一成了一套格式你只需要写一份代码就能在各种模型之间无缝切换顺带把成本统计、负载均衡、权限管理这些脏活累活一起干了。这篇文章我不打算念文档而是直接把我这段时间从安装、配置到落地生产的完整经验捋一遍包括我是怎么设计路由策略的、怎么调参的、又踩了哪些坑。如果你正在为项目里同时对接多个模型 API 头疼或者想给团队搭一个统一的模型访问入口这篇文章应该能帮你少走不少弯路。1. 核心思路与方案选型1.1 为什么要搞一个统一网关而不是直接调各家 SDK很多从单体应用时代过来的开发者一开始接触多个大模型 API 时直觉反应就是每个厂商封装一个 Service 类然后在业务代码里写一堆 if-else 或者策略模式来分发请求。我最早也是这么干的但实测下来发现问题非常棘手。首先是接口格式的差异。OpenAI 系的接口是按messages数组传对话上下文Anthropic 系则要求system和user字段分开甚至要求system/system标签包裹系统提示词Google 系的gemini模型返回结构又不一样候选答案、安全评分、引用来源各是各的字段。如果你的业务代码直接面向这些 SDK 编程那么每接入一个新模型就需要写一套对应的解析逻辑请求参数要适配流式返回也要适配异常处理更是各写各的。这种重复劳动不仅仅是浪费时间更致命的是埋下了隐患——一旦某个接口升级你的适配代码可能就静默失效了。其次是账号和成本管理混乱。每个模型厂商都需要独立的 API Key如果是团队协作Key 一多管理起来就是灾难。开发同学把 Key 写在代码里提交到仓库运维同学要审计成本只能去各个厂商后台逐个看账单财务月底对账要对着好几个 Excel 表。这还只是管理问题更麻烦的是稳定性和容灾某家厂商的服务出故障了你的应用没有自动切换机制就只能等着用户投诉。我当时的经历是手里同时维护着三个模型供应商的对接代码每次模型版本更新都要重新翻文档、改解析。有一次线上出了个线上问题排查了半天发现是新版本模型返回里多了一个reasoning_content字段而我的解析器把它忽略了。那一刻我就明白这种刀耕火种式的直连模式不可持续。litellm 的出现正好补上了这个缺口。它做的事情本质上是一个 BFF 层只暴露一个统一的 OpenAI 兼容接口然后把请求转发到任意后端模型同时把后端返回的结果统一转换成标准格式。这个设计思路和 API 网关在微服务架构里的定位完全一致——隔离内部复杂度对外提供稳定的契约。区别在于litellm 面向的是模型层面的路由和治理而不只是 HTTP 层面的转发。1.2 为什么选 litellm 而不是自己写一个网关有人可能会说既然核心就是协议转换那我用一个 Nginx 反向代理或者用 FastAPI 自己包一层不也一样表面上看确实可行但真正落地的时候你会遇到很多隐蔽的坑而这些坑恰恰是 litellm 已经替你踩平了的。第一是细粒度的模型路由能力。Nginx 只能按 URL 路径来做转发做不到按模型名、按用户、按预算额度或按实时可用状态来做智能路由。litellm 的路由策略是内建的支持哈希路由、轮询、最少请求数、基于延迟的加权路由等你只需要在配置文件里声明策略不用自己撸负载均衡算法。第二是重试和故障转移的语义。调用大模型 API 时常见的错误类型五花八门限流返回 429、服务过载返回 503、超时无响应、连接被重置。每种错误的处理策略其实是不一样的。比如 429 应该退避重试而不是立即重试超时应该快速失败并切到备用模型。litellm 内置了这些逻辑而且可以针对每个模型单独配置重试次数、超时时间和熔断阈值。自己用 Nginx 做反向代理要做精细的重试策略就得写 Lua 脚本成本完全不同。第三是成本治理。我自己用 Python 脚本统计过 token 消耗最后发现误差很大——流式输出时 token 数本身就难精确统计多个用户共享一个 Key 时更无法拆账。litellm 直接把 token 计量和成本核算做进了每一条请求链路按模型单价、按倍率换算成美元或人民币金额并且提供按 Key、按用户、按团队维度的报表查询接口。这一块如果全都自己造轮子工作量至少是以周为单位的。还有一个常被忽略的点是生态兼容性。因为 litellm 对外暴露的是 OpenAI 兼容格式所以它可以直接兼容 OpenAI 的官方 SDK、LangChain、LlamaIndex 以及各种支持 OpenAI 协议的开源工具。这意味着你不需要为每一个新工具再写一套适配层只要是能连 OpenAI 的工具改一行 base_url 就能切到 litellm 上。这个生态红利是自己写网关永远得不到的。所以我最终的选型就是 litellm而且把它布置成团队内所有 LLM 访问的统一入口。后续不管底层接入了多少个新模型对业务方来说入口永远只有一个这就省掉了大量沟通和文档同步成本。2. 安装部署与基础配置实操2.1 最简方式Python 包直接集成如果你只是个人项目里想快速试水不需要单独的网关服务最简单的接入方式是直接安装 Python 包然后在代码里调用。这里我贴着实际操作来写。pip install litellm然后你的代码里只需要这样写import litellm response litellm.completion( modelgpt-4o, messages[{role: user, content: 你好介绍一下你自己}] ) print(response.choices[0].message.content)看着是不是非常像 OpenAI SDK没错这就是 litellm 刻意为之的设计。你只需要改model参数的值换成claude-3-5-sonnet-20240620或者gemini/gemini-1.5-pro这种带前缀的格式就能调用对应厂商的模型而返回结果的结构完全不变。这里要注意调用非 OpenAI 的模型时你需要把对应的 API Key 设置成环境变量。比如走 Anthropic 就设置ANTHROPIC_API_KEY走 Google 就设置GEMINI_API_KEY。litellm 的模型命名规范是[提供商/]模型名比如gemini/gemini-1.5-flash。如果是 OpenAI 自家的模型可以省略前缀直接写模型名。我个人更喜欢在项目里单独建一个llm_client.py模块把所有调用逻辑收敛到里面这样即使未来底层模型换了业务层的调用方代码一行都不用动。模块内部用一个字典维护模型别名和实际模型名的映射比如业务层传一个chat实际路由到的是gpt-4o-mini等预算提高了直接改这个映射就能全局切换模型。2.2 生产推荐部署 Proxy 网关服务个人开发可以直接包引用但团队协作和生产环境我强烈建议跑独立的 Proxy 服务。这样所有业务服务通过 HTTP 接口访问统一网关从架构上就把模型供应商的细节和业务系统完全隔离了。部署起来非常简单一条命令就能起服务litellm --config config.yaml --port 4000如果你更习惯用容器化部署我也顺手把 Docker Compose 配置写出来了方便直接抄作业version: 3.9 services: litellm: image: ghcr.io/berriai/litellm:main-latest ports: - 4000:4000 volumes: - ./config.yaml:/app/config.yaml command: [--config, /app/config.yaml] environment: - DATABASE_URLpostgresql://litellm:litellmdb:5432/litellm depends_on: - db db: image: postgres:16 environment: POSTGRES_USER: litellm POSTGRES_PASSWORD: litellm POSTGRES_DB: litellm volumes: - pgdata:/var/lib/postgresql/data volumes: pgdata:跑起来之后GitHub 风格的 UI 管理面板默认也会开在 4000 端口。在管理后台里你可以直观地看到所有注册的模型、当前的请求量、Token 消耗和响应延迟基本上运维同学不需要任何培训就能上手看数据。不过提前给你打个预防针如果你不需要历史记录和可视化报表可以先不接数据库直接用内存模式跑。但一旦你想按用户限流、按 Key 做预算控制就必须要配一个 Postgres 数据库。我之前图省事试过 SQLite结果在并发稍微上来之后写锁定问题很严重最后还是老老实实换成了 Postgres。别在这上面省事经验之谈。2.3 配置文件怎么写才不容易踩坑litellm 的配置核心是一个 YAML 文件我可以给你看一个我目前在生产环境用的精简版保证了核心功能齐全又不至于过于复杂model_list: - model_name: gpt-4o-mini litellm_params: model: openai/gpt-4o-mini api_key: os.environ/OPENAI_API_KEY - model_name: claude-3-5-sonnet litellm_params: model: anthropic/claude-3-5-sonnet-20240620 api_key: os.environ/ANTHROPIC_API_KEY - model_name: gemini-pro litellm_params: model: gemini/gemini-1.5-pro api_key: os.environ/GEMINI_API_KEY litellm_settings: drop_params: true set_verbose: true general_settings: master_key: sk-your-master-key database_url: postgresql://litellm:litellmlocalhost:5432/litellm这里有个细节值得展开讲就是model_name和litellm_params.model的区别。前者是你对外暴露给业务方的模型名可以随意起别名比如统一叫gpt-4o-mini简化业务调用的心智负担后者才是真正要发给上游厂商的完整模型名。这个别名机制非常有价值比如你上游实际用了 Azure 的 OpenAI 模型但业务方根本不需要知道他们只认gpt-4o-mini这个入口名就够了。配置里还有两个容易被忽略的开关。drop_params这个参数我很推荐打开它的作用是自动过滤掉当前模型不支持的请求参数。举个例子有些模型支持response_format参数有些不支持如果你在代码里统一传了不支持的模型会直接报错。开了drop_params之后litellm 会自动剔除不适用的参数这大大降低了多模型适配的复杂度。set_verbose则是控制日志详细程度的。排查问题时开启可以看到请求和响应的完整日志但生产环境建议关掉否则日志量会非常大而且可能把敏感信息打到日志里。3. 路由、负载均衡与故障转移配置3.1 多模型部署下的负载均衡策略在网关层面做模型路由和传统负载均衡最大的区别在于我们不仅要考虑流量分配还要考虑成本、延迟、可用性这三个互相约束的维度。litellm 的路由策略配置非常灵活我建议结合自己的业务形态来选。轮流分配round-robin是最基础的方式适合多个后端能力相当的场景。比如你配置了三个不同的 OpenAI 账号希望请求均匀分散到三个 Key 上免得单个账号被限流。配置时只需要在model_list里给同一个model_name配置多个litellm_params然后在router_settings里指定routing_strategysimple-shufflelitellm 就会自动把请求轮流分发给这几个后端。最少请求数策略则适合后端响应时间差异较大的场景。有些模型响应快有些模型响应慢如果平均分配慢的模型会积压大量请求延迟进一步恶化。用least-busy策略litellm 会把新请求分发给当前活跃请求数最少的后端。这个策略我没有直接用因为我们的场景里不同的模型能力有差异用户对响应速度的预期也不一样混在一起用最少请求数反而会让模型选择变得随机。如果多个模型能力相同但成本不同那么成本加权路由就有价值了。比如你有两个价格不同的服务商都能跑同一个模型litellm 支持配置routing_strategyusage-based-routing并且结合预算权重让流量更倾向于低价服务商。这种玩法比较进阶我还在测试阶段建议你先从简单策略跑通之后再迭代优化。3.2 配置重试与超时参数避免雪崩模型接口的响应速度波动很大有时候 1 秒回来有时候 40 秒还在转圈。生产环境里我强烈建议把所有模型的超时和重试策略显式地写进配置不要依赖默认值。litellm_settings: num_retries: 3 request_timeout: 60 retry_after: 5这几个参数的含义很直接num_retries是请求失败后的最大重试次数request_timeout是单个请求的总超时时间retry_after是重试前的等待秒数。但这里有个非常重要的细节重试策略不是对所有错误一视同仁的。429 限流错误意味着上游太忙必须退避重试狂试只会加重对方负担5xx 服务端错误可以稍作等待后重试4xx 客户端错误比如 401 鉴权失败重试一万次也没用应该直接失败。litellm 的默认行为基本遵循这个逻辑但如果你想更精细地控制可以在litellm_settings里单独配置重试条件。我在调试自己的服务时发现过短的超时时间也是问题源头。有一次我把 20 秒改成 15 秒发现部分长上下文的调用老是报超时。后来看日志才发现上下文长了之后模型本身的首次响应时间就是十几秒网关超时反而先触发了。所以超时时间需要结合你的实际业务负载来设定不要拍脑袋。注意重试不是越多越好。重试次数过多会放大上游压力加重故障。我一般把重试控制在 2 到 3 次并且开启快速失败宁可让业务调用方拿到一个超时错误自行兜底也不要在网关层无限重试把故障放大。3.3 按模型分组与优先级切换litellm 还有一个非常实用的能力就是给模型分组实现主备切换。打个比方你主力模型是某厂商的旗舰模型但因为服务不稳定你需要一个同能力的备胎模型。传统做法是在前端代码里硬编码切换逻辑有了 litellm 之后你只需要在配置里把备选模型挂在同一个model_name下面并设置优先级。model_list: - model_name: flagship-chat litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY model_info: priority: 1 - model_name: flagship-chat litellm_params: model: anthropic/claude-3-5-sonnet-20240620 api_key: os.environ/ANTHROPIC_API_KEY model_info: priority: 2当主用模型返回错误超过阈值时litellm 会自动把流量切换到备用模型。这种故障转移能力对我而言特别实用尤其是做线上 Demo 演示的时候我不会因为上游的偶发故障而陷入尴尬。这个配置的逻辑核心是把“业务逻辑”和“底层模型”解耦。业务代码只认flagship-chat这个名字至于今天这个名字背后被路由到了哪个实际模型完全是网关层面的事情。这种抽象思维应该贯穿整个网关使用过程。4. 成本追踪、限流与权限治理4.1 Token 计量和成本换算原理直连大模型 API 时Token 消耗的准确统计是很麻烦的。特别是流式输出一个完整回复被拆成多个 chunk每个 chunk 里的usage字段又通常是空的只有最后一个 chunk 才带完整的 token 统计。你要是自己在应用层做汇总不仅要解析 chunk 流还要考虑上下文缓存的重复计费问题非常容易算错。litellm 在这块的实现思路值得点赞。它在网关层截获了每次调用过程中的所有元数据包括请求 token、响应 token、缓存命中情况然后按照模型配置里声明的单价做换算。你不需要关心具体某个 chunk 的 token 数因为最终计费是以整次完整调用为单位来算的。成本换算的关键在于模型的单价表。litellm 内置了一份主流模型的单价数据按每百万 token 算钱。但这里有个容易踩坑的地方各家厂商的计费维度不同。OpenAI 区分输入和输出 token分别按不同的单价计费Anthropic 还会对带有缓存的部分按折扣价计费还有一些模型按图片张数、按调用次数计费不单纯按 token 算。这些差异如果处理不好成本报表就会失真。litellm 的方案是允许你在model_info里手动补充模型的input_cost_per_token和output_cost_per_token以内置单价为基础再按实际使用情况微调。我第一次跑成本报表时发现数字比预期高了不少排查了半天发现是gpt-4o的输入缓存和输出缓存被算重了。后来在 litellm 的模型配置里我把缓存 token 的单价单独写明了这才把数据校准。所以光靠内置单价是不够的一定要结合自己的账单做核对按实际调整。4.2 面向团队的 Key 管理、预算限制和用户级限流如果你是把网关开放给团队或者客户使用的那么光有成本统计还不够还得有权限控制和配额管理。litellm 的虚拟 Key 机制就是干这个的。流程是这样的每个租户团队、部门、或者个人项目可以创建一把独立的虚拟 Key每把 Key 绑定一个或多个模型组可以设置每月的预算上限、每分钟的请求速率限制、允许的并发数等。业务系统通过这个虚拟 Key 调用网关网关在转发之前会强制校验配额超出就拒绝。配置虚拟 Key 有两种方式一种是在管理后台手动创建另一种是通过 API 动态创建。curl -X POST http://localhost:4000/key/generate \ -H Authorization: Bearer sk-your-master-key \ -H Content-Type: application/json \ -d { models: [flagship-chat, gpt-4o-mini], max_budget: 50.0, rpm_limit: 60, tpm_limit: 100000 }这一层治理机制可以说是我把 litellm 推荐给所有团队管理者的核心理由。以前每个开发拿一个公司的总 Key 去调 API出了 bug 或者写了个死循环分分钟能把整月的预算烧光。现在每把 Key 都有独立的预算和限流即使测试代码里有 bug影响范围也被限制在了这把特定 Key 的额度之内。对于不同团队的预算分级我的做法是设置几个固定档位开发环境 Key 每天限额低但速率宽松测试环境 Key 预算中等生产环境 Key 预算最高且严格审计。每个环境用不同颜色的虚拟 Key 命名前缀一眼就能看出是哪条链路的流量。4.3 基于 Prometheus 的监控指标接入光有管理后台的报表还不够真正的生产系统必须得有指标监控和告警。litellm 天生支持 Prometheus 指标暴露只需要在配置里打开开关它就会在/metrics端点上吐出一堆标准的监控指标。主要的指标包括litellm_total_tokens总 Token 消耗可以按模型、按 API Key、按用户维度打标签litellm_response_latency_ms响应延迟的直方图分布litellm_requests_total总请求数按状态码和模型标签分组litellm_deployment_failures上游调用失败的次数是判断故障转移是否频繁触发的依据我写了几个 PromQL 告警规则比如最近 5 分钟 P95 延迟超过 20 秒就告警失败率超过 10% 就告警这些基础规则在网关稳定运行之后非常有用。有一次我们线上报故障我第一反应是看 Grafana 面板发现某个模型的全部流量在几分钟内都切换到了备用模型而这个切换动作正是故障转移机制自动完成的。虽然备用模型撑住了服务但滑过的延迟暴增还是暴露了问题。5. 常见问题与排查技巧实录5.1 模型返回格式不统一解析器崩溃这个问题我太有发言权了。就算 litellm 做了格式统一不同模型返回的字段差异依然存在。比如有些模型会返回reasoning_content这种额外的思维链字段有些模型的工具调用字段叫tool_calls有些叫function_call。业务解析层如果写死了字段名遇到不认识的字段就可能崩溃。我的解决办法是在业务侧再包装一层解析函数主动提取核心字段对附加字段做类型兜底def parse_model_response(response): message response.choices[0].message content getattr(message, content, None) or tool_calls getattr(message, tool_calls, None) reasoning getattr(message, reasoning_content, None) return { content: content, tool_calls: tool_calls, reasoning: reasoning, }这里的关键是使用getattr和默认值绝不假设字段一定存在。模型在迭代过程中经常增加新字段你的解析器必须对这些未知字段保持容忍。还有一个细节是content可能为None如果模型只是返回了工具调用而没有文本内容你的解析逻辑得分别处理这两种情况。5.2 流式响应模式下成本统计偏差流式响应是另一个重灾区。litellm 对流式请求的成本统计和普通请求的处理方式是不同的。你如果开了流式模式每条 chunk 本身是不带 token 用量的litellm 会在流结束之后补记录一条完整用量。但这里有个时序问题如果你的网关注册了回调函数去处理用量事件而这些回调是异步触发的那么账单数据的入库顺序可能和请求完成的顺序不一致导致报表里出现负消耗或者错位的记录。我的建议是流式请求的用量统计不要依赖实时回调而是定期从 litellm 的数据库中捞取用量记录做一次汇聚入账。这样能确保数据的一致性和准确性。如果是对账我有一个土办法但很有效直接对比 litellm 报表里的 token 总数和厂商后台账单里的 token 总数如果两者差异超过百分之十那一定是某处配置不对。找到差异之后优先检查是不是流式模式或者缓存命中的计价方式搞错了。5.3 部署中遇到的其他常见问题速查表我把这段时间遇到的、以及社区里高频出现的问题整理了一张速查表方便你排查时直接对号入座。现象可能原因解决方法启动报错找不到配置项YAML 缩进错误或键名拼错用litellm --config config.yaml --detailed_debug看完整报错某个模型一直调用失败API Key 未设置或权限不足检查环境变量名不要写在代码里确认厂商后台模型权限所有模型都超时网络代理未配置或者防火墙拦截设置HTTPS_PROXY环境变量检查出网策略不同模型返回的文本长度不一致模型各自的默认max_tokens不同在业务侧显式传max_tokens参数统一生成长度成本报表数字偏高或偏低模型单价配置不准按实际账单核验必要时在model_info里手动声明单价切换模型后代码报错解析层写了模型特有字段统一用兼容层解析用getattr兜底虚拟 Key 突然失效预算用尽或到期在管理后台查看 Key 的状态和剩余额度及时续费或充值5.4 排查思路分享先看日志再动手对于这类网关组件我的排查步骤始终遵循一个固定的套路先确认是不是配置问题再确认是不是上游问题最后才怀疑代码逻辑。具体到 litellm我会先开set_verbose: true然后看网关日志里记录的完整请求参数、上游返回的原始响应体和错误码。如果日志显示请求根本没有发出去那就是配置和路由问题如果日志显示上游已经返回 5xx那是上游问题应该考虑切换模型或者联系厂商而不是继续在网关层纠结。有一次排查一个诡异的问题所有请求都正常返回但偶尔会出现部分响应内容乱码。我一开始以为是编码问题查了很久才发现是某个模型在特定提示词下返回了原始字节流litellm 的 SDK 把它当作普通字符串处理了。最后我在配置里给那个模型单独指定了响应编码策略问题才解决。这种问题不看全量日志只靠现象猜测的话可能要折腾一整天。还有一次是最让我记忆深刻的——生产环境某个模型突然成功率从 99% 掉到 60%但我看网关配置没有任何改动。后来检查上游厂商的公告发现对方在升级服务版本部分区域出现了波动。这时候我甚至连代码都不用改直接在 litellm 的管理后台调整了那两个模型的路由权重把流量分发到其他稳定的模型上整个过程不到五分钟。这就体现了有一个统一网关在手应急处置能力完全不一样了。6. 从单体到平台litellm 在项目里的角色扩展litellm 的定位虽然是 LLM 网关但当你把它放到更宏观的系统架构里去看它的价值就不只是转发请求那么简单了。我现在参与的模拟项目X已经把它从单纯的模型代理慢慢扩展成了一个模型能力治理平台。首先是审计与合规视角。所有经过网关的请求都会留下完整的审计日志包括调用者身份、请求模型、Token 消耗、时间戳、错误信息等。这对一个需要满足内部合规要求的企业系统来说几乎是刚需。以前直连模型时这个审计能力是完全缺失的出了问题无法追溯现在任何一条异常流量都能快速定位到具体的虚拟 Key 和调用方。其次是灰度发布与模型迭代。我们内部会把新模型先挂到一个灰度模型名上只对一部分测试流量开放。在 litellm 后台做这个操作的成本极低改一下配置项就能完成。等新模型表现稳定了再把灰度模型名的权重逐步调高最后完全替换老模型。这套机制让模型升级有了一个缓冲期不会出现一次性全量切换带来的业务风险。另外还有统一提示词模板和缓存管理。网关层面可以对相同的请求做缓存减少重复调用的开销还能全局管理一套提示词模板不同服务按模板 ID 引用方便运营人员统一修改话术。这些功能虽然单项看起来都不复杂但能由一个控制平面统一管理带来的效率提升是实打实的。我也见过一些团队把 litellm 和内部的知识库检索系统接在一起做成一个带业务上下文的模型路由网关。因为 litellm 支持在请求链路中嵌入自定义逻辑你可以在转发前动态注入检索到的文档片段让模型在回答时参考内部知识。这种扩展方向一旦走通网关就不再只是管模型而是开始介入到业务逻辑编排了。当然这个更多是业务层面的玩法litellm 本身只是提供了足够的灵活度。回看这段时间的使用经历我最大的感受是litellm 真正解决的不是“调哪个模型”的问题而是“怎么管好一堆模型”的问题。它把一个原本散落在各家 SDK 里的复杂度收敛到了一个可统一控制、可观测、可治理的入口上。这篇内容里提到的配置案例和踩坑实录都是我实际跑过、验证过的东西你可以直接参考。如果你也在搭建多模型的调用层希望这篇内容能给你提供一些思路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑