Skip to content

Commit 7ff93cd

Browse files
committed
Revert "Merge pull request #12865 from aholmberg/holmberg/default-reasoning"
This reverts commit 68f4847, reversing changes made to df39320.
1 parent 3cb8e23 commit 7ff93cd

File tree

4 files changed

+80
-243
lines changed

4 files changed

+80
-243
lines changed

litellm/completion_extras/litellm_responses_transformation/transformation.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ def transform_request(
157157
responses_api_request["metadata"] = value
158158
elif key in ("previous_response_id"):
159159
responses_api_request["previous_response_id"] = value
160-
161-
responses_api_request["reasoning"] = self._map_reasoning_effort(optional_params.get("reasoning_effort"))
160+
elif key == "reasoning_effort":
161+
responses_api_request["reasoning"] = self._map_reasoning_effort(value)
162162

163163
# Get stream parameter from litellm_params if not in optional_params
164164
stream = optional_params.get("stream") or litellm_params.get("stream", False)
@@ -452,7 +452,7 @@ def _convert_tools_to_responses_format(
452452
responses_tools.append(tool)
453453
return cast(List["ALL_RESPONSES_API_TOOL_PARAMS"], responses_tools)
454454

455-
def _map_reasoning_effort(self, reasoning_effort: Optional[str]) -> Reasoning:
455+
def _map_reasoning_effort(self, reasoning_effort: str) -> Optional[Reasoning]:
456456
if reasoning_effort == "high":
457457
return Reasoning(effort="high", summary="detailed")
458458
elif reasoning_effort == "medium":
@@ -462,7 +462,7 @@ def _map_reasoning_effort(self, reasoning_effort: Optional[str]) -> Reasoning:
462462
return Reasoning(effort="low", summary="auto")
463463
elif reasoning_effort == "minimal":
464464
return Reasoning(effort="minimal", summary="auto")
465-
return Reasoning(summary="auto")
465+
return None
466466

467467
def _map_responses_status_to_finish_reason(self, status: Optional[str]) -> str:
468468
"""Map responses API status to chat completion finish_reason"""

litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -420,10 +420,8 @@ def apply_response_schema_transformation(self, value: dict, optional_params: dic
420420

421421
@staticmethod
422422
def _map_reasoning_effort_to_thinking_budget(
423-
reasoning_effort: Optional[str],
423+
reasoning_effort: str,
424424
) -> GeminiThinkingConfig:
425-
if not reasoning_effort:
426-
return { "includeThoughts": True }
427425
if reasoning_effort == "low":
428426
return {
429427
"thinkingBudget": DEFAULT_REASONING_EFFORT_LOW_THINKING_BUDGET,
@@ -617,17 +615,6 @@ def map_openai_params( # noqa: PLR0915
617615
optional_params = self._add_tools_to_optional_params(
618616
optional_params, [_tools]
619617
)
620-
621-
######################################################################################
622-
# If the model supports reasoning and `thinkingConfig` is not set as yet
623-
# we should set it to includeThoughts
624-
######################################################################################
625-
if supports_reasoning(model) and "thinkingConfig" not in optional_params:
626-
optional_params["thinkingConfig"] = (
627-
VertexGeminiConfig._map_reasoning_effort_to_thinking_budget(
628-
non_default_params.get("reasoning_effort")
629-
)
630-
)
631618
if litellm.vertex_ai_safety_settings is not None:
632619
optional_params["safety_settings"] = litellm.vertex_ai_safety_settings
633620

tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py

Lines changed: 73 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -10,152 +10,77 @@
1010
import pytest
1111

1212
sys.path.insert(
13-
0, os.path.abspath("../../../../..")
14-
) # Adds the parent directory to the system path
13+
0, os.path.abspath("../../..")
14+
) # Adds the parent directory to the system-path
1515
import litellm
16-
from litellm.completion_extras.litellm_responses_transformation.transformation import (
17-
LiteLLMResponsesTransformationHandler,
18-
OpenAiResponsesToChatCompletionStreamIterator,
19-
)
20-
from litellm.types.llms.openai import Reasoning
21-
from litellm.types.utils import Delta, ModelResponseStream, StreamingChoices
22-
23-
24-
class TestLiteLLMResponsesTransformation:
25-
def setup_method(self):
26-
self.handler = LiteLLMResponsesTransformationHandler()
27-
self.model = "responses-api-model"
28-
self.logging_obj = MagicMock()
29-
30-
def test_transform_request_reasoning_effort(self):
31-
"""
32-
Test that reasoning_effort is mapped to reasoning parameter correctly.
33-
"""
34-
# Case 1: reasoning_effort = "high"
35-
optional_params_high = {"reasoning_effort": "high"}
36-
result_high = self.handler.transform_request(
37-
model=self.model,
38-
messages=[],
39-
optional_params=optional_params_high,
40-
litellm_params={},
41-
headers={},
42-
litellm_logging_obj=self.logging_obj,
43-
)
44-
assert "reasoning" in result_high
45-
assert result_high["reasoning"] == Reasoning(effort="high", summary="detailed")
46-
47-
# Case 2: reasoning_effort = "medium"
48-
optional_params_medium = {"reasoning_effort": "medium"}
49-
result_medium = self.handler.transform_request(
50-
model=self.model,
51-
messages=[],
52-
optional_params=optional_params_medium,
53-
litellm_params={},
54-
headers={},
55-
litellm_logging_obj=self.logging_obj,
56-
)
57-
assert "reasoning" in result_medium
58-
assert result_medium["reasoning"] == Reasoning(effort="medium", summary="auto")
59-
60-
# Case 3: reasoning_effort = "low"
61-
optional_params_low = {"reasoning_effort": "low"}
62-
result_low = self.handler.transform_request(
63-
model=self.model,
64-
messages=[],
65-
optional_params=optional_params_low,
66-
litellm_params={},
67-
headers={},
68-
litellm_logging_obj=self.logging_obj,
69-
)
70-
assert "reasoning" in result_low
71-
assert result_low["reasoning"] == Reasoning(effort="low", summary="auto")
72-
73-
# Case 4: no reasoning_effort
74-
optional_params_none = {}
75-
result_none = self.handler.transform_request(
76-
model=self.model,
77-
messages=[],
78-
optional_params=optional_params_none,
79-
litellm_params={},
80-
headers={},
81-
litellm_logging_obj=self.logging_obj,
82-
)
83-
assert "reasoning" in result_none
84-
assert result_none["reasoning"] == Reasoning(summary="auto")
85-
86-
# Case 5: reasoning_effort = None
87-
optional_params_explicit_none = {"reasoning_effort": None}
88-
result_explicit_none = self.handler.transform_request(
89-
model=self.model,
90-
messages=[],
91-
optional_params=optional_params_explicit_none,
92-
litellm_params={},
93-
headers={},
94-
litellm_logging_obj=self.logging_obj,
95-
)
96-
assert "reasoning" in result_explicit_none
97-
assert result_explicit_none["reasoning"] == Reasoning(summary="auto")
98-
99-
def test_convert_chat_completion_messages_to_responses_api_image_input(self):
100-
"""
101-
Test that chat completion messages with image inputs are converted correctly.
102-
"""
103-
user_content = "What's in this image?"
104-
user_image = "https://w7.pngwing.com/pngs/666/274/png-transparent-image-pictures-icon-photo-thumbnail.png"
105-
106-
messages = [
107-
{
108-
"role": "user",
109-
"content": [
110-
{
111-
"type": "text",
112-
"text": user_content,
113-
},
114-
{
115-
"type": "image_url",
116-
"image_url": {"url": user_image},
117-
},
118-
],
119-
},
120-
]
121-
122-
response, _ = self.handler.convert_chat_completion_messages_to_responses_api(messages)
123-
124-
response_str = json.dumps(response)
125-
126-
assert user_content in response_str
127-
assert user_image in response_str
128-
129-
print("response: ", response)
130-
assert response[0]["content"][1]["image_url"] == user_image
131-
132-
def test_openai_responses_chunk_parser_reasoning_summary(self):
133-
"""
134-
Test that OpenAI responses chunk parser handles reasoning summary correctly.
135-
"""
136-
iterator = OpenAiResponsesToChatCompletionStreamIterator(
137-
streaming_response=None, sync_stream=True
138-
)
139-
140-
chunk = {
141-
"delta": "**Compar",
142-
"item_id": "rs_686d544208748198b6912e27b7c299c00e24bd875d35bade",
143-
"output_index": 0,
144-
"sequence_number": 4,
145-
"summary_index": 0,
146-
"type": "response.reasoning_summary_text.delta",
147-
}
148-
149-
result = iterator.chunk_parser(chunk)
150-
151-
assert isinstance(result, ModelResponseStream)
152-
assert len(result.choices) == 1
153-
choice = result.choices[0]
154-
assert isinstance(choice, StreamingChoices)
155-
assert choice.index == 0
156-
delta = choice.delta
157-
assert isinstance(delta, Delta)
158-
assert delta.content is None
159-
assert delta.reasoning_content == "**Compar"
160-
assert delta.tool_calls is None
161-
assert delta.function_call is None
16+
17+
18+
def test_convert_chat_completion_messages_to_responses_api_image_input():
19+
from litellm.completion_extras.litellm_responses_transformation.transformation import (
20+
LiteLLMResponsesTransformationHandler,
21+
)
22+
23+
handler = LiteLLMResponsesTransformationHandler()
24+
25+
user_content = "What's in this image?"
26+
user_image = "https://w7.pngwing.com/pngs/666/274/png-transparent-image-pictures-icon-photo-thumbnail.png"
27+
28+
messages = [
29+
{
30+
"role": "user",
31+
"content": [
32+
{
33+
"type": "text",
34+
"text": user_content,
35+
},
36+
{
37+
"type": "image_url",
38+
"image_url": {"url": user_image},
39+
},
40+
],
41+
},
42+
]
43+
44+
response, _ = handler.convert_chat_completion_messages_to_responses_api(messages)
45+
46+
response_str = json.dumps(response)
47+
48+
assert user_content in response_str
49+
assert user_image in response_str
50+
51+
print("response: ", response)
52+
assert response[0]["content"][1]["image_url"] == user_image
53+
54+
55+
def test_openai_responses_chunk_parser_reasoning_summary():
56+
from litellm.completion_extras.litellm_responses_transformation.transformation import (
57+
OpenAiResponsesToChatCompletionStreamIterator,
58+
)
59+
from litellm.types.utils import Delta, ModelResponseStream, StreamingChoices
60+
61+
iterator = OpenAiResponsesToChatCompletionStreamIterator(
62+
streaming_response=None, sync_stream=True
63+
)
64+
65+
chunk = {
66+
"delta": "**Compar",
67+
"item_id": "rs_686d544208748198b6912e27b7c299c00e24bd875d35bade",
68+
"output_index": 0,
69+
"sequence_number": 4,
70+
"summary_index": 0,
71+
"type": "response.reasoning_summary_text.delta",
72+
}
73+
74+
result = iterator.chunk_parser(chunk)
75+
76+
assert isinstance(result, ModelResponseStream)
77+
assert len(result.choices) == 1
78+
choice = result.choices[0]
79+
assert isinstance(choice, StreamingChoices)
80+
assert choice.index == 0
81+
delta = choice.delta
82+
assert isinstance(delta, Delta)
83+
assert delta.content is None
84+
assert delta.reasoning_content == "**Compar"
85+
assert delta.tool_calls is None
86+
assert delta.function_call is None

tests/test_litellm/llms/vertex_ai/gemini/test_vertex_and_google_ai_studio_gemini.py

Lines changed: 2 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -442,82 +442,6 @@ def test_vertex_ai_map_thinking_param_with_budget_tokens_0():
442442
}
443443

444444

445-
def test_vertex_ai_reasoning_effort_mapping():
446-
"""
447-
Test that reasoning_effort is mapped to thinkingConfig correctly for models that support it.
448-
- A default thinking config is applied if reasoning_effort is not specified.
449-
- reasoning_effort correctly maps to thinkingConfig.
450-
- No thinkingConfig is applied for models that do not support reasoning.
451-
- reasoning_effort is prioritized over thinking param.
452-
"""
453-
v = VertexGeminiConfig()
454-
optional_params = {}
455-
456-
# Case 1: Model supports reasoning, no reasoning_effort provided
457-
# Should apply default thinkingConfig
458-
with patch(
459-
"litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini.supports_reasoning",
460-
return_value=True,
461-
):
462-
result_params = v.map_openai_params(
463-
non_default_params={},
464-
optional_params=deepcopy(optional_params),
465-
model="gemini-2.5-pro",
466-
drop_params=False,
467-
)
468-
assert "thinkingConfig" in result_params
469-
assert result_params["thinkingConfig"] == {"includeThoughts": True}
470-
471-
# Case 2: Model supports reasoning, reasoning_effort is 'low'
472-
# Should apply thinkingConfig with budget
473-
with patch(
474-
"litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini.supports_reasoning",
475-
return_value=True,
476-
):
477-
result_params_with_effort = v.map_openai_params(
478-
non_default_params={"reasoning_effort": "low"},
479-
optional_params=deepcopy(optional_params),
480-
model="gemini-2.5-pro",
481-
drop_params=False,
482-
)
483-
assert "thinkingConfig" in result_params_with_effort
484-
assert result_params_with_effort["thinkingConfig"]["includeThoughts"] is True
485-
assert "thinkingBudget" in result_params_with_effort["thinkingConfig"]
486-
487-
# Case 3: Model does not support reasoning
488-
# Should not apply thinkingConfig
489-
with patch(
490-
"litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini.supports_reasoning",
491-
return_value=False,
492-
):
493-
result_params_no_support = v.map_openai_params(
494-
non_default_params={},
495-
optional_params=deepcopy(optional_params),
496-
model="gemini-pro",
497-
drop_params=False,
498-
)
499-
assert "thinkingConfig" not in result_params_no_support
500-
501-
# Case 4: Model supports reasoning, but reasoning_effort is set, should be prioritized over thinking
502-
with patch(
503-
"litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini.supports_reasoning",
504-
return_value=True,
505-
):
506-
result_params_with_effort = v.map_openai_params(
507-
non_default_params={
508-
"reasoning_effort": "low",
509-
"thinking": {"type": "enabled", "budget_tokens": 1000},
510-
},
511-
optional_params=deepcopy(optional_params),
512-
model="gemini-2.5-pro",
513-
drop_params=False,
514-
)
515-
assert "thinkingConfig" in result_params_with_effort
516-
assert result_params_with_effort["thinkingConfig"]["includeThoughts"] is True
517-
assert "thinkingBudget" in result_params_with_effort["thinkingConfig"]
518-
assert result_params_with_effort["thinkingConfig"]["thinkingBudget"] != 1000
519-
520-
521445
def test_vertex_ai_map_tools():
522446
v = VertexGeminiConfig()
523447
tools = v._map_function(value=[{"code_execution": {}}])
@@ -1109,10 +1033,11 @@ def test_vertex_ai_code_line_length():
11091033
This is a meta-test to ensure the code change meets the 40-character requirement.
11101034
"""
11111035
import inspect
1036+
11121037
from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import (
11131038
VertexGeminiConfig,
11141039
)
1115-
1040+
11161041
# Get the source code of the _transform_parts method
11171042
source_lines = inspect.getsource(VertexGeminiConfig._transform_parts).split('\n')
11181043

0 commit comments

Comments
 (0)