@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 98060b001d
Fork 0

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):