做AI应用最烦的一件事是什么不是模型效果不行而是模型太多了。今天要聊的litellm就是专门解决这件事的——一个开源的大模型统一调用网关。简单说你在代码里写一套接口就能无缝切换主流厂商的模型、本地部署的开源模型甚至还能替你管密钥、做负载均衡、设预算、看用量。这篇文章我会从为什么需要它、核心功能怎么拆解、到实际部署怎么配一步步讲清楚最后再分享几个生产环境里容易踩的坑。1. 为什么会出现litellm大模型时代的第一道基础工程1.1 被模型API碎片化支配的日常先聊一个真实的工作场景。某天你在一家小团队做AI应用早上用A厂商的模型写了个原型跑通之后领导说换B厂商的模型试试效果。你打开代码发现要改的东西远不止“换一个模型名”这么简单请求格式可能不一样鉴权方式不一样流式返回的解析方式不一样甚至连参数名都不同。A那边叫max_tokensB那边叫max_tokenC那边叫max_tokens_to_sample。改完A的代码还得重新写B的解析逻辑。如果在同一个应用里同时接几个模型代码会变得非常痛苦。每个模型一套SDK、一套错误码、一套限流逻辑最后你写的不再是业务代码而是一堆模型适配器。更麻烦的是各家的调用计费方式还不一样有的按token、有的按请求数客户问你这个月AI花了多少钱你算半天才算明白。litellm解决的就是这个碎片化问题。它把各家模型API的差异处理收敛到一个统一格式里。你在代码里只打交道一个接口传model参数时写“厂商名/模型名”剩下的转换、鉴权、重试、计费统计都交给它。1.2 它到底是个什么角色我的理解是litellm做的事有点像“支付网关”之于各种支付渠道前端商家不需要关心你用的是支付宝、微信还是银行卡后端统一走一套接口平台帮你把各种渠道的差异消化掉。它有两种典型用法。第一种是当成SDK/库pip安装后直接在Python代码里调用适合单个项目、脚本、Notebook里的快速实验。第二种是当成独立代理服务Proxy Server跑起来对外提供一个兼容OpenAI格式的HTTP接口所有应用都能通过这个网关统一访问模型。第二种才是企业落地最关心的形态因为密钥、用量、预算、监控都集中在这层了。一句话总结如果你在项目里已经感觉“换一家模型要改好多地方”或者“团队里很多人都在各自用各自的API Key成本乱成一锅粥”那litellm大概率对你有帮助。2. 核心功能拆解一个网关到底能做多少事2.1 统一调用格式从100个SDK变成1个先看肉眼最直观的部分。不经litellm时你要分别维护多个供应商的SDK用了litellm后代码里的请求是这个样子的from litellm import completion response completion( modelprovider-a/gpt-4o, messages[ {role: system, content: 你是一个资深的Python工程师。}, {role: user, content: 用三句话解释什么是闭包。} ], temperature0.7, )model参数里的斜杠前面是供应商前缀后面是模型名。这个前缀要写对litellm才知道该走哪家供应商的鉴权和接口。比如你本地起了个Ollama模型就写“ollama/llama3.1:8b”用的是某云上的托管模型服务就写对应的前缀。那段代码的返回结构也是统一好的一个带choices、usage等字段的CompletionResponse对象。你不需要分别处理不同家返回的结构差异。更换模型有多容易改model参数里那个字符串就够了。# 换一个模型改一行 response completion( modelprovider-b/gemini-1.5-pro, # 换这里 messages[...] )底层的prompt格式有没有被自动改写举个例子某个模型走的是对话历史格式另一个模型走的是消息列表格式这类差异litellm会自动完成转换。你不用去背每个厂商的消息格式差异这是直接省时间的地方。提示斜杠前缀不能漏。有个常见错误就是只写了“gpt-4o”没写前缀结果litellm默认按某个约定处理绕了一圈才反应过来。官方推荐的做法是写全“厂商/模型名”。2.2 自动完成请求格式的输入输出转换这里值得多聊几句因为很多靠“调接口”混日子的朋友根本没意识到各家API的格式差异有多大。同样是“多轮对话”有的接口是messages数组有的要把历史记录拆成单独的字段同样是“让模型输出JSON”有的在请求里用response_format有的用结构化输出有的干脆要靠prompt约束。litellm内部维护了一套与各厂商模型对应的转换参数配置。你传一个标准的统一参数集它会拆分成对应服务商需要的样子返回时又把各家的原始格式归一化成统一结构。这套转换的细节非常多比如流式输出stream模式下各家吐出来的chunk格式五花八门litellm会统一翻译成OpenAI风格的chunk结构。这样你做流式输出时上游应用不用改动下面随便换模型。在这个层面上litellm很像一个“翻译层”前面对着你的业务代码说统一语言后面对着各家模型API说它们各自的语言。所谓兼容性不是说让各厂商API长得一样而是有一个中间人帮你做翻译。2.3 网关模式的杀手锏多Key管理、预算、限流与观测SDK模式适合单点使用但真正让团队协作和上线部署顺畅的是代理网关模式。你只需要在某台服务器上启动一个litellm服务把真实验证信息配置好然后让团队所有人访问这一个地址。这样做的直接收益有四个。第一密钥安全。业务代码里不再需要硬编码真实密钥。开发同学只需要知道网关地址和自己的虚拟Key就能正常访问模型。第二预算可控。给每个开发、每个应用、每个部门设置独立的预算上限和速率限制超了就自动拒绝请求月底再也不会收到爆炸的账单。第三统一观测。在网关这一层能看到每一次请求谁发的、用的哪个模型、输出了多少token、响应耗时多久、是否重试、是否失败。不用再到每家后台去翻报表。第四高可用。同一个模型可以配多个上游渠道或多个真实Key网关自动做负载均衡某个渠道挂了自动重试或降级到备用模型对业务方透明。2.4 成本、用量与模型表现的可观测性线上跑了几个月后你会发现成本、用量、模型效果这三角关系是团队最常问的问题。“上个月那个新人的Key干了什么”“现在按用户来看人均token消耗是多少”“模型A的失败率为什么比模型B高”这些在litellm里都能直接查到。它可以记录每一次请求的用量明细并且提供按Key、按用户、按模型聚合的统计视图。配合后端数据库比如PostgreSQL存储日志数据不会丢随时可以做分析。对中小团队来说这就是一个轻量级的LLM运维后台不用再自己拼一个统计系统。3. 实操过程从零搭出一个可用的模型网关3.1 安装与初始化环境先准备环境。建议用Python 3.9以上版本建一个虚拟环境避免依赖冲突。python -m venv llm-gateway source llm-gateway/bin/activate pip install litellm装完先做个冒烟测试确认SDK能跑通。如果没有真实密钥可以用Ollama本地模型试ollama pull llama3.1:8b然后写个简单脚本from litellm import completion response completion( modelollama/llama3.1:8b, messages[{role: user, content: 用一句话介绍你自己}], api_basehttp://localhost:11434 ) print(response[choices][0][message][content])这里显式传了api_base是因为本地Ollama服务地址和默认值不一致。这个细节在生产里很常见有些供应商的兼容接口不是默认地址你必须在请求或配置里指对它。3.2 用config.yaml配置多供应商信息跑通单次调用后就该配一个正式的代理服务了。litellm的代理服务支持多种配置方式我习惯用config.yaml来管理因为它可以一个文件描述清楚所有模型、密钥和策略而且能放进版本控制。先建一个config.yaml内容类似这样model_list: - model_name: my-gpt-4o litellm_params: model: provider-a/gpt-4o api_key: os.environ/PROVIDER_A_API_KEY rpm: 100 - model_name: my-claude litellm_params: model: provider-b/claude-sonnet api_key: os.environ/PROVIDER_B_API_KEY rpm: 50 - model_name: my-local-llama litellm_params: model: ollama/llama3.1:8b api_base: http://localhost:11434 litellm_settings: drop_params: true set_verbose: false general_settings: database_url: os.environ/DATABASE_URLmodel_name是暴露给上层应用的“别名”litellm_params则是这个别名背后的真实模型和参数。为什么要设计别名因为上层业务不应该关心你到底用的哪个具体模型。某天你把某个应用从A模型切到B模型只需改config.yaml里的映射业务代码一行不动。这就是“模型路由”的核心思路。3.3 启动代理服务并接入应用启动服务litellm --config ./config.yaml --port 4000看到日志里出现类似“Uvicorn running on http://0.0.0.0:4000”的信息说明网关起来了。接下来在任意语言里用OpenAI兼容SDK接入。因为litellm对外暴露的接口就是OpenAI的接口风格所以你可以直接用openai SDKfrom openai import OpenAI client OpenAI( api_keysk-随便填一个虚拟key, base_urlhttp://你的服务器地址:4000 ) completion client.chat.completions.create( modelmy-gpt-4o, messages[{role: user, content: 你好请介绍下你自己}] ) print(completion.choices[0].message.content)注意model传的是config里的别名my-gpt-4o。如果你想让业务团队只使用某些别名就在这里做收口。3.4 为什么第一次接入要用这种“配置别名”的方式很多新手一开始跳过config.yaml直接命令行启动“litellm --model gpt-4o”这样做确实能跑但只适合本地试验。生产中一定要用配置原因有几点只有通过config才能同时管理多个供应商的密钥才能把每个模型的限流参数、备用渠道写清楚才能让上层应用不用改代码就切换模型才能让网关实例的配置是声明式、可审计、可回滚的。这个习惯跟写基础设施代码要“用配置而不是命令”是一个道理。命令改起来一时爽后头维护火葬场。4. 进阶玩法路由策略、降级方案与成本管控4.1 把多个真实密钥组合成一个逻辑模型用同一个上游模型但配多个真实密钥是很常见的需求。这样做能突破单个账号的速率限制也能在某个账号出问题时自动换到另一个。config里可以这样写model_list: - model_name: scalable-gpt-4o litellm_params: model: provider-a/gpt-4o api_key: os.environ/PROVIDER_A_KEY_1 - model_name: scalable-gpt-4o litellm_params: model: provider-a/gpt-4o api_key: os.environ/PROVIDER_A_KEY_2两个条目用了同一个model_name“scalable-gpt-4o”litellm会在它们之间做负载均衡。默认策略是带权重的轮询后续你可以结合各Key的稳定性、速率限制设置更智能的权重。4.2 设置失败次数冷却与自动重试网关的意义不只是“翻译”还要有容错能力。比如你的优选模型突然报错你希望请求自动降级到备用模型。可以在config中加fallbacksmodel_list: - model_name: main-model litellm_params: model: provider-a/gpt-4o api_key: os.environ/KEY_A - model_name: backup-model litellm_params: model: provider-b/claude-sonnet api_key: os.environ/KEY_B litellm_settings: fallbacks: [{main-model: [backup-model]}] num_retries: 3 request_timeout: 30 allowed_fails: 3 cooldown_time: 60这几个参数解释一下。num_retries是同一个上游失败后的重试次数allowed_fails是某个上游连续失败多少次后会进入冷却状态cooldown_time是冷却时长冷却期间新请求会直接走备用。这些参数要在“业务可用性”和“请求延迟”之间做平衡。重试太多会让用户等很久冷却太快又会让模型切换过于频繁。建议先按“3次重试3次失败触发冷却60秒冷却”起步观察线上指标后再调。4.3 虚拟Key与预算控制代理服务启动后默认情况下所有人共用你配置的上游密钥。但做团队协作时你更希望每个成员或每个应用有一个独立的虚拟Key这样能单独统计和限流。先用管理接口生成虚拟Keycurl --location http://localhost:4000/key/generate \ --header Authorization: Bearer sk-1234 \ --header Content-Type: application/json \ --data { budget: 10, max_parallel_requests: 5, tpm_limit: 100000, metadata: {team: algorithm, app: demo} }这里budget字段是该Key最多能花的美元金额实际单位以你的配置为准max_parallel_requests限制并发请求数tpm_limit限制每分钟token吞吐量。生成的Key要发给对应成员并要求他们在代码中用这个虚拟Key。真正的上游密钥永不下发到业务端。4.4 团队场景按人和按应用核算成本之前有次分享有人问“预算控制会不会很粗暴误伤正常业务”这个问题问得好。所以litellm敢做这件事前提是它能按粒度统计。它支持“用户”维度——你在调用时可以通过user字段传入业务里真实用户的ID或应用名后续在网关日志里就能按这个维度看消费情况。比如你的业务里有A、B两个应用你希望在同一个网关下分别统计它们各花了多少钱只需在请求里带上不同的user标识然后查询时按该字段分组。这套能力对中大型团队特别实用不再需要让“ChatGPT小组”和“搜索增强小组”分别去开户、分别去报销统一走一个平台月底看报表时直接按维度切分。4.5 成本追踪的底层逻辑为什么网关能算清账核心在于它在转发前后都会记录usage字段。不管你是直接SDK调用还是走代理它都会把该请求的prompt_tokens和completion_tokens取出来再结合该模型对应的单价换算成成本并落库。下面这句是配置里的说明units的计算依旧按模型单价字段来。你可以在请求列表里看到每一次调用的token明细这就省去了“对着各厂商后台Excel手算”的噩梦。5. 常见问题与排查经验实战里最容易坑人的那些事5.1 请求报错AuthenticationError最常见的是认证错误。排查看几点真实密钥是否写入环境变量并在服务器重启后正确加载config.yaml里是否用了os.environ/XXX的写法而不是把密钥明文写进去宿主机环境变量是否导出成功代理服务有没有使用你预期的那份配置文件。有次一个小伙伴把密钥写在代码里调试没问题一上config就报认证失败。查了半天发现是环境变量文件加载顺序问题——服务先启动了环境变量还没注入。务必先确认环境变量已加载再启动litellm。提示千万不要把真实密钥提交到Git仓库。用os.environ方式加载并在gitignore里忽略对应的.env文件这是最基本的底线。5.2 模型名报Not Found / BadRequest这通常是“别名不存在”或“上游模型名写错”。“modelmy-gpt-4o”但config里根本没有定义这个别名立即报错“modelprovider-a/gpt-4o”但真实服务商那边没这个版本号也会报错。排查方法是先用一个最小请求逐层拆解先测真实上游是否能调用再测通过网关是否能调用最后测业务侧配置。一层层定位而不是对着整个链路猜。5.3 流式响应时中断或乱码走代理做流式输出时如果发现内容中断、报错常见原因是超时配置过短或网络中间层有缓冲。将请求超时适当调大确认没有引入会缓冲完整响应后再转发的组件如某些默认开启动态缓冲的网关。有一点要强调litellm本身会以流式方式转发上游的chunk但如果你外面再包了另一层代理那层代理可能会把流式响应缓冲成整体导致前端体验变差。排查时优先绕开无关中间层。5.4 限流429与并发优化上游限流是常态。一上来就疯狂并发基本都会撞429。先检查config里的rpm/tpm是否贴近上游能承受的量级再检查是否用了多个真实Key做负载均衡最后看是否启动了重试和冷却。并发连接还有一个容易忽略的地方——连接池大小。如果你用Python的请求库通过网关调模型默认连接池比较小高峰期TCP连接会被占满表现为大量超时或连接被重置。可以在客户端侧调大连接池上限或者在litellm侧调大并发worker数。具体的连接池参数不是万能的要结合你机器CPU与内存逐步加压测。5.5 日志里看不到请求记录很多人配置了代理服务也用了数据库但在查询页面里看不到任何日志。原因大部分是数据库连接没生效或者数据库表迁移没跑。启动时会自动建表但如果DBA权限不够就建不了。确认database_url配置正确确认具备对应库的写权限确认服务启动日志中没有连接失败的警告。日志数据是后续做成本分析的基础尽早确认链路是值得的。6. 部署到服务器上的几个忠告6.1 服务编排与Docker部署代理服务本身是无状态的迁移、扩容都容易。但如果你挂了数据库存储日志数据库就是有状态依赖。生产上最简单的做法是用Docker容器跑服务用托管数据库存日志。docker run一下docker run -d \ --name litellm-proxy \ -p 4000:4000 \ -v $(pwd)/config.yaml:/app/config.yaml \ -e DATABASE_URLpostgres://user:passhost:5432/llm_logs \ ghcr.io/berriai/litellm:main-latest \ --config /app/config.yaml这一步里你只需要传环境变量进去config挂在容器里服务自然起在4000端口。如果团队用编排平台也可以把同样的启动参数写进工作负载定义里。记得把4000端口的健康检查路径配置好比如用“/health/liveliness”做存活探针。6.2 安全加固网关本身的访问控制网关是对外提供模型能力的入口绝不能裸奔。至少要做三件事一是给管理端接口单独设置授权不能用默认那个主Key长期跑生产二是对请求开启速率限制防止内部某个失控任务拖垮整层三是把网关放在内网或边缘层前面的鉴权交给统一的网关层处理。如果是暴露在公网必须配HTTPS和正确的跨域策略同时限制管理端接口只对运维网段开放。6.3 维护习惯配置先行、日志掌舵我个人的习惯是每加一个新上游模型先改config再针对它跑一轮前台自测最后确认日志里有记录。更新模型版本时也是这么一套。上线后多观察“失败率”“平均TTFT首字延迟”“token吞吐量”这几个指标任何一个指标出现明显恶化都该检查是上游问题、配置问题还是业务请求问题。7. 使用门槛与适用边界的个人体感litellm的门槛真的不高。至少会装Python包、会写几行配置就能把个人项目的多模型调用统一起来。但它的上限很高路由策略、预算体系、观测平台、多环境隔离每一点深入下去都可以做很多工程改造。我的建议是如果你只是写个小Demo不需要上代理模式SDK就够一旦你的项目要上线、有多个人接入、有成本统计需求请尽早走到代理模式别等服务上线再补补的时候一定会痛。还要多说一句别被“支持100多家供应商”吓到你不需要一次配齐那么多。大多数人实际用的就是那么两三家litellm只是把“以后想换”的灵活性留给了你。核心思路是哪怕今天只用一家也建议通过这个统一入口去调因为明天的事谁说得准呢。最后一个使用上的小技巧做模型切换时使用别名方式model_name而不是真实模型名这样未来切模型只改配置不改代码。这个操作听起来不起眼但在真正的生产迭代里能帮你减少一大半的返工成本。
阅读完成 · 觉得有帮助?