diff --git a/tests/entrypoints/launchers/api_server/test_api_server_process_manager.py b/tests/entrypoints/launchers/api_server/test_api_server_process_manager.py index 668f115448..80a2577dba 100644 --- a/tests/entrypoints/launchers/api_server/test_api_server_process_manager.py +++ b/tests/entrypoints/launchers/api_server/test_api_server_process_manager.py @@ -489,3 +489,49 @@ def test_rust_frontend_launch_log_redacts_credentials(monkeypatch, caplog): assert hf_token not in message assert api_key not in message assert '"hf_token": "***"' in message + + +def test_rust_frontend_uses_config_model_as_model_tag(monkeypatch, caplog, tmp_path): + """Config-only model selection must be forwarded to the Rust frontend.""" + import subprocess as subprocess_mod + + from vllm.entrypoints.launchers.cli_args import make_arg_parser + from vllm.utils.argparse_utils import FlexibleArgumentParser + from vllm.v1.utils import RustFrontendProcessManager + + config_path = tmp_path / "config.yml" + config_path.write_text("model: org/model\n") + args = make_arg_parser(FlexibleArgumentParser()).parse_args( + ["--config", str(config_path)] + ) + assert args.model == "org/model" + assert args.model_tag is None + + class _FakeProc: + pid = 4321 + returncode = 0 + + def poll(self): + return 0 + + def wait(self, timeout=None): + return 0 + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + monkeypatch.setattr(subprocess_mod, "Popen", lambda *a, **kw: _FakeProc()) + with caplog.at_level("INFO", logger="vllm.v1.utils"): + RustFrontendProcessManager( + binary_path="/nonexistent/vllm-rs", + sock=sock, + args=args, + input_address="ipc:///tmp/in", + output_address="ipc:///tmp/out", + engine_start_index=0, + engine_count=1, + data_parallel_size=1, + ) + finally: + sock.close() + + assert '"model_tag": "org/model"' in caplog.text diff --git a/vllm/v1/utils.py b/vllm/v1/utils.py index 81f4eaf842..f3bd97784e 100644 --- a/vllm/v1/utils.py +++ b/vllm/v1/utils.py @@ -391,6 +391,16 @@ class RustFrontendProcessManager: "data_parallel_hybrid_lb", }, ) + + # `model_tag` is the positional `vllm serve` model argument. When the + # model is supplied only through `--config`, argparse populates `model` + # while leaving `model_tag` unset. The Rust frontend requires + # `model_tag` in its JSON bootstrap payload, so use the resolved model + # as a fallback. + model_tag = getattr(args, "model_tag", None) or getattr(args, "model", None) + if model_tag is not None: + args_dict["model_tag"] = model_tag + # The Rust `frontend` subcommand parses --args-json via serde_json, # which bypasses clap and therefore ignores any `#[arg(env = ...)]` # declarations on SharedRuntimeArgs fields. Forward the env-driven