做 AI 应用的人多半都有过这种经历上个月刚把项目从 OpenAI 切到 Anthropic这个月又来了个 Gemini 的优惠老板还说“顺手也把国产模型接上”。每家的 SDK 用法都不一样请求体结构不同模型名规则不同返回字段也不同等你挨个适配完光调用层的胶水代码就能写小一千行。我后来在项目里全面用 LiteLLM 来做这件事才算是把这摊子事彻底理顺了。这篇文章就把我的上手过程、配置细节和踩坑记录完整分享出来希望能帮你少走弯路。LiteLLM 是一个开源的 Python 库兼轻量级代理服务核心功能是提供一套统一的大模型调用接口屏蔽各家 LLM API 的格式差异。它对外暴露 OpenAI 兼容的请求格式底层再自动转换成 OpenAI、Anthropic、Gemini、Azure OpenAI 等不同服务商实际需要的格式。适合做 AI 应用后端、RAG 系统、Agent 框架、内部模型网关的人参考也适合刚接触多模型接入、被各厂 SDK 折腾到想骂人的朋友。1. LiteLLM 到底解决了一个什么真实痛点1.1 不同厂商的 API 格式地狱先看一个很典型的对比。OpenAI 的聊天补全接口请求结构长这个样子{ model: gpt-4o, messages: [ {role: user, content: 你好} ] }Anthropic 的 Messages API字段就完全不一样了模型名要写版本号系统提示要单独放内容结构是数组而不是简单的字符串{ model: claude-3-5-sonnet-20240620, system: 你是一个助手, messages: [ {role: user, content: [{type: text, text: 你好}]} ] }Google Gemini 那边又是另一套逻辑它的消息结构是contents和parts角色和内容拆得更细。这种差异不是说“稍微改改字段名就行”那么简单。消息结构、角色枚举、参数命名比如温度 OpenAI 叫temperature部分服务商叫top_p配套参数、鉴权方式、错误返回结构全部不一样。你要在业务代码里同时维护三套调用逻辑每加一个模型就要重写一次客户端适配。1.2 换模型的时候业务代码跟着大手术我最开始做的一个模拟项目里所有 Agent 逻辑都直接散落调用着 OpenAI SDK。后来要切入 Claude 做复杂推理问题立刻暴露了chat/completions调用散落在十几个文件里参数名、消息结构、异常处理全部按 OpenAI 写死。改一个模型等于把所有文件翻一遍。用 LiteLLM 之后业务层只需要认model字符串和messages结构。今天配置文件里写的是openai/gpt-4o明天改成anthropic/claude-3-5-sonnet业务代码一行不用动。模型切换从“修改多处业务代码”变成“改配置”这个动作。1.3 更深一层的价值多模型共用一个网关入口个人项目用 LiteLLM 可能体验还不深真正体会到它威力是在做团队内部模型网关的时候。后端要给前端、给不同业务线提供模型能力如果每个人各自拿厂商的 API Key密钥管理会失控费用统计也做不准。用它的代理模式统一收口所有请求走同一个网关谁调了哪个模型、花了多少 token、消耗了多少预算全部可查。这里说一句我很认同的设计理念LiteLLM 不是去“消灭”各家 API 的差异而是把这些差异收拢到一个统一层里处理。业务代码永远只面对一套接口差异留给网关解决。2. 从零接入先跑通 Python SDK 再说2.1 安装和全局环境变量配置安装非常简单一个 pip 命令pip install litellm[proxy]我把 proxy 组件一起装上了因为后面必然要起代理服务。如果只用 Python SDK不需要代理装pip install litellm就够了。环境变量建议放在项目根目录的.env文件里LiteLLM 会自动读取OPENAI_API_KEYsk-xxxxxx ANTHROPIC_API_KEYsk-ant-xxxxxx GEMINI_API_KEYAIza-xxxxxx注意一个细节环境变量的前缀要和model字符串里的 provider 前缀对应。LiteLLM 的模型名规范是提供商前缀/模型名比如openai/gpt-4o、anthropic/claude-3-5-sonnet、gemini/gemini-1.5-pro。它会根据前缀自动找对应的环境变量。提示如果你在代码里直接传api_key参数它会覆盖环境变量。但实际项目里要小心不要把密钥写死在业务代码里尤其是提交到 Git 仓库的情况基本等于裸奔。2.2 第一段能跑通的调用代码安装好之后最简调用几乎和 OpenAI SDK 长得一样from litellm import completion response completion( modelopenai/gpt-4o, messages[ {role: user, content: 你好介绍一下你自己} ] ) print(response.choices[0].message.content)这段代码和直接调 OpenAI SDK 的区别只是把from openai import OpenAI换成了from litellm import completion。但如果把model换成anthropic/claude-3-5-sonnet同样这段代码就能跑 Anthropic 的模型业务层完全无感。如果想换 Gemini那就改成response completion( modelgemini/gemini-1.5-pro, messages[{role: user, content: 用一句话解释什么是缓存}] )这种“一个函数统一所有模型”的体验用惯之后是真的回不去。不是说你从此不需要了解底层各家 API 的特性了而是普通业务代码完全没必要背这些包袝。2.3 流式输出和异步场景做对话类应用流式输出几乎是标配。LiteLLM 的流式用法也接近 OpenAIfrom litellm import completion response completion( modelopenai/gpt-4o, messages[{role: user, content: 写一段关于分布式系统的比喻}], streamTrue ) for chunk in response: if chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end)异步场景用acompletion和同步调用参数一致。我自己的经验是FastAPI 里处理流式响应时要注意返回类型是StreamingResponse需要把异步生成器接上去不要直接在异步函数里同步遍历流式 chunk。LiteLLM 官方文档里有完整示例照着抄就行。2.4 Token 计数与成本预估completion()函数的返回值里有一个usage字段里面是 prompt tokens、completion tokens、total tokens。LiteLLM 还内置了成本换算可以用litellm.completion_cost()根据模型实际单价估算单次调用成本from litellm import completion_cost cost completion_cost(completion_responseresponse) print(f本次调用花费: ${cost:.4f})这个功能在代理模式下更好用每一次请求的花费都会被记录月底不用再人工去各个平台拉账单对账。后面会详细讲。3. 代理模式LiteLLM 的核心价值所在3.1 为什么我最终选择代理模式Python SDK 模式适合自己本地测模型、写脚本跑批量任务。但一旦涉及团队协作、多个后端服务共用模型能力SDK 模式就有几个明显问题一是密钥分散每个人的本机环境变量都要配置一遍换一个人就要交接一次密钥。二是逻辑重复每个服务都要单独写 fallback、写重试、写日志。三是无法统一控制预算谁在调、花了多少完全不可见。代理模式等于将 LiteLLM 打包成一个独立服务你启动一个网关进程所有模型请求打到这个网关由它统一转发到各家厂商。各业务服务的调用方不需要配置任何厂商密钥只需要知道网关地址和一个虚拟密钥就可以了。这种模式在我做过的某跨平台系统中帮了很大的忙后端四个服务同时接模型原来每个服务都要接三套厂商 SDK接入代理后这套复杂度直接消失。3.2 最小化的 config.yaml 配置代理模式基于一个 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-20240620 api_key: os.environ/ANTHROPIC_API_KEY - model_name: gemini-1.5-pro litellm_params: model: gemini/gemini-1.5-pro api_key: os.environ/GEMINI_API_KEY然后启动litellm --config config.yaml --port 4000启动后LiteLLM 会在本机4000端口开一个服务同时还会在浏览器里给你一个管理后台地址一般是http://localhost:4000/ui。这个后台在后续密钥管理和预算管理里会很常用。模型名这里我单独说一下逻辑model_list中的model_name是给外部调用方“看”的名字litellm_params.model才是真正映射到厂商的模型名。也就是说你可以对外暴露一个比较友好的内部模型名比如gpt-4o只是业务代号后端想换成别的真实模型时改映射关系就好了调用方完全感知不到。3.3 用 curl 快速验证网关是否正常代理启动后先用最直接的方式验证curl http://localhost:4000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: gpt-4o, messages: [{role: user, content: 你好网关通了吗}] }返回的结构和 OpenAI 的原生响应几乎一致这其实是设计使然LiteLLM 的端点本身就是按 OpenAI 兼容格式暴露的。这里有个常见的坑model字段传的是model_list里的model_name值比如gpt-4o而不是openai/gpt-4o。如果你在代理模式里传了带前缀的完整模型名很可能会收到一个模型不存在的错误因为网关是按你配置的别名来路由的。4. 进阶玩法路由、降级、密钥与预算4.1 让多组 Key 自动负载均衡当某个模型调用的并发量大单把 Key 容易吃速率限制的时候可以在配置里给同一个模型配置多个 API Key让 LiteLLM 自动轮询model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY model_info: mode: completion - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY2 model_info: mode: completion它支持的路由策略包括simple-shuffle随机轮询和least-busy挑当前负载最低的通过routing_strategy配置。我自己用下来普通场景simple-shuffle够了高并发场景least-busy更稳。注意一个model_name出现多条配置在 UI 后台看起来是同一个模型但流量的分配是自动的。这一点对规模化接入特别有用团队内部出 Key 就可以做到“多 Key 轮询”不用自己写负载均衡逻辑。4.2 fallback主模型挂了自动切备用模型服务偶尔会不稳定5xx、超时、限流是常有的事。LiteLLM 支持在配置里写 fallback主模型失败后自动改调备用模型model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY model_info: mode: completion fallbacks: - model_name: gpt-4o fallback_models: [claude-3-5-sonnet]这个配置表达的意思是请求gpt-4o失败后自动把请求转发给claude-3-5-sonnet。用户在业务代码里完全无感。但这里我要提醒一个关键点fallback 只解决“可用性”不解决“一致性”。GPT 和 Claude 的输出风格、能力边界有差异用户感知上可能发现“明明选的 GPT突然变成另一个模型的语气”。所以在实际项目里我把 fallback 视为最后一道保险而不是常态策略并且会把 fallback 的日志单独标记出来方便追溯是哪一跳发生了切换。4.3 虚拟密钥与预算控制代理模式跑起来之后业务方不能直接拿厂商 Key 来调而是应该使用 LiteLLM 生成的虚拟密钥。生成方式有两种管理后台手动建或用命令行创建。管理后台的操作路径进入http://localhost:4000/ui在 API Keys 页面创建新 Key。生成的 Key 形如sk-Fake-Key-0001...只显示一次需要自己保存。给外部服务配置时就把这把虚拟 Key 当成 OpenAI 的 Key 来用。虚拟 Key 的好处是可控。你可以给不同服务、不同项目分别创建 Key然后再给每个 Key 设置预算上限litellm_settings: max_budget: 100在 UI 里也可以单独给某把 Key 设置“最大预算美元”。当这个 Key 的累计花费到了上限LiteLLM 会直接拒绝后续请求。这个能力对团队管理特别实用测试环境放个小预算防止同事调模型测试调出天价账单线上业务放个大预算配上告警。4.4 日志与花费统计钱的事情一定要看到数据才放心。LiteLLM 会把每次请求的模型名、tokens、花费记录到后台的 Spend Logs 页面。我这里给个基础思路按虚拟 Key 维度看可以知道哪个业务方消费最高按模型维度看可以分析每个模型的调用频率和成本占比按天维度看可以发现有没有异常的调用高峰如果是自托管官方建议把日志持久化到数据库中而不是只放在内存里。默认的 SQLite 配置适合小规模试用生产环境建议挂上 PostgreSQL 之类的数据库把 spend logs、key 信息统一存下来。5. 实践中的坑与我的排查思路5.1 模型名不带提供商前缀导致的神秘错误我刚开始部署时在 Python SDK 模式下调模型名随手写了gpt-4o没带前缀。LiteLLM 的默认行为是不带前缀的模型名会按 OpenAI 解析。有些模型如果 OpenAI 平台没有LiteLLM 自身也没收录对应的映射就直接抛Model not found。排查思路先确认模型名是否带了前缀例如想调 Claude 就必须写anthropic/claude-...想调 Gemini 就写gemini/gemini-...。如果不确定当前配置的模型名是否被支持可以用官方维护的模型列表比对或者干脆做一次最小调用测试把模型名打印出来看。5.2 异步环境下的请求挂起问题用过一段时间后我遇到一个现象在 FastAPI 的 async 接口里用标准同步completion()某些并发场景下请求会莫名其妙挂起很久。后来排查发现根源在于同步调用阻塞了事件循环。解决思路很简单在 async 函数里优先用acompletion()或者用asyncio.to_thread把同步调用丢到线程池去跑。这一点虽然不是 LiteLLM 本身的问题但引入统一网关后调用面变广了异步环境下的阻塞问题会更加明显。5.3 timeout 配置不合理导致雪崩LiteLLM 默认会有超时和重试机制。最初我没配timeout某次上游模型服务响应极慢所有请求都在等待导致网关服务的连接池被占满后面的请求全部排队看起来就像网关“挂了”。排查之后发现本质上就是两个配置没调好timeout给单次模型请求设置硬超时比如timeout60超过直接报错max_retries控制失败重试次数比如max_retries2这两个参数在 Python SDK 里可以直接传在代理模式里可以写进配置litellm_settings: timeout: 60 num_retries: 2我最后把这两个值调到了一个稳妥的范围超时 60 秒、最多重试 2 次。效果是上游抽风时业务方最多等 60 秒就会收到明确错误而不是无限挂起。5.4 代理模式下接 OpenAI SDK 的 base_url 问题很多业务代码里已经用了 OpenAI SDK不想改成 LiteLLM 的completion()。这个时候你可以把 OpenAI SDK 的base_url指到 LiteLLM 网关from openai import OpenAI client OpenAI( base_urlhttp://localhost:4000/v1, api_keysk-Fake-Key-0001 ) response client.chat.completions.create( modelgpt-4o, messages[{role: user, content: 你好}] )这个方案在迁移场景里非常香代码几乎不用动原来用 OpenAI SDK 的地方只需要把base_url换成网关地址api_key换成虚拟 Key。不过要留意不是所有历史代码都能直接兼容。如果你的业务之前用的是 OpenAI SDK 的底层openai直连接口有些新特性比如 Responses API在网关端不一定支持因为网关对外暴露的主路径是chat/completions兼容接口。5.5 流式模式下的预算统计偏差还有一个小细节在流式输出模式下LiteLLM 的 usage 信息其实分布在整个流式 chunk 流里如果调用方提前中断了请求也就是客户端主动断开网关可能无法完整统计到 tokens。我碰到过一次账单金额偏小的情况最后发现是客户端频繁中断流导致。要修正这个偏差建议在代理层开启按请求记录usage的配置并在业务端尽量让对话流程自然结束不要动不动就终止流式生成。这个问题不只在 LiteLLM 里有任何代理类服务都会遇到知道有这么回事就行。6. 一点个人使用体会和扩展方向从我经手的几个项目来看LiteLLM 最适合的场景是团队里有不止一个模型需求或者预期未来大概率要换模型。在一个“模型尚未确定”的早期阶段它给你的不只是方便而是避免后续重构的最优解。我现在的默认做法是哪怕只有一个模型在跑我也会先把 LiteLLM 搭好把调用层统一掉后面加模型只是加配置的问题。要说缺点它也真实存在多包了一层排查问题时链路会稍微变长需要同时看网关日志和上游厂商日志新模型发布后LiteLLM 的适配存在一定的滞后性如果你第一时间就要用某个新模型还是得去查版本更新说明确认是否支持。但这些问题比“每接一个模型就重写一遍代码”的成本小得多。最后再分享一个小技巧如果你想在本地快速体验代理模式但不想手动创建虚拟 Key可以直接在 config.yaml 里省略虚拟 Key 配置先用sk-1234之类的任意值顶替等确认请求链路通了再补上正式的 Key 权限控制。这能帮你把“接入”和“治理”两件事分开每一步的验证目标更清晰。