diff --git a/tests/entrypoints/launchers/test_cli_args.py b/tests/entrypoints/launchers/test_cli_args.py index 0a4c97141d..7fb555c141 100644 --- a/tests/entrypoints/launchers/test_cli_args.py +++ b/tests/entrypoints/launchers/test_cli_args.py @@ -300,6 +300,16 @@ def test_passes_with_reasoning_parser(serve_parser): validate_parsed_serve_args(args) +@pytest.mark.parametrize( + ("value", "expected"), + [("none", ""), ("None", ""), ("NONE", ""), ("deepseek_r1", "deepseek_r1")], +) +def test_reasoning_parser_none_disables_parser(serve_parser, value, expected): + """`--reasoning-parser none` disables parsing, as in `vllm-rs serve`.""" + args = serve_parser.parse_args(args=["--reasoning-parser", value]) + assert args.reasoning_parser == expected + + def test_chat_template_validation_for_happy_paths(serve_parser): """Ensure validation passes if the chat template exists.""" args = serve_parser.parse_args( diff --git a/vllm/engine/arg_utils.py b/vllm/engine/arg_utils.py index c9aa433162..e0cfb3b6d2 100644 --- a/vllm/engine/arg_utils.py +++ b/vllm/engine/arg_utils.py @@ -184,6 +184,11 @@ def union_dict_and_str(val: str) -> str | dict[str, str] | None: return optional_type(json.loads)(val) +def parse_reasoning_parser(val: str) -> str: + """Map `none` (any case) to the unset default, as `vllm-rs serve` does.""" + return "" if val.lower() == "none" else val + + def is_type(type_hint: TypeHint, type: TypeHintT) -> TypeIs[TypeHintT]: """Check if the type hint is a specific type.""" return type_hint is type or get_origin(type_hint) is type @@ -1114,6 +1119,10 @@ class EngineArgs: # Structured outputs arguments structured_outputs_kwargs = get_kwargs(StructuredOutputsConfig) + structured_outputs_kwargs["reasoning_parser"]["type"] = parse_reasoning_parser + structured_outputs_kwargs["reasoning_parser"]["help"] += ( + "\n\n`none` disables reasoning parsing, the same as leaving it unset." + ) structured_outputs_group = parser.add_argument_group( title="StructuredOutputsConfig", description=StructuredOutputsConfig.__doc__,