From a6e6bbce355e5033a887a516a4ceef9a6300d3c2 Mon Sep 17 00:00:00 2001 From: ShwStone Date: Wed, 29 Jul 2026 14:12:37 +0800 Subject: [PATCH 1/2] Fix pure-text AFD model config identity Signed-off-by: ShwStone --- .../model_executor/models/model_utils.py | 11 ++++++++-- tests/unit/package/test_package.py | 22 ++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/afd_plugin/model_executor/models/model_utils.py b/afd_plugin/model_executor/models/model_utils.py index 4edc7273..bfc94e48 100644 --- a/afd_plugin/model_executor/models/model_utils.py +++ b/afd_plugin/model_executor/models/model_utils.py @@ -19,7 +19,14 @@ def get_afd_model_config(model_config: ModelConfig) -> ModelConfig: for model_arch in model_config.hf_config.architectures: if model_arch in _DEEPSEEK_MODEL_REGISTRATIONS: afd_model_config = copy(model_config) - afd_model_config.hf_config = copy(model_config.hf_config) - afd_model_config.hf_config.architectures = [f"AFD{model_arch}"] + afd_hf_config = copy(model_config.hf_config) + afd_hf_config.architectures = [f"AFD{model_arch}"] + afd_model_config.hf_config = afd_hf_config + + # Pure-text ModelConfig uses the same object for hf_config and + # hf_text_config. Preserve that identity: vLLM Ascend uses it to + # distinguish text models from multimodal models. + if model_config.hf_text_config is model_config.hf_config: + afd_model_config.hf_text_config = afd_hf_config return afd_model_config return model_config diff --git a/tests/unit/package/test_package.py b/tests/unit/package/test_package.py index 6a379557..d4053a42 100644 --- a/tests/unit/package/test_package.py +++ b/tests/unit/package/test_package.py @@ -50,18 +50,38 @@ def test_afd_model_config_uses_private_architecture_copy(): pytest.importorskip("vllm") from afd_plugin.model_executor.models.model_utils import get_afd_model_config + hf_config = SimpleNamespace(architectures=["DeepseekV2ForCausalLM"]) model_config = SimpleNamespace( - hf_config=SimpleNamespace(architectures=["DeepseekV2ForCausalLM"]), + hf_config=hf_config, + hf_text_config=hf_config, ) afd_model_config = get_afd_model_config(model_config) assert afd_model_config is not model_config assert afd_model_config.hf_config is not model_config.hf_config + assert afd_model_config.hf_text_config is afd_model_config.hf_config assert afd_model_config.hf_config.architectures == ["AFDDeepseekV2ForCausalLM"] assert model_config.hf_config.architectures == ["DeepseekV2ForCausalLM"] +def test_afd_model_config_preserves_nested_text_config(): + pytest.importorskip("vllm") + from afd_plugin.model_executor.models.model_utils import get_afd_model_config + + hf_text_config = SimpleNamespace() + model_config = SimpleNamespace( + hf_config=SimpleNamespace(architectures=["DeepseekV2ForCausalLM"]), + hf_text_config=hf_text_config, + ) + + afd_model_config = get_afd_model_config(model_config) + + assert afd_model_config.hf_config is not model_config.hf_config + assert afd_model_config.hf_text_config is hf_text_config + assert afd_model_config.hf_text_config is not afd_model_config.hf_config + + def test_entry_point_is_registered(): entry_points = importlib.metadata.entry_points(group="vllm.general_plugins") matches = [ep for ep in entry_points if ep.name == "afd"] From 38df180ce38429866b2441eba48d4897fe9f1980 Mon Sep 17 00:00:00 2001 From: ShwStone Date: Wed, 29 Jul 2026 14:30:40 +0800 Subject: [PATCH 2/2] change to deepcopy Signed-off-by: ShwStone --- .../model_executor/models/model_utils.py | 18 +++++++----------- tests/unit/package/test_package.py | 4 +++- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/afd_plugin/model_executor/models/model_utils.py b/afd_plugin/model_executor/models/model_utils.py index bfc94e48..ecfb1568 100644 --- a/afd_plugin/model_executor/models/model_utils.py +++ b/afd_plugin/model_executor/models/model_utils.py @@ -4,7 +4,7 @@ from __future__ import annotations -from copy import copy +from copy import deepcopy from typing import TYPE_CHECKING from afd_plugin import _DEEPSEEK_MODEL_REGISTRATIONS @@ -18,15 +18,11 @@ def get_afd_model_config(model_config: ModelConfig) -> ModelConfig: for model_arch in model_config.hf_config.architectures: if model_arch in _DEEPSEEK_MODEL_REGISTRATIONS: - afd_model_config = copy(model_config) - afd_hf_config = copy(model_config.hf_config) - afd_hf_config.architectures = [f"AFD{model_arch}"] - afd_model_config.hf_config = afd_hf_config - - # Pure-text ModelConfig uses the same object for hf_config and - # hf_text_config. Preserve that identity: vLLM Ascend uses it to - # distinguish text models from multimodal models. - if model_config.hf_text_config is model_config.hf_config: - afd_model_config.hf_text_config = afd_hf_config + # deepcopy preserves aliasing within the copied object graph, so + # the pure-text identity hf_text_config is hf_config is retained + # automatically. vLLM Ascend uses that identity to distinguish + # text models from multimodal models. + afd_model_config = deepcopy(model_config) + afd_model_config.hf_config.architectures = [f"AFD{model_arch}"] return afd_model_config return model_config diff --git a/tests/unit/package/test_package.py b/tests/unit/package/test_package.py index d4053a42..6966bc18 100644 --- a/tests/unit/package/test_package.py +++ b/tests/unit/package/test_package.py @@ -77,8 +77,10 @@ def test_afd_model_config_preserves_nested_text_config(): afd_model_config = get_afd_model_config(model_config) + # deepcopy privatizes the whole graph; a genuinely distinct nested + # hf_text_config stays distinct from hf_config. assert afd_model_config.hf_config is not model_config.hf_config - assert afd_model_config.hf_text_config is hf_text_config + assert afd_model_config.hf_text_config is not hf_text_config assert afd_model_config.hf_text_config is not afd_model_config.hf_config