LiteLLM Proxy 用法:用一个端点聚合 100+ 大模型
LiteLLM Proxy 是目前功能最完备的开源聚合代理之一:一条命令启动,统一 OpenAI 兼容接口,支持 100+ 上游模型。如果你的项目用 Python 栈或深度集成 LangChain,LiteLLM 是最自然的选择。
我第一次上手 LiteLLM 是被一个很具体的问题逼出来的:团队里三个项目分别接了 OpenAI、Claude、DeepSeek 三套 SDK,各自维护 key、各自写重试逻辑,一旦某个上游限流或者宕机,改代码的人得挨个项目去改。后来把三套接入全部收敛成一份 litellm_config.yaml,业务代码只认一个 base_url,谁挂了在配置层面切换,业务代码一行不用动。这才是聚合代理真正省下来的时间——不是省了调用 API 的那几行代码,而是省了「换模型要改几个项目」这种运维成本。
LiteLLM Proxy 是什么
LiteLLM 分两层:SDK 模式(在代码里 import litellm 直接调用)和Proxy 模式(独立 HTTP 服务,对外暴露 OpenAI 兼容端点)。Proxy 模式的优点是语言无关——任何能发 HTTP 请求的客户端都能接入,不限 Python。
两者的取舍很直接:如果你就一个 Python 服务、团队小、没有跨语言接入需求,SDK 模式够用,少一层网络跳转,延迟更低;一旦出现「Node 服务也要调、前端要直连、多个微服务共享一套 key 和预算」这类需求,就必须上 Proxy 模式——虚拟 key、预算控制、多租户这些能力都挂在 Proxy 这一层,SDK 模式里没有。
本文聚焦 Proxy 模式,适合需要为团队或多个服务提供统一入口的场景。
快速部署
安装与启动只需两步:
pip install litellm[proxy]
# 用配置文件启动
litellm --config litellm_config.yaml --port 4000
最小化配置文件 litellm_config.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"
- model_name: deepseek-chat
litellm_params:
model: deepseek/deepseek-chat
api_key: "os.environ/DEEPSEEK_API_KEY"
启动后,用标准 OpenAI SDK 接入,只改 base_url:
from openai import OpenAI
client = OpenAI(
api_key="anything", # Proxy 未启用鉴权时填任意值
base_url="http://localhost:4000/v1"
)
response = client.chat.completions.create(
model="claude-sonnet",
messages=[{"role": "user", "content": "你好"}]
)
这里有个第一次用的人容易踩的坑:model 字段填的是你在 model_name 里起的别名(比如 claude-sonnet),不是上游真实模型标识(anthropic/claude-3-5-sonnet-20241022)。如果你把上游标识直接填进业务代码的 model 参数,Proxy 会报 BadRequestError: model not found——因为 Proxy 只认你在配置文件里注册过的别名,这一层间接映射才是它能做路由和 fallback 的前提。排查这类报错的第一步永远是先看 litellm_config.yaml 里到底注册了哪些 model_name。
启动时加 --detailed_debug 能看到每一次请求实际打到了哪个上游、耗时多少,调试路由策略时非常有用,生产环境记得关掉,日志量会很大。
核心路由策略
LiteLLM 的路由能力是其核心竞争力,支持多种策略:
| 策略 | 配置字段 | 说明 |
|---|---|---|
| 权重轮询 | weight | 按比例分流,适合 A/B 测试 |
| 最低延迟优先 | routing_strategy: latency-based-routing | 实时测速选最快上游 |
| 成本最优 | routing_strategy: cost-based-routing | 选当前最便宜的上游 |
| 使用量均衡 | routing_strategy: usage-based-routing | 防止单个 key 超限 |
| Fallback 链 | model_group_alias + fallbacks | 主路由失败切备用模型 |
Fallback 示例:
router_settings:
fallbacks:
- gpt-4o:
- claude-sonnet # gpt-4o 失败时自动重试 claude
num_retries: 3
timeout: 30
这几个策略怎么选,不是越花哨越好,看你的业务诉求:
| 场景 | 推荐策略 | 原因 |
|---|---|---|
| 灰度上线新模型,想小比例试跑 | 权重轮询 | 简单直接,改个数字就能调比例,出问题秒回滚 |
| 对响应速度敏感(比如实时对话) | 最低延迟优先 | LiteLLM 会持续采样各上游的实际耗时,自动避开临时变慢的节点 |
| 跑批量任务,对速度不敏感但要控成本 | 成本最优 | 按 token 单价选最便宜的上游,适合离线任务、内容生成这类场景 |
| 单个 key 有 QPS/TPM 限额 | 使用量均衡 | 防止某个 key 被打满导致 429,把请求摊到多个 key 上 |
| 主力模型不稳定,需要兜底 | Fallback 链 | 保证服务不中断,代价是备用模型的输出质量/风格可能和主模型不完全一致 |
num_retries 和 timeout 这两个参数容易被忽略但很关键。timeout: 30 表示单次请求超过 30 秒 LiteLLM 就判定失败、触发 fallback 或重试;如果你的场景里有些模型响应本来就慢(比如推理类模型思考时间长),这个值设得太低会导致「模型其实没坏,只是慢,却被当成故障切走了」。num_retries: 3 是对同一个上游的重试次数,重试之间 LiteLLM 默认走指数退避(等待时间随重试次数递增),避免在上游本来就限流的时候还拿高频重试去加重它的负担。这两个参数没有放之四海而皆准的值,得结合你接的模型的真实响应时间分布去调,可以先跑一段时间监控日志里的实际耗时分布再定。
鉴权与多租户
Proxy 支持生成虚拟 key,实现多用户隔离和预算控制:
# 创建一个有月限额的虚拟 key(需启用数据库)
curl -X POST http://localhost:4000/key/generate \
-H "Authorization: Bearer sk-master-key" \
-d '{"max_budget": 10, "budget_duration": "1mo"}'
每个虚拟 key 独立追踪用量,适合将 Proxy 作为内部平台分发给多个团队或项目使用。
这个功能背后的逻辑值得说清楚:虚拟 key 不是真实的上游 API key,而是 LiteLLM 自己签发、自己校验的一层凭证,请求进来后 Proxy 拿这个虚拟 key 去数据库查它对应的预算、限额、允许调用的模型列表,校验通过才用真正的上游 key 去转发。也就是说你的团队成员、下游服务永远看不到真实的 OpenAI/Anthropic key,只持有一个 sk- 开头的虚拟凭证——这对多人协作的团队是刚需,避免真实 key 到处传导致泄露风险扩散。
max_budget 超限之后会发生什么?Proxy 会直接拒绝该 key 的新请求,返回 403,不会等到你手工去查用量表才发现超支——这比很多团队自己拿 Excel 手动记账的土办法靠谱得多。查某个 key 当前用了多少额度也很简单:
curl http://localhost:4000/key/info \
-H "Authorization: Bearer sk-master-key" \
-d '{"key": "sk-xxxx"}'
需要注意,虚拟 key、预算、多租户这套体系依赖数据库(Postgres),如果你只是单机跑起来没接数据库,key/generate 这类接口会直接报错或者数据在重启后丢失,这也是为什么下一节的生产部署一定要带上 PostgreSQL。
Docker 生产部署
生产环境推荐 Docker Compose,并搭配 PostgreSQL 持久化日志:
services:
litellm:
image: ghcr.io/berriai/litellm:main-latest
ports:
- "4000:4000"
volumes:
- ./litellm_config.yaml:/app/config.yaml
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/litellm
command: --config /app/config.yaml --detailed_debug
main-latest 这个 tag 在生产环境不建议长期用——它跟着主分支滚动更新,某天你重新拉镜像可能会带来配置字段的破坏性变更(LiteLLM 迭代很快,routing_strategy 这类字段偶尔会调整命名)。稳妥的做法是锁定一个具体版本号(比如 ghcr.io/berriai/litellm:v1.x.x),升级前先在测试环境跑一遍你的配置文件确认没有报错再上生产。
--detailed_debug 在生产 Docker 部署里也建议去掉,换成默认日志级别,否则容器日志会迅速把磁盘打满,尤其是流量稍大的场景。
进阶:流式、并发与成本估算
流式输出:LiteLLM Proxy 完整支持 stream=True,用法和直连 OpenAI 完全一致,不需要额外配置:
response = client.chat.completions.create(
model="claude-sonnet",
messages=[{"role": "user", "content": "写一段长文本"}],
stream=True
)
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
需要留意的是,走 fallback 链的流式请求如果主模型是在返回过程中才失败(比如流到一半上游断连),客户端已经收到的那部分内容不会被撤回,LiteLLM 会在检测到中断后触发 fallback 重新发起一次完整请求——这意味着调用方可能看到「半截内容 + 完整内容」拼在一起的情况,如果你的前端是逐字追加渲染,这里要加一个「fallback 触发时清空已渲染内容」的处理逻辑,否则用户会看到内容重复或者错乱。
并发:Proxy 本身是异步架构(基于 FastAPI + Uvicorn),单实例可以扛住相当高的并发连接数,但真正的瓶颈通常不在 Proxy 这一层,而在上游 API 的 QPS/TPM 限额上。压测时不要只看 Proxy 的 CPU/内存,要盯 /metrics 里各上游的 429 计数——一旦某个上游的 429 频繁出现,说明并发已经超过它的限额,这时候用「使用量均衡」路由策略配合多个 key 分流,比一味加机器更有效。
成本估算:/spend/logs 接口能拉出每个 key、每个模型的历史花费明细,按天或按月聚合,接入内部报表很方便:
curl http://localhost:4000/spend/logs \
-H "Authorization: Bearer sk-master-key"
这个数据是 LiteLLM 按官方公布的单价自动折算的,具体到每家模型的实时价格仍以各厂商官网为准(截至 2026-06 各家价格都在动态调整),不要把 LiteLLM 里的折算值当成绝对精确的账单依据,只做趋势参考和内部预算预警用。
常见问题
LiteLLM Proxy 和直接用 SDK 模式有什么区别? SDK 模式嵌入进程,适合单个 Python 应用;Proxy 模式独立运行,语言无关,适合作为团队共享基础设施。生产场景推荐 Proxy 模式,便于统一监控和鉴权。
国内的 DeepSeek、通义千问能接入吗?
可以。LiteLLM 支持 deepseek/ 和 dashscope/ 前缀,在 litellm_params.model 字段填入对应上游标识即可。但网络层需确保部署环境能访问这些 API 端点,大陆服务器访问境外模型可能需要额外网络配置。
Proxy 挂掉会影响业务吗? 会。单点部署的 Proxy 是单点故障。生产环境应在 Proxy 前加负载均衡,或使用多副本部署。也可以考虑直接使用托管聚合服务规避自运维风险,详见多模型聚合 API 完整指南。
LiteLLM 的可观测性怎么做?
Proxy 内置 /metrics Prometheus 端点,支持对接 Grafana。详细监控方案见聚合层日志与可观测性实践。
遇到 AuthenticationError: Incorrect API key 怎么排查?
这个报错九成情况不是 LiteLLM 本身的问题,而是环境变量没读到。配置文件里写的 api_key: "os.environ/OPENAI_API_KEY" 依赖启动 Proxy 的进程能读到这个环境变量,如果你是用 systemd 或者 Docker 启动,环境变量必须显式传进容器/服务单元里,而不是只在你本机 shell 里 export 了一下——这是最常见的翻车点。排查顺序:先在容器里执行 env | grep OPENAI 确认变量真的存在,再看 litellm_config.yaml 里的字段名有没有拼错(区分大小写)。
遇到 429 频繁触发怎么办?
先看是单个上游 key 的限额问题还是模型本身在限流。如果是前者,配置多个 key 用 usage-based-routing 分流;如果是模型全局限流(尤其是刚发布的新模型,官方限额通常比老模型低很多),只能降低并发或者加排队机制,硬重试只会让 429 更密集。num_retries 配太高在这种场景下反而是帮倒忙。
请求超时报 Timeout 或者卡住不返回,怎么定位?
先确认是网络层问题还是模型本身推理慢。用 curl 直接打上游 API(跳过 LiteLLM)测一次耗时,如果直连也慢,说明是模型或网络的问题,调大 router_settings.timeout 即可;如果直连快但走 Proxy 慢,大概率是 Proxy 自身负载过高或者 fallback 链配置有问题导致多次无谓重试,看日志里这一次请求实际打了几个上游。
遇到 ContextWindowExceededError(上下文超限)怎么处理?
这是模型的硬限制,跟 LiteLLM 无关,说明你这次请求的 prompt + 历史消息加起来超过了该模型的上下文窗口。LiteLLM 不会帮你自动截断消息,需要业务层自己做历史消息裁剪或者摘要压缩。如果你的 fallback 链里配置了上下文窗口更大的备用模型,倒是可以利用 fallback 机制在超限时自动切换过去,但这属于「治标」,长期看还是得在业务层控制好上下文长度。
中文返回出现乱码或者被截断,是什么原因?
基本是两类:一是客户端没有正确处理流式分片,把 UTF-8 多字节字符从中间切断打印,看起来像乱码,实际数据是完整的,检查你的流式拼接逻辑;二是 max_tokens 设置得太小,模型在句子中途被截断,这种情况看返回的 finish_reason 字段,如果是 length 而不是 stop,就是被截断了,调大 max_tokens 或者做续写处理。
延伸阅读:
不想自己运维 LiteLLM?申请力达云聚合 API 内测,托管方案开箱即用,无需配置服务器。