做AI应用最烦的往往不是模型本身而是把一堆模型供应商接进来的过程。写一套业务代码要同时兼容多家平台的API格式今天这个改字段名明天那个更新SDK密钥散落在各个环境变量里成本报表还得自己手动汇总。我见过好几个团队本来模型效果调得挺好一上生产就被集成问题拖了后腿。LiteLLM就是为这个场景出现的。它本身是一个轻量的开源服务核心思路是把自己伪装成一个OpenAI兼容接口然后在背后帮你把请求转发给不同厂商的真实模型接口。你只维护一套代码只认一个入口模型随便换、随便配。除了统一接入它还能做多模型负载均衡、自动降级、虚拟密钥、预算封顶、缓存限流、用量审计基本上把一个AI网关该有的能力都补齐了。这篇文章适合正在做AI应用集成、想统一管理多模型接入或者要给团队搭建API网关的开发者。我会从整体设计思路、最小部署、路由策略、预算治理、进阶能力到常见排查完整过一遍实际跑生产时会用到的配置和踩坑经验。1. 先看整体思路为什么需要“模型代理”这一层1.1 多模型接入的真实痛点不少团队最初只有一个模型供应商代码写起来确实很简单一个SDK搞定一切。可一旦想接入第二家、第三家问题就来了。每家API的请求结构、鉴权方式、超时语义、错误码体系都不一样。OpenAI用messages数组某家可能喜欢自定义顶层字段另一家可能要求额外的version参数。SDK之间的类型定义也不同client.chat.completions.create和client.generate这种差异是常态。更麻烦的是密钥管理。上游供应商的API Key如果直接放在客户端或各个微服务里泄露半径太大。今天有人把Key打到前端日志里明天有人在公共仓库不小心提交了一份.env都需要挨个轮换。要是每个团队各自维护一套接入逻辑出问题的时候根本不知道在哪里排查。我见过一个比较典型的项目业务方接了三家模型供应商代码里写满了if provider xxx这类分支。后来要对某家模型做A/B测试改动量大得吓人。最后他们花了一周时间把所有调用层重构到LiteLLM代理后面之后的模型切换就变成改一行配置文件的事。1.2 LiteLLM的设计哲学OpenAI兼容格式作为统一中间层LiteLLM最聪明的地方是它没有自己发明一套“统一格式”而是选择兼容OpenAI的接口规范。OpenAI的/chat/completions格式已经被社区广泛接受很多开源工具和SDK原生支持。你只需要把base_url指到LiteLLM代理地址原来用OpenAI SDK写的代码基本不用改就能请求到其他供应商的模型。代理层收到请求后会根据你配置的“上游模型类型”做格式转换。比如请求anthropic/claude-3-opus它会把你发来的OpenAI消息结构翻译成Anthropic的格式请求google/gemini-1.5-pro就翻译成Google的格式。这个转换逻辑被封装在库里不需要业务代码感知。除了格式翻译代理层还能在转发前后做很多事情判断当前模型是否健康、是否需要先查缓存、当前虚拟Key是否超预算、要不要限流、请求失败后是否切换到备用模型。这些原本散落在业务代码里的逻辑全部被收敛到网关这一层。也就是说LiteLLM解决的不只是“接入”而是把模型层的运维治理能力集中化了。2. 本地部署与最小配置5分钟把代理跑起来2.1 环境准备与安装方式LiteLLM本身是Python项目安装非常直接。官方提供了带代理依赖的安装方式pip install litellm[proxy]这个命令会同时安装核心调用库和代理服务器组件。如果你本机已经有Python 3.8以上环境一条命令就能装完。不过实际使用中我建议用虚拟环境避免污染全局Python环境。除了pip也可以直接跑Docker镜像适合不想折腾本机依赖的情况docker pull litellm/litellm:main docker run -p 4000:4000 -v $(pwd)/config.yaml:/app/config.yaml litellm/litellm:main --config /app/config.yaml --port 4000两种方式各有各的好处。pip方式调试灵活可以直接在代码里打断点看代理日志Docker方式好在与宿主机隔离上线部署时可以沿用同一套方式环境差异更小。我自己的习惯是本地开发用pipCI和测试环境用Docker。2.2 配置模型供应商并启动代理最核心的配置文件是config.yaml里面定义了“代理对外暴露哪些模型名”和“这些名字背后对应哪个真实供应商的哪个模型”。下面是最小可用的例子model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: claude-3-5-sonnet litellm_params: model: anthropic/claude-3-5-sonnet api_key: os.environ/ANTHROPIC_API_KEY - model_name: gemini-1.5-pro litellm_params: model: google/gemini-1.5-pro api_key: os.environ/GEMINI_API_KEY注意model_name是客户端看到的“代理模型名”你可以随便取名比如把gpt-4o命名为fast-ai。请求发到代理时model字段填的就是这个名字。litellm_params.model则必须带供应商前缀比如openai/gpt-4o、anthropic/claude-3-5-sonnet、google/gemini-1.5-pro代理靠这个前缀识别该调用哪个翻译器。api_key支持直接填密钥也支持通过os.environ/变量名引用环境变量。我强烈建议用环境变量引用原因很简单配置文件通常要提交到Git仓库明文密钥一旦进了历史记录后面想彻底清除非常麻烦。启动代理只需要一条命令litellm --config config.yaml --port 4000看到LiteLLM Proxy started之后服务就算跑起来了。默认地址是http://localhost:4000如果你用Docker并且映射了端口那外部访问地址就是宿主机的对应端口。2.3 用curl验证“一个入口多模型”启动之后直接用curl发一个OpenAI格式的请求就能验证curl http://localhost:4000/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-1234 \ -d { model: claude-3-5-sonnet, messages: [{role: user, content: 你好介绍一下你自己}], temperature: 0.7 }你会发现这个请求和调用OpenAI官方接口没有任何区别。我测试的时候甚至直接把OpenAI SDK的base_url切换到代理地址业务代码一行没动model换成gemini-1.5-pro请求就发到Google那边去了。这个验证过程能说明一个关键点接入LiteLLM的成本极低。你不需要改业务代码只需要把请求地址和模型名改一改就完成了“换模型供应商”的动作。如果后面想把默认模型从A供应商切到B供应商只需要修改config.yaml里某个model_name对应的上游再重启代理即可。3. 路由、负载均衡与降级策略生产可用的关键3.1 基础路由与可用的模型组单个模型映射太简单真正有价值的是把一个model_name映射到多个上游模型让代理按权重分发请求。这个能力在做模型灰度、容量分流的时候非常有用。举个例子我设计过一个“主力模型组”对外统一暴露为gpt-4o-group下面挂了两个上游model_list: - model_name: gpt-4o-group litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY rpm: 600 model_info: weight: 70 - model_name: gpt-4o-group litellm_params: model: openai/gpt-4o-mini api_key: os.environ/OPENAI_API_KEY rpm: 1000 model_info: weight: 30客户端请求model: gpt-4o-group代理会根据权重分配流量70%到gpt-4o30%到gpt-4o-mini。加上rpm限制后一旦某个上游达到每分钟请求上限代理就不会再往它分流量而是优先转给其他还有余量的节点。这个能力背后是LiteLLM自带的Router组件。它会实时追踪每个上游的失败率、响应延迟、余量配额然后综合决策该把请求发给谁。你不用自己维护一堆故障转移逻辑配置好健康检查和重试参数即可。3.2 重试、超时与自动降级生产环境最怕的不是模型本身慢而是上游偶发5xx或超时。如果业务代码里自己写重试很容易造成流量翻倍放大。LiteLLM把重试逻辑放在代理层配合“备用模型”机制可以做到比较优雅的降级。在litellm_params里配置几个关键参数model_list: - model_name: multi-llm litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY request_timeout: 30 num_retries: 2 cooldown_time: 60 model_info: weight: 50 - model_name: multi-llm litellm_params: model: anthropic/claude-3-5-sonnet api_key: os.environ/ANTHROPIC_API_KEY request_timeout: 30 num_retries: 1 cooldown_time: 60 model_info: weight: 50request_timeout是单个上游请求的超时时间超过这个时间就算失败。num_retries是失败后在同一上游上重试的次数。cooldown_time是某个上游连续失败后进入“冷却期”的秒数冷却期内不会向它发流量。注意不要盲目调大num_retries。如果上游因为负载过高而超时你重试3次只会加剧它的压力。我一般设置为1到2次配合冷却机制让流量能及时转移到其他模型。真正合理的做法是“快速失败快速转移”而不是“死磕同一个上游”。3.3 自定义路由策略按Tag、用户或团队分流除了简单的权重负载均衡LiteLLM还支持更细粒度的路由规则。它可以识别请求里的user字段、metadata里的tag然后把这些属性映射到不同的模型组。比如你希望免费用户走便宜模型付费用户走旗舰模型。可以在config.yaml里给每个模型组打上走route_by_tag的规则router_settings: routing_strategy: usage-based routing_strategy_args: tag1: [model_group_a] tag2: [model_group_b]应用侧在发起请求时只要在metadata里携带业务标签代理就会自动把流量路由到对应的模型组。我在一个内部平台上试过这种玩法把不同业务线的请求用不同标签隔离成本归属自动就分清了月底对账非常省心。自定义路由的核心价值是把“模型选择策略”从业务代码里剥离出来。以后要调整模型分配比例只需要改配置文件不需要让各个业务团队改代码重新发布。4. 密钥治理、预算控制与用量追踪算清楚每一分钱4.1 虚拟密钥别再直接暴露上游Key让终端用户直接持有真实模型供应商的Key风险非常高。LiteLLM提供了虚拟密钥机制相当于在上游Key前面再套一层。你通过代理生成一个sk-xxx格式的虚拟Key客户端拿它请求代理代理再拿真实上游Key去请求模型供应商。生成虚拟Key的命令很简单curl http://localhost:4000/key/generate \ -H Authorization: Bearer sk-my-admin-key \ -H Content-Type: application/json \ -d {name: test-user, models: [gpt-4o, claude-3-5-sonnet], max_budget: 50, budget_duration: 1mo}这条命令会返回一个sk-...字符串你需要把它保存下来之后客户端使用它作为Bearer Token。虚拟Key可以绑定模型白名单、预算上限、有效期和速率限制。这样即使某把Key泄露影响范围也被限制在固定的模型和额度里。管理虚拟Key有一套专门的接口包括/key/info查看Key详情、/key/delete注销Key、/key/update修改配额。我在生产里会把虚拟Key的生成流程接入内部审批系统谁要开通模型权限就提交工单避免Key满天飞。4.2 预算控制与限额配置预算控制是LiteLLM最实用的功能之一。它支持按虚拟Key设上限也支持全局模型、全局Key总额度上限。max_budget是金额上限budget_duration是计算周期比如1d代表一天1mo代表一个月1y代表一整年。实际配置时可以这样写general_settings: master_key: sk-my-admin-key database_url: postgresql://user:passhost:5432/litellm max_budget: 1000 budget_duration: 1mogeneral_settings.max_budget会对整个代理实例做总额限制超过之后代理会拒绝新的请求并返回预算超限错误。虚拟Key层面的限制则更灵活比如某个内部AI助手项目一个月预算只有200美元超了就停用等下个周期再恢复。我踩过的一个坑是如果预算上限设得太靠近真实用量很容易在高峰时期误伤正常请求。建议至少给20%的缓冲空间并且提前配置告警让运维同学在预算快用完的时候能收到通知。4.3 用量日志与可观测性用数据做决策没有明细用量数据根本没法回答“这个模型到底花了多少钱”“哪个项目在烧钱”。LiteLLM默认会把每次请求的元数据、token消耗、模型名、延迟都记录到数据库。默认情况下使用SQLite生产环境建议切换PostgreSQL。配置数据库之后代理会创建一张消费记录表你可以执行SQL去查SELECT model, sum(spend) as total_spend, sum(total_tokens) as total_tokens FROM litellm_usage WHERE start_time now() - interval 7 days GROUP BY model ORDER BY total_spend DESC;除了数据库LiteLLM还暴露了/metrics端点以Prometheus格式输出指标。把这些指标接入Grafana之后就能看到每个模型每分钟的请求数、错误率、平均延迟以及花费总额的趋势图。我在具体落地时会重点盯两个指标模型错误率和单日成本。错误率突增往往能比模型供应商的状态页面更早暴露问题成本曲线能直观地帮助判断是否要切换到更经济的模型。5. 缓存、限流与多租户进阶能力5.1 缓存机制减少重复调用成本对于大量重复或非常相近的问题每次都去调用模型有点浪费。LiteLLM提供了缓存功能默认支持简单缓存和语义缓存两种模式。简单缓存直接以请求的messages内容作为键相同请求在过期时间直接返回缓存结果。配置方式是在config.yaml中加入cache: true cache_params: type: redis host: localhost port: 6379语义缓存则是通过向量化相似度判断即使两句话表述不完全相同只要语义足够接近也能命中缓存。这个能力适合客服问答、知识库查询这类场景。启用时把type设为semantic并配置similarity_threshold比如0.8超过阈值就认为是相似内容。缓存对成本的改善非常明显。我拆过一个内部问答系统接入语义缓存后重复请求占比大约35%当月token成本直接下降三成。不过要小心实时性要求高的场景比如需要模型输出最新结果的就不要轻易开语义缓存。5.2 速率限制与并发保护上游模型供应商对单Key和单账户都有速率限制一旦你某个时刻流量暴涨很容易收到429。LiteLLM在虚拟Key和模型两个层面都支持限流。在虚拟Key里可以设置rpm和tpmcurl http://localhost:4000/key/generate \ -H Authorization: Bearer sk-my-admin-key \ -H Content-Type: application/json \ -d {rpm: 10, tpm: 20000}rpm限制每分钟请求数tpm限制每分钟token数。这样即使某个上层应用有突发流量也会在代理层被拦住避免把上游Key打到限流。同时在litellm_params里也可以设置每个上游模型的rpm和tpm防止某一个模型组占用其他模型的额度。这套双层限流机制在实践里很有用我一般先按业务预期给虚拟Key设置一个偏低的rpm再慢慢根据监控调整避免一上来就超额。5.3 多租户与团队隔离给多个业务团队提供AI能力的时候最好做到“各自管各自的钱、各自的Key、各自的模型白名单”。LiteLLM支持Team可以把虚拟Key绑定到某个Team再给Team设置独立预算。我先创建Team再在Team里生成Key。这样每个Team的请求都有独立的预算和消费记录。多租户模式下我建议启用单独的数据库而不是默认的SQLite因为并发写入和查询性能都要好很多。多租户隔离的核心不只是预算还有数据边界。团队A不能查到团队B的用量明细不能使用团队B创建的虚拟Key。LiteLLM会在鉴权阶段就校验Key对应的Team信息如果你的内部系统有权限控制需求可以基于这个Key的TTL和模型白名单再包一层。6. 实战中遇到的坑与排查流程6.1 模型总是404问题多半出在模型名映射最典型的报错是请求代理时返回Unknown model。这通常不是代理本身的问题而是config.yaml里model_name和客户端请求里model字段不一致。有些团队复制了别人的配置客户端却还在用旧的模型名代理自然匹配不上。排查时可以请求/model/info接口查看当前代理已注册的所有模型名。另外注意模型名的空格和全半角问题我从日志里见过有人把模型名写成“gpt-4o ”带着尾部空格直接导致匹配失败。配置里最好统一用一个小写短横线风格。还有一种情况是改完config.yaml没有重启代理。LiteLLM代理不会自动热加载配置文件model_list的变更需要重启进程。所以每次改完配置后我都会在启动日志里确认总模型数量是否正确。6.2 上游超时和429调整重试策略当上游供应商负载高时代理会返回504或429。遇到这个情况第一件事是去查看统计指标确认是单模型异常还是全局异常。如果只是单模型就把该模型的num_retries调低让其他模型多分担流量。另一个容易被忽略的点是客户端自身的超时设置。代理层可以配置30秒超时但客户端如果设了10秒代理还没返回客户端就断了业务感知就是超时。这个锅经常被甩给LiteLLM实际是客户端超时太短。建议把客户端的超时时间设置为代理端的两倍以上。429报错里通常带有Retry-After头部LiteLLM的Router可以根据供应商返回的信息动态延长冷却时间。你只要保证开启了cooldown_time它会自动短期避开被限流的上游。6.3 成本记录与实际账单对不上成本统计不准最常见的原因是缓存命中时没有记录消费。默认情况下缓存命中的请求不会产生真实上游调用所以也不会记录成本。如果你需要看到“如果没缓存本来要花多少钱”可以把litellm_params.store_cache_spendTrue打开。另一个坑是时区问题。LiteLLM默认以UTC记录时间如果你在财务核算时用本地时间对齐账单很容易产生几小时的偏差。建议在数据库连接配置里统一时区或者在SQL查询时显式转换时区。还有一个场景是并发写库导致记录丢失。生产环境如果一直用默认SQLite高并发下写库会锁表某些用量记录可能丢失。我的建议是只要流量超过每分钟几百次就赶紧迁到PostgreSQL。换库很简单改一下database_url重启即可但数据连续性需要提前确认。6.4 个人实操体会做了这么多模型接入项目之后我的体会是LiteLLM最厉害的地方不是“功能多”而是把模型层常见的问题收敛到了一个可配置可观测的入口。刚开始用的时候不建议把所有高级功能一次性铺开先最小配置跑通一条主链路再慢慢加缓存、预算、多租户每一步都能用指标验证价值。最后分享一个小技巧在配置多个模型组时给每个模型model_info里加一个description字段写明这个模型适合什么场景、延迟大概多少、成本量级。这样等团队扩大以后其他同学查看配置就能明白为什么默认走这个模型减少瞎改配置的情况。
阅读完成 · 觉得有帮助?