☰
Litellm 网关层详解:统一 OpenAI、Claude、Gemini 等模型接口
2026/10/14 8:20:16 网站建设 项目流程

Litellm 这个名字,我建议所有做 AI 应用的后端开发都先记下来。它不是一个"AI 神器"或者花哨的提示词工具,而是一个被很多团队实打实用了很久的 LLM 网关层。一句话概括:它把 OpenAI、Anthropic、Google、Azure,以及各类基于 OpenAI 协议的开源模型服务,全部统一成一套 OpenAI 兼容接口,让你用一份代码、一个地址去调用所有模型。我最初接触 litellm,是因为一个内部工具要同时接入 GPT 系列、Claude 和本地部署的开源模型做效果对比。原本每个人对接方式都不一样,参数命名也不统一,有的叫 max_tokens,有的叫 max_output_tokens,有人在代码里对着各家文档疯狂做 if else 适配,看着就头疼。后来项目里有人提议用 litellm 把这一层收敛掉,结果证明这几乎是当时最正确的决定。

它适合谁?后端开发、AI 应用工程师,或者带一个小团队做 AI 产品的人。如果你手上同时有多个模型提供方的 key,想统一管理调用、路由、限流和成本,又不想自己写一个完整的适配层和网关,litellm 是同类方案里最省事的一个。下面我把它的核心原理、部署模式、进阶配置,以及我在实际使用中踩过的坑完整讲一遍,希望你能少走点弯路。

1. litellm 到底在做什么:统一接口背后的三种能力

1.1 接口差异是真实痛点,不是矫情

很多人觉得"各家 API 不就是换个 URL 和鉴权头嘛",真去接的时候才知道不是这么回事。OpenAI 的 Chat Completions 返回结构是 choices 数组里套 message,Anthropic 的 Messages API 返回结构是 content 数组,Google 那边又是另一种 JSON 结构,流式输出的格式更是五花八门。更烦人的是参数名。OpenAI 用 max_tokens,Google Gemini 用 max_output_tokens,OpenAI 的 system prompt 是 messages 里的 system role,Anthropic 是单独一个 system 字段,Claude 还有 temperature、top_p 支持范围也不一样。工具调用(function calling)在各家的定义更是各玩各的。

这些差异单看哪一个都不难适配,难点在于你要维护的模型数量一多,组合数就爆炸了。今天业务方说"把默认模型从 4o 换成 Sonnet",你不仅要改配置,还得确认代码里有没有用到不受支持的参数,有没有读取响应里某个字段。模型换成 Gemini,又要重新看一遍文档。这种适配工作极其消耗精力,而且没有任何业务价值,纯属给生态分裂买单。

1.2 请求改写、响应还原、流式兼容

litellm 做的事,本质上就是把你和各家 SDK 之间做一个翻译层。你只管用 OpenAI 风格发请求,它内部把请求改写成目标模型服务商认识的格式,再把响应还原成 OpenAI 风格给你。具体拆开是三件事:

第一是请求改写。你在 litellm 里传 model 参数的时候带上供应商前缀,比如 claude-3-5-sonnet、gemini/gemini-1.5-pro、ollama/llama3.1:8b,它根据前缀找到对应的供应商,把 messages、temperature、max_tokens、tools 这些参数映射成目标 API 的字段。比如传过去的 max_tokens 会被翻译成 Gemini 的 maxOutputTokens,tools 会被改写成对方认识的 tool 定义格式。

第二是响应还原。各家返回的 token 用量、角色字段、内容位置都不一样,litellm 统一转成和 OpenAI SDK 一致的 response 结构。你在代码里response.choices[0].message.content拿内容,不管背后是哪个模型,写法完全一样。这一点对业务代码的稳定性影响很大,换模型的时候大部分代码根本不用动。

第三是流式兼容。各家流式接口的 SSE 事件格式不同,Anthropic 是 event 流,OpenAI 是 choices 增量,litellm 把后端的流翻译成 OpenAI 的 chunk 格式。你客户端只要按 OpenAI 的方式解析 stream 就行。

这就是为什么我说它更像"翻译层"而不是"SDK 封装"。SDK 只是替你说了一门语言,翻译层是你说一种语言,它能把你的话转给所有语种的人。

1.3 为什么不建议自己写适配层

当然,自己写也不是不行,能跑,但你会很快遇到几个问题。

首先是知识成本。你要维护各家 API 的变更,今天这个供应商把某个字段 deprecated,明天那个改了限流策略,光跟踪文档就够喝一壶的。litellm 背后有一套持续跟进的维护机制,这些信息它帮你消化掉了。

其次是功能扩展。你要做故障转移、负载均衡、预算控制、虚拟 key,全部自己写的话,工作量不比业务系统小。litellm 这些基本都内置了,你只需要填配置。

最后是团队协作。你自己写的适配层,注释水平取决于当时写代码的人状态,人一走就是灾难。litellm 是开源项目,有社区、有文档、有 issue 沉淀,后来的人接手成本低得多。所以"自己写更可控"这个想法,我建议只停留在"我试过之后真的后悔了"这个阶段就够了。

2. 核心组件与部署形态:SDK、Router、Proxy 三件套

2.1 三种使用方式,定位完全不同

litellm 不是一个单一形态的库,它有三种典型用法,对应不同需求。

第一种是当作 Python SDK 直接在代码里用。litellm.completion(model="gpt-4o", messages=messages)这种方式适合快速验证、写脚本、在单机应用里直接用。不需要起服务,装个 pip 包就行。

第二种是 Router 模式。它在 SDK 之上加了一层路由能力,你可以同时配置多个模型、多个 key、多个供应商,Router 负责负载均衡、健康检查、失败重试和故障转移。适合需要高可用的业务服务,在代码里初始化一个 Router 实例,然后到处调用。

第三种是 Proxy 模式,这是团队使用最推荐的方式。litellm 启动一个独立的服务,暴露 OpenAI 兼容的 HTTP 接口,你现有的 OpenAI SDK、LangChain、或者其他任何支持自定义 base_url 的工具,直接把地址指向 litellm 就行。业务方根本不需要知道自己背后接的是什么模型,也不需要安装 litellm。所有 key 管理、限流、日志都在网关这一层完成。

这三种模式可以叠加。有了 Proxy 之后,Router 的故障转移能力依然可以配置在网关层,SDK 则退化成业务方手里的通用客户端。

2.2 Proxy 模式的定位:团队里的"唯一出口"

Proxy 模式我最看重的一点,是它把模型供应商的 key 从业务代码里剥离了。没有网关之前,每个项目都要配置 OPENAI_API_KEY,有人还直接把 key 硬编码在代码里或写进前端请求。有了 litellm 做网关,业务方只需要知道一个网关地址和一个虚拟 key,真正的供应商 key 全部锁在网关配置里,权限收敛了很多。

另一个价值是对所有模型调用做统一观测。所有请求都经过 Proxy 这个唯一出口,自然就能记录每次调用的模型、耗时、token 用量和费用,哪个团队在烧钱一目了然。如果你准备让公司里多个项目组共用一套模型资源,这个价值比省那点适配代码重要得多。

2.3 模型别名与路由的玩法

litellm 配置里有个关键概念叫 model_name 和 litellm_params 分离。你可以给一个模型起个业务别名,比如 model_name: "company-main" 实际指向 litellm_params 里的 gpt-4o,还可以让同一个 model_name 指向多个真实模型,由 Router 做分配。这样业务方永远只认你的逻辑名称,底层换模型、加并发副本,业务方完全无感。

这个设计很实用。比如你担心"gpt-4o"这个 API 模型名在未来被上游废弃,业务侧代码又写死了字符串,那就在 litellm 里定义一个别名即可,底层换成新版本模型,一行配置的事,业务代码都不用动。

3. 实操入门:从安装到把请求打通的完整过程

3.1 安装与第一个 completion 请求

安装很简单,pip 直接装:

pip install litellm

装完之后,先确认环境变量里有对应的供应商 key。比如要调 OpenAI,就设置:

export OPENAI_API_KEY=你的key

然后写个最简单的调用:

import litellm response = litellm.completion( model="gpt-4o", messages=[ {"role": "system", "content": "你是一个简洁的助手"}, {"role": "user", "content": "用一句话解释什么是路由器"} ], temperature=0.3 ) print(response.choices[0].message.content)

跑通这一小段,说明 安装、鉴权、请求翻译 全部正常。

如果要同时调 Anthropic,不用改代码,只需要把 model 参数换成claude-3-5-sonnet,并且在环境变量里加上 ANTHROPIC_API_KEY。这就是统一接口最大的直观感受:代码不动,换模型只换字符串。

再复杂一点,你可以请求流式输出:

response = litellm.completion( model="gpt-4o", messages=[{"role": "user", "content": "写一段 200 字的产品简介"}], stream=True ) for chunk in response: delta = chunk.choices[0].delta.content if delta: print(delta, end="")

流式输出的 chunk 已经被 litellm 标准化成 OpenAI 风格,直接按 OpenAI 的解析方式处理就行了。

3.2 用配置文件把 proxy 跑起来

SDK 模式适合单人用。如果要多团队共用,或者想统一收口 key 和策略,得用 Proxy 模式。

先创建一个配置文件,比如 proxy_config.yaml:

model_list: - model_name: gpt-4o litellm_params: model: gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: sonnet litellm_params: model: claude-3-5-sonnet api_key: os.environ/ANTHROPIC_API_KEY - model_name: gemini-pro litellm_params: model: gemini/gemini-1.5-pro api_key: os.environ/GEMINI_API_KEY general_settings: master_key: sk-gateway-master-001

注意 model_name 不带供应商前缀,它是暴露给业务方的"逻辑名称";litellm_params.model 才是带前缀的真实模型标识。api_key 可以写成 os.environ/环境变量名,litellm 会自动从环境变量读取,避免把密钥明文写进配置文件。

然后启动:

litellm --config proxy_config.yaml --port 4000

启动后,litellm 会监听 4000 端口。你可以直接 curl 验证:

curl http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-gateway-master-001" \ -d '{ "model": "gpt-4o", "messages": [{"role": "user", "content": "你好"}] }'

如果配置没问题,这里返回的 JSON 结构和 OpenAI 官方接口基本一致。这就是整个网关的核心入口。

3.3 用 OpenAI SDK 接入 litellm Proxy

网关起来之后,业务方接入非常傻瓜。任何一个支持自定义 base_url 的 OpenAI SDK 都可以直接用,不需要安装 litellm。

from openai import OpenAI client = OpenAI( base_url="http://localhost:4000/v1", api_key="sk-gateway-master-001" ) response = client.chat.completions.create( model="sonnet", # 这是配置里的逻辑名称 messages=[{"role": "user", "content": "介绍一下你自己"}] ) print(response.choices[0].message.content)

这里最关键的一点是,model 参数传的是配置文件里的 model_name,而不是真实的供应商模型名。业务方只需要知道"我调用 sonnet 这个逻辑名",至于 sonnet 背后是 Claude 哪个版本、key 是哪个、会不会被路由到别的模型,都是网关侧的事。

LangChain 也一样,设置 OpenAIChat 时把 base_url 指向 litellm 网关即可。对已有项目来说,改动量很小。

3.4 接入本地模型和 OpenAI 兼容服务

生产环境经常要接私有化部署的模型,比如用 vLLM、SGLang 起了个 OpenAI 兼容服务。litellm 对这类服务支持很直接,配置里用openai/前缀再指定 api_base 就行:

model_list: - model_name: qwen-local litellm_params: model: openai/qwen2.5-72b-instruct api_base: http://127.0.0.1:8000/v1 api_key: fake-key

这样本地模型也进入了统一路由,业务方调 qwen-local 就能同时用上远程和本地模型,故障转移也能把流量从远程模型切到本地模型。还有一类常见的本地服务是 Ollama,前缀换成ollama/:

- model_name: llama-local litellm_params: model: ollama/llama3.1:8b api_base: http://localhost:11434

接入门槛同样很低,Ollama 服务跑起来,litellm 配好,业务方就是一个新的模型名。

4. 进阶配置:成本、限流、故障转移与可观测性

4.1 成本统计与预算设置

模型调用成本是很多团队忽略的隐性炸弹,尤其是做批量任务时,一个循环调几万次接口,月底账单能让人当场社死。litellm 对成本追踪做得很细。

代码里直接拿响应算钱:

import litellm from litellm import completion_cost response = litellm.completion(model="gpt-4o", messages=[...]) cost = completion_cost(completion_response=response) print(f"本次调用花费: ${cost:.6f}")

它内部自带一份常见模型的价格表,会根据 prompt tokens 和 completion tokens 分别计算。对自定义模型,你可以在配置里补充 model_info:

model_list: - model_name: my-custom-model litellm_params: model: openai/qwen2.5-72b-instruct api_base: http://127.0.0.1:8000/v1 api_key: fake-key model_info: input_cost_per_token: 0.000002 output_cost_per_token: 0.000006

在 Proxy 模式下,还可以给每个虚拟 key 设置预算上限,一个团队一个 key,预算一超直接拒绝请求,防止有人写个 bug 导致整个账号半夜刷爆。

4.2 限流和并发控制

很多供应商对 API 有 RPM、TPM 限制,尤其是共享账号时,一不小心就触发 429。litellm 的路由层可以做两层控制。

第一层是全局并发控制。在配置里限制整个网关的最大并发请求数,防止业务高峰把后端供应商打爆:

general_settings: max_parallel_requests: 100

第二层是 per-key 限制。生成虚拟 key 时,可以指定这个 key 允许的模型范围、预算上限、每分钟请求数。这个虚拟 key 的速率限制是在网关侧执行的,不会被供应商的限流策略突然打断。

实际操作中,我倾向于把限流值设置得比供应商限制激进一些,比如供应商允许 60 RPM,我就在网关侧设 50 RPM,留出余量给重试和并发波动,避免一堆请求同时撞墙。

4.3 故障转移与重试

这是 Router 和 Proxy 模式下最有价值的功能。一个模型挂了、被限流了、或者响应超时,litellm 可以自动把请求转到备用模型。

在 Proxy 配置里加 router_settings:

router_settings: fallbacks: [ {"gpt-4o": ["sonnet", "gemini-pro"]}, {"sonnet": ["gpt-4o"]} ] num_retries: 2 retry_after: 2

意思是:当 gpt-4o 失败时,尝试转到 sonnet,再不行转到 gemini-pro;每个模型节点最多重试 2 次,重试间隔 2 秒。这样业务方调用时完全感知不到故障,只看到最终成功了。

配合 Retry 机制一起看,它是先重试同节点,再转移节点。设置重试次数和转移策略时要注意一个现实问题:如果请求内容很长,重试成本会翻倍。所以对长上下文的请求,我的建议是重试次数不要超过 1,转移顺序把成本更低的模型放前面。

4.4 日志、Trace 与回调

没有观测的网关等于没有网关。litellm Proxy 本身就带请求日志,你可以把成功和失败回调接到自己的可观测系统里。代码模式下,用回调就够:

litellm.success_callback = ["langfuse"] response = litellm.completion( model="gpt-4o", messages=[{"role": "user", "content": "记录一次调用"}] )

回调会自动把 token 数、模型、耗时、成本等元数据送出去,不需要在业务代码里埋点。

Proxy 模式下还有两个比较实用的端点:一个是 /health,用来做网关的健康检查;另一个是 /models,用来列出当前网关所有可用的逻辑模型名。接入负载均衡或者给前端展示模型列表时,这两个端点很省事。

5. 踩坑实录:最常遇到的五个问题与排查思路

5.1 model_name 对不上导致的 404

第一次用 Proxy 的人,十有八九会遇到这个。你在代码里明明用的是 "claude-3-5-sonnet",但配置里 model_name 定义的是 "sonnet",结果请求返回 404 或者模型不存在。

原因很简单:Proxy 只认配置里的 model_name,不认供应商的真实模型名。你的逻辑名字和配置不一致,网关层根本不知道这个模型是什么。

排查思路分两步:先 curl /models 看看网关实际暴露了哪些模型名,再检查请求体里的 model 字段是否和配置的 model_name 完全一致。这个完全一致包括大小写、连字符,一个字符都不能差。我们当时就在配置里写了两个 gpt-4o 的定义,一个带版本后缀一个不带,结果请求方用错名字找了大半天。

5.2 超时问题:长输出和高延迟模型

litellm 默认超时时间比较短,遇到长输出任务,比如让模型生成 2000 行代码,或者用 Claude 处理超大上下文,请求很容易在网关层被掐掉。当时我们内部跑一批长文本生成任务,8 个请求里能有 3 个超时,第一反应是模型太慢,后来发现是网关把请求给截了。

解决方式是在 litellm_params 里加超时配置:

- model_name: sonnet litellm_params: model: claude-3-5-sonnet api_key: os.environ/ANTHROPIC_API_KEY timeout: 600

或者全局设置:

litellm_settings: request_timeout: 600

我的习惯是,短交互模型设 60 秒,处理长文档的模型设 600 秒起步。另外要注意,超时设置是透传到供应商的,设太短真正吃亏的是你自己,该给长任务留的余量一定要留够。

5.3 key 管理不当带来的鉴权问题

用 Proxy 模式就要明确 master_key 和业务方 key 的区别。master_key 是高权限的管理 key,可以调用配置管理接口、生成虚拟 key。业务方用的是虚拟 key,权限范围受创建时设定的模型和预算约束。

我们早期图省事,让业务方直接用 master_key 调接口,后来发现日志里分不清是谁在调,没法做预算拆分,还担心 key 泄露影响整个网关。后来统一改成虚拟 key 方案,每个团队一个 key,出了问题一键撤销,再也不用全局换 key 了。

如果你发现某个请求 401,先确认这个 key 有没有被授权调用对应模型。虚拟 key 的权限是创建时就锁定的,不是所有模型都能调。

5.4 参数不兼容与 drop_params

不同模型对参数的支持程度不同。比如某个模型不支持 top_p 或者 frequency_penalty,你按 OpenAI 的习惯传了,供应商可能直接报错拒绝。litellm 会在翻译层尽量映射已知参数,但总有覆盖不到的角落。

最简单的兜底方案是打开 drop_params:

litellm_settings: drop_params: true

打开之后,litellm 会把目标供应商不支持的参数悄悄丢弃,而不是把请求硬传过去收到 400 错误。这个开关在对接开源本地模型时尤其好用,因为本地模型的参数支持往往比云端 API 少很多。

5.5 流式请求的坑

Proxy 模式下,流式请求经常遇到的问题不是不通,而是"看起来不通"。业务方用 requests 库直接调网关,传了 stream: true,然后收到一整块 JSON 而不是分块的 SSE 流,就以为出了问题。

其实这是正常的。litellm 会把后端供应商的流转换成 OpenAI 风格的 SSE 分块,但你必须用支持 SSE 的客户端去解析,比如 OpenAI SDK 的 stream=True 模式,或者自己按 SSE 协议解析 data 行。我建议团队统一约定:流式请求一律走 OpenAI SDK,不要自己拼 HTTP 请求,省掉的麻烦比想象中多。

还有个细节:如果网关后端的模型本身不支持流式,litellm 会把整个响应缓冲完之后一次性吐给你,这时候即使响应成功,客户端看到的也不是增量输出。做实时打字机效果前,记得确认后端模型真的支持流式。

6. 什么场景适合上 litellm,什么场景要慎重

6.1 适合上 litellm 的情况

如果你的项目符合这几条里的任意两条,litellm 基本是值得引入的:

一是多供应商接入。手上有两个以上模型的 key,并且经常要做对比、切换、容灾。二是多团队共享资源。多个项目组要用同一个模型账号,需要统一发 key、限制预算、按团队拆分成本。三是对稳定性有要求。单个模型提供方不可用的时候,希望业务能自动切换备用模型。四是希望沉淀统一观测。想让所有模型调用都有日志、trace、成本记录,而不是每个项目各记各的。

我自己的经验是,litellm 最适合作为团队基础设施来建设,而不是某个项目的临时依赖。一旦它成为全组统一的模型接入层,后续新增模型就是改配置、刷新列表的事,效率提升是肉眼可见的。

6.2 要慎重的情况

反过来,有几种情况我不建议上来就上 litellm。

第一个是只有一个模型、一个人用、调量也不大的小脚本项目。为这种场景起一个网关服务,引入配置和运维成本,是自找麻烦。你直接用 litellm SDK 或者干脆用官方 SDK 就好。

第二个是对响应格式有高度定制需求的场景。虽然 litellm 能做很多自定义,但如果你和模型供应商签了私有协议、有大量定制字段,可能有部分特性在统一接口下覆盖不到,这时候原生的供应商接口反而更直接。

第三个是团队没有运维能力却硬上 Proxy 模式。网关是会挂的,高可用、升级、日志存储都需要人,把网关做成单点反而比不做好。小团队建议先用 SDK 模式,等规模上来再演进。

7. 写在最后:几点使用体会

最后分享几个我自己的体会。

配置文件的版本管理很重要。litellm 的配置本身就是代码,我们把它放进 Git 仓库,改模型路由、加新模型都走代码评审流程。这样任何一次变更都有记录,出了问题能回溯。这个习惯帮我们避免过一次"误把生产流量切到未验证模型"的意外。

第二个体会是关于"过度路由"的。不要把路由规则设计得太花哨,什么按用户 tag 走不同模型、按消息长度动态选模型,听着很聪明,实际排障的时候会让你疯掉。我们后来收敛到最简单的策略:默认模型 + 故障转移顺序,复杂路由只留给特定业务线。简单才是可持续的。

最后,litellm 迭代很快,文档是跟着版本变的。看到新功能不要急着上生产,先在测试环境用几天,观察日志和成本表现再切流量。我在实际使用中一直保持"先读 changelog 再升级"的习惯,这个习惯让我避开了好几次不兼容更新的雷。你如果正在规划团队的模型接入方案,litellm 值得花一个下午跑通全流程,这笔时间投入会很值。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询