用litellm构建统一大模型API网关:多模型接入、路由与成本控制
这个标题我太熟了如果你最近在折腾大模型应用大概率已经被“各家的API格式不统一”这件事折磨过。今天要聊的litellm就是专门解决这个问题的。简单说它是个开源的API网关用一套标准格式对接几乎所有主流大模型服务顺便把密钥管理、成本控制、负载均衡这些脏活累活全包了。这篇文章会从它为什么值得用、核心配置怎么写、部署时有哪些坑一直聊到实际跑起来之后的运维心得适合正在做大模型应用开发、或者公司里要统一管模型API的团队参考。1. 项目定位为什么你需要一个AI API聚合层1.1 不只是一个“翻译器”那么简单很多人第一次接触litellm以为它就是个把各家API格式转成统一格式的翻译工具。这个理解方向没错但格局小了。它真正解决的是你在生产环境里管理多个模型供应商时遇到的一整类问题每个平台单独申请密钥、单独写SDK接入、单独对账、单独监控模型一换就动代码供应商一出故障就全线崩溃。我最早是在一个做内容审核的模拟项目X里用上litellm的。那会儿要同时调三家不同供应商的审核模型覆盖不同语言和场景代码里全是if-else判断该走哪家的SDK每个SDK的请求格式、超时重试逻辑都不一样。项目上线第一周光排查“为什么这家限流导致整个审核队列堵死”就花了两个通宵。后来把请求全部切到litellm由一个统一的网关转发到各家问题瞬间简单了。litellm的定位是标准的“网关”层它站在你的应用和各家模型供应商之间把你对单一SDK的依赖转移成对一套标准HTTP接口的调用。这意味着你业务代码里只需要维护对OpenAI格式的调用逻辑背后实际是哪个供应商在响应应用层完全不感知。1.2 解决了哪些具体的痛点逐个说下它在实际项目里帮我省下的事情多供应商统一接入现在支持的供应商数量非常多从主流大厂到开源社区模型托管服务基本覆盖了市面上你能叫上名字的产品。新增一个供应商改几行配置文件就行不用新引入一个SDK。虚拟密钥管理真实的API密钥只保存在网关环境里业务侧拿着你发的虚拟密钥就能调用谁用了多少、调了哪些模型全都可以按密钥追踪审计。新增一个供应商改几行配置文件就行不用新引入一个SDK。成本可见化每次请求的账单、Token消耗、成本明细都会记录可以按密钥、按团队、按模型维度统计。这对于内部多个小组共享一套模型资源的情况尤其重要不然月底对账全靠拍脑袋。负载均衡与故障转移同一个模型配置多个上游供应商时可以按权重分配流量某一家的服务挂了自动把流量切到另一家业务无感。统一监控网关层集中输出请求日志、缓慢查询、错误追踪配合Grafana这类可视化工具整个模型调用链路的健康状况一目了然。1.3 和直接调用各家SDK相比多一层网关会不会影响性能这是每次安利litellm时都会有人问的问题。坦率讲纯转发带来的延迟损耗是纳秒级的基本可以忽略不计前提是你的网关服务器和被调用的服务之间网络通畅。它不像传统的API网关那样做复杂的流量治理和协议转换litellm的核心逻辑就是把请求重新包装一下转发出去开销非常小。相比之下收益是实实在在的你的代码里不再有遍布各处的供应商SDK升级模型、换供应商都不再是“半年一重构”级别的大工程。当然前提是你要接受“多一个组件需要运维”这个事实后面第四节我会专门说部署和维护的问题。2. 核心细节解析路由、密钥与模型映射机制2.1 三层结构入口、匹配、转发litellm的请求处理逻辑可以拆成三步。第一步接收到你发来的HTTP请求这个请求的格式是你熟悉的OpenAI兼容格式路径一般是/v1/chat/completions。第二步根据请求里的model字段和你的配置规则决定这个请求该路由到哪个真实模型、哪个供应商。第三步把请求改写成目标供应商期待的格式带着真实密钥发出去再把响应原样传回来。最核心的“匹配”环节依赖的是配置文件里的model_list。它里面定义了路由表对外暴露的模型名是什么内部对应哪个供应商的哪个真实模型。举个例子你在代码里调用modelgpt-4o-mini网关会查路由表发现这个名字对应的真实目标是某个供应商的具体模型然后改写请求头里的认证信息把请求转过去。model_list: - model_name: gpt-4o-mini litellm_params: model: openai/gpt-4o-mini api_key: os.environ/OPENAI_API_KEY - model_name: claude-sonnet litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: os.environ/ANTHROPIC_API_KEY - model_name: qwen-plus litellm_params: model: openai/qwen-plus api_base: https://dashscope.aliyuncs.com/compatible-mode/v1 api_key: os.environ/DASHSCOPE_API_KEYmodel_name是你给外部暴露的别名litellm_params里则藏着真实调用的细节。注意openai/qwen-plus这个写法openai表示这个模型走的是OpenAI兼容协议后面才是真正的模型名api_base用来指向第三方服务商的兼容端点。这种命名方式意味着只要供应商提供OpenAI兼容接口就能非常轻松地接进来。2.2 路由策略的真实玩法优先级、权重与自动重试model_list本身只能做“名字到真实模型”的映射真正的“路由”玩法要靠router_settings或者请求里的参数。litellm支持在同一个对外模型名下配置多个上游目标然后按策略分发流量model_list: - model_name: gpt-4o-mini litellm_params: model: openai/gpt-4o-mini api_key: os.environ/OPENAI_API_KEY model_info: priority: 1 - model_name: gpt-4o-mini litellm_params: model: azure/gpt-4o-mini api_key: os.environ/AZURE_API_KEY api_base: https://your-resource.openai.azure.com/ model_info: priority: 2这种配置在实际生产环境里非常常用。比如我手头有个某跨平台系统核心链路依赖单一供应商。某天上午十点高峰期供应商侧限流问题立刻传导到线上请求排队飙升。后来我把主备两个供应商按优先级配置进去平时主供应商承接流量一旦报错网关自动把失败请求转向备供应商业务侧完全无感。注意priority数值越小越优先这个逻辑别搞反。再看权重路由。上面的配置只能“主备切换”而权重轮询适合那种“多供应商同时用按比例分配流量”的场景考虑的主要是成本均衡或者避免单个供应商被打满限流的风险。litellm支持用router_settings配置routing_strategyweighted然后在每个模型的model_info里用weight参数指定比重。2.3 虚拟密钥让团队协作和成本追踪变得干净litellm的虚拟密钥机制我愿称之为“多团队协作场景的救星”。真实密钥永远只配置在网关的环境变量或者配置文件里团队里的每个人、每个服务拿到的都是一串LTI开头、完全独立的虚拟密钥。创建虚拟密钥的方式有两种。一是写配置文件general_settings: master_key: sk-1234 # 管理密钥用于访问管理接口 database_url: postgresql://user:passhost:5432/litellm virtual_keys: - key: sk-common-team-key-1 models: [gpt-4o-mini, claude-sonnet] max_budget: 100 budget_duration: 30d另一种是通过管理接口动态创建请求路径是/key/generate。动态创建的方式更灵活特别适合让业务方自助申请密钥。每个虚拟密钥可以绑定可访问的模型白名单、设置预算上限、绑定特定的租户ID月底成本报表直接按虚拟密钥分组导出谁用了多少一目了然。这里说下数据库配置。如果不用数据库密钥的创建记录和成本追踪功能会受到很大限制。我建议生产环境务必配置PostgreSQL它能持久化存储所有密钥信息和计费记录。搭好之后在管理面板里能看到每次请求消耗的Token、估算花费、命中的模型名这些数据对于多团队分摊成本是真的救命。2.4 模型映射的隐藏价值无感升级和无感降级model_name配什么名字全看你自己的需求这里有个特别招人喜欢的用法——让业务固定一个版本名后端悄悄换模型。比如业务侧一直调用modelgpt-4o-mini某天你想把体验升级到新版本但不想让业务方改代码直接改litellm_params里的真实模型名就行。应用端无感你也不用发版本。反过来如果你发现某个新版本模型在特定场景下表现不稳想临时回退到老版本同样是一行配置的事。这种“前后端解耦”的能力在生产环境里异常宝贵。很多时候业务方并不关心API背后是哪个具体模型他们只需要一个稳定的调用入口而这个入口背后的实现细节应该由平台团队掌握。这就是litellm作为“模型中间层”的价值它把模型选型、切换、降级的主动权从应用开发团队手里收回到平台团队手里。这么做最大的好处是你做任何模型变更都不需要推动多个下游业务团队配合改造。3. 部署落地从零搭建一个可用的litellm服务3.1 最省事的部署方式Docker一条命令litellm的官方Docker镜像发布在公共仓库直接拉下来跑就行。最简单的起步方式是docker run但直接跑一个光秃秃的容器后续日志和配置都不好管理。我建议用docker-compose顺便把依赖的数据库也一起跑起来version: 3.9 services: litellm: image: ghcr.io/berriai/litellm:main-latest ports: - 4000:4000 environment: - LITELLM_MASTER_KEYsk-1234 - DATABASE_URLpostgresql://litellm:litellmpostgres:5432/litellm - OPENAI_API_KEYsk-xxxx - ANTHROPIC_API_KEYsk-xxxx volumes: - ./config.yaml:/app/config.yaml command: [--config, /app/config.yaml, --port, 4000] depends_on: - postgres postgres: image: postgres:16 environment: POSTGRES_USER: litellm POSTGRES_PASSWORD: litellm POSTGRES_DB: litellm volumes: - pgdata:/var/lib/postgresql/data volumes: pgdata:这里LITELLM_MASTER_KEY是网关的管理员密钥所有敏感配置建议通过环境变量注入config.yaml所在容器不要在仓库里明文提交。DATABASE_URL指向PostgreSQL如果暂时不想用数据库也可以删掉这段只是动态创建虚拟密钥和成本统计功能就没了。等容器起来之后访问http://localhost:4000就能看到管理界面默认会让你录入master key然后就能看到整个网关的配置状态、密钥列表、请求日志。3.2 配置OpenAI兼容的第三方服务别被“兼容”两个字骗了我接到过好几个咨询说接了某个第三方兼容服务后用不了报401或者404。排查了一圈十有八九是漏配了api_base。像国内的一些大模型服务对外确实提供了OpenAI兼容模式但它们的HTTP地址不是OpenAI的默认地址必须显式指定model_list: - model_name: internal-embedding litellm_params: model: openai/text-embedding-004 api_base: https://some-provider.com/v1 api_key: os.environ/EMBEDDING_API_KEY另外注意model_info里可以加一个mode: embedding的标注。这个标注很重要它能告诉网关这个模型是聊天模型、Embedding模型还是图像模型网关会据此走不同的校验和路由逻辑。特别是做RAG应用时Embedding模型的请求量通常很大做好类型标注后续做限流和配额管理会更精准。配置里还有一个隐藏的小坑model字段写成openai/xxx时litellm会严格按OpenAI协议打包请求。如果目标服务的兼容实现不完全标准比如不支持response_format参数或者对max_tokens的字段名做了特殊处理你需要在litellm_params里追加extra_headers或者extra_body去适配。别偷懒动手测一下不同参数的实际表现比上线后让用户替你踩坑要强得多。3.3 启动前的核心参数校验清单准备上线前建议先对照这份清单过一遍都是踩过坑的老司机总结出来的所有供应商的真实API密钥是否都通过环境变量注入而不是写在config.yaml里。master_key是否已换成强随机值默认的sk-1234留在生产环境等于裸奔。模型路由表里每个对外model_name是否有且只有一个主配置重复配置时是否确认过优先级顺序。是否配置了database_url没有数据库的话能用的功能少一大半。是否设置了general_settings里的max_parallel_requests限制防止突发流量直接把上游供应商打爆。如果用了自定义api_base是否实测过连通性以及是否正确处理了自定义的认证头。是否设置了litellm_settings里的drop_params: true。这个参数建议打开因为不同供应商对同一个参数的容忍度不同比如OpenAI支持temperature某些开源模型托管服务遇到这个参数直接报错打开drop_params后网关会自动剔除目标服务不支持的参数能省掉一堆兼容性报错。litellm_settings: drop_params: true set_verbose: false num_retries: 3 request_timeout: 600num_retries和request_timeout也要重点留意。超时时间设太短长上下文生成任务会频繁误报超时设太长一旦供应商真卡死了你的应用侧也跟着一起等。我个人的经验是普通聊天类请求超时设60秒离线批量生成任务单独走更长的超时配置不要把两种不同类型的请求混在一个网关配置里共用一套时间参数。4. 生产经验稳定运行需要的那些细节4.1 监控与日志体系怎么搭litellm暴露了Prometheus格式的监控指标这是上生产环境最值得先做的一件事。用prometheus-client的/metrics端点把请求总量、错误率、平均延迟、按模型分的Token消耗量全量暴露出来再接入Prometheus和Grafana一句话总结就是整个模型调用链路变得“可视化”了。举一个用Grafana自查的真实经历。某天我发现gpt-4o-mini对应模型的P95延迟从2秒飙到8秒但应用侧反馈还算正常——可能因为他们接口本身有异步兜底。通过Grafana按供应商标签查看了指标发现问题出在某个供应商的api_base端点波动。后来在litellm配置里给该供应商加了一个备选目标并设置了故障转移策略。延迟瞬间回落整个过程业务侧无感知。Prometheus指标里比较关键的有几个litellm_total_requests、litellm_total_failures、litellm_llm_latency_duration_seconds、litellm_spend_total。最后一个spend指标特别有用它直接暴露每次请求的开销做成本审计时能在Grafana里直接拉出“哪个团队、这个月、花了多少模型费用”的图。4.2 缓存、限流与预算别让一个小失误拖垮整套服务litellm支持在网关层做语义缓存也就是把相同请求的返回结果缓存一段时间。对于高频的、请求内容变化不大的场景比如客服机器人的固定问答、品牌知识库查询缓存能帮你省下一大笔Token费用。配置方式是litellm_settings: cache: true cache_params: type: redis host: localhost port: 6379但缓存也有让我栽过跟头的地方。早期把缓存TTL设得比较长结果上游模型悄悄更新了知识下游还在吐旧答案被业务方追问得相当尴尬。如果你对数据新鲜度有要求缓存TTL宁短勿长甚至可以对部分模型单独关闭缓存。预算控制这块也是属于“用了就回不去”的功能。你可以按虚拟密钥设定max_budget按天、按周、按月算都行。到了上限网关会直接拒绝请求并返回一个明确的预算超额报错。对内部孵化项目来说这个机制让模型成本始终处于可控范围不会出现月底账单吓人一跳的情况。限流同样在config.yaml里配置。可以针对某个虚拟密钥限制RPM和TPM防止有人不小心写了个死循环把你的成本打穿。配置方式很直观virtual_keys: - key: sk-common-team-key-1 models: [gpt-4o-mini] rpm_limit: 100 tpm_limit: 50000 max_budget: 50 budget_duration: 30d4.3 链路追踪和请求日志的最佳实践生产环境最怕的是“用户报错了但你不知道是哪一步出问题”。litellm链路追踪要解决的就是这个。它支持把每次请求的完整链路信息发到监控后端比如Langfuse、Prometheus、Sentry或者纯粹的日志系统。配置方式通常是在litellm_settings里启用回调litellm_settings: callbacks: [langfuse, prometheus]这里重点提醒一下如果没做任何回调配置litellm默认的日志是打到标准输出的容器一重启日志就丢了。对于需要事后追查的线上问题建议至少接一个日志聚合服务。我用过最常见的组合是callbacks: [sentry]做错误上报再把成功请求的日志打到JSON格式输出交给日志采集器统一消费。另外litellm支持配置custom_auth也就是自定义认证逻辑。如果公司内部有统一登录体系可以在general_settings里挂一个自定义认证函数在请求到达网关时先校验内部身份通过之后才生成或者匹配对应的虚拟密钥。这样业务方连网关密钥申请流程都省了直接用公司统一账号体系登录使用模型能力。5. 避坑实录常见问题与排查方案速查5.1 请求超时或连接被重置最典型的场景是请求一个长上下文模型刚发出去没多久就收到超时报错。这里有排查方向先看request_timeout是不是设得太短了。生成类任务的响应时间和你的输入Token数高度相关一个几万Token的输入光是排队和处理就可能超过30秒。我建议把request_timeout调到300秒以上并且把流式输出stream: true作为默认选项开起来。流式模式下网关可以在开始输出后就持续返回内容大幅度降低单次请求的“等待感”同时也减轻了超时风险。再看网络链路里有没加代理或负载均衡设备。有个某图像处理Demo就遇到个奇怪问题本地测试一切正常一到测试环境就偶发断连。最后排查发现是测试环境出网要经过内容过滤设备把长连接给切断了导致的症状就是“响应一会儿有一会儿没有”。5.2 模型报错提示模型不存在这种错误90%的原因是路由表里没有匹配到请求里的model字段。注意看报错信息里提示的模型名是什么再对比model_list里的model_name一个常见低级失误是配置里写的是model_name: gpt-4o但业务代码里调用的却是gpt-4-o或者gpt4o。还有一种隐蔽的情况model_name相同但litellm_params里指定的真实模型名写错了型号比如模型托管服务那边升级后把老型号下线了。遇到这种情况去供应商平台确认当前真实的模型标识符更新配置后重启网关就好。5.3 密钥鉴权失败先确认你用的是虚拟密钥还是真实密钥。业务侧调用时请求头里的Authorization应该是Bearer sk-xxxxxx这里的sk-xxxxxx是你在litellm里创建出来的虚拟密钥不是上游供应商的真实密钥。如果用的是master_key去调有些版本里master_key只用于管理接口调用模型接口时会因为权限范围问题被拒。建议单独创建业务用虚拟密钥并且给每个不同小组分一个独立密钥出问题好定位。5.4 数据库连接问题导致网关起不来PostgreSQL没启动成功或者连接串不正确litellm进程可以直接起不来或者反复重启。排查思路是先用客户端工具手动连一下DATABASE_URL里的地址确认账号密码和库名都对再确认下网络隔离组策略放行了相应端口。一段经验容器化部署时不要用localhost要使用服务名或者真实的数据库地址。5.5 成本数据对不上账如果发现litellm后台统计的Token消耗跟供应商官网的账单对不上先看看是不是某些模型没设置model_info里的input_cost_per_token和output_cost_per_token字段。没设置的话网关只能估算成本这是对不上的主因。model_info: mode: chat input_cost_per_token: 0.000005 output_cost_per_token: 0.000015把这些单价参数补全之后成本报表才会有参考价值。对于第三方小众模型这些单价信息一般在供应商文档里有明确标注挨个配好就行。常见现象优先排查项注意事项请求超时request_timeout配置、流式开关区分普通请求和批量离线任务分开设置模型不存在model_list名称匹配、真实模型标识符注意OpenAI兼容服务的完整模型名鉴权失败虚拟密钥使用、权限绑定master_key只用于管理别用来跑业务流量网关起不来数据库连接、环境变量注入容器内不要用localhost访问外部服务成本对不上model_info成本参数第三方模型务必补全单价字段返回内容不新鲜缓存TTL、缓存开关数据敏感场景下对部分模型关闭缓存写在最后的几点实在话litellm不是一个多复杂的东西但它在整个AI应用架构里的位置很关键属于典型的“小投入、大回报”组件。从我实际维护的经验来看它对中小团队最友好的地方是不需要专门养一个网关团队一个人花半天时间读一遍配置文档就能跑起来后续基本是“配一次用很久”的状态。有几个习惯是我个人强烈建议保持的一是所有密钥全部走环境变量注入不进代码仓库二是每周抽时间看一眼Grafana上的延迟和成本趋势往往比用户反馈更早发现隐患三是每次切换模型前先在测试环境跑一遍配置确认新供应商的参数兼容性再动生产配置。如果你目前正被“多供应商接入”这件事搞得焦头烂额或者团队里想建立一套统一的模型调用规范litellm确实值得花一个下午研究一下。先从部署一个最简单的网关开始把一两个测试模型路由配好再逐步接入真实业务流量你会感受到“所有模型一个入口”这件事能省掉多少无意义的重复劳动。