资讯动态

Litellm实战:用开源API网关统一大模型接入与治理

发布时间:2026/10/13 21:24:03 来源:尧图企业网站定制
1. 先说说我为什么盯上了litellm多模型接入的混乱必须治过去两个月我们团队手上有三条AI业务线在并行推进每一条连接的模型来源都不一样。第一条业务线用的是某头部云厂商的闭源模型接口第二条业务线接了一个开源模型的私有化部署第三条业务线在试几个新出的小模型想看看效果。麻烦很快就来了每个接口都有自己的SDK、自己的鉴权方式、自己的返回结构甚至同一个需求在三个接口里要用三种完全不同的代码去写。最崩溃的一次为了给三个接口统一做一个问答质量评估的调试脚本我硬是写了三套解析逻辑因为有的返回choices[0].message.content有的返回output.text还有的返回结构里套了两层data。这种状态持续了大概一周我就受不了了。代码仓库里到处是xxx_client、yyy_sdk这样的适配层命名都还算是小事问题是每接入一个新模型就要重新读一遍别人的文档重新写一遍请求和解析的胶水代码。出问题的时候还得一个接口一个接口去排查。我当时的想法很简单能不能有一个东西让我只用一种方式去调用所有模型模型变更、供应商切换、密钥管理、成本统计这些统统在这一层解决业务代码不感知后面发生了什么。然后我就找到了litellm。简单来说litellm是一个开源的大模型API网关它把一百多种模型服务的接口差异全部屏蔽掉对外统一暴露成OpenAI格式的API。也就是说无论背后是闭源模型、开源模型、云上托管的模型还是你自己GPU机器上跑着的模型你都可以用同一套OpenAI SDK去调用。光这一点就已经解决了我们80%的对接痛苦。更让我觉得值得写一篇长文的是它还顺手解决了密钥管理、预算控制、日志审计、负载均衡这些本来要自己造轮子的事情。这篇文章我想以一个实际落地者的身份把litellm从知道到用起来再到用得顺手的过程里那些文档里写得不够直白、官网示例覆盖不到的东西都讲清楚。如果你也是那种手上一堆模型接口、天天写适配代码的人这篇文章应该能帮你省下不少时间。2. 为什么需要这样一个网关卡换模型不该改业务代码2.1 各家接口的差异到底有多大很多人会觉得模型API不都差不多嘛就是发个请求拿个回复。真不是这样。我把我们当时接入的几家接口放在一起对比过差异大到让人头疼差异点模型接口A模型接口B模型接口C鉴权方式Header里放Authorization: Bearer自定义Header塞API Key既支持Header也支持Query参数请求体结构messages数组配model字段prompt字符串配max_tokens既有inputs又分parameters返回文本字段choices[0].message.contentoutputs[0].textdata.text模型名称格式模型名-版本号需要拼上instruct后缀用部署ID而不是模型名流式返回格式SSE的data: [DONE]结尾分隔符略有不同需要额外传stream: true才给SSE流错误码语义429限流、401鉴权429也限流但是包了一层用的HTTP状态码基本一致但body结构完全不同这些差异单独看都不算什么只要肯花时间每个都能适配。但它们组合在一起就很要命了。你的业务代码里每接一个模型就要面对一套新的字段映射规则每次模型供应商那边调整返回结构你的解析逻辑就要跟着改。我们有一条业务线的解析代码就因为这个改了三次每次都是供应商版本升级导致的字段变动。2.2 网关这层存在的意义litellm做的事情可以理解成在模型接口和你的业务代码之间加了一个翻译层。你的业务代码只需要按照OpenAI的格式去发请求litellm内部会帮你把请求翻译成目标模型能理解的格式再把目标模型的返回翻译回OpenAI的格式。这个思路就像是你去国外出差不需要学每一个国家的语言只需要找一个翻译跟着你走就行。只是这个翻译不只是翻译文本这么简单litellm还帮你把周边一堆琐碎的事情也一起办了密钥托管真实模型供应商的API Key集中在litellm的服务端保存业务侧拿到的是一个虚拟密钥。就算某个虚拟密钥泄露了你也可以单独吊销它不用动真实密钥。预算和速率控制可以按项目、按团队、按虚拟密钥分别设置额度上限也可以设置每分钟/每小时的请求数限制。这一点在有多条业务线共用模型额度的时候特别有用不然一条业务线发起疯来能把整个月的预算烧光。日志和审计所有经过网关的请求都会被记录包括谁调的、调的哪个模型、传了多少token、花了多少钱、响应状态怎么样。出了安全事故或者成本异常的时候有日志可以查。路由和容错同一个模型可以配置多个供应商来源一个供应商限流了自动切换备用。还可以做简单的负载均衡把请求分散到价格不同的模型上实现在效果和成本之间找一个平衡。我见过有团队觉得这些功能自己写也不难就打算直接在业务代码里做适配层。短期看确实能顶一阵子但随着模型供应商变多、业务方变多代码里就会到处是if-else最后变成一个谁都不敢动的泥潭。网关这一层存在的意义就是把模型接入这个横切关注点从业务逻辑里剥离出来集中治理。3. 从零跑通安装、起一个网关、用OpenAI SDK调用起来3.1 环境准备和安装litellm是Python写的安装非常简单有Python 3.8以上环境就行pip install litellm[proxy]注意我这里是带[proxy]后缀的。litellm本身是个Python SDK你可以直接把它作为一个库导入到自己的代码里用但那样的话你只是省去了写适配代码的工作并没有获得网关的好处。真正要获得完整的密钥管理、日志、预算这几个能力需要把它的代理模式跑起来也就是启动一个服务端进程所有请求先到它这里再由它转发到真实的模型服务。如果你只需要在Python脚本里快速用一下不启动服务端也是可以的from litellm import completion response completion( modelgpt-3.5-turbo, messages[{role: user, content: 你好}] )但是这篇文章我主要讲代理模式因为代理模式才是把它当网关用的时候。装好包之后可以先用python -m litellm --help看一眼命令行参数确认安装成功。3.2 最小可用配置model_listlitellm跑起来之后需要一个配置文件通常是config.yaml用来告诉它你能访问哪些模型、每个模型对应的供应商是谁、密钥是什么。下面是一个最简配置model_list: - model_name: my-gpt-4o litellm_params: model: openai/gpt-4o api_key: sk-xxx - model_name: my-claude litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: sk-ant-xxx - model_name: my-llama litellm_params: model: openai/llama3.1:8b-instruct api_base: http://localhost:11434这里有个细节值得注意model_name是你给这个模型起的别名是业务代码里要用的名字而litellm_params.model是litellm内部的模型标识符格式是供应商/模型名。比如openai/gpt-4o表示通过OpenAI兼容格式访问gpt-4oanthropic/claude-3-5-sonnet-20241022表示通过Anthropic原生的接口访问。如果你的模型跑在某个OpenAI兼容服务的本地环境上就在litellm_params里再加一个api_base指向那个服务的地址。litellm支持的供应商前缀非常多从常见的openai、anthropic、azure、bedrock到ollama、vllm都有不用自己写适配代码。然后启动服务python -m litellm --config config.yaml --port 4000启动日志里如果出现Uvicorn running on http://0.0.0.0:4000网关就算起来了。3.3 三行代码接入网关起来之后你业务代码里的调用方式就变得异常简单了。因为litellm对外暴露的是OpenAI兼容接口所以直接用官方OpenAI SDK就行只需要把base_url指到你的网关地址from openai import OpenAI client OpenAI( api_keysk-anything, # 只要非空即可 base_urlhttp://localhost:4000/v1 ) resp client.chat.completions.create( modelmy-gpt-4o, messages[{role: user, content: 我用litellm跑通了}], streamFalse ) print(resp.choices[0].message.content)你甚至不需要注册任何真实密钥只要网关起了配置里写了对的供应商密钥业务代码里随便填一个非空的api_key就能通过鉴权。这个设计在本地开发阶段很舒服你可以在不太关心密钥体系的情况下先把流程走通。如果想要流式输出把streamTrue传进去收到的是一个流式对象和官方SDK的用法完全一致如果你用的是JavaScript同理官方Node.js SDK里设置baseURL然后正常调用就行。当初我一个人花了一个下午折腾出来的效果换成litellm之后一个全新业务线接入第一个模型从写配置到跑通五分钟差不多了。4. 把网关用好虚拟密钥、预算、路由这些硬核功能逐个捋4.1 虚拟密钥到底解决了什么问题如果你只是给一个小工具做接入直接用真实密钥也说得过去。但团队的场景是多人、多服务、多项目共享模型额度这个时候真实密钥的痛点就出来了密钥放在代码仓库里容易泄露。一个密钥被多个服务共用出了问题不知道是哪个服务干的。某个服务被攻击或者代码写死循环了一个月额度一下烧完其他服务全部停摆。litellm针对这个问题提供了虚拟密钥机制。你先把真实供应商密钥写在config.yaml里然后在gateway运行期间通过管理接口创建一个虚拟密钥curl -X POST http://localhost:4000/key/generate \ -H Authorization: Bearer sk-1234 \ -H Content-Type: application/json \ -d {aliases: {my-gpt-4o: my-gpt-4o}}创建成功后你会拿到一串sk-开头的新密钥。把它发给业务侧使用。每个虚拟密钥可以绑定一组模型、设置额度上限、设置过期时间。业务侧拿着虚拟密钥调用网关网关再用真实密钥去请求上游模型供应商。如果某个虚拟密钥异常消耗额度你可以单独限流、暂停、删除完全不影响其他虚拟密钥的使用。我自己的习惯是每个服务用单独的虚拟密钥名称和服务一一对应比如order-service、search-service然后用元数据字段再打上负责人和项目的标签。这样哪天某个虚拟密钥的token消耗异常我能在日志里一眼定位到是哪个服务干的不需要猜。4.2 预算控制要这样配才有效litellm的预算控制有几个层级配置方式略有不同。最基本的层级是全局预算写在config.yaml的general_settings下面general_settings: max_budget: 1000 # 美元 budget_duration: 30d这个配置意思是在30天周期内整个网关的总花费不能超过1000美元。超过之后所有经过网关的请求都会被拒绝。不过在实际落地过程中我建议你优先配置虚拟密钥维度的预算因为这样可以精确到服务model_list: - model_name: my-gpt-4o litellm_params: model: openai/gpt-4o api_key: sk-xxx max_budget: 200 budget_duration: 30d这样my-gpt-4o这个模型在30天内最多花费200美元。还有更细的键值维度、用户维度、团队维度预算可以根据你的组织架构来安排。我只提醒一句预算参数要区分max_budget和rpd_limit、tpm_limit这几个字段前者管钱后两者管请求速率和token速率。很多人在配置的时候容易混淆明明是速率问题却去调预算调半天没有效果。litellm完成一次请求之后会做异步的成本统计回传token数和费用。这类统计数据多了之后对系统性能有一点影响在生产环境建议把默认的日志存储换成数据库后端而不是用内存模式不然重启一次网关统计数据就全没了。4.3 路由、负载均衡与自动故障转移litellm的一个实用功能是同一个model_name可以配置多个上游来源网关会根据设置的策略自动分配请求。例如model_list: - model_name: my-gpt-4 litellm_params: model: openai/gpt-4 api_key: sk-xxx - model_name: my-gpt-4 litellm_params: model: azure/openai-gpt-4-deployment api_base: https://my-azure-resource.openai.azure.com/ api_key: azure-xxx这样你公开的模型名只有一个my-gpt-4上游却有两个来源。默认情况下litellm使用简单的轮询策略也可以配置成基于rr或者自定义权重。如果某个上游供应商返回限流、超时或者5xx错误litellm会把请求自动切换到另一个上游。对业务侧来说它感知不到这个切换过程看到的还是一个正常的成功响应。我在生产环境中用这个功能做了两件事。第一件是容灾把主用供应商和备用供应商都配置上主用那个出现问题了备用自动顶上。第二件是成本优化大部分请求走价格便宜的型号少量复杂请求走更高端的型号通过权重调整比例整体效果不错账单下降也很明显。4.4 日志、分析与可观测性litellm在默认配置下会把每次请求的元数据打印在控制台包括模型名、响应耗时、token用量和花费。生产环境就不建议只看控制台了可以配置接入数据库比如用PostgreSQL存储日志和token统计。启动的时候加--database_url参数或者配置里写数据库连接字符串即可。我用下来觉得最有价值的几个日志维度是按模型统计的token消耗趋势可以看出来哪些模型是成本黑洞该不该换更便宜的替代品。按虚拟密钥统计的使用量可以看出来每个服务对模型资源的消耗是否合理。失败请求的错误分布能快速发现某个供应商在这个时间段内是不是在频繁限流或者报错。请求延迟的P50/P95模型接口延迟波动大的时候通过这个指标判断该不该加缓存或者引入异步处理。有一次我们排查线上问题发现某个模型接口的P50延迟正常但P95异常高导致部分用户的体验明显变差。后来通过日志定位到是供应商那边高峰期的流式输出变慢我们给这个模型加了一个备用上游问题就缓解了。如果没有网关这一层的日志这种问题排查起来要麻烦得多。5. 进阶玩法模型映射、成本控制策略和多端集成5.1 模型别名与统一命名规范前面提到model_name可以自己起别名这个能力在处理模型升级切换的时候非常有用。比如你现在对外提供的模型名是chat-assistant业务代码全部用的这个名字某一天你想把它从模型A换成模型B你只需要修改config.yaml里chat-assistant指向的litellm_params.model重启网关业务代码一行都不用动。这是一次真正的改配置就能切模型。我建议团队内部在命名上做一点规划以用途命名模型而不是以具体型号命名。比如用chat-fast实时场景用快速模型、chat-powerful复杂推理用高端模型、embedding-default默认向量化模型、vision-default图片理解模型。这样业务侧不用关心底层是什么型号后续供应商怎么换、型号怎么升级对业务代码来说都是透明的。5.2 成本控制策略什么时候手动切换模型litellm有一个有意思的字段叫max_input_tokens和max_output_tokens分别限制输入和输出的token上限。配置之后超过上限的请求会被拦截从源头避免意外的巨额账单。之前发生过一次事故某个prompt注入的请求把几万字的内容全都塞进了上下文导致那一次请求的输入token费用暴涨。这个设置虽然挡不住所有费用异常但至少能设置一个明确的顶。如果你还想更精细一点litellm支持配置custom_auth回调来实现自定义的鉴权逻辑。比如有一个需求是不同用户角色只能使用不同的模型池普通用户只能调用便宜的模型VIP用户才能用更高阶的模型。这个在litellm里可以写一个Python文件在请求进来的时候根据用户ID查一下权限然后在litellm_params里动态指定可以使用的模型。文档对这个功能的介绍比较简略但是方案确实是可行的。有一点要提醒大家动态指定模型不等于绕过模型权限配置。litellm的模型权限控制是通过model_group和allowed_model_group实现的如果你要严格控制谁只能用哪组模型建议先把配置层的关系理清楚再考虑自定义回调的方案。5.3 在LangChain和LlamaIndex生态里使用litellm如果你的RAG应用或Agent应用是基于LangChain或LlamaIndex的litellm有两种集成方式。第一种是把litellm作为底层调用库因为LangChain的ChatOpenAI类可以接收openai_api_base参数直接指向litellm网关然后传一个虚拟密钥进去这样你的RAG链条就串到了litellm上from langchain_openai import ChatOpenAI llm ChatOpenAI( modelmy-gpt-4o, openai_api_basehttp://localhost:4000/v1, openai_api_keysk-virtual-key-xxx, )第二种方式是直接用litellm.get_llm_class()或对接到LangChain的自定义llm类。官方文档推荐方式不一定是最简单的实际项目中我都是直接用第一种方式效果非常稳定。LlamaIndex那边也有类似的通用方式在OpenAI类初始化时传入api_base即可。5.4 多实例部署时要注意的状态存储litellm默认会把虚拟密钥、预算信息、日志等信息放在内存里或者本地SQLite里这在单实例部署的时候没问题。但如果你把网关部署成多个副本放在负载均衡后面就需要注意了虚拟密钥信息是存在某个实例内存里的请求被调度到另一个实例的时候密钥可能就不认了。好在litellm支持把状态存储放到外部依赖上比如Redis和PostgreSQL。用--redis_host参数可以接Redis用于速率限制和预算计数器用--database_url参数接PostgreSQL用于密钥信息和日志持久化。生产环境如果你不是只跑单实例这个绝对是必做的准备不然某个实例重启、网络抖动导致请求落到别的实例上体验就是时好时坏。配置示例python -m litellm --config config.yaml --port 4000 \ --database_url postgresql://user:passdbhost:5432/litellm \ --redis_host redis-host --redis_port 6379 --redis_password xxx这样你和/key/generate创建出来的虚拟密钥会写入PostgreSQL预算计数会写入Redis所有实例共享同一份状态。6. 踩坑记录用litellm过程中遇到的5个真实问题6.1 超时设置比你想的更影响体验litellm默认的请求超时时间有时候不太够用尤其是一些推理很慢的开源模型。如果业务侧在发起调用时没有设置超时参数网关转发给上游的时候也可能因为上游响应太慢而触发超时。我的经验是在litellm_params里显式配置timeout比如litellm_params: model: openai/llama3.1:70b api_base: http://192.168.1.10:8000 timeout: 300虽然绝大多数供应商的响应速度在几十秒以内但遇到那种复杂生成场景你如果没配置好超时用户侧就会看到连接中断一类的错误体验非常差。6.2 流式输出和max_tokens的交互陷阱有一次我发现某条业务线使用流式输出时输出被截断了一半。查了半天发现是供应商那边有个默认的max_tokens值而litellm的配置里没有对max_tokens做显式控制。流式输出模式下如果不把max_tokens设置足够大输出刚超过服务端默认值就被掐断了客户端这边还不知道看到的是一个正常的流结束标志。后来我养成了一个习惯在接入任何一个新模型前先手动测试一次长文本的流式输出确认输出长度确实是符合预期的。另外对所有模型统一配置max_output_tokens并把这个值和业务侧期望的最大输出长度对齐。6.3 上下文窗口溢出问题context_window这个参数控制的是模型上下文窗口的大小但它和供应商侧限定的上下文长度不完全是一回事。litellm会以这个配置去限制输入token如果你设置得比供应商的实际值大请求打到供应商那边依然会被拒绝如果设置得比实际值小那么你的合法请求也进不去。经验做法是设置成供应商官方文档标注的窗口大小并且比那个值略小一点给输出预留一点空间。6.4 虚拟密钥权限最小化有些人创建虚拟密钥时图省事把所有模型都挂在一个密钥下。其实litellm创建密钥的时候可以指定这个密钥只能访问哪些模型我强烈建议按照服务的最小需求来分配。比如只有客服场景才用高成本的模型那客服服务的密钥就只给那个模型授权其他服务就算拿到了这个密钥也用不了它不认识的模型。权限控制这种结构性的问题越早做越好等成本异常再回头治理就很被动了。6.5 什么时候你其实不需要litellmlitellm确实很强大但如果你只是一直在用某个单一固定供应商的固定模型代码里也没有多供应商切换的需求那引入litellm就是给自己增加不必要的运维负担。网关层的存在会带来一次额外的网络跳转虽然延迟开销通常很小毕竟多一跳就是多一次不确定性。没有一个工具是万能的litellm最适合的场景是多模型、多供应商、多业务方共用一套基础设施的情况。单一模型的场景里它反而是多余的那一层。7. 我在实际落地中的几点体会最后想聊几句这段时间用下来的个人感受。litellm最好的地方不仅仅是省了适配代码而是它改变了团队协作的方式。以前接入一个新模型要拉上开发、运维一起忙活半天现在只需要维护配置的人把config.yaml改一下再新建一个虚拟密钥业务侧就能立刻用了。模型供应商的升级、替换、故障转移这些事情从业务开发的工作清单里消失了变成基础设施层面的日常运维。如果你现在正处在每个模型一套SDK、每次接入都重写适配层的状态我建议你先花半个下午把litellm的代理模式跑通再把一个非核心业务线接上去试试。你会发现原来那些最烦人的接口差异问题真的可以在一层网关里被解决掉。

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

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

免费获取报价 →
↑