LiteLLM 接 Claude:三条路由路径、参数映射与那些像 bug 的坑
LiteLLM 夹在你的应用和模型提供方之间,用一套统一接口——通常是 OpenAI 那套形状——去访问多个后端。把它指向 Claude 是很多团队装 LiteLLM 的首要原因,同时也是配置最容易绕晕的地方:因为 LiteLLM 能通过好几条不同的路径连到 Claude,而这几条路的行为并不一致。
这篇把这些路径、各自需要的配置、哪些参数能翻译过去哪些不能,以及那些「看起来像 bug、其实是映射缺口」的故障形态,一次讲清。
LiteLLM 到底在做什么
LiteLLM 有两种形态,动手写配置之前先分清:
- Python SDK。 你在代码里 import 它,调用
completion()。从统一调用签名到具体提供方请求的转换,发生在进程内。 - Proxy 代理服务。 你把它作为独立服务跑起来,对外暴露一个 OpenAI 兼容的 HTTP 端点。你的应用像调 OpenAI 一样调这个端点,LiteLLM 在后面路由到真实提供方。
单个应用用 SDK 更简单。当多个服务、或者你改不动的第三方工具需要经由一个网关访问模型时,就该用 proxy——因为任何能被指向一个 OpenAI base URL 的东西,都能就此访问到 Claude,而它本身完全不需要知道 Claude 的存在。
连到 Claude 的三条路
|
路径 |
怎么配 |
适合什么情况 |
|---|---|---|
|
直连 Anthropic |
|
你有直接账号,想走最短路径 |
|
经云厂商 |
Bedrock 或 Vertex 的模型前缀 + 该云的凭据 |
组织已经通过该云采购模型 |
|
经 OpenAI 兼容网关 |
自定义 base URL + 该网关的 key |
你走内部或第三方端点中转 |
模型字符串就是路由决策。 anthropic/claude-... 走 Anthropic API;Bedrock 前缀走 AWS;覆盖 base URL 就把请求发往你指定的地方。碰到 model not found,几乎总是前缀和凭据对「你指的是哪个后端」这件事产生了分歧。
最小可用配置
SDK 形态,关键就是模型字符串和 key:
from litellm import completion
response = completion(
model="anthropic/claude-sonnet-5",
messages=[{"role": "user", "content": "帮我把这份 changelog 总结一下。"}],
max_tokens=1024,
)proxy 形态,在配置文件里声明模型,然后把服务起起来:
model_list:
- model_name: claude-sonnet # 你的应用会用这个名字来请求
litellm_params:
model: anthropic/claude-sonnet-5 # 真实的后端模型
api_key: os.environ/ANTHROPIC_API_KEY这个「两个名字」的结构正是 proxy 的价值所在:应用请求 claude-sonnet,而它实际映射到哪个真实模型,你改配置就行,不用动应用代码。要有意识地用好它——代码里放稳定的别名,真实模型标识只出现在配置里。
哪些能干净地翻译过去,哪些不能
大部分意外都在这一节。OpenAI 的请求形状和 Anthropic 的,像到让人以为可以互换,又在若干具体位置不同到会直接报错。
能干净翻译的:
user/assistant角色的基础对话消息max_tokens、temperature、stream- 常见情况下的工具/函数定义与工具调用返回
- 响应里的用量统计,会被归一化成一致的结构
需要留神的:
- System prompt。 OpenAI 把系统指令作为
role: "system"的一条消息带着;Anthropic 把它作为顶层的独立参数。LiteLLM 会做转换,但如果你在检查原始请求、或者写了会操作 message 数组的中间件,别假设你发出去的数组就是最终发往模型的数组。 - Anthropic 强制要求
max_tokens。 OpenAI 把它当可选。一个在 OpenAI 上跑得好好的调用,可能仅仅因为你从没设过它,在 Claude 上就失败。显式设置,别依赖默认值。 - 消息必须交替。 Anthropic 期望 user 与 assistant 轮次交替,且对话以 user 轮开始。随手拼出来的历史——连续两条 user 消息、开头是 assistant 消息——是 400 错误的常见来源。
- OpenAI 独有参数。 那些在 Anthropic 侧没有对应物的参数,会被丢弃还是被拒绝,取决于你的设置,由
drop_params控制。静默丢弃在开发阶段很方便,在生产环境很危险——你以为在控制模型行为的某个参数,可能根本没送到模型那里。 - Prompt caching 等提供方特有能力。 这些要用提供方原生的术语来配。别假设统一接口一定把它暴露出来了,查一下 LiteLLM 当前对该具体特性的支持情况。
流式输出
流式是能用的,proxy 会把 Anthropic 的事件流归一化成 OpenAI 风格的 chunk,让 OpenAI 形状的客户端代码继续照常工作。有两件事请在你自己的环境里验证,别想当然:
- 流式响应里的用量数据。 流式模式下 token 计数的到达方式不一样。如果你要按用量计量或计费,确认在流式路径上确实收到了这些数字,而不只是在非流式路径上收到。
- 流式下的工具调用。 工具调用的参数是分片到达的,必须先累积完整再解析。对每个 chunk 都去
json.loads()的代码会间歇性失败——这看起来像模型有问题,其实不是。
建议一开始就配好的运维项
- Fallback(降级链)。 定义一个有序的 fallback 列表,让某个提供方故障时是「降级」而不是「失败」。这是 proxy 相对直接用 SDK 最有力的理由之一。
- 重试与超时。 显式设置。适合快速模型的默认值,不适合长文本生成。
- 按 key 的预算与限流。 proxy 能签发带各自额度的虚拟 key,这是阻止某个行为异常的服务吃光共享配额的办法。
- 日志。 尽早打开请求日志。一旦出现翻译层的问题,你要问的永远是「LiteLLM 实际发出去的是什么」,没有日志就只能靠猜。
常见报错与它们通常意味着什么
|
现象 |
通常的原因 |
|---|---|
|
|
模型字符串的前缀与该后端配置的凭据对不上 |
|
同样的请求在 OpenAI 正常、在 Claude 报 400 |
缺 |
|
某个参数看起来完全不起作用 |
它在翻译中被丢掉了——查 |
|
key 明明有效却报鉴权错误 |
key 配给的是 A 后端,而模型前缀路由到了 B 后端 |
|
工具调用非流式能解析、流式就失败 |
chunk 参数还没累积完就去解析了 |
什么时候 LiteLLM 是错的那一层
LiteLLM 是翻译与路由层。有两类问题,人们常拿来找它,但它不该负责:
- 要把某个提供方的特有能力用到最深。 如果你的应用依赖只在某一家原生 API 里存在的特性,统一接口永远会滞后于它。这条路径直接调那家的 API。
- 不同模型之间的 prompt 与行为差异。 换个模型字符串不会让两个模型表现一致。统一接口让调用可移植,不让输出等价,你的评测仍然要按模型分别跑。
常见问题
LiteLLM 的 SDK 和 proxy 有什么区别?
SDK 是你在应用内部调用的 Python 库;proxy 是一个独立服务,对外暴露 OpenAI 兼容的 HTTP 端点并路由到真实提供方。单个应用用 SDK;当多个服务、或你改不动的工具需要经由一个网关访问模型时,用 proxy。
用 LiteLLM 接 Claude,需要改应用代码吗?
通常不用——前提是你的代码已经说 OpenAI 那套请求格式。把它指向 proxy 的 base URL,请求一个你在配置里映射到 Claude 的模型名即可。代码层面主要要预期的改动是显式设置 max_tokens,因为 Anthropic 要求它而 OpenAI 不要求。
为什么在 OpenAI 正常的请求,到 Claude 就返回 400?
最常见的两个原因:缺 max_tokens;以及消息数组没有做到「以 user 轮开始、user 与 assistant 交替」。这两点 OpenAI 都接受,Anthropic 都会拒绝。
路由到 Claude 时,我的 OpenAI 参数会被静默忽略吗?
有可能。在 Anthropic 侧没有对应物的参数,会被丢弃还是被拒绝,取决于你的 drop_params 配置。打开请求日志,这样你能看到实际传输了什么,而不是从行为去反推。
通过 LiteLLM 用 Claude,流式输出能用吗?
能——Anthropic 的事件流会被归一化成 OpenAI 风格的 chunk。请在自己的环境里验证两件事:流式路径上用量数据确实到达了你;以及工具调用参数在解析前已经跨 chunk 累积完整。
Claude 不可用时,LiteLLM 能自动切到别的模型吗?
可以。配置一个有序的 fallback 列表(放在 proxy 上最有用),这样故障或限流会降级到另一个后端,而不是直接让请求失败。
把 OpenAI 形状的流量路由到 Claude 时,下面那个端点和上面的客户端一样重要。ROIBest AI 提供面向 Claude 及其他模型的 OpenAI 兼容 API 端点,让那些只接受 base URL 加 key 的工具无需改代码即可访问。