fix(deepseek): map reasoning_effort=none to thinking disabled

DeepSeek V4 defaults to thinking mode when no thinking parameter is
set. When a user passes reasoning_effort="none", LiteLLM should
explicitly send thinking={"type": "disabled"} to turn off reasoning.

Previously, reasoning_effort="none" was silently ignored, leaving
the model in its default thinking-enabled state.

Also passes through thinking={"type": "disabled"} when set directly,
which was previously dropped by the enabled-only filter.

Fixes #27453
This commit is contained in:
Jonathan Wrede 2026-05-10 20:00:43 +00:00
parent 0af33fbe70
commit 0827eb1011
3 changed files with 101 additions and 9 deletions

View file

@ -47,18 +47,20 @@ class DeepSeekChatConfig(OpenAIGPTConfig):
thinking_value = optional_params.pop("thinking", None)
reasoning_effort = optional_params.pop("reasoning_effort", None)
# Handle thinking parameter - only accept {"type": "enabled"}
# Handle thinking parameter
if thinking_value is not None:
if (
isinstance(thinking_value, dict)
and thinking_value.get("type") == "enabled"
if isinstance(thinking_value, dict) and thinking_value.get("type") in (
"enabled",
"disabled",
):
# DeepSeek only accepts {"type": "enabled"}, ignore budget_tokens
optional_params["thinking"] = {"type": "enabled"}
optional_params["thinking"] = {"type": thinking_value["type"]}
# Handle reasoning_effort - map to thinking enabled
elif reasoning_effort is not None and reasoning_effort != "none":
optional_params["thinking"] = {"type": "enabled"}
# Handle reasoning_effort - map to thinking enabled/disabled
elif reasoning_effort is not None:
if reasoning_effort == "none":
optional_params["thinking"] = {"type": "disabled"}
else:
optional_params["thinking"] = {"type": "enabled"}
return optional_params

View file

@ -0,0 +1,90 @@
"""
Tests for DeepSeekChatConfig.map_openai_params thinking/reasoning_effort handling.
Regression tests for https://github.com/BerriAI/litellm/issues/27453
"""
import os
import sys
sys.path.insert(0, os.path.abspath("../../../.."))
import pytest
from litellm.llms.deepseek.chat.transformation import DeepSeekChatConfig
@pytest.fixture
def config():
return DeepSeekChatConfig()
class TestReasoningEffortNone:
"""reasoning_effort='none' should disable thinking."""
def test_reasoning_effort_none_disables_thinking(self, config):
result = config.map_openai_params(
non_default_params={"reasoning_effort": "none"},
optional_params={},
model="deepseek-v4-pro",
drop_params=False,
)
assert result["thinking"] == {"type": "disabled"}
def test_reasoning_effort_high_enables_thinking(self, config):
result = config.map_openai_params(
non_default_params={"reasoning_effort": "high"},
optional_params={},
model="deepseek-v4-pro",
drop_params=False,
)
assert result["thinking"] == {"type": "enabled"}
def test_reasoning_effort_low_enables_thinking(self, config):
result = config.map_openai_params(
non_default_params={"reasoning_effort": "low"},
optional_params={},
model="deepseek-v4-pro",
drop_params=False,
)
assert result["thinking"] == {"type": "enabled"}
class TestThinkingParam:
"""Direct thinking parameter should be passed through."""
def test_thinking_enabled(self, config):
result = config.map_openai_params(
non_default_params={"thinking": {"type": "enabled", "budget_tokens": 5000}},
optional_params={},
model="deepseek-v4-pro",
drop_params=False,
)
assert result["thinking"] == {"type": "enabled"}
def test_thinking_disabled(self, config):
result = config.map_openai_params(
non_default_params={"thinking": {"type": "disabled"}},
optional_params={},
model="deepseek-v4-pro",
drop_params=False,
)
assert result["thinking"] == {"type": "disabled"}
def test_thinking_strips_budget_tokens(self, config):
result = config.map_openai_params(
non_default_params={"thinking": {"type": "enabled", "budget_tokens": 5000}},
optional_params={},
model="deepseek-v4-pro",
drop_params=False,
)
assert "budget_tokens" not in result["thinking"]
def test_no_thinking_params_leaves_thinking_unset(self, config):
result = config.map_openai_params(
non_default_params={"temperature": 0.5},
optional_params={},
model="deepseek-v4-pro",
drop_params=False,
)
assert "thinking" not in result