Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
9 changes: 8 additions & 1 deletion vllm/config/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1082,7 +1086,10 @@ def _get_transformers_backend_cls(self) -> str:
# 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":
Expand Down
7 changes: 7 additions & 0 deletions vllm/config/vllm.py
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,7 @@ def with_hf_config(

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)

Expand Down Expand Up @@ -1331,6 +1332,12 @@ def __post_init__(self):
# 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":
Expand Down
Loading