我们来做一次访谈要同时接好几家大模型的API都会头疼。
不是模型效果的问题,是这些东西实在太难伺候了。OpenAI那边的接口长一个样,Claude长一个样,各家国内的、海外的模型再长一个样,参数名不同,返回结构不同,连报错格式都不带回重样的。再加上每个平台的Token计费方式也不同,项目上线之后还得操心成本控制和额度分配。只要接了两家以上,SDK版本冲突、参数格式互转、异常处理分支这些破事就会铺满整个开发排期。今天要聊的litellm,当初就是为了干掉这些杂事而生的。
litellm不是我瞎编的东西,它是个已经在开发者社区里被大规模使用的开源项目。说人话就是:它提供一套统一的调用格式,帮你把所有主流的大模型API接入工作收拢到一个入口上。你可以通过一套代码,随时在多个模型供应商之间来回切换,不用改业务逻辑。它还带了一个代理网关模式,可以把密钥管理、成本统计、请求限流、缓存这些都集中处理掉。
这篇博文适合谁看?适合那些准备搞AI应用、但已经被多模型接入折磨过的人。也适合团队里负责技术选型、需要给项目搭一个AI统一入口的人。我会把litellm的安装接入、核心使用方法、代理部署和注意事项全部讲清楚,附上我自己实操时碰到的坑和排查方法,希望能帮你少走点弯路。
1. 这套方案到底解决了什么痛点
1.1 多模型接入的混乱局面
做AI应用开发越久,越能体会什么叫“接口碎片化”。今天这个模型出了新版,明天那个平台调整了限流策略,后天又有新的模型厂商杀出来。每接一个新模型,都要重新读文档、适配SDK、处理鉴权方式、调整请求参数。等接了三家以上,你可能会面对这样一段代码:顶层是根据不同平台写死的分支,每个分支里有各自的参数构造逻辑和返回解析逻辑。真到了要替换供应商的那一天,改动量巨大,甚至需要重构。
我见过不少团队为了解决“模型切换”问题,自己封装了一层Adapter。这个做法本身没有错,但问题是:大模型API的格式差异太大了,而且各家还在频繁变动,自己维护一套Adapter的成本并不低。时间一长,适配代码越堆越多,越来越难维护。
litellm的切入点就在这里。它把所有支持的大模型API都统一成了OpenAI风格的接口格式。当你调用时,只需要用一套客户端、一套请求参数、一套错误码,就能连接一百多家模型供应商。至于底层各家API的差异,全都被它消化掉了。
1.2 为什么是OpenAI格式作为统一标准
你可以把litellm的接入方式想象成万能插座转换头。它兼容的“插头”是各家模型原生的API格式,而它输出的标准接口,选的是OpenAI的格式。这个选择不是随意的。OpenAI的接口结构在行业内已经事实性地成了“通用语”,很多模型厂商在设计API时会主动对齐这个格式,生态里的工具链、SDK也是最完整的。
所以用litellm最大的好处之一就是:你只需要熟悉一套API调用方式,就能在那些格式完全不同的模型之间自由切换。有些模型API在细节上做不到完全兼容OpenAI,litellm还会在中间层做一些参数映射、字段转换,尽量保证接口体验是统一的。
1.3 一个死板的比喻和一些亲切的补充
如果还是要给不太了解这块的朋友打个比方,可以把它想象成外卖平台的聚合页。你平时下单,并不需要分别记住每个饭店老板的电话和菜单风格,只需要在外卖平台里搜索筛选,然后统一完成结算。litellm就是这个聚合页:它把各家模型的服务封装好,你只需要面向它这一个入口来订餐。模型在平台里怎么换、后厨怎么做,那是litellm的事。
当然,这个比喻只能帮你建立直觉,具体到工程上它做的远不止格式转换。代理模式下,litellm还承担了密钥管理、请求量统计、成本核算、缓存、LB、熔断等一堆生产环境的脏活累活。这些后边我会逐个展开聊。
2. 快速跑通基础接入:核心API操作详解
2.1 安装与最小调用示例
安装litellm很简单,用pip直接装就行。不过需要提醒一句:它的依赖项比较重,建议在虚拟环境或者隔离环境里装,不要直接把公司的生产环境当成试验场。
pip install litellm装完之后,写一个最简调用:
import litellm response = litellm.completion( model="gpt-4o-mini", messages=[ {"role": "user", "content": "你好,帮我用一句话介绍北京"} ] ) print(response.choices[0].message.content)注意,这里虽然写的是“gpt-4o-mini”,但你完全可以让它调用Claude、Gemini、通义千问这些模型。只需要把model参数值改成对应的模型标识就行,核心用法不变。如果你用的是OpenAI官方的key,连环境变量名都不用改,直接认OPENAI_API_KEY。其他平台的key,比如ANTHROPIC_API_KEY、GEMINI_API_KEY、DASHSCOPE_API_KEY这些,litellm也会自动去环境变量里找。
如果某个平台需要额外的配置项——比如需要填接口地址base_url,或者要使用代理——litellm也提供了对应的参数。一般常见格式是:
response = litellm.completion( model="hosted_vllm/Qwen/Qwen2.5-7B-Instruct", api_base="http://your-llm-server:8000/v1", api_key="your-key", messages=[{"role": "user", "content": "你好"}] )2.2 用起来最频繁的几个方法
litellm的方法命名整体很顺,如果你是靠肌肉记忆写代码的,很容易上手。
completion()是补全类的文本生成接口,几乎所有对话模型都走这里。
acompletion()是它的异步版本。如果你的应用里有大量并发的处理场景,用异步版本会比较合适,可以避免阻塞事件循环。
embedding()用于生成向量,想要做知识库检索的话会用得到。
还有一个容易忽略的是model_list这个工具函数,它可以直接列出当前支持的所有模型名称。我建议你把litellm.model_list打出来,存到本地笔记里。这个列表的更新频率可能比你想的高,过一阵子就会多出不少新模型。
顺便多说一句,litellm.completion里面还支持一个stream=True参数。当你把stream打开时,接口会以流式的方式返回生成结果。这个在搭建聊天类应用时几乎必用,不然用户要干等好几秒才能看到完整回复,体验会很生硬。
2.3 模型别名与参数透传的妙用
litellm支持给模型起别名,这在切换模型时特别好用。你可以先在代码里定义一个假名字,比如"my-main-model",然后在初始化配置里把它指向某个具体的模型。哪天想换模型时,直接改配置,不用动任何业务代码。
litellm.model_alias_map = { "my-main-model": "gpt-4o-mini" } response = litellm.completion( model="my-main-model", messages=[{"role": "user", "content": "你好"}] )这样一来,业务代码里的模型名就彻底跟具体供应商解耦了。配合环境变量甚至远程配置来切换模型,就能做到一套代码在各家模型之间丝滑切换。
还有一个细节是参数透传。不同模型总有自己的一些特有参数,比如有的模型支持top_p,有的模型支持frequency_penalty,有的模型还支持自定义的extra_body。litellm允许你把额外参数透传给底层API,甚至可以通过litellm.modify_params这个钩子在请求发出前对参数做统一改写。
3. 正经生产环境要用代理模式:部署与配置
3.1 为什么开发模式不够用
直接pip装好、在代码里调用,这种模式适合开发和本地调试。但它有几个让人头疼的问题:
首先是密钥分散。如果每个服务实例都要自己配置各家模型的API key,那密钥管理就成了一团乱麻。其次是没法统一做成本统计和权限控制。再就是,底层模型API如果出了限流或故障,缺少一层统一的兜底处理。
所以litellm提供了第二个模式:代理服务器模式。你把litellm部署成一个独立服务,所有内部业务都请求这个代理,再由代理去请求各家模型API。代理端负责统一鉴权、转发、限流、记账,业务端只需要把它当成一个普通的OpenAI服务来调用就行。
3.2 快速启动一个代理实例
启动代理之前,先准备一个配置文件。下面是一个非常简化的版本:
model_list: - model_name: gpt-4o-mini litellm_params: model: gpt-4o-mini api_key: os.environ/OPENAI_API_KEY - model_name: claude-3-5-sonnet litellm_params: model: claude-3-5-sonnet-20240620 api_key: os.environ/ANTHROPIC_API_KEY然后跑起来:
litellm --config config.yaml --port 4000代理默认会监听4000端口。完成后,业务侧代码不需要装litellm,只需要把base_url指到这个代理地址就行了:
from openai import OpenAI client = OpenAI( api_key="sk-any-string", base_url="http://localhost:4000/v1" ) response = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": "你好"}] )是的,就是这么简单。因为代理暴露出来的就是OpenAI兼容接口,业务侧用任何语言的OpenAI SDK都能直接连上来。
3.3 配置文件的进阶玩法
上面的只是一个最小配置,实际生产环境会考虑更多东西。
假设你一个模型供应商想配置多个API key来做负载均衡,比如同一个服务买了多个账号,不希望单个key被限流打爆。可以通过api_key列表的方式配置多个key,litellm会轮流使用:
model_list: - model_name: gpt-4o litellm_params: model: gpt-4o api_key: - os.environ/KEY_ONE - os.environ/KEY_TWO还想限制单用户的请求频率?可以在配置里加上rpm_limit和tpm_limit,分别表示每分钟请求数和每分钟Token数限制。这个在给团队内部统一提供服务时,是非常有用的成本控制手段。
还有一个很实用的功能是按用户来记账。在代理模式里,请求方调用时可以通过请求头带上自己团队的用户ID,litellm会把Token消耗按用户维度打点,方便后续做成本分摊。这是很多公司在多部门共用一套模型服务时的刚需。
3.4 接入自定义模型
不是所有人都在用遥遥领先的大厂云服务。很多人其实在本地或公司内网里跑着开源模型,用vLLM或TGI这类推理框架提供OpenAI兼容接口。这类模型litellm也能统一纳管,配置方式跟前面说的hosted模型类似。
model_list: - model_name: qwen2.5-7b litellm_params: model: openai/qwen2.5-7b-instruct api_base: http://localhost:8000/v1 api_key: dummy在这种场景下,代理成了很好的“路由中转站”。外部业务只认得qwen2.5-7b这一个名字,哪天你把这个名字映射到云端一个更大的模型,业务侧无感知。
4. 几个保命功能:重试、熔断、缓存与预算控
4.1 自动重试和错峰退避
模型API偶尔抖一下是常态。你请求发出去,可能遇到限流状态码,也可能后端临时降级。这种情况下,业务侧如果直接报错给用户,是很不友好的。
litellm对常见的几种限流状态码有内置处理。你可以在参数里配置重试次数和退避策略。比如:
litellm.num_retries = 3 litellm.retry_after = 5它的重试不是无脑原地重试,而是会在遇到限流状态码时,读取响应头里返回的Retry-After字段,尽量按服务端建议的时间来等待。这样可以减少对底层API的冲击,也能提高重试成功率。我实际用下来的感受是,这个机制比自己手写重试要省心得多。
4.2 缓存命中省掉真金白银
如果你做的是一个问答类应用,大概率会碰到大量重复问题——比如频繁出现的客服咨询、产品说明、配置指南。这些重复请求如果每次都真实调用付费模型,成本会很失控。
litellm的代理模式支持本地缓存和Redis缓存两种方式,对完全相同的请求,命中缓存后直接返回结果,不再调用底层模型。Redis缓存的优势是可以多实例共享,适合部署多个代理副本的生产环境。
在代理配置里开缓存的方式:
general_settings: cache: true参数上还有更细的玩法,比如:
litellm.cache = True litellm.cache_params = { "ttl": 3600 }TTL可以按业务需求调整。有些信息实时性要求高,缓存时间短一点;有些知识库类答案几乎不变,可以缓存个把小时甚至更久。
4.3 预算控制和费用预警
模型API的计费是不透明的黑盒,如果应用用量突然暴涨,钱烧起来是很恐怖的。litellm提供了一个相对轻量的成本追踪机制:它对每次调用都会估算出Token消耗,并按模型的实际单价换算成费用,记录在日志中。
代理模式里你可以给某个团队、某个用户设置预算上限。当额度耗尽之后,litellm会拿捏该用户后续的请求,而不是让账单一直溜下去。这个机制在给客户做对外服务、或者给公司内部多个部门提供模型调用通道时,都属于刚需功能。
具体的预算配置很简单:
general_settings: budget: 500这里的数字单位是美元。当然你也可以按用户维度去配置更细粒度的限制。我建议在正式对外开放之前就把这套预算控制配置好,不然真的可能出现审计时才发现费用超支的情况。
5. 实测踩过的坑与排查思路
5.1 最大的坑:模型标识写错
这是新手最常碰见的问题,没有之一。model参数并不是你随便写一个模型名字就能自动匹配的,它内部有一套严格的名称映射规则。不同平台在litellm框架里的模型名称格式并不完全一样。
比如同样一个开源模型,在某个平台上叫Qwen/Qwen2.5-7B-Instruct,在另一个推理框架里可能就叫qwen2.5-7b-instruct。复制粘贴文档里的模型名时,一定要核对完整。否则litellm会抛出一个看起来像是网络问题的异常,排查半天才发现其实是模型标识不匹配。
我建议凡是报错先看一眼model参数。如果用的是代理模式,配置里的model_name是代理对外的名字,而litellm_params.model才是传给底层API的真实模型名。这两个别搞混。
5.2 环境变量与密钥优先级
环境变量加载不成功也是个高频问题。尤其在公司内部服务器上用systemd或容器部署时,环境变量没有正确注入,导致litellm一直报401认证失败。
litellm读取API key的优先级是:显式传参 > 环境变量 > 配置文件中的默认值。有时候你明明在配置文件里写了API key,但代码里又传了别的空值,就会出现相互覆盖的诡异情况。
我建议在写代码和部署时,只保留一条密钥注入路径,不要同时在多个位置配置。别问我为什么这么说,问就是被覆盖过。
5.3 代理部署后经常遇到的CORS问题
如果你在浏览器端直接调用litellm代理,会遇到跨域问题。代理服务需要显式配置允许跨域请求:
general_settings: allowed_origins: - "https://你的前端域名"不配置这个,浏览器控制台会报一句“跨域请求被阻止”,很多人绕了一大圈才发现是这个原因。生产环境多实例部署时,还有个很容易踩的坑:Redis缓存必须提前配好,否则每个实例各自持有一份缓存,命中率上不去,还会出现不同实例间缓存不一致的边界情况。
5.4 流式请求的异常捕获
滥用流式响应时,你可能会踩到一个语义不明的坑:在stream=True模式下,如果底层模型在生成中途断开连接,litellm抛出的异常可能不会走常规的错误处理分支。这时我一般会在调用处额外捕获一次生成器迭代异常,避免主流程被中断。
经验总结下来,在处理大规模并发情况下,代理模式一定要打开timeout配置。很多底层API响应很慢,尤其复杂模型生成长文时超过默认超时时间是常事。适当调高超时时间——比如120秒甚至180秒——能够减少很多没必要的重试。但注意不要把超时调到无穷大,否则一旦底层服务挂掉,你的代理会跟着卡死。
6. 一个更好的工程化思路:把它嵌入你的服务统一网关
6.1 服务定位的再思考
litellm可以当做一个开源工具来用,也可以当做一个基础组件来设计。如果你所在的公司或团队正在做AI中台,那它大概率可以承担“模型网关”这个角色。代理部署好之后,所有模型服务都汇合到一个入口,团队内部不需要关心底层是哪个供应商,只需要关心调用什么模型、多少预算、能不能完成需求。
在AI应用研发里,这种“网关”思路的价值远大于给业务代码省几行适配逻辑。它不只是一个SDK,而是一个管理平台的前身。你可以在代理的外围补充监控、告警、权限审批等内部系统,把模型资源的运维集中管起来。
6.2 围绕litellm搭一套简单的内部AI平台
一个很朴素但有效的内部AI基础平台的架构可以是:最底层是各家模型API和自建的模型推理服务;中间是litellm代理,负责统一接入、路由、限流、缓存和记账;再往上是业务系统,它们不直接对着各家模型API调,而是只对接中间那层。
这个架构的好处是:切换模型不再需要业务部门提需求、排期、改代码。平台管理员改一下配置文件,甚至调用管理接口,就能完成全部切换。这种灵活度我实测下来非常值钱,因为业务对模型的需求是经常在变的。今天想试新模型,明天想降低某个场景成本,只需要在网关层面调整。
6.3 后续可以扩展的方向
litellm本身支持的功能已经不少,但如果你愿意,还能进一步扩展。比如你可以定期把litellm记录的Token消耗数据导出来,接到自己的报表系统里。比如你可以基于它的预算提醒回调,喂给自己的告警系统,一旦出现异常高消耗就自动发通知。再比如你要是对某些请求有审核需求,也可以利用代理这一层做内容的二次校验,在请求发给模型之前或之后塞进一道自定义逻辑。
这些扩展听起来有点轻描淡写,实际做起来也不复杂,核心就是先有一个统一网关,后续才能谈得上在网关上做治理。没有网关的项目,这些功能全都得在各业务模块里重复实现,维护成本不可同日而语。
7. 个人总结:它适合谁,也聊聊不适合谁
litellm给我的整体感觉是:它不是那种花里胡哨的技术,更像个踏实干活的基础设施。API不复杂,该有的生产能力都有,社区迭代还快。
适合它的人有几类:第一类是个人开发者,手里握着好几个模型平台的Key,想在一个项目里灵活切换模型;第二类是创业团队,想把模型接入的成本和运维复杂度收束起来;第三类是公司里的基础架构组或平台组,正在规划公司统一的AI能力入口。
不适合它的人也有。如果你只是在做一个纯玩具Demo,只接一家模型,那引入litellm确实会显得多余。另外如果你所在的组织对供应链有极其严格的审查要求,那“引入一个第三方开源依赖做统一网关”这件事本身就需要做合规评估。这种时候没有绝对正确答案,得结合实际环境来权衡。
再补充一个真实的体会:litellm最大的价值不是帮你省调用代码,而是改变你团队的工作方式。从“遇到模型就写一段适配代码”转变为“所有模型都从统一入口进出”,这两个思路带来的长期维护成本差距是数量级的。
最后分享一个小技巧:每当你准备接入一种新的模型服务时,在官方的模型列表里把所有相近的候选模型都翻一圈,把它们的中位延迟、价格和上下文长度记到一张表上。之后要切换,直接在代理配置里换一个名称就行,连业务代码都不用动。这个习惯帮我省掉过无数次临阵改代码的尴尬。