A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 15, 12:15 UTC
[Feature][Frontend]: Deprecate --enable-reasoning (#17452)
Signed-off-by: chaunceyjiang <chaunceyjiang@gmail.com>
Chauncey committed
May 1, 2025 at 21:46 UTC
98060b001dfae385c73d2380ad6a38456cbf42c9
16 files changed
+49
-91
docs/source/features/reasoning_outputs.md
+5
-8
@@ -21,11 +21,10 @@ vLLM currently supports the following reasoning models:
21
22
## Quickstart
23
24
-To use reasoning models, you need to specify the `--enable-reasoning` and `--reasoning-parser` flags when making a request to the chat completion endpoint. The `--reasoning-parser` flag specifies the reasoning parser to use for extracting reasoning content from the model output.
24
+To use reasoning models, you need to specify the `--reasoning-parser` flags when making a request to the chat completion endpoint. The `--reasoning-parser` flag specifies the reasoning parser to use for extracting reasoning content from the model output.
25
26
```bash
27
-vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B \
28
- --enable-reasoning --reasoning-parser deepseek_r1
27
+vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B --reasoning-parser deepseek_r1
28
```
29
30
Next, make a request to the model that should return the reasoning content in the response.
@@ -140,8 +139,7 @@ Remember to check whether the `reasoning_content` exists in the response before
139
The reasoning content is also available in the structured output. The structured output engine like `xgrammar` will use the reasoning content to generate structured output. It is only supported in v0 engine now.
140
141
```bash
143
-VLLM_USE_V1=0 vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B \
144
- --enable-reasoning --reasoning-parser deepseek_r1
142
+VLLM_USE_V1=0 vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B --reasoning-parser deepseek_r1
143
```
144
145
Please note that the `VLLM_USE_V1` environment variable must be set to `0` to use the v0 engine.
@@ -316,9 +314,8 @@ class DeepSeekReasoner(Reasoner):
314
315
The structured output engine like `xgrammar` will use `end_token_id` to check if the reasoning content is present in the model output and skip the structured output if it is the case.
316
319
-Finally, you can enable reasoning for the model by using the `--enable-reasoning` and `--reasoning-parser` flags.
317
+Finally, you can enable reasoning for the model by using the `--reasoning-parser` flags.
318
319
```bash
322
-vllm serve <model_tag> \
323
- --enable-reasoning --reasoning-parser example
320
+vllm serve <model_tag> --reasoning-parser example
321
```
examples/online_serving/openai_chat_completion_structured_outputs_with_reasoning.py
+1
-1
@@ -9,7 +9,7 @@ parser:
9
10
```bash
11
vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B \
12
- --enable-reasoning --reasoning-parser deepseek_r1
12
+ --reasoning-parser deepseek_r1
13
```
14
15
This example demonstrates how to generate chat completions from reasoning models
examples/online_serving/openai_chat_completion_tool_calls_with_reasoning.py
+1
-1
@@ -9,7 +9,7 @@ the reasoning parser and tool calling enabled.
9
10
```bash
11
vllm serve Qwen/QwQ-32B \
12
- --enable-reasoning --reasoning-parser deepseek_r1 \
12
+ --reasoning-parser deepseek_r1 \
13
--enable-auto-tool-choice --tool-call-parser hermes
14
15
```
examples/online_serving/openai_chat_completion_with_reasoning.py
+1
-1
@@ -8,7 +8,7 @@ with the reasoning parser:
8
9
```bash
10
vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B \
11
- --enable-reasoning --reasoning-parser deepseek_r1
11
+ --reasoning-parser deepseek_r1
12
```
13
14
This example demonstrates how to generate chat completions from reasoning models
examples/online_serving/openai_chat_completion_with_reasoning_streaming.py
+1
-1
@@ -8,7 +8,7 @@ parser:
8
9
```bash
10
vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B \
11
- --enable-reasoning --reasoning-parser deepseek_r1
11
+ --reasoning-parser deepseek_r1
12
```
13
14
Unlike openai_chat_completion_with_reasoning.py, this example demonstrates the
tests/entrypoints/openai/test_chat_with_tool_reasoning.py
+3
-3
@@ -13,9 +13,9 @@ MODEL_NAME = "Qwen/QwQ-32B"
13
@pytest.fixture(scope="module")
14
def server(): # noqa: F811
15
args = [
16
- "--max-model-len", "8192", "--enforce-eager", "--enable-reasoning",
17
- "--reasoning-parser", "deepseek_r1", "--enable-auto-tool-choice",
18
- "--tool-call-parser", "hermes"
16
+ "--max-model-len", "8192", "--enforce-eager", "--reasoning-parser",
17
+ "deepseek_r1", "--enable-auto-tool-choice", "--tool-call-parser",
18
+ "hermes"
19
]
20
21
with RemoteOpenAIServer(MODEL_NAME, args) as remote_server:
tests/entrypoints/openai/test_cli_args.py
+3
-11
@@ -122,31 +122,23 @@ def test_enable_auto_choice_fails_with_enable_reasoning(serve_parser):
122
"""Ensure validation fails if reasoning is enabled with auto tool choice"""
123
args = serve_parser.parse_args(args=[
124
"--enable-auto-tool-choice",
125
- "--enable-reasoning",
125
+ "--reasoning-parser",
126
+ "deepseek_r1",
127
])
128
with pytest.raises(TypeError):
129
validate_parsed_serve_args(args)
130
131
131
-def test_enable_reasoning_passes_with_reasoning_parser(serve_parser):
132
+def test_passes_with_reasoning_parser(serve_parser):
133
"""Ensure validation passes if reasoning is enabled
134
with a reasoning parser"""
135
args = serve_parser.parse_args(args=[
135
- "--enable-reasoning",
136
"--reasoning-parser",
137
"deepseek_r1",
138
])
139
validate_parsed_serve_args(args)
140
141
142
-def test_enable_reasoning_fails_without_reasoning_parser(serve_parser):
143
- """Ensure validation fails if reasoning is enabled
144
- without a reasoning parser"""
145
- args = serve_parser.parse_args(args=["--enable-reasoning"])
146
- with pytest.raises(TypeError):
147
- validate_parsed_serve_args(args)
148
-
149
-
142
def test_chat_template_validation_for_happy_paths(serve_parser):
143
"""Ensure validation passes if the chat template exists"""
144
args = serve_parser.parse_args(
vllm/config.py
+2
-3
@@ -3225,10 +3225,9 @@ class DecodingConfig:
3225
in the JSON schema. This is only supported for the `guidance` backend and
3226
is used to better align its behaviour with `outlines` and `xgrammar`."""
3227
3228
- reasoning_backend: Optional[str] = None
3228
+ reasoning_backend: str = ""
3229
"""Select the reasoning parser depending on the model that you're using.
3230
- This is used to parse the reasoning content into OpenAI API format.
3231
- Required for `--enable-reasoning`."""
3230
+ This is used to parse the reasoning content into OpenAI API format."""
3231
3232
def compute_hash(self) -> str:
3233
"""
vllm/engine/arg_utils.py
+12
-5
@@ -365,8 +365,9 @@ class EngineArgs:
365
calculate_kv_scales: bool = CacheConfig.calculate_kv_scales
366
367
additional_config: Optional[Dict[str, Any]] = None
368
- enable_reasoning: Optional[bool] = None
369
- reasoning_parser: Optional[str] = DecodingConfig.reasoning_backend
368
+ enable_reasoning: Optional[bool] = None # DEPRECATED
369
+ reasoning_parser: str = DecodingConfig.reasoning_backend
370
+
371
use_tqdm_on_load: bool = LoadConfig.use_tqdm_on_load
372
373
def __post_init__(self):
@@ -798,8 +799,15 @@ class EngineArgs:
799
"--enable-reasoning",
800
action="store_true",
801
default=False,
801
- help="Whether to enable reasoning_content for the model. "
802
- "If enabled, the model will be able to generate reasoning content."
802
+ help=
803
+ "[DEPRECATED] " \
804
+ "The --enable-reasoning flag is deprecated as of v0.8.6. "
805
+ "Use --reasoning-parser to specify " \
806
+ "the reasoning parser backend instead. "
807
+ "This flag (--enable-reasoning) will be " \
808
+ "removed in v0.10.0. "
809
+ "When --reasoning-parser is specified, " \
810
+ "reasoning mode is automatically enabled."
811
)
812
813
return parser
@@ -1088,7 +1096,6 @@ class EngineArgs:
1096
disable_additional_properties=\
1097
self.guided_decoding_disable_additional_properties,
1098
reasoning_backend=self.reasoning_parser
1091
- if self.enable_reasoning else None,
1099
)
1100
1101
observability_config = ObservabilityConfig(
vllm/engine/llm_engine.py
+1
-1
@@ -2096,7 +2096,7 @@ class LLMEngine:
2096
guided_decoding.backend = guided_decoding.backend or \
2097
self.decoding_config.backend
2098
2099
- if self.decoding_config.reasoning_backend is not None:
2099
+ if self.decoding_config.reasoning_backend:
2100
logger.debug("Building with reasoning backend %s",
2101
self.decoding_config.reasoning_backend)
2102
vllm/entrypoints/openai/api_server.py
+1
-2
@@ -967,7 +967,6 @@ async def init_app_state(
967
return_tokens_as_token_ids=args.return_tokens_as_token_ids,
968
enable_auto_tools=args.enable_auto_tool_choice,
969
tool_parser=args.tool_call_parser,
970
- enable_reasoning=args.enable_reasoning,
970
reasoning_parser=args.reasoning_parser,
971
enable_prompt_tokens_details=args.enable_prompt_tokens_details,
972
) if model_config.runner_type == "generate" else None
@@ -1053,7 +1052,7 @@ async def run_server(args, **uvicorn_kwargs) -> None:
1052
f"(chose from {{ {','.join(valid_tool_parses)} }})")
1053
1054
valid_reasoning_parses = ReasoningParserManager.reasoning_parsers.keys()
1056
- if args.enable_reasoning \
1055
+ if args.reasoning_parser \
1056
and args.reasoning_parser not in valid_reasoning_parses:
1057
raise KeyError(
1058
f"invalid reasoning parser: {args.reasoning_parser} "
vllm/entrypoints/openai/cli_args.py
-5
@@ -284,11 +284,6 @@ def validate_parsed_serve_args(args: argparse.Namespace):
284
raise TypeError("Error: --enable-auto-tool-choice requires "
285
"--tool-call-parser")
286
287
- # Enable reasoning needs a reasoning parser to be valid
288
- if args.enable_reasoning and not args.reasoning_parser:
289
- raise TypeError("Error: --enable-reasoning requires "
290
- "--reasoning-parser")
291
-
287
288
def create_parser_for_docs() -> FlexibleArgumentParser:
289
parser_for_docs = FlexibleArgumentParser(
vllm/entrypoints/openai/serving_chat.py
+14
-45
@@ -58,8 +58,7 @@ class OpenAIServingChat(OpenAIServing):
58
chat_template: Optional[str],
59
chat_template_content_format: ChatTemplateContentFormatOption,
60
return_tokens_as_token_ids: bool = False,
61
- enable_reasoning: bool = False,
62
- reasoning_parser: Optional[str] = None,
61
+ reasoning_parser: str = "",
62
enable_auto_tools: bool = False,
63
tool_parser: Optional[str] = None,
64
enable_prompt_tokens_details: bool = False,
@@ -82,18 +81,17 @@ class OpenAIServingChat(OpenAIServing):
81
" the parallel_tool_calls client option is preset for "
82
"compatibility reasons, it will be ignored.")
83
85
- self.enable_reasoning: bool = enable_reasoning
84
self.reasoning_parser: Optional[Callable[[AnyTokenizer],
85
ReasoningParser]] = None
88
- if self.enable_reasoning:
86
+ if reasoning_parser:
87
try:
88
self.reasoning_parser = (
89
ReasoningParserManager.get_reasoning_parser(
90
reasoning_parser))
91
+ assert self.reasoning_parser is not None
92
except Exception as e:
94
- raise TypeError("Error: --enable-reasoning requires "
95
- f"reasoning_parser:'{reasoning_parser}' "
96
- "which has not been registered") from e
93
+ raise TypeError(
94
+ f"{reasoning_parser=} has not been registered") from e
95
self.tool_parser: Optional[Callable[[AnyTokenizer], ToolParser]] = None
96
if self.enable_auto_tools:
97
try:
@@ -423,15 +421,12 @@ class OpenAIServingChat(OpenAIServing):
421
not tool_choice_function_name
422
and self._should_stream_with_auto_tool_parsing(request))
423
426
- should_stream_with_reasoning_parsing = (
427
- self._should_stream_with_reasoning_parsing(request))
428
-
424
all_previous_token_ids: Optional[list[list[int]]]
425
function_name_returned: Optional[list[bool]] = None
426
427
# Only one of these will be used, thus previous_texts and
428
# all_previous_token_ids will not be used twice in the same iteration.
434
- if tool_choice_auto or should_stream_with_reasoning_parsing:
429
+ if tool_choice_auto or self.reasoning_parser:
430
# These are only required in "auto" tool choice case
431
previous_texts = [""] * num_choices
432
all_previous_token_ids = [[]] * num_choices
@@ -446,12 +441,7 @@ class OpenAIServingChat(OpenAIServing):
441
previous_texts, all_previous_token_ids = None, None
442
443
try:
449
- # There is no need to check if the reasoning_parser is None
450
- # because the should_stream_with_reasoning_parsing check
451
- # already ensures that the reasoning_parser is not None.
452
- # but the pre-commit hook requires it.
453
- if should_stream_with_reasoning_parsing and \
454
- self.reasoning_parser is not None:
444
+ if self.reasoning_parser:
445
reasoning_parser = self.reasoning_parser(tokenizer)
446
except RuntimeError as e:
447
logger.exception("Error in reasoning parser creation.")
@@ -459,7 +449,6 @@ class OpenAIServingChat(OpenAIServing):
449
yield f"data: {data}\n\n"
450
yield "data: [DONE]\n\n"
451
return
462
-
452
# Prepare the tool parser if it's needed
453
try:
454
if tool_choice_auto and self.tool_parser:
@@ -592,7 +581,7 @@ class OpenAIServingChat(OpenAIServing):
581
delta_message: Optional[DeltaMessage]
582
583
# just update previous_texts and previous_token_ids
595
- if tool_choice_auto or should_stream_with_reasoning_parsing:
584
+ if tool_choice_auto or self.reasoning_parser:
585
assert previous_texts is not None
586
assert all_previous_token_ids is not None
587
previous_text = previous_texts[i]
@@ -603,7 +592,7 @@ class OpenAIServingChat(OpenAIServing):
592
593
# handle streaming deltas for tools with named tool_choice
594
if tool_choice_function_name:
606
- if (self.enable_reasoning
595
+ if (self.reasoning_parser
596
and not reasoning_parser.is_reasoning_end(
597
previous_token_ids)):
598
assert reasoning_parser is not None
@@ -630,7 +619,7 @@ class OpenAIServingChat(OpenAIServing):
619
current_text = ""
620
else:
621
# Just to add remaining `content`
633
- if self.enable_reasoning:
622
+ if self.reasoning_parser:
623
delta_text = previous_text + delta_text
624
current_text = ""
625
@@ -660,7 +649,7 @@ class OpenAIServingChat(OpenAIServing):
649
650
# handle streaming deltas for tools with "auto" tool choice
651
# and reasoning parser
663
- elif tool_choice_auto and self.enable_reasoning:
652
+ elif tool_choice_auto and self.reasoning_parser:
653
assert tool_parser is not None
654
assert reasoning_parser is not None
655
assert added_content_delta_arr is not None
@@ -728,8 +717,7 @@ class OpenAIServingChat(OpenAIServing):
717
delta_token_ids=output.token_ids,
718
request=request))
719
# when only reasoning
731
- elif self.enable_reasoning:
732
- assert reasoning_parser is not None
720
+ elif self.reasoning_parser:
721
delta_message = (reasoning_parser.
722
extract_reasoning_content_streaming(
723
previous_text,
@@ -744,7 +732,7 @@ class OpenAIServingChat(OpenAIServing):
732
delta_message = DeltaMessage(content=delta_text)
733
734
# update the previous values for the next iteration
747
- if tool_choice_auto or should_stream_with_reasoning_parsing:
735
+ if tool_choice_auto or self.reasoning_parser:
736
assert previous_texts is not None
737
assert all_previous_token_ids is not None
738
previous_texts[i] = current_text
@@ -931,17 +919,9 @@ class OpenAIServingChat(OpenAIServing):
919
)
920
else:
921
logprobs = None
934
-
935
- should_stream_with_reasoning_parsing = (
936
- self._should_stream_with_reasoning_parsing(request))
937
-
938
- # In the OpenAI API the finish_reason is "tools_called"
939
- # if the tool choice is auto and the model produced a tool
940
- # call. The same is not true for named function calls
922
auto_tools_called = False
923
943
- if should_stream_with_reasoning_parsing and \
944
- self.reasoning_parser is not None:
924
+ if self.reasoning_parser:
925
try:
926
reasoning_parser = self.reasoning_parser(tokenizer)
927
except RuntimeError as e:
@@ -1176,17 +1156,6 @@ class OpenAIServingChat(OpenAIServing):
1156
return (request.tools and self.tool_parser and self.enable_auto_tools
1157
and request.tool_choice in ['auto', None])
1158
1179
- def _should_stream_with_reasoning_parsing(self,
1180
- request: ChatCompletionRequest):
1181
- """
1182
- Utility function to check if streamed tokens should go through the
1183
- reasoning parser that was configured.
1184
-
1185
- We only want to do this IF reasoning is enabled and a reasoning
1186
- parser is configured.
1187
- """
1188
- return self.enable_reasoning and self.reasoning_parser is not None
1189
-
1159
def _should_check_for_unstreamed_tool_arg_tokens(
1160
self,
1161
delta_message: Optional[DeltaMessage],
vllm/model_executor/guided_decoding/__init__.py
+2
-2
@@ -103,7 +103,7 @@ async def get_guided_decoding_logits_processor(
103
reasoning_backend: str | None = None) -> LogitsProcessor | None:
104
105
reasoner = None
106
- if reasoning_backend is not None:
106
+ if reasoning_backend:
107
reasoner_class = ReasoningParserManager.get_reasoning_parser(
108
reasoning_backend)
109
reasoner = reasoner_class(tokenizer)
@@ -146,7 +146,7 @@ def get_local_guided_decoding_logits_processor(
146
guided_params = maybe_backend_fallback(guided_params)
147
148
reasoner = None
149
- if reasoning_backend is not None:
149
+ if reasoning_backend:
150
reasoner_class = ReasoningParserManager.get_reasoning_parser(
151
reasoning_backend)
152
reasoner = reasoner_class(tokenizer)
vllm/model_executor/guided_decoding/outlines_logits_processors.py
+1
-1
@@ -61,7 +61,7 @@ class BaseLogitsProcessor:
61
"""Use the FSM to bias the logits before sampling the next token."""
62
63
# Skip the structured logits processing if reasoning is not finished.
64
- # reasoner is not None only when `--enable-reasoning` is set.
64
+ # reasoner is not None only when `--reasoning-parser` is set.
65
if self._reasoner is not None:
66
if not self._reasoner.is_reasoning_end(input_ids):
67
return scores
vllm/model_executor/guided_decoding/xgrammar_decoding.py
+1
-1
@@ -346,7 +346,7 @@ class XGrammarLogitsProcessor:
346
scores: torch.Tensor) -> torch.Tensor:
347
348
# Skip the structured logits processing if reasoning is not finished.
349
- # reasoner is not None only when `--enable-reasoning` is set.
349
+ # reasoner is not None only when `--reasoning-parser` is set.
350
if self.reasoner is not None and \
351
not self.reasoner.is_reasoning_end(
352
input_ids):