快速结论:当多个 deployment 指向同一个 provider model 时,LiteLLM Router 会把它们注册到同一个共享的 litellm.model_cost 条目中,model_info.mode 因此被写成对该 provider model 全局生效的值。只要有一个 deployment 注册了 mode: "responses",同 provider model 的其他 deployment 就可能被改走 Responses API 桥接,表现为间歇性 400。
适用环境:Issue 确认的工具为 LiteLLM(问题影响 v1.87.0+,复现环境为 v1.97.0);多 deployment 共享同一 provider model、单 Pod 代理与多 Pod 负载均衡场景均有涉及。Issue 未给出具体的操作系统、Python、CUDA、显卡或依赖版本信息。
最快修复方案:暂无确认的一步修复方案。Issue 指出 #46263 已合并,修复后 deployment 自身的 mode 决定其路由;在包含该修复的版本上,删除并重建受影响的 deployment 是 Issue 中唯一被提到的恢复路径。
注意事项:删除 deployment 后共享 key 不一定会立即清除,需要等 cost map 重建(例如重启);POST /reload/model_cost_map 只作用于处理该请求的 Pod,在多 Pod 负载均衡下无法清空全部 Pod。POST /model/update 返回 200 但会静默忽略 model_info.mode,因此不能在原记录上直接改写 mode。
问题场景
用户在 LiteLLM Router 中配置了多个 deployment,这些 deployment 即使 model_name 不同、属于不同团队、使用不同的 virtual key,只要指向同一个 provider model,就会共享 litellm.model_cost 中的同一条“shared backend key”。当其中一个 deployment 以 mode: "responses" 注册后,其他 deployment 的请求也可能被 responses_api_bridge_check 判定为走 Responses API(该检查按 provider model 名查找 mode,而不是按 model group)。
Issue 中的实际影响是:新增一个用于评估的 responses deployment,导致一个已在生产运行的 model group 被切到 Responses API,凡是依赖 response_format: {"type": "json_object"} 且只在 system message 中出现 “json” 的请求开始失败。由于注册按 Pod 发生,故障表现为间歇性错误,容易被误判为上游服务商的偶发问题。
报错原文
Response input messages must contain the word 'json' in some form
to use 'text.format' of type 'json_object'. ("param": "input")
同一 deployment、同一 payload 在多 Pod 负载均衡下的日志表现如下:
iter1 400 Response input messages must contain the word 'json' ... 'text.format' <- Responses
iter2 400 Response input messages must contain the word 'json' ... 'text.format' <- Responses
iter3 200 <- Chat
iter4 400 Response input messages must contain the word 'json' ... 'text.format' <- Responses
原因分析
根本原因在于 model_info.mode 被存放在按 provider model 共享的 model_cost 条目中,而不是按 deployment 独立保存。v1.87.0 引入的逻辑会阻止已有 shared mode 被清除:
- 当已有 shared mode 为
"responses"、新 deployment 的 mode 为"chat"时,保留原值; - 当已有 shared mode 非空、新 deployment 未提供 mode 时,同样保留原值。
因此一旦某个 deployment 写入 mode: "responses",后续无论是注册 chat 还是省略 mode,都无法把它改回或清空。随之而来的路由偏差会让 Chat Completions 原本合法的 system message 在 Responses API 下变成 instructions,不再属于 input,从而触发上述 400。
此外,GET /model/info 返回的是数据库记录而不是运行时的共享 key 状态,因此受影响的 deployment 配置看起来正常,难以从接口发现异常。删除 deployment 时 register_model 以 persist_across_reloads=False 调用,共享条目不会被主动 unset,需要重建 cost map 才可能消失。
环境排查
- 确认 LiteLLM 版本是否处于 v1.87.0 及以上,并检查是否已包含 #46263 的修复。
- 确认是否存在多个 deployment 指向同一 provider model(包括不同
model_name、不同团队、不同 virtual key 的情况)。 - 检查是否有任一 deployment 配置了
model_info.mode: "responses",即使是用于临时评估的 deployment。 - 确认部署是否为多 Pod 架构,以及负载均衡下的请求是否分散到不同 Pod。
- Issue 未提供 Python、CUDA、PyTorch、显卡或依赖版本信息,这些项目在本次排错中不作为确认依据。
解决步骤
- 先排查所有指向同一 provider model 的 deployment,重点找出注册了
mode: "responses"的 deployment,包括评估或临时用途的配置。 - 升级到包含 #46263 修复的 LiteLLM 版本;Issue 说明修复后 deployment 自身的 mode 决定其路由。
- 删除受影响的 deployment 并重新创建。注意
POST /model/update返回 200 但会静默忽略model_info.mode,因此不能通过更新接口原地修正 mode。 - 如果使用多 Pod 部署,删除并重建后需要在全部 Pod 上确保共享条目被清除。重启可触发 cost map 重建;
POST /reload/model_cost_map只能作用于处理该请求的 Pod,不能作为清空整个集群的手段。 - 重新创建 deployment 时避免沿用会触发 ratchet 的旧
responsesmode,并确认新配置中的 mode 与预期执行路径一致。
验证方法
用与 Issue 复现中相同的 response_format: {"type": "json_object"} 请求,在 system message 中仅包含 “json” 字样,对目标 model group 多次发起请求。应稳定返回 200,而不是在多 Pod 间交替出现上述 400。若仍需验证路由,可对比同一 deployment 在多个 Pod 上的行为是否一致;Issue 中 GET /model/info 不反映运行时共享 key 状态,因此不宜单独作为验证依据。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


