1. 项目概述与核心定位litellm 这个项目简单来说就是一个统一的大模型调用中间层。它的核心价值在于你不需要为每个模型厂商单独写一套 SDK 调用代码而是通过 litellm 这一层抽象用同一套接口去调用不同厂商的模型服务。OpenAI、Anthropic、Cohere、HuggingFace、Ollama、Azure OpenAI 等等全部可以用一个统一的completion()函数搞定。我第一次接触 litellm 是在一个多模型对比测试的需求里。当时项目要求同时对接三家不同厂商的 API每家的请求格式、认证方式、返回结构都不一样。如果按传统做法我得写三套客户端封装维护三份重试逻辑、三份错误处理、三份流式解析。光是想想就头大。后来发现了 litellm整个对接工作量直接压缩了七成以上。这个项目适合什么人用我总结下来主要是三类第一类是做模型评测和对比的开发者需要快速切换不同模型跑同一批测试用例第二类是构建 AI 应用的后端工程师希望在自己的服务里灵活替换底层模型而不改业务代码第三类是做 AI 网关或代理服务的团队需要在多个模型供应商之间做路由、降级和成本控制。litellm 解决的核心问题就是碎片化。大模型生态现在处于一个百花齐放的阶段每家都有自己的 API 规范这对开发者来说既是好事也是负担。好事在于选择多负担在于适配成本高。litellm 的思路就是做一层薄薄的适配层把差异屏蔽掉让你用统一的 OpenAI 格式去调用一切。注意litellm 的定位是“翻译层”而不是“抽象层”。它不会试图重新定义一套全新的接口规范而是选择 OpenAI 的接口格式作为事实标准把其他厂商的接口映射过来。这个设计决策非常务实因为 OpenAI 的接口格式目前是业界最通用的。2. 核心架构与设计思路拆解2.1 为什么选择 OpenAI 格式作为统一接口这个问题的答案其实很直接生态惯性。OpenAI 的 Chat Completions 接口格式已经被大量工具链、框架和开发者所接受成为了事实上的行业标准。litellm 如果自己发明一套新格式那它就失去了“低迁移成本”这个最大的优势。从技术角度看OpenAI 的接口设计确实比较合理messages 数组结构清晰role 区分明确function calling 和 tool use 的格式也足够灵活。其他厂商的接口虽然各有特色但核心概念是相通的——都是把一组消息传给模型然后拿到一个回复。litellm 做的事情就是在这层共性上做映射。我实测下来litellm 对 OpenAI 格式的兼容度做得相当彻底。你甚至可以直接把原来调 OpenAI 的代码里的openai.ChatCompletion.create()换成litellm.completion()然后在 model 参数里加上厂商前缀其他代码一行不用改。这个迁移成本几乎为零。2.2 适配器模式的具体实现litellm 内部为每个支持的厂商都写了一个适配器。每个适配器负责三件事请求格式转换、认证信息注入、响应格式归一化。请求格式转换是最复杂的部分。比如 Anthropic 的接口要求 system 消息单独放在一个字段里而不是像 OpenAI 那样放在 messages 数组里。litellm 的适配器会自动帮你做这个拆分。再比如 Cohere 的接口对消息角色的命名和 OpenAI 不完全一样适配器也会做映射。认证信息注入这块litellm 支持从环境变量读取 API Key也支持在调用时显式传入。环境变量的命名规则是厂商名_API_KEY比如ANTHROPIC_API_KEY、COHERE_API_KEY。这个设计很符合十二要素应用的原则配置和代码分离。响应格式归一化则是把各家不同的返回结构统一成 OpenAI 的格式。你拿到的 response 对象里choices[0].message.content永远是你的模型输出文本不管底层调的是哪家。这个一致性对上层业务代码来说太重要了。2.3 支持的模型范围与更新节奏litellm 支持的模型列表相当长而且更新很勤快。我观察下来基本上主流厂商发布新模型后一两周内litellm 就会跟进支持。这个更新速度对于一个开源项目来说相当难得。目前覆盖的主要厂商包括OpenAI 全系列、Anthropic 的 Claude 系列、Google 的 Gemini 系列、Cohere 的 Command 系列、Mistral 系列、Meta 的 Llama 系列通过 Together AI、Replicate 等平台、以及本地部署方案如 Ollama 和 vLLM。实操心得如果你用的模型 litellm 还没官方支持可以看看它是否兼容 OpenAI 接口格式。很多新兴的推理平台都提供了 OpenAI 兼容接口这种情况下你可以直接用openai/前缀加上自定义的api_base来调用不需要等官方适配。3. 快速上手与核心功能实操3.1 安装与基础配置安装很简单一条命令pip install litellm如果你需要用到某些特定厂商的功能可以安装带 extras 的版本pip install litellm[proxy]这个 proxy 模式后面会详细讲是 litellm 一个非常有价值的功能。配置 API Key 有两种方式。第一种是环境变量推荐在生产环境用这种export OPENAI_API_KEYyour-key-here export ANTHROPIC_API_KEYyour-key-here第二种是在代码里传适合快速测试import litellm response litellm.completion( modelgpt-4o, messages[{role: user, content: 你好}], api_keyyour-key-here )我个人建议在开发阶段用环境变量因为这样代码更干净而且不容易把密钥误提交到代码仓库。如果团队协作可以用.env文件配合python-dotenv来管理。3.2 统一调用不同模型的代码示例这是 litellm 最核心的用法。假设你要对比三个模型对同一个问题的回答import litellm messages [{role: user, content: 用一句话解释什么是递归}] models [ gpt-4o, claude-3-5-sonnet-20241022, gemini/gemini-1.5-pro, ] for model in models: response litellm.completion( modelmodel, messagesmessages, temperature0.7, max_tokens200, ) print(f模型: {model}) print(f回答: {response.choices[0].message.content}) print(- * 50)你看除了 model 参数不同其他代码完全一样。这就是 litellm 的价值所在。如果不用 litellm你得为每个模型写不同的调用代码处理不同的返回格式工作量至少翻三倍。3.3 流式输出的统一处理流式输出是现在 AI 应用的标配功能。litellm 对流式的支持也很到位import litellm response litellm.completion( modelclaude-3-5-sonnet-20241022, messages[{role: user, content: 写一首关于秋天的短诗}], streamTrue, ) for chunk in response: content chunk.choices[0].delta.content if content: print(content, end, flushTrue)不管底层是 OpenAI 还是 Anthropic你拿到的 chunk 结构都是一样的。chunk.choices[0].delta.content这个路径永远有效。这个一致性省去了大量条件判断代码。注意事项流式模式下不同厂商对 chunk 的切分粒度可能不同。有些厂商按 token 切有些按字符切。如果你需要精确控制输出节奏可能需要在应用层做缓冲。另外流式模式下错误处理要格外小心因为连接可能在传输过程中断开。3.4 函数调用与结构化输出litellm 对 function calling 的支持也是统一的。你按照 OpenAI 的格式定义 toolslitellm 会自动转换成目标厂商支持的格式import litellm tools [ { type: function, function: { name: get_weather, description: 获取指定城市的天气, parameters: { type: object, properties: { city: {type: string, description: 城市名称} }, required: [city] } } } ] response litellm.completion( modelgpt-4o, messages[{role: user, content: 北京今天天气怎么样}], toolstools, tool_choiceauto, ) tool_calls response.choices[0].message.tool_calls if tool_calls: for call in tool_calls: print(f函数名: {call.function.name}) print(f参数: {call.function.arguments})这里有个细节值得注意不是所有厂商都支持 function calling。如果你调用的模型不支持litellm 会抛出明确的错误提示而不是静默失败。这个设计很友好方便你快速定位问题。4. 代理模式与生产环境部署4.1 为什么需要代理模式litellm 的 proxy 模式是我认为这个项目最有价值的功能之一。它把 litellm 从一个 Python 库变成了一个独立的 HTTP 服务对外暴露 OpenAI 兼容的接口。这个模式解决了一个很实际的问题多语言团队协作。如果你的团队里有 Python、Node.js、Go 多种技术栈不可能要求每个人都装 litellm 的 Python 包。但如果你部署一个 litellm proxy所有人用 HTTP 请求就能调用所有模型语言无关。另一个场景是密钥管理。在代理模式下API Key 只存在服务器端客户端不需要接触任何密钥。这对安全合规要求高的场景非常重要。4.2 代理服务的启动与配置启动一个基础的代理服务litellm --model gpt-4o --port 8000但实际生产中你肯定需要更复杂的配置。litellm 支持用 YAML 配置文件来定义模型列表、路由策略、限流规则等model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: claude-sonnet litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: os.environ/ANTHROPIC_API_KEY general_settings: master_key: sk-your-master-key database_url: postgresql://user:passlocalhost:5432/litellm然后用这个配置文件启动litellm --config config.yaml --port 8000启动后你就可以用任何 OpenAI 客户端来调用了from openai import OpenAI client OpenAI( base_urlhttp://localhost:8000, api_keysk-your-master-key ) response client.chat.completions.create( modelclaude-sonnet, messages[{role: user, content: 你好}] )注意这里的 model 参数填的是你在 YAML 里定义的model_name而不是实际的模型 ID。这层映射让你可以在不改客户端代码的情况下后端灵活切换实际模型。4.3 负载均衡与降级策略litellm proxy 支持在多个同能力模型之间做负载均衡。比如你有两个 OpenAI 的 Key可以这样配置model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY_1 - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY_2两个条目用同一个model_namelitellm 会自动在它们之间轮询。如果其中一个 Key 触发限流请求会自动切到另一个。降级策略的配置也很实用。你可以定义一个 fallback 列表当主模型调用失败时自动尝试备用模型litellm_settings: fallbacks: [{gpt-4o: [claude-sonnet, gemini-pro]}]这个配置的意思是当 gpt-4o 调用失败时依次尝试 claude-sonnet 和 gemini-pro。对于生产环境来说这个功能能显著提升服务的可用性。实操心得降级策略要谨慎使用。不同模型的输出风格和能力差异可能很大如果业务对输出一致性要求高降级可能导致用户体验不一致。建议只在非关键路径上开启自动降级关键路径上宁可报错也不要静默切换。4.4 成本追踪与预算控制litellm 内置了成本计算功能。每次调用后它会根据模型的定价和 token 用量算出这次调用的花费。在代理模式下这些数据可以写入数据库方便你做成本分析。你还可以设置预算上限litellm_settings: max_budget: 100 budget_duration: 30d这个配置表示每个 API Key 在 30 天内最多花费 100 美元超出后请求会被拒绝。对于给多个团队或客户分配额度的场景这个功能非常实用。5. 常见问题与排查技巧实录5.1 模型名称写错导致的报错这是新手最常遇到的问题。litellm 的模型命名有固定规则厂商前缀 斜杠 模型 ID。比如anthropic/claude-3-5-sonnet-20241022、gemini/gemini-1.5-pro。如果你只写claude-3-5-sonnetlitellm 可能无法识别厂商导致认证失败。排查方法很简单先确认模型名称是否在 litellm 的支持列表里。可以查官方文档的 providers 页面或者直接在代码里打印litellm.model_list看看。5.2 环境变量未生效有时候你明明设置了环境变量但 litellm 还是报认证错误。常见原因有三个第一环境变量是在 Python 进程启动后才设置的进程内读不到第二变量名拼写错误比如把ANTHROPIC_API_KEY写成了ANTHROPIC_KEY第三用了.env文件但没调load_dotenv()。我的习惯是在代码最开头加一段自检import os import litellm required_keys [OPENAI_API_KEY, ANTHROPIC_API_KEY] for key in required_keys: if not os.environ.get(key): print(f警告: {key} 未设置)这样能在启动阶段就发现问题而不是等到第一次调用时才报错。5.3 流式输出中断的处理流式输出中断是个比较棘手的问题。可能的原因包括网络抖动、厂商服务端超时、token 超限被截断。litellm 在流式模式下会抛出异常你需要用 try-except 包裹import litellm try: response litellm.completion( modelgpt-4o, messages[{role: user, content: 写一篇长文}], streamTrue, timeout30, ) for chunk in response: content chunk.choices[0].delta.content if content: print(content, end, flushTrue) except litellm.exceptions.Timeout as e: print(f\n请求超时: {e}) except litellm.exceptions.APIError as e: print(f\nAPI 错误: {e})设置合理的 timeout 很重要。对于长文本生成timeout 设太短会导致频繁中断设太长又会让用户等太久。我的经验是短回复设 15 秒长文生成设 60 秒流式模式下可以适当放宽。5.4 常见问题速查表问题现象可能原因解决方法认证失败 401API Key 未设置或错误检查环境变量名和值模型不存在 404模型名称拼写错误核对 litellm 支持的模型列表请求超时网络问题或模型响应慢增加 timeout检查网络连通性返回格式异常厂商接口变更升级 litellm 到最新版本流式中断网络抖动或 token 超限加重试逻辑检查 max_tokens成本计算不准定价数据未更新升级 litellm 或手动配置定价5.5 版本升级的注意事项litellm 更新很频繁升级时偶尔会有 breaking change。我的建议是生产环境锁定版本号不要用pip install --upgrade直接升到最新。先在测试环境验证新版本确认没问题再更新生产。另外litellm 的某些功能依赖特定的厂商 SDK 版本。如果你同时装了多个厂商的 SDK可能会出现版本冲突。这种情况下用虚拟环境隔离是最稳妥的方案。6. 进阶用法与扩展思路6.1 自定义模型接入litellm 支持通过 OpenAI 兼容接口接入自定义模型。如果你自己部署了一个推理服务只要它暴露了 OpenAI 兼容的/v1/chat/completions接口就可以这样接入import litellm response litellm.completion( modelopenai/my-custom-model, messages[{role: user, content: 你好}], api_basehttp://localhost:8080/v1, api_keydummy-key, )这个能力非常实用。现在很多推理框架都提供了 OpenAI 兼容接口用这种方式你可以把自部署模型和云端模型统一管理。6.2 回调与可观测性litellm 支持回调机制可以在每次调用前后执行自定义逻辑。常见的用途包括记录日志、上报监控指标、写入审计表。import litellm from litellm.integrations.custom_logger import CustomLogger class MyLogger(CustomLogger): def log_success_event(self, kwargs, response_obj, start_time, end_time): print(f调用成功耗时: {(end_time - start_time).total_seconds():.2f}秒) print(f模型: {kwargs.get(model)}) print(fToken 用量: {response_obj.usage.total_tokens}) def log_failure_event(self, kwargs, response_obj, start_time, end_time): print(f调用失败: {kwargs.get(exception)}) litellm.callbacks [MyLogger()]这个机制对于生产环境的可观测性建设很有帮助。你可以把数据推到自己的监控系统做调用量、延迟、错误率的实时看板。6.3 缓存策略减少重复调用litellm 内置了缓存支持可以把相同请求的响应缓存起来避免重复调用浪费成本import litellm litellm.cache litellm.Cache( typeredis, hostlocalhost, port6379, ) response litellm.completion( modelgpt-4o, messages[{role: user, content: 什么是机器学习}], cachingTrue, )缓存对开发调试特别有用。你在调 prompt 的时候相同的输入会直接命中缓存响应速度极快而且不消耗 token 额度。生产环境里对于 FAQ 类的高频重复问题缓存也能显著降低成本。注意事项缓存要设置合理的过期时间。模型输出可能随版本更新而变化如果缓存时间太长用户可能拿到过时的回答。我的经验是开发环境设 1 小时生产环境设 5 到 15 分钟。6.4 与 LangChain 等框架的配合litellm 可以无缝集成到 LangChain 生态里。LangChain 提供了ChatLiteLLM类让你在 LangChain 的链式调用中使用 litellm 的统一接口from langchain_community.chat_models import ChatLiteLLM from langchain_core.messages import HumanMessage chat ChatLiteLLM(modelclaude-3-5-sonnet-20241022) response chat.invoke([HumanMessage(content你好)]) print(response.content)这样一来你既享受了 LangChain 的编排能力又获得了 litellm 的多模型统一调用能力。两个工具的组合使用在构建复杂 AI 应用时效率很高。7. 实际项目中的经验总结7.1 什么时候该用 litellm什么时候不该用litellm 不是银弹。如果你的项目只用一个模型而且短期内没有切换计划那直接用官方 SDK 可能更简单。litellm 的价值在于多模型场景单模型场景下它反而增加了一层不必要的抽象。另一个不适合的场景是对延迟极度敏感的应用。litellm 的适配层会带来少量额外开销虽然通常可以忽略不计但在毫秒级敏感的场景下这层开销可能成为瓶颈。7.2 生产环境的配置建议我在生产环境用 litellm 踩过几次坑总结下来几条经验第一一定要设超时默认超时可能很长导致请求堆积第二一定要配重试网络抖动是常态litellm 支持配置重试次数和退避策略第三一定要监控成本多模型调用很容易在不知不觉中花超预算第四日志要脱敏请求和响应里可能包含敏感信息写入日志前要过滤。7.3 关于版本选择litellm 的版本迭代很快新功能多但偶尔有回归问题。我的建议是生产环境用稳定版不要追最新。具体来说选择发布超过两周、没有严重 issue 的版本。升级前在测试环境跑一遍核心用例确认没问题再上生产。这个项目后续还可以这样扩展结合自己的业务场景在 litellm 的适配层之上再封装一层业务逻辑比如 prompt 模板管理、输出格式校验、多轮对话状态维护等。litellm 负责模型调用的统一你的业务层负责业务逻辑的统一两层各司其职架构会很清晰。
阅读完成 · 觉得有帮助?