1. 项目概述与核心定位
litellm 这个项目,简单来说就是一个大模型调用的统一接口层。它的核心价值在于:你不需要为每个模型厂商写一套单独的调用代码,而是用一套 OpenAI 兼容的格式,去调用市面上几乎所有主流的大语言模型。不管是云端 API 还是本地部署的模型,litellm 都能帮你抹平差异。
我第一次接触这个项目是在一个多模型对比测试的场景里。当时团队需要同时对接好几家模型服务,每家的 SDK、鉴权方式、请求参数、返回格式都不一样,光是适配层就写了一堆重复代码。后来发现了 litellm,基本上把原来几百行的适配逻辑压缩到了几十行,而且切换模型只需要改一个字符串。
它解决的问题非常明确:模型调用的碎片化。你想想,今天用这家,明天换那家,后天又要加一个本地模型做兜底,如果没有统一层,每次都要重新读文档、改代码、调参数。litellm 把这些脏活累活都封装掉了,对外暴露的就是一个completion()函数。
适合谁来用?我觉得三类人最需要:一是做 AI 应用开发的工程师,尤其是需要多模型切换或对比的场景;二是做模型评测的研究人员,需要快速批量调用不同模型;三是个人开发者,想低成本试各种模型但不想折腾各家 SDK。
注意:litellm 本身不提供模型能力,它只是一个路由和适配层。你需要自己有各个模型的 API Key 或者本地推理服务的地址。
2. 核心架构与设计思路拆解
2.1 为什么需要统一接口层
在没有 litellm 这类工具之前,调用不同模型的代码大概是这样的:OpenAI 用openai.ChatCompletion.create(),Anthropic 用anthropic.messages.create(),本地模型可能又是另一套 HTTP 请求。每个厂商的参数命名还不一样,比如有的叫max_tokens,有的叫max_output_tokens,有的叫max_new_tokens。
这种碎片化带来的问题不只是代码量大,更麻烦的是维护成本。厂商 API 一升级,你就得跟着改。多个模型混用时,错误处理、重试逻辑、超时控制都要分别写。
litellm 的设计思路是:以 OpenAI 的接口格式为基准,做一层翻译。你按照 OpenAI 的格式传参,litellm 内部把它转换成目标模型需要的格式,拿到结果后再转回 OpenAI 的格式返回。这样你的业务代码只需要认一种格式。
这个选择很聪明。OpenAI 的接口格式事实上已经成了行业默认标准,大部分开发者都熟悉,文档也最全。以它为基准,学习成本最低。
2.2 核心抽象:模型标识符
litellm 用模型名前缀来区分不同的提供商。比如gpt-4默认走 OpenAI,claude-3-opus走 Anthropic,ollama/llama3走本地 Ollama 服务。这个设计的好处是零配置切换——你只要改模型名字符串,其他代码不用动。
我实测下来,这个前缀机制覆盖了绝大多数场景。你可以在配置文件里定义模型别名,也可以直接在代码里写完整前缀。对于团队协作来说,建议统一用配置文件管理模型列表,避免每个人写的模型名不一致。
2.3 代理模式与 SDK 模式
litellm 提供两种使用方式:一种是作为 Python SDK 直接 import 使用,另一种是启动一个代理服务,对外暴露 OpenAI 兼容的 HTTP 接口。
SDK 模式适合 Python 项目,直接调用函数,性能损耗最小。代理模式适合多语言项目或者需要统一网关的场景,任何能发 HTTP 请求的语言都能用。代理模式还支持负载均衡、限流、成本追踪等高级功能。
选哪种?我的经验是:如果是纯 Python 项目且不需要多实例共享配置,直接用 SDK;如果需要给前端或其他服务提供统一入口,或者要做 API Key 管理和用量统计,就上代理模式。
3. 核心功能与实操要点解析
3.1 安装与基础调用
安装很简单:
pip install litellm基础调用示例:
from litellm import completion response = completion( model="gpt-4", messages=[{"role": "user", "content": "你好"}] ) print(response.choices[0].message.content)这里有几个关键点需要注意。第一,API Key 的传递方式。litellm 会自动读取环境变量,比如OPENAI_API_KEY、ANTHROPIC_API_KEY。你也可以在调用时通过api_key参数显式传入。我建议用环境变量管理,避免 Key 硬编码在代码里。
第二,messages的格式完全遵循 OpenAI 规范,支持 system、user、assistant 三种角色。多轮对话就是把历史消息按顺序放进列表。
第三,返回对象的结构也是 OpenAI 格式,response.choices[0].message.content拿文本,response.usage拿 token 统计。
3.2 多模型切换的实操细节
切换模型只需要改model参数:
# 调用 OpenAI completion(model="gpt-4", messages=[...]) # 调用 Anthropic completion(model="claude-3-opus-20240229", messages=[...]) # 调用本地 Ollama completion(model="ollama/llama3", messages=[...], api_base="http://localhost:11434")但实际用的时候有几个坑。不同模型对参数的支持程度不一样。比如temperature大部分模型都支持,但top_p和frequency_penalty就不是所有模型都认。litellm 会尽量做映射,但遇到不支持的参数可能会报错或者静默忽略。
我的做法是:在配置文件里为每个模型单独设置默认参数,调用时只传必要的覆盖项。这样既保证了兼容性,又保留了灵活性。
提示:本地模型的
api_base一定要写对。Ollama 默认端口是 11434,vLLM 默认是 8000,LM Studio 默认是 1234。端口写错是最常见的连接失败原因。
3.3 流式输出的处理
流式输出在对话类应用里几乎是刚需。litellm 支持stream=True:
response = completion( model="gpt-4", messages=[{"role": "user", "content": "写一段话"}], stream=True ) for chunk in response: content = chunk.choices[0].delta.content if content: print(content, end="")流式模式下,返回的是一个生成器,每个 chunk 的结构和 OpenAI 流式格式一致。需要注意的是,不是所有模型都支持流式,有些本地模型需要额外配置。另外,流式模式下 token 统计可能不准确,因为 usage 信息通常在最后一个 chunk 才返回。
3.4 异步调用与并发控制
litellm 提供了acompletion异步接口:
import asyncio from litellm import acompletion async def call_model(): response = await acompletion( model="gpt-4", messages=[{"role": "user", "content": "你好"}] ) return response asyncio.run(call_model())异步在批量调用时特别有用。比如你要同时测试 10 个模型对同一个问题的回答,用异步可以并发发起请求,总耗时取决于最慢的那个,而不是累加。
但并发要注意限流。各家 API 都有 RPM(每分钟请求数)和 TPM(每分钟 token 数)限制。我一般用asyncio.Semaphore控制并发数,或者用 litellm 代理模式自带的限流功能。
4. 代理模式部署与高级配置
4.1 代理服务的启动
代理模式通过命令行启动:
litellm --model gpt-4 --port 8000或者用配置文件:
model_list: - model_name: gpt-4 litellm_params: model: gpt-4 api_key: os.environ/OPENAI_API_KEY - model_name: claude litellm_params: model: claude-3-opus-20240229 api_key: os.environ/ANTHROPIC_API_KEY然后启动:
litellm --config config.yaml --port 8000启动后,你就可以用任何 OpenAI 客户端去调用http://localhost:8000,模型名写配置文件里定义的model_name。
4.2 负载均衡与故障转移
代理模式支持同一个模型名配置多个后端:
model_list: - model_name: gpt-4 litellm_params: model: gpt-4 api_key: os.environ/OPENAI_API_KEY_1 - model_name: gpt-4 litellm_params: model: gpt-4 api_key: os.environ/OPENAI_API_KEY_2这样请求会轮流打到两个 Key 上,相当于做了简单的负载均衡。如果其中一个 Key 失效,litellm 会自动切换到另一个。
故障转移的配置稍微复杂一点,需要设置fallbacks参数。比如主模型挂了自动切备用模型:
litellm_settings: fallbacks: [{"gpt-4": ["claude-3-opus"]}]这个功能在生产环境里非常实用。我遇到过某家 API 突然抽风的情况,有了 fallback 配置,服务基本无感知。
4.3 成本追踪与用量统计
litellm 内置了成本计算功能。每次调用后,response._hidden_params里会包含成本信息。代理模式下还可以把用量数据写到数据库或者日志里。
配置方式:
litellm_settings: success_callback: ["langfuse"]支持多种回调,比如 Langfuse、Helicone 等。如果你不想接第三方,也可以自己写回调函数,把数据存到自己的数据库。
我自己的做法是:在代理层记录每次请求的模型、token 数、耗时、成本,定期汇总分析。这样能清楚知道钱花在哪了,也方便做预算控制。
5. 常见问题与排查技巧实录
5.1 连接类问题
问题:调用本地模型报连接错误。
排查顺序:先确认服务是否启动,用curl直接测一下端口通不通。然后检查api_base是否写对,注意结尾不要多加斜杠。最后看模型名是否匹配,有些本地服务对模型名大小写敏感。
问题:API Key 无效。
litellm 读取环境变量的优先级是:调用参数 > 环境变量 > 配置文件。如果报鉴权失败,先确认环境变量名是否正确。各家环境变量名不一样,OpenAI 是OPENAI_API_KEY,Anthropic 是ANTHROPIC_API_KEY,可以在 litellm 文档里查完整列表。
5.2 参数兼容性问题
问题:某些参数传了没效果。
不同模型支持的参数集不一样。比如logit_bias很多模型不支持,response_format只有部分模型支持 JSON 模式。遇到这种情况,先查目标模型的文档,确认它支持哪些参数。litellm 会尽量做映射,但不会凭空创造能力。
问题:返回格式和预期不一致。
有些模型返回的 JSON 结构可能和 OpenAI 有细微差异,比如finish_reason的取值。litellm 会做标准化,但偶尔会有遗漏。如果遇到,可以在 GitHub 上提 issue,或者自己在业务层做兼容处理。
5.3 性能与稳定性问题
问题:并发高了之后大量超时。
这通常是两个原因:一是目标 API 的限流,二是本地网络带宽。先看错误信息,如果是 429 就是限流,需要降低并发或者申请更高配额。如果是超时,可以适当调大timeout参数,默认是 600 秒。
问题:流式输出中断。
流式模式下,如果网络不稳定或者服务端主动断开,生成器会抛异常。建议在业务层加 try-except,捕获后可以选择重试或者降级到非流式。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 连接被拒绝 | 服务未启动或端口错误 | 检查服务状态和 api_base |
| 401 鉴权失败 | API Key 无效或未设置 | 检查环境变量名和值 |
| 429 限流 | 请求频率超限 | 降低并发或申请提额 |
| 参数无效 | 模型不支持该参数 | 查阅模型文档,移除不支持参数 |
| 流式中断 | 网络波动或服务端断开 | 加重试逻辑或降级非流式 |
| 成本统计为零 | 模型未在价格表中 | 手动配置模型价格 |
提示:litellm 的版本更新很快,遇到奇怪的问题先升级到最新版试试。很多 bug 在新版本里已经修了。
6. 个人实操经验与建议
用了大半年 litellm,有几个体会比较深。
第一,配置文件比代码硬编码好。一开始我图省事,模型名和参数都写在代码里,后来模型一多,改起来很痛苦。换成 YAML 配置文件后,加模型、改参数都不用动代码,重启服务就行。
第二,代理模式适合团队,SDK 模式适合个人。团队用代理模式可以统一管理 Key 和用量,个人用 SDK 更轻量。我现在是本地开发用 SDK,部署到服务器用代理。
第三,不要过度依赖自动映射。litellm 的参数映射虽然方便,但遇到不支持的参数时行为不确定。关键参数最好显式传递,并且在文档里记录每个模型的实际支持情况。
第四,成本追踪要尽早做。我一开始没在意,后来发现某些模型的调用成本远超预期。现在每次调用都会记录成本,月底一看就知道该优化哪里。
最后分享一个小技巧:如果你需要频繁切换模型做对比测试,可以写一个简单的封装函数,把模型列表和测试问题传进去,自动跑完所有模型并输出对比表格。这个用 litellm 的异步接口实现起来非常快,几十行代码就能搞定。