
1. 项目概述与核心定位1.1 这个项目到底解决什么问题第一次接触 litellm 是在一个多模型混用的项目里。当时团队同时接入了好几家不同厂商的大模型服务每家的接口格式、鉴权方式、返回结构都不一样代码里到处是 if-else 分支维护起来非常头疼。litellm 这个项目就是冲着这个痛点来的——它提供了一层统一的调用接口让你用同一套代码去访问不同厂商的模型服务。说白了它就是一个大模型调用的中间层。你不需要为每个厂商单独写适配代码只需要按照 litellm 的规范传入模型名称和参数它会自动帮你路由到对应的服务商并把返回结果统一成 OpenAI 兼容的格式。这个设计思路在工程上非常实用尤其是在需要快速切换模型、做 A/B 对比测试、或者搭建多模型 fallback 机制的场景下。适合谁来参考这个项目我认为三类人最需要一是正在做 AI 应用开发但被多厂商适配搞得焦头烂额的工程师二是想快速对比不同模型效果的产品或算法同学三是需要搭建统一模型网关的运维和平台开发人员。不管你用的是 Python 还是 Node.jslitellm 都有对应的 SDK 支持。1.2 核心能力一览litellm 的能力可以归纳为几个层面。最基础的是统一调用接口它支持上百种模型的接入包括主流的商业模型服务和本地部署的开源模型。你只需要把模型名称写成厂商/模型名的格式剩下的交给它处理。第二个层面是成本追踪与预算控制。它内置了各厂商的计费规则每次调用后会自动计算消耗的 token 数和对应费用还能设置预算上限超出后自动拦截。这个功能在做成本敏感型项目时特别有用。第三个层面是可靠性保障。它支持 fallback 机制当主模型调用失败时自动切换到备用模型支持重试策略可以配置重试次数和退避算法还支持负载均衡在多个 API Key 之间轮询分发请求。第四个层面是可观测性。它提供了回调机制可以把每次调用的日志、耗时、token 消耗等信息推送到你指定的监控系统方便做链路追踪和性能分析。2. 架构设计与选型考量2.1 为什么选择代理层而非直接集成很多人会问为什么不直接在业务代码里调用各家 SDK而要加一层代理这个问题我在项目初期也纠结过。直接调用的好处是链路短、延迟低、没有额外依赖。但当你的项目需要接入超过三个模型服务时直接调用的维护成本会急剧上升。我做过一个粗略统计每接入一个新厂商平均需要写 200 到 300 行适配代码包括请求构造、鉴权处理、响应解析、错误映射、重试逻辑。如果再加上流式输出的处理代码量还要翻倍。而用 litellm 之后接入新厂商的工作量缩减到改一行配置。另一个关键考量是统一错误处理。不同厂商的错误码体系完全不同有的用 HTTP 状态码有的在响应体里返回错误信息有的甚至用自定义的 header 传递错误。litellm 把这些统一映射成标准的异常类型业务层只需要捕获一种异常就够了。注意代理层会引入额外的网络跳转如果你的场景对延迟极其敏感比如实时对话建议把 litellm 部署在和业务服务同一台机器或同一个内网环境把网络开销降到最低。2.2 核心模块拆解litellm 的代码结构比较清晰主要分为几个核心模块。Router 模块负责请求路由和负载均衡它维护了一个模型列表和对应的 API Key 池根据配置的策略选择目标服务。Provider 模块是各厂商的适配器集合每个厂商一个文件实现了统一的接口规范。Cost 模块负责计费计算内置了各模型的单价表。Callback 模块处理回调事件支持同步和异步两种模式。这种模块化设计的好处是扩展性强。如果你想接入一个 litellm 尚未支持的厂商只需要按照 Provider 的接口规范写一个适配器文件然后在配置里注册即可不需要改动其他模块的代码。2.3 部署模式选择litellm 支持两种部署模式SDK 模式和代理服务模式。SDK 模式是把 litellm 作为 Python 库直接集成到你的项目里适合 Python 技术栈的项目。代理服务模式是单独启动一个 HTTP 服务业务代码通过 HTTP 请求调用适合多语言技术栈或需要集中管理的场景。我个人的建议是如果你的项目是纯 Python 的且模型调用逻辑不复杂直接用 SDK 模式最省事。如果你需要给多个团队或多个语言的项目提供统一的模型调用入口那就用代理服务模式。代理服务模式还支持配置文件和数据库两种配置方式前者适合小规模固定配置后者适合动态调整的场景。3. 实操部署与核心配置3.1 环境准备与安装先说一下基础环境要求。litellm 对 Python 版本的要求是 3.8 以上推荐用 3.10 或 3.11这两个版本在性能和兼容性上比较平衡。安装方式很简单pip install litellm如果你需要用到代理服务模式还需要额外安装pip install litellm[proxy]安装完成后建议先跑一个最小验证脚本确认基础功能正常from litellm import completion response completion( modelopenai/gpt-4o, messages[{role: user, content: 你好}] ) print(response.choices[0].message.content)这段代码里model参数的格式是厂商/模型名litellm 会根据前缀自动识别厂商并路由。API Key 通过环境变量传入比如 OpenAI 的 Key 就设置OPENAI_API_KEY。3.2 代理服务的配置文件详解代理服务模式的核心是配置文件。我以一个典型的多模型配置为例逐项说明关键参数model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY rpm: 100 - model_name: claude-sonnet litellm_params: model: anthropic/claude-sonnet-4-20250514 api_key: os.environ/ANTHROPIC_API_KEY rpm: 50 router_settings: routing_strategy: usage-based-routing num_retries: 3 timeout: 30 fallbacks: - gpt-4o: - claude-sonnet general_settings: master_key: sk-your-master-key database_url: os.environ/DATABASE_URL这里有几个关键点值得展开说。rpm参数控制的是每分钟请求数限制这个值要根据你实际购买的配额来设置设太高会被厂商限流设太低又浪费配额。routing_strategy我推荐用usage-based-routing它会根据各 Key 的剩余配额动态分配请求比简单的轮询更合理。fallbacks配置的是降级链路。上面这个例子的意思是当 gpt-4o 调用失败时自动切换到 claude-sonnet 重试。这个机制在实际生产环境里非常有用我遇到过好几次某厂商突发故障的情况全靠 fallback 保证了服务不中断。提示master_key是代理服务的管理密钥所有通过代理的请求都需要在 header 里带上这个 key。生产环境一定要用强密码并且定期轮换。3.3 启动与验证配置文件准备好之后启动命令如下litellm --config config.yaml --port 4000 --num_workers 4num_workers控制工作进程数建议设置为 CPU 核心数的 1 到 2 倍。启动后可以用 curl 验证curl http://localhost:4000/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-your-master-key \ -d { model: gpt-4o, messages: [{role: user, content: 测试}] }如果返回正常的 JSON 响应说明服务已经跑起来了。这里注意model字段填的是配置文件里的model_name不是litellm_params.model这两个容易搞混。4. 高级功能与实战技巧4.1 流式输出的正确处理流式输出是大模型应用的常见需求litellm 对这块的支持比较完善。SDK 模式下只需要加一个参数response completion( modelopenai/gpt-4o, messages[{role: user, content: 写一首诗}], streamTrue ) for chunk in response: content chunk.choices[0].delta.content if content: print(content, end, flushTrue)代理服务模式下流式输出遵循 SSE 协议前端用 EventSource 接收即可。这里有个坑要注意不同厂商的流式返回格式在细节上有差异比如有的厂商会在最后一个 chunk 里带上 usage 信息有的不会。litellm 做了统一处理但如果你需要精确的 token 统计建议在流式结束后再发一个非流式的轻量请求来获取 usage。4.2 成本追踪与预算告警成本追踪是 litellm 的亮点功能。开启方式是在配置里加上litellm_settings: success_callback: [langfuse] failure_callback: [langfuse]回调系统会把每次调用的详细信息推送出去包括模型名、输入输出 token 数、耗时、费用等。你可以对接自己的监控平台也可以直接用 litellm 内置的预算控制general_settings: max_budget: 100 budget_duration: 30d这个配置的意思是30 天内总预算 100 美元超出后所有请求会被拒绝。对于给多个团队分配额度的场景还可以按 Key 设置独立预算。4.3 自定义 Provider 接入虽然 litellm 已经支持了绝大多数主流厂商但总有遇到小众服务或自部署模型的时候。这时候就需要自定义 Provider。核心是实现一个继承自CustomLLM的类from litellm import CustomLLM, completion, ModelResponse import requests class MyCustomLLM(CustomLLM): def completion(self, model, messages, **kwargs): # 构造请求发给你的服务 resp requests.post( http://your-service/v1/chat, json{messages: messages} ) data resp.json() return ModelResponse( choices[{ message: {content: data[reply]}, index: 0 }] ) import litellm litellm.custom_provider_map [ {provider: my-llm, custom_handler: MyCustomLLM()} ]注册之后就可以用my-llm/模型名来调用了。这个机制在对接内部自研模型服务时特别方便。5. 常见问题与排查实录5.1 典型报错与解决方案在实际使用中我整理了几个高频问题做成速查表方便对照报错信息根本原因解决方案AuthenticationErrorAPI Key 无效或未设置检查环境变量名是否正确注意大小写RateLimitError超出厂商配额降低 rpm 配置或增加 Key 池ContextWindowExceeded输入超出模型上下文限制做消息截断或换用长上下文模型Timeout网络延迟或厂商响应慢调大 timeout检查网络链路InvalidModelError模型名格式错误确认是厂商/模型名格式5.2 性能调优经验代理服务的性能瓶颈通常出现在两个地方一是网络 IO二是日志写入。网络 IO 方面建议开启连接池复用配置如下litellm_settings: request_timeout: 30 num_retries: 2 allowed_fails: 3allowed_fails控制的是某个 Key 连续失败多少次后被暂时剔除这个值设太小会导致频繁切换设太大又会让故障 Key 继续拖累整体成功率。我实测下来 3 次是个比较平衡的值。日志写入方面如果开启了数据库存储建议用异步写入模式避免阻塞主请求链路。另外数据库要定期清理历史记录否则表会越来越大查询性能会明显下降。5.3 踩过的坑说几个我实际踩过的坑。第一个是环境变量加载顺序问题。litellm 在启动时读取环境变量如果你用 systemd 管理服务要注意EnvironmentFile的加载时机我遇到过配置文件里写了 Key 但服务读不到的情况排查了半天才发现是加载顺序问题。第二个是流式输出的超时设置。流式请求的总耗时可能很长但 litellm 的 timeout 参数默认是单次请求的超时对流式场景要单独设置stream_timeout否则长回答会被中途掐断。第三个是多实例部署时的 Key 竞争。如果你部署了多个 litellm 实例共享同一批 API Key需要引入外部存储来做配额同步否则各实例独立计数会导致实际用量超出配额。litellm 支持 Redis 作为共享存储配置redis_host和redis_port即可。6. 扩展思路与个人体会litellm 的扩展性是我比较欣赏的一点。除了基础的模型调用它还可以作为模型评测平台的底层支撑通过统一接口批量跑测试集对比不同模型的表现。也可以作为成本优化工具通过分析各模型的调用数据找出性价比最高的组合方案。我个人在实际项目中的体会是litellm 最大的价值不在于它支持多少模型而在于它把多模型管理的复杂度收敛到了一个配置文件和一套接口里。以前切换模型要改代码、重新测试、重新部署现在改一行配置重启服务就行。这个效率提升在快速迭代的阶段非常明显。最后分享一个小技巧如果你不确定某个模型是否被 litellm 支持可以直接查它的model_prices_and_context_window.json文件里面列出了所有支持的模型及其上下文长度和计费信息。这个文件在 GitHub 仓库的根目录下比翻文档快得多。