资讯动态

用litellm统一多模型API调用:路由、负载均衡与生产级网关实践

发布时间:2026/10/14 9:14:19 来源:尧图企业网站定制
前阵子要从某个模型服务切到另一个光改一个 model 参数显然不够返回结构变了、计费口径变了、超时报错也变了。这大概是所有做 AI 应用的团队都经历过的场面。litellm这个工具就是冲着这个痛点来的它把几十家不同模型提供方的 API 全部收敛成 OpenAI 兼容格式统一由它做模型调度、密钥管理、成本统计和负载均衡。无论是个人脚本里想同时调多种模型还是团队需要一套内部统一的模型网关litellm 都值得放进工具链。这篇博文我从安装、路由、预算到生产代理逐层讲最后给出实际踩坑记录帮你少走弯路。1. 为什么盯上 litellm多供应商接入的真实痛苦1.1 每家一个 SDK每个项目一堆胶水代码凡是认真做过大模型应用的人大概率都写过这种代码先封装一个call_gpt()再照葫芦画瓢写一个call_claude()然后是call_gemini()。每个函数要处理各自的鉴权、请求体、字段命名、异常类型返回解析还得单独适配。最气人的是这些供应商的接口还版本迭代上个月还能用的字段这个月就废弃。等你想加一个新模型意味着又多一坨胶水代码和一套测试用例。litellm直接把这个层抽掉了。它对外只暴露一个统一的 completion 接口入参风格跟 OpenAI 的chat.completions长得几乎一样内部替你完成不同供应商的协议转换。你的业务代码只需要记住一套 API任何时候想换模型改一行配置或者环境变量就行。这种设计本质上属于 API 网关模式模型供应商是后端服务litellm 是中间代理层业务方只跟网关打交道。1.2 从工具库到服务网关的演进litellm 最初给我的印象就是一个纯 Python 库方便在脚本里调用各家模型。但后来发现它还带了一个完整的代理服务端proxy server可以启动一个本地或远端 HTTP 服务让团队里所有成员通过这个服务访问模型密钥统一管理、调用统一审计、成本统一统计。这意味着同一个工具既能用于开发期快速实验也能在生产环境作为内部网关长期运行。它支持的范围相当广覆盖主流云服务商的模型、开源模型托管服务、还有各类兼容 OpenAI 格式的自建服务。你甚至可以接入自己的私有模型服务只要它暴露的是 OpenAI 兼容接口就能透传。这种开放姿态很讨人喜欢等于把“统一入口”这件事做到了不绑死任何一家。2. 一小时跑通安装、配置与第一次统一调用2.1 安装两个常用组件litellm主体是一个 Python 包安装非常直接pip install litellm如果只是本地实验装上面这个就够了。如果要跑网关服务官方推荐另一种方式把代理 server 一起装上pip install litellm[proxy]这里的[proxy]会额外拉取 FastAPI、uvicorn 等依赖。我建议直接装 proxy 版本反正后面用得上省得装完库发现要跑服务又缺依赖。2.2 环境变量是第一步配置模型服务商的密钥通常通过环境变量读取。litellm 的命名规则很土但很好记基本是[供应商名]_API_KEYexport OPENAI_API_KEYsk-xxxx export ANTHROPIC_API_KEYsk-ant-xxxx export GEMINI_API_KEYAIza...建议把这些写进.env文件加载别硬编码在代码里。litellm 在启动时会自动读取环境变量不需要额外传参非常省心。2.3 第一次调通的代码骨架假设你想在一个脚本里同时调 GPT、Claude、Gemini 三个模型写起来是这样的from litellm import completion response completion( modelgpt-4o, messages[{role: user, content: 你好介绍一下你自己}], ) print(response.choices[0].message.content)换 Claude 只需要把model参数换成claude-3-5-sonnet-20241020Gemini 就换成gemini/gemini-1.5-pro。注意 Gemini 前面带了gemini/前缀这是路线名provider prefix用来告诉 litellm 走哪一家供应商不指定时它靠模型名自动推断。如果模型名字带版本号后缀最好把完整 ID 写对否则会 404。返回对象也是统一的 OpenAI 风格对象.choices[0].message.content直接拿文本。这对从 OpenAI 迁移过来的开发者极其友好几乎不用改业务逻辑。2.4 为什么统一返回结构比看起来更重要很多人觉得“反正我最终只要一个字符串”返回结构统不统一无所谓。但真实场景里你要拿usage.total_tokens做计费和限流要拿model字段确认实际命中的模型还要处理finish_reason判断输出是否被截断。这些字段如果每个供应商都不一样你的计费系统就要写 N 套适配逻辑。litellm 把这些元数据都映射成了 OpenAI 风格你在统一网关后面做埋点和账务就容易得多。3. 真正拉开差距的四个核心能力模型路由、负载均衡、重试降级与预算管控3.1 模型路由用 Router 替代手动选择单次调用看不出 litellm 的本事多个模型组合起来才显功夫。litellm.Router允许你定义一个模型池然后让路由器按策略选择模型from litellm import Router router Router( model_list[ {model: gpt-4o, api_key: sk-xxx}, {model: claude-3-5-sonnet-20241020, api_key: sk-ant-xxx}, {model: gemini/gemini-1.5-pro, api_key: AIza...}, ] ) resp router.completion( modelgpt-4o, messages[{role: user, content: 用哪种模型都行策略路由决定}], )这里的model参数不是让你在调用时重新选而是指代模型池里的一组模型。一个模型名可以背后挂多个供应商实例比如gpt-4o同时配置了主供应商和备供应商请求进来时路由器会按照你设定的策略挑选。3.2 负载均衡策略与配置细节Router 默认提供几种负载均衡策略常用的是simple轮询和least-busy按当前负载分配。我实际用下来最稳的配置是记录每个供应商的成功率和响应延迟然后优先打给成功率最高、延迟最低的目标router_settings: routing_strategy: usage-based-routing allowed_fails: 3 cooldown_time: 60allowed_fails表示连续失败多少次后暂时把该实例摘除cooldown_time是冷却时间。production 环境里这套机制能自动避开发了一半故障的模型服务比自己在业务层写重试要省心得多。3.3 重试与降级的实战配置法重试最怕的不是重试本身而是无脑重试同一家结果故障没恢复反而把超时拉长好几倍。litellm 支持在 Router 层面配置重试到备选模型例如response router.completion( modelgpt-4o, messages[...], fallbacks[claude-3-5-sonnet-20241020], )当gpt-4o请求失败并触发重试上限后请求自动转到 Claude。我把这种降级策略当成高可用方案的基础版主链路出问题业务并不感知只是延迟增大了一点。这种能力靠业务方手动实现是非常痛苦的因为你需要维护两套客户端逻辑而 litellm 在网关层就把事情做完了。3.4 预算管控防止失控的硬性手段模型调用成本失控是常见事故。litellm 提供了max_budget参数可以按项目、按 API Key、按团队分别设置预算。例如给某个测试 Key 设置月度上限超出后直接拒绝调用from litellm import BudgetManager budget BudgetManager() budget.create_budget( max_budget100.0, duration30d, api_keysk-test-key, )这比事后再看账单止损要强太多。预算系统配合它的日志功能每个请求的 token 数和预估费用都会被记录下来。虽然模型厂商的计费标准有时会变litellm 的费用计算通常基于各厂商公布的单价误差在一个可接受范围内用于预警和用量趋势分析完全够用。4. 当网关真正接进生产鉴权、代理模式与可观测性的补课4.1 启动代理服务让整个团队走统一入口本地脚本里用库函数固然方便但多人协作时每个同事各自的密钥不统一、代码里散落各种 API Key我很难接受这种状态。litellm 的代理服务模式解决了这个问题。启动命令很简单litellm --model gpt-4o --port 8000它会起一个 OpenAI 兼容的 HTTP 服务。业务方只需要把 base_url 指向这个网关密钥在网关统一配置。个人开发时用这个模式还可以避免代码里到处塞密钥。更精细的玩法是写一个config.yaml把模型、密钥、预算、路由策略全部集中管理model_list: - model_name: gpt-4o litellm_params: model: gpt-4o api_key: os.environ/OPENAI_API_KEY model_info: mode: completion general_settings: master_key: sk-master-xxx database_url: postgres://...用litellm --config config.yaml启动服务就按这套配置跑起来。4.2 虚拟密钥与多租户隔离生产环境直接让大家用母钥匙不合适。litellm 提供虚拟密钥virtual keys机制管理员生成一个只读或限流限额的 Key发给团队成员或下游系统使用。这样每一笔调用都能追踪到具体使用方也能按 Key 独立设置预算。我通常的做法是每位开发者一把测试 Key每个内部项目一把专用 Key生产环境再用一把严格限流的 Key。出了事故能快速定位是谁在调用、调了哪个模型、花了多少钱。4.3 日志、指标与监控的接入思路litellm 带有内置的日志记录能力能下钻每个请求的 model、prompt、response、usage、latency。默认的日志输出格式适合日常排障但生产建议接入外部可观测系统。它提供了 Callback 机制可以把数据推到主流监控平台或者在本地写一个简单回调函数把耗时和 token 用量打成结构化日志from litellm.integrations.custom_logger import CustomLogger class MyLogger(CustomLogger): def log_success_event(self, kwargs, response_obj, start_time, end_time): print(kwargs[model], kwargs[messages], response_obj.get(usage))接入回调后可以把关键指标汇总成表格p95 延迟、错误率、token 分布、成本分布。我个人经验是先盯三个数总 token 成本、模型错误率、p95 延迟这三个数健康其他问题通常不会太严重。5. 实测中反复踩过的坑与对应解法5.1 模型名称映射不一致导致的 404最常见的问题是模型名写错。OpenAI 的模型 ID 和 Anthropic 的模型 ID 完全是两套命名规则依赖 litellm 自动推断并不总能猜对。比如本地模型自己起的名字如果不在它的默认映射表里就会报 provider 找不到。解法是在 Router 或代理配置里显式指定模型到供应商的映射不要靠猜model_list: - model_name: my-local-llama litellm_params: model: ollama/llama3.1 api_base: http://localhost:11434另一个坑是某些供应商需要额外的api_base地址不传就默认请求官方 Endpoint。自建服务或 Azure OpenAI 部署尤其明显必须把这个参数补上。5.2 多模态与特殊参数的格式差异文本模型之间差异不大一上多模态就传参混乱。OpenAI 多模态要传content数组某些开源模型却要求单独的image_url字段。litellm 对主流多模态模型做了兼容但前提是你得按它的规范传 messages。我第一次对接视觉模型时直接把 OpenAI 的 content 数组原样传给了别的模型返回报错说格式不支持。这一步没有黑魔法就是多看对应模型 demo 里的消息结构照它的规范来。litellm 的文档里对每个供应商的传参差异做了整理喂入前先查一眼能省很多调试时间。5.3 计费与 token 统计的陷阱litellm 的成本统计基于返回的usage和模型单价。但有些模型服务商根本不返回 prompt_tokens或者像某些开源模型服务只返回总 token。当 litellm 拿不到细分 token 时cost 计算会不准。我在脚本里发现某天成本虚高排查之后才发现是某个模型返回的 usage 结构异常litellm 按默认单价补算导致预算告警。解法对接成本敏感业务时自己设定每个模型的计费单价用 callback 记录时再做一次校验别盲信自动统计。5.4 超时与代理底层的连接堆积默认超时有时候太激进或太宽松。某些供应商响应慢是常态有次我处理长文本生成网关默认等待时间不够上游还没答完我就断了连接业务侧收到一个莫名其妙的中断错误。后来在 Router 配置里单独调大超时router Router( model_list[...], timeout60, )如果是代理服务模式还要注意客户端连接数。高并发场景下大量请求同时打到网关底层如果还是同步调用容易造成连接堆积。建议在网关前面加一层异步调用或者直接用支持异步的方式调用 litellm 的acompletion接口。实测里把业务代码从同步改成异步p95 延迟能下降一个量级。5.5 缓存策略命中率与一致性难两全litellm 支持缓存 prompt 级别的响应能显著降低重复请求的成本。但它有自己的性格——如果同一个 prompt 在模型升级、版本变化后依然命中旧缓存结果就可能是过时的。我遇到过一次很隐蔽的问题模型温度参数变了缓存却仍然返回原来的结果。原因是缓存键默认没有把 temperature 纳入计算。后来我把缓存策略改成按需求自定义缓存键把 temperature、top_p、max_tokens 这些都拼进去这才解决了误导。对于做对话类产品的团队我建议对缓存保持谨慎能不用就不用或只缓存纯问答、无状态的请求。6. 部署形态与扩展方向6.1 本地跑实验、Docker 跑服务、K8s 做高可用litellm 作为 Python 工具很轻但在团队场景建议容器化部署。官方提供了镜像一条 docker run 就能起服务docker run -d \ -p 4000:4000 \ -v $(pwd)/config.yaml:/app/config.yaml \ ghcr.io/berriai/litellm:main-latest \ --config /app/config.yaml如果团队已经上了 Kubernetes把它当成一个无状态服务部署在集群里挂自动伸缩策略再前面配一层负载均衡整个模型网关的高可用就成型了。数据存储可以外挂 PostgreSQL用来写预算、密钥和调用日志。多个副本共享同一份数据库状态虚拟密钥、预算数据都保持一致。6.2 与现有内部平台的整合方式litellm 最大的价值在于它的接口是 OpenAI 风格这意味着现有基于 openai SDK 的代码只要把base_url改成 litellm 网关地址几乎零改动就能切换到统一网关。团队内部的 LLM 平台可以把它作为底层底座上面再做自己的权限、审批、流程编排。我实际落地过的一个方案是内部系统通过网关拿到模型能力再把上层封装成公司内部的模型服务平台业务方甚至不用感知 litellm 的存在只需要在平台上申请一个 Key。这种分层结构的好处是将来想引入新模型、做灰度切换、控制成本都只需在网关配置层调整不用业务方重新发版。6.3 后续值得深入的两个方向一个方向是接入自己的私有模型litellm 对 vLLM、Ollama、LocalAI 等开源推理框架都有支持搭一套混合云架构部分模型走公有云供应商部分模型走内部 GPU 集群网关统一调度。另一个方向是配置策略的自动化通过它对多模型状态的成功率、延迟、成本数据进行采集再交给上层调度系统做动态路由让模型选择更智能。7. 个人体会与最后的实用建议跑通 litellm 只需要十几分钟真正花时间的往往是把网关接入现网的那一小段路。我个人的体会是先从小流量开始在一个非核心业务模块上切到网关观察延迟和报错确认无误后再逐步扩大范围。不要一上来就把所有模型调用全部改道否则遇到配置遗漏会同时影响所有业务线。几个比较实用的配置习惯直接分享给正在排查问题的人模型名前缀和供应商显式匹配不要完全依赖自动推断尤其在 Router 里有相近名字时显式映射最保险。预算先设小再放大别开大了再后悔。一周内如果日志显示成本逼近阈值再做调整也来得及。网关日志里增加一个request_id字段业务侧也透传这个 ID出了问题两边一对照就能定位。升级版本前先在测试环境跑一遍litellm 迭代快升级带来的行为变化比想象中多。写这篇文章时候我顺手看了眼手边项目里这周的成本统计前三天走的一批流量已经由网关统一记账模型错误率也因为有自动降级被压到了很低的水平。如果你也正在被多个模型供应商的接入问题困扰litellm 至少值得花一个下午试试它可能没法解决你全部问题但大概率能让你的调用层整洁一大截。

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

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

免费获取报价 →
↑