快速结论:用 LiteLLM 通过 DeepSeek V4(Pro/Flash)发起请求时,无论传 reasoning_effort="high" 还是 "max",都会被丢弃并统一改写为 thinking: {"type": "enabled"},导致无法请求分级推理强度;优先排查 LiteLLM 的 DeepSeek 参数映射,以及走 openrouter/ 前缀时是否绕过了 DeepSeekChatConfig。
适用环境:Issue 已确认涉及 LiteLLM v1.83.x(2026 年 5 月的 main 分支)、litellm 1.81.14、litellm 1.99.0(proxy,drop_params: true);操作系统、Python、CUDA、显卡信息未在 Issue 中给出。
最快修复方案:暂无确认的一步修复方案。Issue 中相关修复 PR(#28134)未合入,后续替代 PR 未出现。可优先尝试的规避方式是改用直连 deepseek/ 路由而非 openrouter/ 路由,但该方式仅绕过第二类问题,并未验证能恢复 reasoning_effort 透传。
注意事项:DeepSeek API 只接受 none/minimal/low/medium/high/xhigh/max 这些取值;Issue 中的建议修复方案(low/medium→high、xhigh→max)是提议而非已合入代码。走 OpenRouter 时 reasoning_content="" 和缺失字段都会被拒(400),占位值可能需要非空,这一点尚未在 LiteLLM 代码中落地。
问题场景
用户通过 LiteLLM SDK 或 LiteLLM Proxy 调用 DeepSeek V4 Pro / V4 Flash(模型名如 deepseek-v4-pro、deepseek-v4-flash、deepseek/deepseek-flash),或通过 OpenRouter 前缀调用(openrouter/deepseek/deepseek-v4-pro、openrouter/~deepseek/deepseek-v4-flash-latest),并希望用 reasoning_effort 控制思考模式的推理强度时触发。第二种触发场景是思考模式下的多轮对话含 tool_calls:assistant 消息缺少 reasoning_content 或其为空字符串时,下一轮请求直接 400。
报错原文
DeepSeek V4 reasoning_effort ("high"/"max") not passed through to API — stripped to `thinking: {"type": "enabled"}`
OpenrouterException 400: The `reasoning_content` in the thinking mode must be passed back to the API.
reasoning_effort: unknown variant "bogus", expected one of "none", "minimal", "low", "medium", "high", "xhigh", "max"
原因分析
主要原因在 litellm/llms/deepseek/chat/transformation.py 的 DeepSeekChatConfig.map_openai_params():只要 reasoning_effort 非空且不是 "none",就固定写入 optional_params["thinking"] = {"type": "enabled"},传入的具体强度值被丢弃,因此 high 与 max 表现完全一致。
次要原因(可能原因):当模型以 openrouter/deepseek/... 或 openrouter/~deepseek/...-latest 形式调用时,litellm.get_llm_provider() 解析出 provider='openrouter',走的是 OpenrouterConfig 而不是 DeepSeekChatConfig。于是 reasoning_effort 的映射,以及 PR #26660 引入的 _ensure_reasoning_content_on_assistant_messages() 多轮 reasoning_content 补全逻辑,都不会生效。
Issue 评论中的实测进一步表明:OpenRouter 中继比 DeepSeek 官方 API 更严格。对带 tool_calls 的 assistant 消息,reasoning_content 缺失或为 "" 都返回 400,只有非空值才通过;而直连 deepseek/ 路径可以接受 "" 占位。
环境排查
- 确认 LiteLLM 版本:Issue 在 v1.83.x、1.81.14、1.99.0 上均有复现或相关确认。
- 确认调用前缀:
deepseek/...会路由到provider='deepseek',openrouter/...与openrouter/~...-latest会路由到provider='openrouter'。 - 确认 DeepSeek 侧记录的受支持
reasoning_effort取值:none/minimal/low/medium/high/xhigh/max。 - Proxy 场景确认
drop_params: true是否掩盖了参数被丢弃的问题。 - Python、CUDA、PyTorch、显卡版本与本题无直接关系,Issue 中未提供。
解决步骤
- 先定位问题属于哪一类:如果只是
high/max表现一致、无法区分强度,属于参数映射问题;如果多轮tool_calls报 400,属于 reasoning_content 问题。 - 用无效值做判别性测试:向 DeepSeek 官方端点发
"reasoning_effort": "bogus"。直连应返回 HTTP 422 并列出合法取值;如果经 LiteLLM 代理返回 HTTP 200 正常思考响应,说明该字段根本没被转发。 - 检查路由前缀。如果是
openrouter/路径,注意 DeepSeekChatConfig 的逻辑不会执行,此时需要评估是否改走deepseek/路由(可优先尝试)。 - OpenRouter 多轮
tool_calls场景下,确保 assistant 消息的reasoning_content为非空值(Issue 实测合成占位值可用),不要使用""。 - 等待官方修复:Issue 中 #28134 提供了归一化并同时发送
thinking与reasoning_effort的方案,但随后被废弃,替代 PR 未出现。升级前可在本地维护补丁或临时 fork,并注意后续版本变更。
验证方法
重新发送一次无效的 reasoning_effort(如 "bogus"):如果请求被 DeepSeek 以 422 拒绝,说明参数已实际转发;如果仍然 200,说明该值仍被 LiteLLM 消化。对多轮场景,构造一条带 tool_calls 且 reasoning_content 缺失或为空的 assistant 消息,确认下一轮不再返回 OpenrouterException 400。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。
![typing.Dict[str, X] return annotation is wrapped in {"result": ...}, unlike dict[str, X]](https://www.chat-gpts.plus/wp-content/uploads/2026/10/3745-7e2d6b6c-768x403.jpg)
![[BUG] LanceDBStorage.list_records() returns oldest records instead of newest first due to premature query truncation](https://www.chat-gpts.plus/wp-content/uploads/2026/10/7394-ea476651-768x403.jpg)
![[Bug]: decisions (typesafe): missing usage becomes zero cost, a 200 with an invalid body becomes a 500, and the error body is only in the me](https://www.chat-gpts.plus/wp-content/uploads/2026/10/48147-5054fca8-768x403.jpg)