1. 从“维护三套大模型对接代码”到“只留一个入口”我刚开始接触 LiteLLM 的时候情况其实谈不上高大上。那会儿我手上有个内部工具平台代码里躺着两套不同厂商的大模型 API 封装一套走的是 HTTP 直连另一套用的是厂商自己的 SDK两边超时时间不一样错误码风格不一样连返回字段都各叫各的。最让我崩溃的是产品经理告诉我下周还要再接一个新模型而且新旧模型要能随时互相切换。我当时心里只有一个念头再这么到处打补丁下去迟早要出事。这个场景其实就是 LiteLLM 最擅长解决的问题。它本身是一个 Python 实现的开源工具包目标非常明确给上层业务提供一个整齐划一的大模型调用入口把不同厂商之间那点“小差异”全部消化在底层。你可以把它理解成一个大模型接入层的翻译官业务方只负责说“我要一次对话补全”剩下的鉴权方式、请求路径、参数命名、流式协议、错误归一化统统由 LiteLLM 去跟上游打交道。有人可能会问现在各家大模型厂商不都提供了兼容接口吗直接照着兼容规范写一套不就行了理论上行但实际维护起来完全不是一回事。所谓“兼容”往往只是路径和请求体长得像参数的语义还是有细微差别有的厂商max_tokens表示输出长度上限有的厂商要求用别的名字有的支持系统提示词有的对角色定义更严格鉴权可能要求请求头不同返回体里的用量统计、结束原因、内容字段也未必一致。更别提不同厂商 SDK 的版本升级节奏了今天这个接口标记废弃明天那个 SDK 改了初始化参数你都得追着改。我在那段时间做的最蠢的一件事就是给每家厂商单独写一个封装模块然后在业务层用 if-else 根据配置切来切去。刚开始模型少勉强能撑住模型一多条件分支开始指数增长A 模型支持联网搜索B 模型支持工具调用C 模型只支持纯文本聊天每个选项都要在封装里补一段差异代码。到后来一个简单的“换模型”操作改完还得出身汗因为你永远不知道哪个分支会被触发。LiteLLM 的解题思路跟“自己写适配层”完全不同。它把模型名做成一种带前缀的规范格式类似“厂商标识/模型编号”在内部把这个名字解析到具体的上游地址、鉴权参数和模型配置。业务代码里不需要感知每个厂商怎么鉴权、怎么拼请求只需要把模型名和消息传进去就行。它同时还提供了一个代理网关模式你可以起一个本地服务让整个团队的所有应用都改调这个网关密钥统一托管、预算统一控制、成本统一统计。这也是我后来最依赖它的原因它不是只解决“代码能不能调通”而是把大模型接入当成一个需要长期运维的基础设施来设计。所以如果你正面临下面任何一种情况LiteLLM 都值得你花半小时试一下项目里同时接了两家以上的大模型、API 密钥散落在多个服务里不好管理、换模型时业务代码改动特别大、希望限制某些业务的调用预算、或者不想每次新增厂商都重写一遍对接层。下面我按自己实际使用的路径拆开来说说核心用法和那些容易踩坑的地方。2. 半小时跑通统一 SDK拆开看一下核心用法2.1 安装这一步要不要装全量依赖先用最简单的方式体验 LiteLLM 的 SDK 能力。打开一个 Python 虚拟环境执行安装。如果只是自己写脚本实验装基础包就够了pip install litellm如果打算后面把代理网关一起跑起来我建议直接装带扩展依赖的版本省得之后缺东西再补pip install litellm[proxy]安装完之后看下版本号顺便确认依赖有没有装干净pip show litellm这里我想多说一句很多人喜欢图省事直接装全量依赖但如果你们的 Python 环境里有严格的依赖冲突检查全量安装可能会带进来一堆用不上的管理端依赖。既然用了虚拟环境还是建议按需安装基础包起步等真要上代理模式再装全量。2.2 第一段“统一补全”代码长这样SDK 模式最直观的用法是直接调用对话补全。下面这一段代码就是把一套调用逻辑同时用于不同厂商模型的最小示例import os import litellm response litellm.completion( model厂商A/模型编号, messages[ {role: system, content: 你是一个乐于助人的助手}, {role: user, content: 用三句话解释什么是API网关}, ], api_keyos.getenv(MODEL_A_API_KEY), ) print(response.choices[0].message.content) print(response.usage)注意看model这个参数它的写法是“厂商标识/模型编号”。比如你想切换到另一家厂商的模型不需要改请求逻辑只需要把model换成“厂商B/模型编号”并配上对应的api_key。同一段代码切换上游服务商这就是 LiteLLM 最基础的价值。有两点新手容易误会。第一litellm.completion不一定只适配那种纯文本聊天模型它对多轮对话、流式输出、工具调用这类常见场景都有统一入口只是不同能力要看上游模型是否支持。第二api_key可以直接传也可以不传然后通过环境变量或代理侧的密钥配置来加载后一种方式明显更安全。如果你想验证流式输出把streamTrue传进去即可返回值会变成一个可迭代的生成器一段一段往外吐内容体验跟直连某个厂商的流式接口非常接近。这个特性在网关模式下尤其重要因为很多实际业务场景都依赖流式输出比如对话机器人逐字展示回答。2.3 统一输出到底统一在哪我刚开始用这个库时一直担心它只是把请求包装了一层返回结构未必稳定。实际用了一段时间之后发现它确实是把响应结构做了统一处理。正常情况下你不用再去记某个厂商的原始返回里用的是text字段还是content字段也不用管结束原因是stop还是别的写法LiteLLM 都会把这堆差异规范成一套结构。比如response.choices[0].message.content拿到的是对话结果response.usage拿到的是 token 消耗统计response.model记录的是实际使用的模型名。这种统一还有另一层意义一旦你在上层写了格式化输出、token 统计、缓存策略这些东西不会因为切换模型而全部需要重写。换模型的成本从“改一堆业务代码”降级成“改一个配置项”这对一个高速迭代的团队来说价值是非常明显的。当然参数层面的差异不会因为统一接口就完全消失。比如某个模型不支持某类参数你还是会收到对应错误LiteLLM 能做的是把这些错误也尽量归一化成统一的异常类型而不是让每种厂商的错误都漏到业务层。实际使用中我习惯在调用外层统一捕获几类异常鉴权失败、请求超时、上游返回错误然后做统一告警和重试这个后面展开说。3. 把 LiteLLM 当 API 网关部署团队接入成本最低的路径3.1 为什么说网关模式比 SDK 模式更“香”SDK 模式只适合自己一个人或一个服务接模型。真正的团队场景里问题往往不是“能不能调通”而是“密钥管不管得住”“预算控不控得住”“换模型别的组配合不配合”。这些事靠 SDK 模式很难解决因为每个服务都得自己拿一份上游密钥都得自己写一遍重试、统计和告警逻辑。网关模式的思路很简单部署一个 LiteLLM 代理服务把它当作团队的大模型入口。所有上游厂商的真实密钥都只配置在这一个地方业务应用不再直接持有真实密钥而是使用代理服务生成的虚拟密钥去调用。代理收到请求后校验虚拟密钥的权限和预算再把请求转发给真正的大模型厂商业务应用不需要知道自己背后接的到底是哪家模型。我认为对绝大多数团队来说这是最值得优先考虑的接入方式。因为它不动用业务代码逻辑你只需要把原来请求大模型 API 的地址改成网关地址把原来的密钥换成代理分配的虚拟密钥把模型名改成配置的别名其他都不用大改。哪怕你的应用是几十个服务理论上也只需要做一次公共客户端配置调整。3.2 一份最小可跑的代理配置文件网关模式的入口是一份 YAML 配置文件。最简配置只需要告诉 LiteLLM对外暴露什么模型名这个模型名背后对应哪家厂商的哪个模型以及用哪个 API 密钥。写一个config.yamlmodel_list: - model_name: team-chat litellm_params: model: 厂商A/模型编号 api_key: os.environ/MODEL_A_KEY model_info: mode: chat这里的team-chat是团队内部约定好的模型别名业务应用只认这个别名不直接接触上游模型名。这样做的好处是哪天你想把内部主模型从厂商A换成厂商B不需要通知所有业务方改代码只需要修改代理配置让team-chat指向新的上游模型重启代理即可。启动代理服务litellm --config config.yaml --port 4000服务起来之后你可以先在本机用 curl 验证一下链路是否通了curl http://127.0.0.1:4000/v1/chat/completions \ -H Authorization: Bearer sk-临时测试key \ -H Content-Type: application/json \ -d {model:team-chat,messages:[{role:user,content:你好}]}如果配置没问题你应该能拿到一个和大模型厂商返回结构类似但已经经过统一定义的结果。网关对外暴露的接口风格是通用的大模型接口风格所以只要你原来的应用客户端支持自定义base_url就能非常平滑地切换到代理上。3.3 集中管理虚拟密钥、预算和限流代理跑起来之后绝对不能直接拿上游密钥对外提供访问。第一步应该先设置一个管理层主密钥用来保护后续的管理操作。在配置的general_settings里加上general_settings: master_key: sk-master-请换成自己的强随机字符串用这个主密钥调用代理的管理接口可以生成虚拟密钥。每个虚拟密钥都代表一个独立的调用身份你可以给不同业务线、不同项目分别发一个虚拟密钥这样后续就能按密钥统计谁消耗了多少 token、花费了多少钱。虚拟密钥不仅能鉴权还能挂预算和限流。比如某个内部工具业务预算有限你可以在生成密钥时配置一个月度预算上限一旦当月累计消耗超过上限代理会直接拒绝后续请求从机制上防止成本失控。同样你还可以给虚拟密钥配置每分钟请求数上限、每天请求数上限、每分钟 token 数上限。这个功能非常实用尤其是当团队里有些业务方会写批量脚本大量拉取模型结果时如果没有限流一次粗心大意的循环就能把你的月度预算烧掉一大截。我实际使用下来的经验是每创建一个虚拟密钥都尽量在备注里写清楚是给哪个系统用的同时把预算上限和限流参数一并配好。等月底对账或者查故障时这些维度能让你快速定位“谁在什么时间点把预算耗光了”。3.4 网关的性能和队列配置网关一旦变成团队入口就不能忽略性能配置。代理服务本身允许你设置并发限制和请求超时这能避免极端流量下上游模型被打爆也避免业务应用在网关排队时无限等下去。一般我会在配置里显式设置比较保守的并发上限同时把单个请求的最长耗时钟调到一个合理值比如 60 秒。到了 60 秒还拿不到结果就尽早返回超时错误而不是让调用端一直挂着。另外提醒一句代理服务需要保持稳定。如果要接生产流量至少得考虑用进程守护工具保活、日志收集、端口健康检查这些常规运维手段。它不需要很重但绝对不能像本地调试脚本那样跑一次就丢。4. 主模型不可用时不让业务陪葬回退、重试与超时4.1 故障转移策略到底该怎么配真实环境里大模型厂商的服务偶尔会抖动这种抖动有时候是区域网络问题有时候是上游限流有时候是对方的模型本身进入高负载状态。如果你的业务只绑定了单一主模型一旦上游出状况你的服务也只好跟着一起挂。用 LiteLLM 的好处是你可以直接在配置里描述“主模型不可用时请求应该转给谁”。在代理配置里增加回退规则思路大概是这样team-chat这个别名先指向厂商A的模型如果厂商A调用失败就把请求转给厂商B的模型再不行就转给厂商C。具体配置项的名称会根据版本略有变化但核心思想是一致的给模型列表定义一个主备顺序代理在每次请求时根据前一次调用的结果决定是否切换。这里我最想强调的是不要把回退条件设置得过于激进。如果上游返回的是参数错误或者权限错误你再怎么回退也没有意义因为换一家模型大概率也会因为同样的参数问题失败。真正值得回退的是鉴权临时失败、5xx 类服务端错误、连接超时这类“瞬时故障”。在配置里可以通过错误类型来做辨别尽量只针对这些可恢复错误触发回退。4.2 重试、指数退避和超时设置除了回退重试机制也很重要。你用 SDK 模式调用时可以设置全局重试次数import litellm litellm.num_retries 3 litellm.timeout 60设置重试次数后如果上游因为限流或者暂时性故障失败SDK 会再次发起请求。为了避免同一时间大量请求并发重试把上游打得更惨LiteLLM 也支持启用指数退避策略。指数退避的意思很好理解第一次失败后等一小会儿再重试第二次稍长一些第三次更长给了上游喘息的空间。这个机制对“偶发限流”特别有效。模型厂商的限流往往不是精确的一分钟几个请求而是存在短暂的突发窗口稍微等个几秒钟再重试成功率能高很多。但我也要泼一盆冷水重试次数不是越多越好。比如把num_retries设成 10 次遇到上游长时间故障你的业务应用会一直卡在重试循环里用户体验反而更差。一般 2 到 3 次比较合理重试间隔采用退避策略。4.3 一个特别容易被忽略的“故障放大”问题如果你通过网关为几十个业务方服务一个故障场景非常值得提前演练上游厂商宕机时所有依赖它的业务请求会被代理同时转给备用模型或者同时发起重试。如果备用模型的配额没那么大它马上也会被冲垮。这个现象叫“故障放大”本质是把原本集中在一个上游的压力瞬间转移到了备用上游身上。要缓解这个问题我建议从两个地方下手一是给每个虚拟密钥设置合理的限流让单个业务方的峰值流量不会无限压向网关二是在网关层设置并发限制不要把所有请求都直接放进去重试。另外一个更实操的办法是对非核心场景设置快速失败一旦连续几次调用都失败就直接返回降级结果而不是让用户一直等重试。记住一句话网关存在的意义不是无限刨资源而是在成本与可用性之间做平衡。5. 除了能调通还要看得见预算、计费与可观测性5.1 每次调用的费用信息从哪儿来大模型调用最怕的不是功能调不通而是月底一算账发现成本高得吓人却说不清钱烧在哪。LiteLLM 在这块做得比较贴近实际需求每次请求完成后它会把 token 用量、模型名、虚拟密钥等关键信息带出来并估算出这次调用的计费金额。你可以在成功回调里拿到这些明细。比如import litellm def my_callback(kwargs, completion_response, start_time, end_time): # 这里可以拿到模型名、token用量、耗时等字段 print(kwargs.get(model)) print(completion_response.usage) print(end_time - start_time) litellm.success_callback [my_callback]回调能力很实用。你可以把每次调用的明细写到日志系统里也可以在内存里做聚合再定时推到成本报表里。如果你们有自己的计费系统完全可以靠这个回调把每次调用记录喂进去。这里要提醒一句回调里尽量不要记录完整的用户消息内容和模型回复内容只记录模型名、token 数、耗时、密钥标识、错误类型这些元数据就够了。一方面是控制日志体积另一方面也是避免敏感信息在日志链路里被多复制一份。5.2 接入指标采集与告警网关模式还内置了一个指标端点它会暴露给指标采集系统一堆统计数据比如请求总量、每分钟 token 消耗、请求耗时分布、失败率等等。你只需要在代理配置里把这个能力打开然后用你团队现有的指标采集器定时去拉取就能在监控面板上看到网关的整体状态。有了指标之后告警规则就是顺水推舟的事。我一般会设置三个最基本的告警网关 5xx 错误率飙高、单次请求 P95 耗时超过阈值、虚拟密钥每日成本超过预算的 80%。前两个保证可用性后一个保证成本不出意外。如果你团队内部还没有成熟的指标采集系统也可以先用日志方案过渡把成功和失败请求都打上结构化日志然后用日志检索平台去做统计和告警。本质上只要能统一拿到数据用什么工具是次要的。5.3 成本归集从虚拟密钥开始成本归集这件事越早做越省心。给每个业务方分配独立虚拟密钥的那一刻你就已经为成本归集打下了基础。月末复盘时你只要按虚拟密钥分组统计消耗金额就能看到哪些业务是成本大头哪些模型使用频率异常高哪些调用路径存在浪费。更进一步你还可以在生成虚拟密钥时给密钥打上标签比如部门、项目、环境。标签的好处是统计口径灵活今天想看某个项目的月度成本明天想看某个环境的费用分布都能快速筛出来。我踩过的一个小坑是前期没有设计好标签规则后面补标签要翻历史调用日志费时费力。所以越早立规矩后面越轻松。6. 几个容易在真实环境里翻车的细节6.1 模型名前缀是第一个坑LiteLLM 的模型名规范里前缀决定了请求会被解析到哪一家厂商。很多人第一次配置时容易犯的错误是模型名不写前缀。如果配置里也没有设置默认厂商请求很可能直接发到一个不合预期的地址然后拿到一个莫名其妙的错误。所以我一贯的建议是在所有配置里都写成“厂商标识/模型编号”的完整格式不要依赖默认值。如果你在接一个第三方兼容服务前缀也有办法处理。你可以把那个服务当成一个自定义厂商在配置里指定它的 base_url 和鉴权方式然后再给模型取一个统一别名。这样业务上依然只感知一个别名不会被复杂的自定义服务细节干扰。6.2 参数透传和工具调用不是每家都一样不同模型对工具调用的支持差异是最大的雷区。有些模型支持函数调用而且参数格式很标准有些模型只支持简单的文本补全你传了工具定义过去它要么报错要么直接忽略。LiteLLM 会在模型元信息里标注是否支持某类能力比如是否支持工具调用。配置模型时建议把model_info里的能力项如实填好代理在转发时就不会硬塞模型不支持的参数。另外是max_tokens这类参数。不同厂商对输出长度的叫法和限制不一样LiteLLM 会做一部分翻译但翻译的准确程度跟上游模型文档的吻合度有关。我的建议是接入新模型后先用一个很小的测试集验证一下输出长度是否可控不要默认所有模型对同一个参数的理解完全一致。6.3 密钥管理的几个安全细节网关模式下虚拟密钥代替了真实上游密钥但真实上游密钥仍然配置在网关这台服务器上。所以网关这台机器的安全级别实际上比单个业务服务要高得多。不要把这些真实密钥硬编码在配置文件里提交到代码仓库最好通过环境变量或密钥管理服务注入。配置文件本身可以进仓库但里面只保留类似os.environ/MODEL_A_KEY这样的引用。还有一个容易被忽视的点虚拟密钥本身也要有一套轮换和撤销机制。某个应用下线了对应的虚拟密钥要及时删除某个密钥疑似泄露要有办法快速暂停或撤销而不是重新部署整个网关。日常操作时我倾向于定期轮换那些权限范围很大的虚拟密钥权限范围小的可以放宽一些。6.4 版本升级前一定要先做回归LiteLLM 的迭代速度不慢配置语法和函数签名偶尔会有调整。最怕的是你直接在生产环境上执行升级命令结果配置文件的某个字段名变了代理起不来全线业务跟着受影响。我自己的习惯是升级前先看一眼官方的变更说明把当前使用的配置文件和依赖版本在本地或测试环境里整套跑一遍确认没有兼容性问题后再动生产。如果条件允许我还建议不光升级包本身顺手把模型路由、回退规则、虚拟密钥这些核心功能一起回归一遍。因为某些配置项的默认行为可能随版本变化比如超时时间、队列策略这些看似隐蔽的变化往往比明显的接口变动更容易在生产环境里搞出事故。最后分享一个小经验如果你团队规模不大强制所有人改 SDK 模式往往阻力很大不如先把网关搭起来让业务方只改一个地址和 key。而如果你还在验证阶段只想自己快速试试 SDK 能力那就先用纯 SDK 模式跑通等真正需要统一管控密钥和成本时再平滑地往代理模式迁移。LiteLLM 的设计决定了这两种路径可以无损切换先用哪个都行别一上来就被复杂的配置吓住先让最小的链路跑起来后面的能力自然会慢慢长出来。
阅读完成 · 觉得有帮助?