[Bugfix] Skip VllmConfig re-validation for with_hf_config submodel views (#58212)

Signed-off-by: Nick Hill <nickhill123@gmail.com>
Co-authored-by: Kimi Code <noreply@moonshot.ai>
Co-authored-by: Roger Wang <rogerw@inferact.ai>
This commit is contained in:
Nick Hill
2026-09-23 00:50:17 +00:00
committed by GitHub
co-authored by Kimi Code Roger Wang
parent d110c2f19c
commit 826e300cde
3 changed files with 55 additions and 1 deletions
+40
View File
@@ -289,6 +289,46 @@ def test_kv_offloading_does_not_skip_dcp_interleave_validation():
VllmConfig.validate_block_size(config)
def test_nixl_dcp_check_skipped_for_submodel_config():
# with_hf_config() builds a submodule view of the config (e.g. a
# multimodal model's text stack) whose architecture list is empty.
# Re-running VllmConfig validation on it is unsafe: the NIXL DCP check
# reads use_mla, which resolves the architecture registry.
model_config = ModelConfig("Qwen/Qwen2-VL-2B-Instruct", max_model_len=2048)
vllm_config = VllmConfig(
model_config=model_config,
device_config=DeviceConfig(device="cpu"),
kv_transfer_config=KVTransferConfig(
kv_connector="NixlConnector",
kv_role="kv_both",
),
)
submodel_config = vllm_config.with_hf_config(model_config.hf_text_config)
assert submodel_config.model_config.is_submodel_config
assert submodel_config.model_config.architectures == []
assert submodel_config.model_config.use_mla is False
def test_nixl_dcp_check_rejects_non_mla_model_with_dcp(monkeypatch):
# Pretend the model has a single KV head so the DCP feasibility checks
# pass and the MLA-only assert is what actually fires.
monkeypatch.setattr(ModelConfig, "get_total_num_kv_heads", lambda self: 1)
with pytest.raises(ValidationError, match="only supported for MLA models"):
VllmConfig(
model_config=ModelConfig("Qwen/Qwen3-0.6B", max_model_len=2048),
device_config=DeviceConfig(device="cpu"),
parallel_config=ParallelConfig(
tensor_parallel_size=2,
decode_context_parallel_size=2,
distributed_executor_backend="mp",
),
kv_transfer_config=KVTransferConfig(
kv_connector="NixlConnector",
kv_role="kv_both",
),
)
def test_compile_config_repr_succeeds():
# setup: VllmBackend mutates the config object
config = VllmConfig()
+8 -1
View File
@@ -187,6 +187,10 @@ class ModelConfig:
"""The Hugging Face config of the model."""
hf_text_config: PretrainedConfig = field(init=False)
"""The Hugging Face config of the text model (same as hf_config for text models)."""
is_submodel_config: bool = field(default=False, init=False)
"""Whether this is a submodule view derived by `VllmConfig.with_hf_config`
(e.g. a multimodal model's text stack). Its architecture list is empty, so
deployment-level validation must not run against it."""
word_embeddings_untied_by_checkpoint: bool = field(default=False, init=False)
"""Whether `tie_word_embeddings` was overridden to `False` because the checkpoint
contains an `lm_head` of its own. The two may still turn out to be identical, in
@@ -1082,7 +1086,10 @@ class ModelConfig:
# Check if the architecture we're wrapping has defaults
runner = None
task = None
if defaults := try_match_architecture_defaults(self.architectures[0]):
# architectures is empty for with_hf_config() submodel views.
if self.architectures and (
defaults := try_match_architecture_defaults(self.architectures[0])
):
_, (runner, task) = defaults
# User specified value take precedence
if self.runner != "auto":
+7
View File
@@ -943,6 +943,7 @@ class VllmConfig:
model_config.hf_config = hf_config
model_config.model_arch_config = model_config.get_model_arch_config()
model_config.is_submodel_config = True
return replace(self, model_config=model_config)
@@ -1331,6 +1332,12 @@ class VllmConfig:
# To give each torch profile run a unique instance name.
self.instance_id = f"{time.time_ns()}"
if self.model_config is not None and self.model_config.is_submodel_config:
# with_hf_config() view: the parent config was already validated,
# and this view's empty architecture list makes the model-dependent checks
# below unsafe (e.g. use_mla resolves the architecture registry).
return
self._resolve_mm_encoder_only()
if self.performance_mode != "balanced":