资讯详情

用litellm搭建LLM统一网关:路由、密钥与成本控制实战

📅 2026/10/13 13:49:26 | 华诺云谱 👁 阅读
用litellm搭建LLM统一网关:路由、密钥与成本控制实战
先交代一下背景我们团队维护的AI应用已经接入了五六个不同厂商的大模型从闭源旗舰到开源自主部署都有。一开始还能靠每个厂商的SDK挨个对接但等业务开始并发增长要处理不同格式的请求体、不同的鉴权方式、不同的超时行为光维护这套对接代码就让人头大。后来我在项目里引入了litellm一个轻量级的LLM API网关把整个调用层收敛成了统一入口逐步把原来散落在各处的模型调用SDK替换掉情况才真正好转起来。这篇文章就把这个工具的核心思路、实操路径和踩坑过程完整讲一遍给同样被多模型调用折磨的人一个可以直接参考的落地方案。先说清楚一件事litellm不是一个 SDK它是个网关。它本身也提供 Python SDK但这个 SDK 不是直接调模型的而是调你自己部署的那个网关服务。真正的模型请求由这个网关去转发到实际的大模型厂商。这个架构上的差别很重要因为它决定了你能在“网关”这个位置上做很多原来 SDK 做不到的事统一鉴权、流量控制、模型路由、成本追踪、日志审计全都可以在一个集中的节点上完成而不是分散在每个调用方进程里。读这篇文章适合谁如果你手里有多个模型需要同时接入或者团队里不同服务各自用不同厂商的 SDK导致模型密钥散落各处又或者你想在模型调用入口做灰度、限流和预算管控那litellm这套思路值得你花时间看完。1. 认清痛点多模型调用为什么总会变成一团乱麻1.1 场景还原项目里的模型调用是怎么失控的先还原一个非常典型的场景。某公司的AI应用一开始只用一家平台的模型一切都很简单引一个官方SDK填好密钥直接调。后来发现单模型在中文长文本生成上不够稳于是接入了第二家。没过多久因为成本原因又引入了一个开源自部署模型。到这一步问题就开始显形了每个厂商的接口签名完全不同。A家的是client.chat.completions.create这种写法B家的是model.messages.create这种风格C家自部署的最后干脆走原生HTTP。于是你不得不写一层又一层的适配代码。遇上模型升级、参数变更或者某家端点临时崩了你的业务代码就得跟着改。更要命的是鉴权方式还不一样。有的厂商支持长期密钥有的项目要求带上额外Header有的网关还要先换临时token。这些信息散布在环境变量、配置文件、部署平台的Secret管理里谁改过、改成了什么时间一长根本说不清。1.2 踩过坑之后我才意识到问题不在于“换SDK”而在于“缺一个集中入口”一开始我们的想法是做一个自定义的封装层用适配器模式把这些SDK统一起来。但做了几周后发现这条路很重每次有新厂商接入都要写适配器要处理流式响应的一致性还要兼容不同厂商对错误码、超时、限流的定义差异。说白了你是在重造一个不完整的轮子。后来转向litellm才想明白一件事与其在每个调用方都塞进一套复杂的适配逻辑不如把所有模型调用收敛成“请求到网关网关转发到真实模型端点”的模式。调用方根本不需要知道模型背后的厂商是谁只需要按 OpenAI 风格接口发请求。网关替你完成协议翻译、密钥管理、路由选择、重试降级。整个模型的接入成本从“每个服务都要改代码”降成了“改一个配置文件约等于完成接入”。1.3 网关模式的关键收益可观测性和可治理性网关模式带来的最大好处不是“少写几行代码”而是可观测性和可治理性。可观测性意味着所有模型调用的日志、Token用量、耗时、失败率都可以在网关这一层统一采集。以前要排查一次“为什么某个请求特别慢”得翻遍调用链路上所有服务的日志。现在网关记录了完整的请求元数据哪个模型、哪个用户、用了多少Token、从哪个IP来的一目了然。可治理性意味着你能在网关层做成本控制。给不同业务线设定不同的Token预算超出就拒绝服务或者降级到便宜模型。这不是事后看账单而是在请求入口实时执行策略。这种能力在做B端项目时几乎是刚需。2. 核心能力拆解路由、密钥、限流与成本控制的实现逻辑2.1 路由与负载均衡请求到底该发给谁规则怎么定路由是litellm最核心的能力之一。它支持把同一个逻辑模型名映射到多个真实模型端点再通过策略分发请求。举个例子你可以定义一个逻辑模型名main-llm背后指向两个不同的云端模型端点。默认情况下请求轮流分发或者按权重分发。权重路由的价值在于灰度你想让新模型承担20%流量就让新旧模型权重比设为 20:80观察一段时间没有明显回退再把权重逐步调成 50:50、80:20最终完成切换。整个过程不需要业务方感知任何变化。路由规则还可以按用户维度来写。比如A组用户永远走稳定性最好的旧模型B组用户走候选新模型。这在做模型效果AB实验时特别顺手——你不用改业务代码只在网关配置里调整分组映射就行。2.2 密钥安全与隔离别再把密钥散落在每个服务里在传统模式下每个服务的环境变量里都放着一个或多个模型厂商的密钥。只要有一个服务日志泄露或者一个仓库的配置文件被误提交密钥就直接暴露了。用litellm做网关之后真实厂商的密钥只存在于网关配置中业务服务只需要拿到一个网关派发的虚拟密钥。这个虚拟密钥可以在管理界面自主创建、吊销、设置过期时间。每一个虚拟密钥可以绑定固定的模型范围、路由规则、预算上限。某个业务线要下线了撤销对应虚拟密钥即可不影响其他业务线。我在项目里见过的最低效做法是把生产密钥和一个临时调试密钥共用一个凭证调试接口日志一旦被错误收集出去生产环境也跟着裸奔。网关的密钥隔离机制可以彻底杜绝这种情况调试密钥只能访问测试模型生产密钥绑定生产模型路由权限边界从一开始就划分清楚。2.3 限流与成本控制让每一分预算都花得明明白白成本控制是很多团队选择自建网关的根本原因。到了月底才看账单已经是过去式了你需要在请求发生时就知道这个请求花多少钱。litellm内置了Token计数和成本计算能力。每个请求结束后网关会统计输入Token、输出Token并根据当前模型的价格系数换算出本次请求成本。这些数据可以持久化存储也可以实时查询。你能够随时看到哪个业务线消耗了多少Token哪个模型整体花费最高每用户平均调用成本是多少。更硬核的是预算限制。你可以给某个虚拟密钥设置“最大累计消费上限”。达到上限之后网关直接拒绝后续请求并返回对应的配额错误信息。这在给外部合作伙伴开API账号时尤其关键——你既给对方能力又不会让对方无节制烧钱。2.4 多租户场景一个网关支撑多条产品线的模型诉求如果你的团队内部同时有好几个产品线每个产品线对模型的需求差异很大那网关天然就是个多租户架构。每个产品线用自己的虚拟密钥配置自己的预算和限流参数甚至可以对不同产品线启用不同的模型白名单。这里面还有一个容易被忽视的细节模型白名单。网关可以控制某个虚拟密钥只能访问哪些逻辑模型名。比如内部工具链只能调用便宜的小模型对外核心产品才能调用旗舰大模型。没有这层控制任何拿到密钥的人都可以调用任何模型你的成本结构很快就会失控。3. 从零到一本地跑通一个可用的 litellm 网关3.1 环境准备与安装litellm基于 Python安装非常简单前提是本机有 Python 3.8 以上环境推荐 3.10 或更高版本。pip install litellm[proxy]这里安装的是带代理服务的完整包装除了核心SDK之外还会拉起一个内置的 FastAPI 服务。如果你只是想在代码里用litellm.completion()这种函数式调用装litellm就行但既然要跑网关建议直接装带proxy的这个版本。安装完成后可以先看版本信息litellm --version如果输出了版本号说明装好了。接下来需要准备一个 YAML 格式的配置文件这是整个网关的核心。注意安装过程中如果遇到依赖编译报错通常是因为本机缺少编译工具链。建议优先用 Python 3.10 以上版本配合虚拟环境安装能避开大部分坑。3.2 最小配置一个 config.yaml 搞定模型接入配置文件是网关的“大脑”。下面这个配置是我自己项目里最常用的最小可用版本逻辑模型名统一了后端的多个真实端点。model_list: - model_name: main-llm litellm_params: model: A厂商模型标识 api_key: os.environ/A_PROVIDER_API_KEY - model_name: main-llm litellm_params: model: B厂商模型标识 api_key: os.environ/B_PROVIDER_API_KEY解释几个关键点model_name是逻辑名称业务方只用这个名字发起请求网关内部根据路由策略决定映射到哪个真实模型。model字段是实际要请求的后端模型标识。litellm内部维护了大量厂商的模型映射表你不需要手写完整的请求URL。api_key推荐用os.environ/变量名这种形式从环境变量读取真实密钥不要把明文密钥直接写进 YAML 文件更不要提交到代码仓库。如果有多个模型需要接入就继续往model_list里追加条目一个逻辑名对应多个真实端点就多写几条相同model_name的配置项。启动网关只需要一条命令litellm --config config.yaml --port 4000默认情况下服务会监听在 4000 端口。启动日志中会打印/health健康检查路径和/chat/completions的调用路径。看到这两条就说明网关已经起来了。3.3 用 OpenAI 风格 SDK 打第一个请求litellm对外提供的是 OpenAI 风格的接口格式但这不代表你必须用 OpenAI 官方的 SDK。任何兼容该接口规范的客户端都可以直接连上来。以下是一个最简单的 curl 请求curl http://localhost:4000/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-虚拟密钥 \ -d { model: main-llm, messages: [{role: user, content: 你好请用一句话自我介绍}], temperature: 0.7 }响应结构也是 OpenAI 风格包含choices、usage、model等标准字段。业务端几乎不用做任何额外适配甚至可以把网关地址填进原本配置 OpenAI SDK 的地方只是把 base_url 指向本地网关即可。如果你是在 Python 里调用更常见的写法是这样from openai import OpenAI client OpenAI( base_urlhttp://localhost:4000/v1, api_keysk-虚拟密钥 ) resp client.chat.completions.create( modelmain-llm, messages[{role: user, content: Hello}], streamTrue ) for chunk in resp: if chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end)注意这里的base_url指向本地网关地址api_key填的是网关的虚拟密钥而不是后端模型的真实密钥。业务代码里完全感知不到真实模型的存在。3.4 部署层面要注意的几个细节本地验证通过后真正上线部署时还有几个细节值得提前规划第一个是服务进程管理。litellm不建议直接裸跑在终端里生产环境要配合进程守护工具比如用 systemd 或容器平台托管保证进程崩溃后能自动拉起。第二个是持久化存储。默认情况下网关的日志和用量数据是存在内存里的服务重启数据就丢了。生产环境需要配置一个后端存储像 PostgreSQL 或 Redis把 Token 用量、请求日志、预算数据持久化。第三个是TLS证书。如果网关要暴露给公司内网之外的调用方务必在网关前面加一层TLS终止要么用平台的负载均衡能力要么在容器平台里配置证书。4. 进阶配置实战路由、重试、降级与预算控制4.1 一次多模型灰度发布的完整配置样本下面是一份稍微复杂一些的配置覆盖了权重路由、重试、超时、预算限制这几个常见的进阶能力。我把注释直接写在 YAML 里方便你对照理解。model_list: - model_name: main-llm litellm_params: model: A厂商稳定版模型 api_key: os.environ/A_API_KEY max_tokens: 2048 model_info: mode: completion - model_name: main-llm litellm_params: model: B厂商候选新版模型 api_key: os.environ/B_API_KEY max_tokens: 2048 model_info: mode: completion router_settings: routing_strategy: simple-shuffle enable_pre_call_check: true allowed_fails: 3 num_retries: 2 request_timeout: 30 cooldown_time: 60 retry_after: 10 general_settings: master_key: sk-网关管理员密钥 database_url: postgresql://用户名:密码数据库地址/litellm这段配置里有几个值得注意的设计routing_strategy: simple-shuffle表示默认情况下请求在多个端点间轮转。如果不设置权重同一逻辑模型名对应的两个真实端点会近似平均分摊流量。这个策略适合先让候选新版模型“试跑”观察稳定性。allowed_fails: 3和cooldown_time: 60是一组熔断参数。当某个端点连续失败达到3次网关会把它临时移出路由池60秒后自动放回避免反复把请求打到已经故障的端点上。实测这个配置在云端模型偶发抖动时特别好用请求自动降级到健康端点业务侧几乎无感。enable_pre_call_check: true表示在调用前先检查配置和密钥有效性如果模型未配置或者密钥无效直接返回错误而不发起真实的网络请求。这个开关能帮你把配置错误和模型错误快速区分开。4.2 更精细的路由规则按请求属性分流默认的简单轮转粒度太粗不适合所有场景。litellm支持更细粒度的路由规则比如按用户标记、按请求元数据、按自定义参数来分发请求。我常用的一种做法是按用户维度分流。举个例子业务方每次请求时带一个user标识网关根据这个标识决定把请求路由到哪个模型router_settings: routing_strategy: usage-based-routing model_group_alias: main-llm: routes: - model: A厂商稳定版模型 condition: user_group: internal-stable - model: B厂商候选新版模型 condition: user_group: beta-users当然上面是一个简化的写法具体条件字段要根据网关版本来调整。这个思路的核心是把灰度策略从业务代码下沉到网关配置。做AB实验时不用再发布新版本只要在网关里调整用户分组的映射关系就能控制不同用户看到不同模型的效果。AB实验跑完只需要把条件删掉、把权重切换完成就相当于全量切换到了新模型。根据我的经验这种配置方式最大的价值是降低了灰度门槛。以前模型切换要压测、要发版、要回滚预案走完整套流程至少一个发布周期。现在通过网关配置调整权重和条件改完配置热加载几分钟内就能看到效果。4.3 预算控制给密钥戴上紧箍咒litellm的预算控制可以细化到“虚拟密钥”级别。也就是说你可以给一个密钥设置每日最大消费上限每月最大消费上限单次请求最大 Token 数每分钟最大请求数。配置方式通常有两种一种是在管理界面上创建密钥时设置另一种是在配置文件中预置初始预算。实测下来对内部研发工具设置月度预算很有效。研发环境里同事跑自动化测试调模型成本不再是一个月底才知道的数字而是在密钥层面实时收敛。预算超限之后网关返回的是一类明确标识的量配额错误。业务代码捕获到这个错误后可以做优雅降级比如切换到本地缓存结果或者提示用户当前服务临时不可用而不是把后端模型的费用无脑刷下去。4.4 流式响应的注意事项如果你的场景大量使用流式响应这里有一个必须关注的细节不同模型厂商的流式格式不完全是字节级一致的。有些厂商会在流式响应里附带额外的元数据字段有些厂商对空delta的处理方式也不一样。litellm在网关层做了统一转换转发给业务方的是 OpenAI 风格的流式事件格式。这避免了你为每个后端模型单独处理流式边界。但要注意接口的兼容不代表语义的兼容如果某个厂商的流式响应里usage字段只在最后一条事件中出现而另一个厂商每条事件都带上你的业务逻辑必须按最稳妥的方式处理——不依赖每条事件里的usage只在流结束时统计汇总。这个坑我们在实际项目里踩过早期某业务端依赖每次流式事件里的usage字段做进度展示接入第二个厂商后发现字段频率不对进度条直接卡住。后来把统计逻辑改成在流结束事件里统一处理问题才彻底解决。5. 常见问题与排障实录5.1 高频错误对照速查表这里整理一份我在使用过程中遇到的高频错误对照表基本覆盖了从配置错误到网络类问题的常见情况。错误现象可能原因排查思路 / 解决方式启动报错缺少模型配置配置文件中model_list为空或格式不正确检查 YAML 缩进确认每个litellm_params下至少有model字段请求返回鉴权失败网关虚拟密钥错误或未配置master_key在管理界面生成新密钥确认请求头里的Authorization带了正确的 Bearer 令牌请求返回模型不存在业务端使用了未定义的逻辑模型名检查配置中model_name是否与请求中的model字段完全一致所有请求都超时后端厂商端点不稳定或网络不通先直接调用真实模型端点确认可用再检查网关日志看卡在哪个环节Token 用量没有记录未配置数据库持久化配置general_settings.database_url重启后重新发起测试请求并查询用量某个端点连续失败但流量还在发往它熔断参数未生效或版本过旧确认allowed_fails和cooldown_time配置正确更新到最新版本请求被拒绝并返回预算错误虚拟密钥的预算已超限在密钥管理页面调整预算上限检查哪个业务线消耗过大5.2 排查问题的通用方法论网关类系统排障有一个基本原则先确认链路三段各自的健康状态。客户端到网关一段网关到后端模型一段两者要分开看。第一步是检查网关自身的日志。启动日志里会打印每个请求的转发情况包括目标模型、响应耗时、失败原因。如果日志里显示转发到后端模型成功但客户端没收到响应问题多半出在客户端与网关之间的网络或协议不匹配上。第二步是直接绕过网关测试后端模型端点。用命令行工具直连真实模型接口确认模型侧没有异常。如果直连正常而经过网关后异常再回头查网关配置重点看超时时间、重试策略、模型标识是否正确。第三步是关注网关版本。这个项目迭代速度极快早期版本中一些配置字段的命名会和当前版本有差异。如果你参考的是半年前的教程请先对照当前版本的官方配置说明否则很容易出现“字段写了对但读不到”的情况。5.3 我踩过的几个值得分享的坑第一个坑是密钥管理方式。早期我把某个厂商的真实密钥直接写在 YAML 配置文件里配置文件还放在项目仓库中。某次代码仓库权限配置不当密钥差点被外部访问到。从那以后我坚持两层密钥配置文件里只写环境变量引用真实变量统一放入部署平台的Secret管理服务中。网关层面的虚拟密钥再往下分发。这样就算仓库泄露攻击者拿到的也只是网关地址信息没有真实密钥。第二个坑是流式请求和重试策略的组合问题。默认情况下litellm对失败请求会重试但流式请求一旦已经开始返回内容重试就没有意义了——你已经把部分流内容推给了客户端再重试会造成内容重叠。需要根据业务场景判断如果对实时性要求高宁可让请求直接失败也不要盲目重试。后来我把流式接口的重试次数调低而不是统一采用默认配置。第三个坑是配置文件热加载的认知偏差。以前我以为改了配置必须重启网关才能生效。实际上litellm支持配置热加载但热加载的生效范围有限部分路由和预算参数在运行时才能完全重新计算。我的建议是本地改了配置后直接重启网关保持环境干净生产环境用管理界面做模型和密钥的动态调整避免频繁改文件。5.4 日志和监控怎么搭才最实用网关接入了之后日志监控一定不能省。我通常的做法是三件套一是网关自身的运行日志确认启动、请求转发、错误捕获是否正常。二是请求日志的持久化记录每次请求的时间、模型、Token数、耗时、错误码。这些数据是后续做成本分析和链路排查的基础。三是针对关键指标设置告警比如每分钟请求量超过阈值、失败率超过5%、某虚拟密钥消费超过预算的80%。触发告警后能提前发现异常而不是等用户反馈才知道出了问题。这三层不是防火墙式堆叠而是互相印证的关系。运行日志告诉你网关活着请求日志告诉你业务跑得怎么样告警告诉你哪天需要介入处理。写在最后的几点实际体会从我自己的使用体验来看litellm最有价值的地方并不是“少写适配代码”这个表面收益而是它把模型接入这件事从“开发任务”变成了“运维配置任务”。新增一个模型供应商不需要安排一次发版改一下配置文件请求就能跑通。这对于模型迭代频繁的团队来说节省的时间和沟通成本是非常可观的。另外一个体会是网关对你的团队组织方式也有潜在影响。因为密钥、预算、模型路由都集中了运维或平台团队可以获得一个统一的管控面业务开发团队则只需要认领自己那部分虚拟密钥。权限边界清晰之后出问题找责任人也快了成本异常定位也快了。如果你正在犹豫要不要引入网关我的建议是从一个最小场景开始不要一上来就想覆盖全部模型。先选一个主力模型走通全链路跑一两周把日志存储、预算统计、监控告警都配齐再逐步增加新模型。回头你会庆幸自己是在模型还没扩展到失控之前就把这条统一入口的路铺好了。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑