litellm这个项目,我第一次看到的时候以为是又一个LLM封装库,差点划走。但真花时间用过之后,我得说,这玩意儿在AI应用落地场景里,解决的是那种“夜里疼醒”级别的痛点——当你手里的模型调用从一个变成五个、十个,每个的API格式还不一样,监控分散,账单混乱的时候,你就知道一个统一的网关有多重要了。
简单来说,litellm就是一个开源的、自托管的LLM代理网关。它把市面上主流的大模型API(OpenAI格式、Anthropic格式、各类国产模型、开源部署的模型等)全部转成统一的OpenAI格式。你只需要用一套代码,就能调用所有模型。它不是又一个UI套壳,也不是简单的SDK,而是站在你和所有大模型之间的一层代理服务。
这篇文章我不打算把它当成一个宣传软文来写,而是从一个实际搞过项目、踩过坑、拿着账单肉疼过的开发者角度,把这个项目的核心价值、部署方式、配置细节和一些网上教程里很少提到的实操心得掰开揉碎。如果你正在被多模型接入、成本失控、Key管理混乱这些问题折磨,这篇文章应该能帮你省下几天的调研时间。
1. 这个网关到底解决了什么问题——先看看没有它的时候有多乱
很多人第一次接触litellm,是冲着“它能把所有模型转成OpenAI格式”这个特性来的。但用了一段时间后我才明白,格式统一只是最表层的价值,它真正解决的是AI应用工程化落地时的三个核心混乱。
1.1 多模型接入时的接口地狱
你得想象一下这个场景:项目初期,你用的某家模型的API,写好的代码里全是/v1/chat/completions的请求体,结构化输出、流式请求、超时设置都是按照它的文档调的。后来业务方觉得效果不够好,想换个更强的模型,或者想在两家模型之间做AB对比。
这时候你会发现一个特别尴尬的事实:虽说现在各家都号称“兼容OpenAI格式”,但真用起来全是细节差异。有的模型流式输出的格式字段名不一样,有的多了一个thinking字段返回,有的temperature参数范围是0到1而别家是0到2,还有的在处理max_tokens和max_completion_tokens这两个参数上的兼容性差异很大。如果你直接在业务代码里对接两家,就得写两套适配逻辑,后面每加一家,就得再来一遍。
litellm的核心思路其实就是代理模式:你的业务代码永远只跟litellm这一个localhost:4000地址通信,格式固定是OpenAI的。至于背后实际调的是哪家、参数怎么映射、鉴权怎么处理,全由litellm在中间层搞定。你的代码层面只需要改一个字符串(模型名对应的channel),其他一概不动。
1.2 Key生命周期管理与安全边界
还有一个痛点,可能得等你的应用被薅过羊毛之后才会后知后觉——API Key的暴露风险。很多时候项目为了赶进度,前端直接嵌了个API Key请求模型,或者把服务端的Key写在代码仓库里,一泄露就是真金白银的损失。
litellm的虚拟Key机制给了一个解法。你可以为每个项目、每个用户、甚至每个功能模块单独生成一个虚拟Key,这些Key只对litellm网关生效。请求到了litellm这一层,再由网关去调用真正的模型服务商Key。这样一来,真实Key永远只存在于你的服务器环境变量里,别人看到的只是虚拟Key。配合预算限制、速率限制,被薅羊毛时你可以在litellm里直接吊销这个虚拟Key,而不需要去服务商后台把那个绑定了支付方式的真实Key作废。
1.3 成本归因与配额管理
这个事我感触很深。以前公司里几个项目组共用同一个模型服务商账号,月底对账的时候,财务拿着账单过来问“这笔一千多块的消费是哪个项目的”,一般就是全员沉默,没有人能给出准确答案。
litellm通过对“Key-用户-项目”的层层绑定,把每一笔token消耗都归因到具体项目或用户上。仪表盘里能看到每个Key的消耗曲线,每天花了多少、调了多少次、平均延迟多少,一目了然。它也有预算控制功能,设好上限之后,超额了会自动熔断(拒绝请求),这个功能对控制生产环境成本来说,我认为是刚需中的刚需,尤其是业务方喜欢在没评估成本的情况下就疯狂调模型接口的场景。
2. 部署与核心配置——从拉镜像到跑通第一个请求
litellm的部署方式很常规,它就是标准的Python服务,官方推荐用Docker跑,也支持直接pip install litellm后作为Python包嵌入使用。这里我把两种方式的选型思路说清楚。
2.1 环境准备与部署方式选型
如果你的应用是Java或Go写的,或者只是想给团队搭一个独立的模型网关服务,直接用Docker镜像是最省事的做法。它打包了服务端和数据库依赖,运行起来就是一个独立的HTTP服务。
# 拉取镜像并启动,暴露4000端口 docker run \ -d \ -p 4000:4000 \ -v $(pwd)/litellm_config.yaml:/app/config.yaml \ -e STORE_MODEL_IN_DB=True \ --name litellm \ ghcr.io/berriai/litellm:main-latest \ --config /app/config.yaml这里解释几个关键参数:
-p 4000:4000:litellm默认监听4000端口,这是网关对外提供服务的人口。-v $(pwd)/litellm_config.yaml:/app/config.yaml:把宿主机上的配置文件挂载进容器。我建议所有配置都用YAML文件统一管理,不要用环境变量散着传,环境变量一多以后根本理不清谁是谁。STORE_MODEL_IN_DB=True:这个值得单独说一说。默认情况下litellm的模型配置读的是YAML文件,改配置需要重启服务。开了这个开关后,配置会持久化到数据库(默认是SQLite,生产环境建议换PostgreSQL),在管理后台改动实时生效,不用再重启网关。
如果你的项目本身就是Python写的,直接在项目里引入import litellm,把它当SDK用,这样就不需要单独的网关服务,代码里直接设置litellm.model_list来指定可用的模型列表。这种方式适合模型数量少、没有跨团队共享需求的场景。
提示:踩过的坑,用Docker部署时容器内的时区默认是UTC,成本账单查询里看时间会对不上,记得在docker run命令里加
-e TZ=Asia/Shanghai把时区改过来。
2.2 配置文件的结构与模型路由规则
litellm的配置文件是核心,它的逻辑其实挺清晰:先定义model_list,也就是这个网关能对外提供哪几个模型入口,再为每个入口指定它背后真实调用的provider和model。下面是一个最小可用的配置示例:
model_list: - model_name: gpt-4o-mini litellm_params: model: openai/gpt-4o-mini api_key: os.environ/OPENAI_API_KEY - model_name: claude-3-5-sonnet litellm_params: model: anthropic/claude-3-5-sonnet api_key: os.environ/ANTHROPIC_API_KEY - model_name: qwen-max litellm_params: model: openai/qwen-max api_base: https://dashscope.aliyuncs.com/compatible-mode/v1 api_key: os.environ/DASHSCOPE_API_KEY注意看几个细节:
第一,model_name这个字段是暴露给调用方的,对外叫什么都行,哪怕内部换了个更强的新模型,只要model_name不变,业务代码一行都不用改。
第二,litellm_params里的model字段格式是provider/model。litellm内部维护了一个很长的provider支持列表,你只要按格式写,它会自动用对应的适配器去处理鉴权和请求格式。比如国产模型服务商一般提供OpenAI兼容接口,那在model字段里就用openai/前缀,再配上api_base指到它家的地址就行。
第三,安全习惯上的一个注意点:配置里不写明文Key,用os.environ/前缀引用环境变量,这样配置仓库即使泄露了也不会连累Key泄露。
2.3 模型重命名与负载均衡
litellm还有一个很实用的能力:同一个model_name背后可以挂多个provider实例,实现自动负载均衡和故障转移。这在生产环境里特别有用,比如你在两家云服务商都开了通义千问的API,怕一家不稳定,就可以这样配:
model_list: - model_name: qwen-max litellm_params: model: openai/qwen-max api_base: https://网关A.example.com/v1 api_key: os.environ/KEY_A model_info: weight: 3 - model_name: qwen-max litellm_params: model: openai/qwen-max api_base: https://网关B.example.com/v1 api_key: os.environ/KEY_B model_info: weight: 1出现两个同名model_name的配置后,litellm会按照weight权重把请求分发到两个instance上。当其中一个接口返回500或者连接超时时,网关会自动将请求转移到另一个实例,不经人工干预就能完成故障转移。用的时候可以留意下:两个真正背后的渠道的模型尽量是同规格或同水平的,不然同一个模型名在不同渠道返回的能力有差异,可能造成线上回答不稳定。
2.4 验证网关连通性
配置写好后,启动服务,先别急着接业务代码,可以用curl验证一下网关是否正常转发:
curl http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ -d '{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "你好,用一句话介绍一下你自己"}] }'注意这里的Authorization使用的是虚拟Key(sk-1234),不是真实Key。如果没有提前在litellm后台创建虚拟Key,也可以用sk-litellm这个默认Key先测试。
3. 核心功能实操——Key管理、预算、缓存与路由策略
光把请求转发起来,只是这轮工作的第一步。litellm真正拉开与其他方案差距的,是它在企业级治理层面的功能。这部分我按实用频率从高到低拆开讲。
3.1 虚拟Key与用户维度的限流配置
在litellm的管理后台或者通过API,可以创建不同粒度的Key。比如给某个外部合作方一个独立的Key,在创建的时候绑定这个Key的预算、单次请求最大token数、每分钟请求频率限制。
# 通过API创建一个新的虚拟Key curl -X POST http://localhost:4000/key/generate \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-1234" \ -d '{ "models": ["gpt-4o-mini", "qwen-max"], "max_budget": 50, "budget_duration": "30d", "rpm_limit": 60, "metadata": {"user": "外部合作方A"} }'这个接口的参数很有价值,简单说说各字段的用途:
max_budget: 50表示这个Key在budget_duration(30天)内的消费上限是50美元(也支持人民币单位通过汇率换算配置)。rpm_limit是每分钟请求数限制,防止某个调用方把网关打爆。metadata用于打标签,方便以后在日志和账单里筛数据。
我建议一个应用只配一个Key,但在这个Key的metadata里通过user或project字段做更细的区分,避免Key数量爆炸导致管理困难。我自己就经历过给每个功能模块建一个Key,没过多久就忘了哪个Key是哪个系统的,还得写脚本去查metadata。
3.2 三种预算控制的力度区别
litellm的预算控制分了三层,各自管的事情不一样,用的时候要分清楚:
| 控制层级 | 作用范围 | 典型配置 | 生效时机 |
|---|---|---|---|
| Key预算 | 单个虚拟Key的消费额度 | max_budget=50,周期30d | 每次请求完成后自动累计并检查 |
| 用户预算 | 某个用户/user_id维度 | 通过用户管理接口创建user时设定 | 用户维度累计,跨Key统计 |
| 全局预算 | 整个网关的最大消费额度 | 在设置页面配置daily/weekly/monthly | 消费者额度熔断 |
这三个层面的预算可以同时启用,优先级是全局 > 用户 > Key,触发后会依次切断对应的请求入口并返回429状态码附带原因说明。需要留意的是,预算统计是异步落库的,在高并发下极短时间内可能出现一些超预算但未及时熔断的请求,这属于正常现象,不建议把预算上限设成与资金承受上限完全相等,建议保留约10%的缓冲空间。
3.3 语义缓存——省钱提速的正确姿势
litellm支持对LLM的响应做缓存,官方叫Redis Cache。在网关层做缓存的思路是:如果用户输入的内容在一定时间内重复出现,直接从缓存把上次的响应结果返回,不再真实调用一次模型,这样既省了推理费又降低了响应延迟。
litellm_settings: set_cache: True cache_params: type: redis host: localhost port: 6379 ttl: 86400配置上如果设置了set_cache: True,默认对所有的请求做语义缓存,但也支持自定义哪些model需要缓存、哪些不需要。这个功能比较适合智能客服或者知识库问答场景,用户的典型问题命中率很高,一天能省下来不少成本。
不过有两个细节要注意:一是别在需要随机性的场景(比如文案生成、故事接龙)开全局缓存,不然用户会发现不同的提问总是得到一模一样的回答,很影响体验;二是缓存key是基于请求体中的messages内容和参数哈希的,只要用户在问题上多打一个空格,缓存值就变了。
3.4 路由策略与重试机制
litellm的请求路由策略有点像一个服务网格里的熔断器。当某个上游模型响应变慢或开始返回错误时,litellm能自动把流量切到备用模型上。这个机制比较可靠的点在于,它不是简单的“挂了就换”,而是动态计算健康的性。它的默认策略包括:
- 连续超过阈值次数的请求失败或超时,自动将该模型熔断,不再向其分发流量。
- 周期性地试探熔断的模型是否恢复,恢复后重新按权重分配流量。
- 在
model_list里设置相同model_name的不同渠道,就能实现这个效果。
举个例子,你对外暴露一个gpt-4o-mini的模型名,背后同时挂A渠道和B渠道,A渠道是官方API,B渠道是某个中转API。如果A渠道的响应连续超时,litellm会把新的请求全部路由到B渠道,直到A恢复。这个机制在设计上的意义还是挺大的,业务侧完全无感,但稳定性有了质的提升。
4. 监控、日志与成本追踪——别等项目炸了才想起来看
这一点是litellm最实打实的功能之一:内置的仪表盘(Admin UI)。作为自托管方案,你不需要把数据送到别人家的监控平台,所有请求日志和成本数据都存在自己的数据库里。
4.1 请求日志里有什么
litellm会在每次请求完成后记录一份完整的元数据,包括:
- 模型名、虚拟Key的别名、调用方的user_id
- 请求token数、响应token数、总token数
- 模型服务的响应延迟(llm_response_time)和总延迟(total_cost)
- 处理成功还是失败、失败的具体错误消息
通过管理后台的日志页面,可以按时间、模型、Key、用户等维度筛选请求。当用户反馈回答质量不对的时候,我通常习惯直接进后台查这部分:这个请求用的哪个模型名背后落在了哪个provider上,用了多少token,耗时多少。这些信息能让排障效率提升不少。
4.2 用成本分析报表做项目决算
管理后台里的Cost Analysis(成本分析)是另一个让我用得很频繁的功能。它能把一段时间内的总消费按照模型、Key、用户维度汇总,形成报表。同步展示的是每天的token消耗趋势和平均单次请求成本。
实际操作里面,我见过很多团队在litellm上做了这样一个流程:每个月月初拉取上月的成本报表,按项目维度的metadata做汇总,然后跟业务方对账。这个流程极其顺畅,因为Key创建时就开始打标签了,后期只需要按标签聚合就好。
4.3 对接Prometheus与告警
litellm支持暴露Prometheus格式的metrics端点,这意味着可以无缝接入现有的监控体系(比如Grafana面板)。如果你已经在用Prometheus技术栈,可以直接配置prometheus的scrape任务来抓取litellm的指标:
# prometheus.yml 配置片段 scrape_configs: - job_name: 'litellm' metrics_path: '/metrics' static_configs: - targets: ['localhost:4000']litellm的metrics里包含了litellm_total_tokens、litellm_requests_total、litellm_failures_total等核心指标。配置告警规则时,我认为这几个指标比较值得关注:失败率突增(可能是provider密钥过期)、平均延迟大于5秒(可能是上游服务抖动),以及预算消耗速率过快(防超支)。把这些接入到告警系统后,网关侧的问题不用等业务方来反馈,我们运维这边就能提前发现。
5. 多团队协作实践——从单体应用到公司的统一网关
litellm有一个特性很适合在团队里推广:它是一个天然的中心化服务,适合公司里搭一个平台供多个产品线共用。
5.1 项目的快速接入流程
如果你的业务方是Java或Node.js技术栈,他们不需要懂得litellm的细节,他们的接入方式跟直连OpenAI差不了多少:
- 拿到平台方分配的一个虚拟Key。
- 将请求的base URL从
https://api.openai.com/v1改成内部网关地址http://internal-gateway:4000。 - 在
model字段填上平台方开放的model_name(比如gpt-4o-company,跟原厂名字不同)。
其中值得提醒的是,业务方的不同服务可能对OpenAI SDK的版本要求不一致,SDK版本过旧时请求参数跟最新版本可能有些兼容性差异,这种情况下把base url切换过来后个别接口可能报参数错误。碰到这种问题时不要慌,通常升级一下SDK版本或者让平台方在网关侧对该模型关闭部分参数即可。
5.2 与公司现有的SSO登录打通
litellm支持SSO(以Google、Okta等几个常见供应商为例),也可以使用自定义认证。在落地时,我是建议把管理后台和虚拟Key的发放流程接进公司现有系统里,让员工通过统一身份认证登录后台、自助申请Key,而不是让一个管理员手工发Key。这是一项投入不大但比较影响平台使用率的事情。
5.3 多环境隔离策略
生产环境与测试环境用同一个litellm实例,是一件容易埋雷的事。我给团队做方案时的建议是:不同环境之间要做隔离,至少是数据库隔离。
做法上可以拆分部署两套litellm实例,生产实例与测试实例使用各自的配置文件和数据库。测试环境可以放开一点限制,让研发同学随手测试不同的模型;生产环境则建议至少确保虚拟Key、预算、告警策略齐全。存量配置如果已经在同一个实例里了,也别急着迁移,可以先把生产虚拟Key的预算策略补上,再考虑物理拆环境的问题。
6. 常见问题与排查技巧实录
这个部分我整理一下当时用litellm时遇到的一些问题,这些问题在官方文档里零零散散也有提及,但这里我把前因后果讲得更通顺一些,方便大家快速定位。
6.1 配置了模型但调用时提示模型不存在
这个问题比较常见。配置在YAML里的model_list项,启动时只有解析了配置文件才生效。如果你修改了YAML但没有重启容器,网关里仍会拿着旧配置运行。
排查顺序一般是这样:
- 用
docker restart或重新部署,让服务重新加载YAML。 - 如果还是提示模型不存在,检查
STORE_MODEL_IN_DB开关。当这个开关打开后,数据库里已有的模型配置优先级会高于YAML文件,你改YAML其实不会生效。 - 优先用管理后台的模型管理页面去修改配置。
6.2 中文提示词在日志里显示乱码
litellm的日志默认打印的是中文原文,但如果配合某些日志收集系统(尤其是ELK技术栈),会出现unicode转义显示成乱码的情况。实际上这不是litellm本身乱码,而是日志收集阶段的转码问题。
处理办法是给litellm的日志输出配置JSON_LOGS=True环境变量,强制输出结构化的JSON日志,让日志收集系统按JSON字段解析就不会再乱码了。
6.3 高并发下出现429 Too Many Requests
429在litellm里不一定代表限流了,它有两种可能性:
- 你设的
rpm_limit触发了限流; - 上游provider返回了限流,litellm把它透传给你。
排查方法是看日志中的litellm_params字段,定位这个429来源。如果是上游限流,建议把该请求的模型路由改为带备用模型的配置;如果是自己设置的限流触发,要结合真实请求量评估这个限流值是否合理,不要盲目调高以免打爆账号配额。
6.4 成本数据显示为0
成本计算依赖模型的价格表,litellm内置了那些常见provider的价格信息。但如果你接的是自定义api_base,且模型名不是它内置的知名模型,litellm无法自动算出价格,成本就会显示为0。
这时候可以在模型配置里手动加上input_cost_per_token和output_cost_per_token,把单价写明,成本统计就会恢复正常。
6.5 流式请求报错或响应中断
流式(streaming)是LLM调用中最容易出问题的环节,尤其是SSE流式输出的解析。litellm在大多数情况下能把上游的流式事件正常透传成OpenAI格式,但如果你用了自定义provider,它的流式事件格式不规范,就可能在网关层出现解析失败。
排查时注意两点:一是将流式请求与普通请求分开看,在网关里把该模型的流式参数单独调优;二是抓取原始的provider响应,确认它返回的SSE事件字段名是否与OpenAI的标准一致,不一致时需要重写自定义回调。
7. 实战经验总结与研究结论
写到这里,还是想用我自己在项目里的一些真实感受来收尾。
litellm这套东西,如果你是个人开发者,用pip包的方式就足够满足日常需求了。但如果是公司内部有多个团队在并行开发AI功能,我认为值得专门投入一到两天搭一个共享网关。它的价值在于把“模型接入”这件事从“业务代码里的一部分”变成了“基础设施层面的一件事”。业务研发不必关心上游模型怎么配、Key怎么管、成本怎么算,只需要拿到一个Key和几个模型名就够了。
还有个细节提醒一下,litellm的更新节奏相当快,GitHub上几乎每周都有新release,功能和配置项变动也快。网上搜到的配置示例,几个月前的很可能就有参数对不上的情况。遇到这种问题不用太纠结,建议直接以官方文档为准,YAML配置里的字段名、管理后台的选项,都以当前版本为准。
另外,如果让我给准备在生产环境落地litellm的团队几个建议,我大概会列这些:
- 虚拟Key的metadata一定要从第一天就开始认真打标签,不然事后补账会非常痛苦;
- 预算上限要多留一点缓冲,不要卡着资金承受上限设置;
- 缓存、重试、负载均衡这些功能在生产环境很香,但要在测试环境充分验证后再开;
- 监控告警尽早接好,尤其是失败率指标和成本消耗速率指标。
我这套配置和流程已经稳定跑了几个月,中间经历了几次上游模型供应商的接口抖动和两次误设预算触发的熔断,都靠litellm的日志和监控快速定位解决了。如果你也在折腾多模型接入的事,希望这篇整理的实战经验能帮你少走几步弯路。