diff --git a/tests/test_config.py b/tests/test_config.py index 9d4567874b..a0c64099dc 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -936,6 +936,30 @@ def test_v2_model_runner_supports_extract_hidden_states(): assert config._get_v2_model_runner_unsupported_features() == [] +@pytest.mark.parametrize("use_heterogeneous_vocab", [False, True]) +def test_v2_model_runner_heterogeneous_vocab_draft_falls_back_to_v1( + use_heterogeneous_vocab, +): + """The V2 draft-model speculator exchanges token ids with the target + without a vocab mapping, so a heterogeneous-vocab (TLI) draft must stay on + V1, where VocabMapping translates them.""" + config = VllmConfig() + config.speculative_config = cast( + SpeculativeConfig, + SimpleNamespace( + method="draft_model", + parallel_drafting=False, + enable_adaptive_verification=False, + use_heterogeneous_vocab=use_heterogeneous_vocab, + ), + ) + + expected = ["heterogeneous-vocabulary draft models"] + assert config._get_v2_model_runner_unsupported_features() == ( + expected if use_heterogeneous_vocab else [] + ) + + def test_v2_model_runner_supports_custom_logits_processors(): config = VllmConfig() config.model_config = cast( diff --git a/vllm/config/vllm.py b/vllm/config/vllm.py index dec1f27fe1..b847da4320 100644 --- a/vllm/config/vllm.py +++ b/vllm/config/vllm.py @@ -3159,6 +3159,11 @@ class VllmConfig: ): unsupported.append("parallel drafting for EAGLE speculative decoding") + # The V2 draft-model speculator has no token mapping between the + # draft and target vocabularies (TLI is TBD in #47172). + if getattr(speculative_config, "use_heterogeneous_vocab", False): + unsupported.append("heterogeneous-vocabulary draft models") + if self.parallel_config.use_ubatching: unsupported.extend(self._get_dbo_unsupported_features())