fix(responses_bridge): map max reasoning effort instead of dropping it

_map_reasoning_effort enumerated none, minimal, low, medium, high and xhigh
but not max, so max fell through to the None return and never reached the
provider. Callers saw a normal 200 with default reasoning depth.

The per-level if/elif chain differed only by the literal it passed through,
so it is replaced by a membership check against the supported levels.
This commit is contained in:
liangliang_microsoft 2026-08-13 17:36:46 +08:00 • committed by Allen Liang
parent 09889e1986
commit 30df6d4bd8
2 changed files with 20 additions and 18 deletions

View file

@ -63,6 +63,9 @@ if TYPE_CHECKING:
from litellm.types.utils import Choices
_REASONING_EFFORT_LEVELS: Final = frozenset({"none", "minimal", "low", "medium", "high", "xhigh", "max"})
class _ReasoningSummaryText(TypedDict):
type: str
text: str
@ -1001,23 +1004,11 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
)
# If string is passed, map with optional summary based on flag/env var
if reasoning_effort == "none":
return Reasoning(effort="none", summary="detailed") if auto_summary_enabled else Reasoning(effort="none")
elif reasoning_effort == "high":
return Reasoning(effort="high", summary="detailed") if auto_summary_enabled else Reasoning(effort="high")
elif reasoning_effort == "xhigh":
return Reasoning(effort="xhigh", summary="detailed") if auto_summary_enabled else Reasoning(effort="xhigh")
elif reasoning_effort == "medium":
return (
Reasoning(effort="medium", summary="detailed") if auto_summary_enabled else Reasoning(effort="medium")
)
elif reasoning_effort == "low":
return Reasoning(effort="low", summary="detailed") if auto_summary_enabled else Reasoning(effort="low")
elif reasoning_effort == "minimal":
return (
Reasoning(effort="minimal", summary="detailed") if auto_summary_enabled else Reasoning(effort="minimal")
)
return None
if reasoning_effort not in _REASONING_EFFORT_LEVELS:
return None
if auto_summary_enabled:
return Reasoning(effort=reasoning_effort, summary="detailed")
return Reasoning(effort=reasoning_effort)
def _add_web_search_tool(
self,

View file

@ -1521,7 +1521,7 @@ def test_map_reasoning_effort_adds_summary_detailed():
handler = LiteLLMResponsesTransformationHandler()
# Test all string effort levels - DEFAULT BEHAVIOR (no summary)
effort_levels = ["none", "low", "medium", "high", "xhigh", "minimal"]
effort_levels = ["none", "minimal", "low", "medium", "high", "xhigh", "max"]
# Save original flag value
original_flag = litellm.reasoning_auto_summary
@ -3400,3 +3400,14 @@ def test_output_item_done_with_stream_map_keeps_empty_delta():
)
assert chunk.choices[0].delta.tool_calls is None
assert chunk.choices[0].finish_reason is None
def test_map_reasoning_effort_rejects_unknown_level():
"""An unrecognized effort must map to None so it is not forwarded upstream."""
from litellm.completion_extras.litellm_responses_transformation.transformation import (
LiteLLMResponsesTransformationHandler,
)
handler = LiteLLMResponsesTransformationHandler()
assert handler._map_reasoning_effort("banana") is None