| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | """Unit tests for reasoning_effort -> enable_thinking mapping. |
| 4 | |
| 5 | Models like Gemma4 require enable_thinking=True in chat_template_kwargs to |
| 6 | activate thinking mode. This mapping ensures that when a user requests |
| 7 | reasoning (via reasoning_effort or reasoning.effort), the template kwarg |
| 8 | is injected automatically. |
| 9 | """ |
| 10 | |
| 11 | import pytest |
| 12 | from openai.types.shared import Reasoning |
| 13 | |
| 14 | from vllm.entrypoints.openai.chat_completion.protocol import ( |
| 15 | ChatCompletionRequest, |
| 16 | ) |
| 17 | from vllm.entrypoints.openai.responses.protocol import ResponsesRequest |
| 18 | |
| 19 | |
| 20 | def _build_chat_request(**kwargs) -> ChatCompletionRequest: |
| 21 | defaults = dict( |
| 22 | model="test-model", |
| 23 | messages=[{"role": "user", "content": "Hello"}], |
| 24 | ) |
| 25 | defaults.update(kwargs) |
| 26 | return ChatCompletionRequest(**defaults) |
| 27 | |
| 28 | |
| 29 | def _build_responses_request(**kwargs) -> ResponsesRequest: |
| 30 | defaults = dict( |
| 31 | model="test-model", |
| 32 | input=[{"role": "user", "content": "Hello"}], |
| 33 | ) |
| 34 | defaults.update(kwargs) |
| 35 | return ResponsesRequest(**defaults) |
| 36 | |
| 37 | |
| 38 | class TestChatCompletionReasoningEffort: |
| 39 | """Chat Completions: reasoning_effort -> enable_thinking.""" |
| 40 | |
| 41 | @pytest.mark.parametrize("effort", ["low", "medium", "high"]) |
| 42 | def test_non_none_effort_injects_enable_thinking_true(self, effort): |
| 43 | request = _build_chat_request(reasoning_effort=effort) |
| 44 | params = request.build_chat_params(None, "auto") |
| 45 | assert params.chat_template_kwargs["enable_thinking"] is True |
| 46 | |
| 47 | def test_none_effort_injects_enable_thinking_false(self): |
| 48 | request = _build_chat_request(reasoning_effort="none") |
| 49 | params = request.build_chat_params(None, "auto") |
| 50 | assert params.chat_template_kwargs["enable_thinking"] is False |
| 51 | |
| 52 | def test_no_effort_does_not_inject(self): |
| 53 | request = _build_chat_request() |
| 54 | params = request.build_chat_params(None, "auto") |
| 55 | assert "enable_thinking" not in params.chat_template_kwargs |
| 56 | |
| 57 | def test_explicit_user_kwarg_not_overridden(self): |
| 58 | request = _build_chat_request( |
| 59 | reasoning_effort="high", |
| 60 | chat_template_kwargs={"enable_thinking": False}, |
| 61 | ) |
| 62 | params = request.build_chat_params(None, "auto") |
| 63 | assert params.chat_template_kwargs["enable_thinking"] is False |
| 64 | |
| 65 | def test_reasoning_effort_still_in_kwargs(self): |
| 66 | request = _build_chat_request(reasoning_effort="high") |
| 67 | params = request.build_chat_params(None, "auto") |
| 68 | assert params.chat_template_kwargs["reasoning_effort"] == "high" |
| 69 | |
| 70 | |
| 71 | class TestResponsesReasoningEffort: |
| 72 | """Responses API: reasoning.effort -> enable_thinking.""" |
| 73 | |
| 74 | @pytest.mark.parametrize("effort", ["low", "medium", "high"]) |
| 75 | def test_non_none_effort_injects_enable_thinking_true(self, effort): |
| 76 | request = _build_responses_request( |
| 77 | reasoning=Reasoning(effort=effort), |
| 78 | ) |
| 79 | params = request.build_chat_params(None, "auto") |
| 80 | assert params.chat_template_kwargs["enable_thinking"] is True |
| 81 | |
| 82 | def test_none_effort_injects_enable_thinking_false(self): |
| 83 | request = _build_responses_request( |
| 84 | reasoning=Reasoning(effort="none"), |
| 85 | ) |
| 86 | params = request.build_chat_params(None, "auto") |
| 87 | assert params.chat_template_kwargs["enable_thinking"] is False |
| 88 | |
| 89 | def test_no_reasoning_does_not_inject(self): |
| 90 | request = _build_responses_request() |
| 91 | params = request.build_chat_params(None, "auto") |
| 92 | assert "enable_thinking" not in params.chat_template_kwargs |
| 93 | |
| 94 | def test_explicit_user_kwarg_not_overridden(self): |
| 95 | request = _build_responses_request( |
| 96 | reasoning=Reasoning(effort="high"), |
| 97 | chat_template_kwargs={"enable_thinking": False}, |
| 98 | ) |
| 99 | params = request.build_chat_params(None, "auto") |
| 100 | assert params.chat_template_kwargs["enable_thinking"] is False |
| 101 | |
| 102 | def test_reasoning_effort_still_in_kwargs(self): |
| 103 | request = _build_responses_request( |
| 104 | reasoning=Reasoning(effort="high"), |
| 105 | ) |
| 106 | params = request.build_chat_params(None, "auto") |
| 107 | assert params.chat_template_kwargs["reasoning_effort"] == "high" |