[ROCm][CI] Add HY-V4 generation coverage (#55667)

Signed-off-by: Andreas Karatzas <Andreas.Karatzas@amd.com>

Andreas Karatzas committed Sep 11, 2026 at 04:24 UTC eb7e89443287cc8ec95b8e6fb993bacbd310f9c3
4 files changed +160 -2
.buildkite/test-amd.yaml
+8
@@ -516,6 +516,11 @@ steps:
516 optional: true
517 working_dir: "/vllm-workspace/tests"
518 source_file_dependencies:
519 + - vllm/models/hy_v4/
520 + - vllm/config/
521 + - vllm/v1/worker/gpu/
522 + - vllm/v1/attention/ops/
523 + - vllm/v1/attention/backend.py
524 - vllm/model_executor/model_loader/sharded_state_loader.py
525 - vllm/model_executor/models/
526 - vllm/model_executor/layers/
@@ -535,6 +540,7 @@ steps:
540 - pytest models/multimodal/generation/test_phi4siglip.py -v -s -m 'distributed(num_gpus=2)'
541 - VLLM_WORKER_MULTIPROC_METHOD=spawn pytest models/multimodal/generation/test_whisper.py -v -s -m 'distributed(num_gpus=2)'
542 - pytest -v -s models/test_vision.py -m 'distributed(num_gpus=2)'
543 + - VLLM_ROCM_USE_AITER=1 pytest -v -s models/test_hyv4_rocm.py -m 'distributed(num_gpus=2)'
544
545 #-------------------------------------------------------- mi300 · benchmarks ---------------------------------------------------------#
546
@@ -1978,9 +1984,11 @@ steps:
1984 - tests/models/test_terratorch.py
1985 - tests/models/transformers/test_backend.py
1986 - tests/models/test_registry.py
1987 + - tests/models/test_hyv4_rocm.py
1988 - tests/models/test_vision.py
1989 commands:
1990 - pytest -v -s models/test_terratorch.py models/transformers/test_backend.py models/test_registry.py
1991 + - VLLM_ROCM_USE_AITER=1 pytest -v -s models/test_hyv4_rocm.py -m 'not distributed'
1992 - pytest -v -s models/test_vision.py::test_simple_mrope_vision_model_spatial_merge
1993
1994 #----------------------------------------------------- mi300 · models / language -----------------------------------------------------#
.buildkite/test_areas/models_basic.yaml
+5
@@ -58,6 +58,11 @@ steps:
58 timeout_in_minutes: 50
59 depends_on:
60 - image-build-amd
61 + source_file_dependencies:
62 + - tests/models/test_hyv4_rocm.py
63 + commands:
64 + - pytest -v -s models/test_terratorch.py models/transformers/test_backend.py models/test_registry.py
65 + - VLLM_ROCM_USE_AITER=1 pytest -v -s models/test_hyv4_rocm.py -m 'not distributed'
66
67 - label: ":nvidia: (B200) Inkling"
68 key: inkling-unit-tests-b200
.buildkite/test_areas/models_distributed.yaml
+10 -2
@@ -42,6 +42,13 @@ steps:
42 depends_on:
43 - image-build-amd
44 source_file_dependencies:
45 + - vllm/models/hy_v4/
46 + - vllm/config/
47 + - vllm/v1/worker/
48 + - vllm/v1/attention/ops/
49 + - vllm/v1/attention/backend.py
50 + - tests/conftest.py
51 + - tests/utils.py
52 - vllm/model_executor/model_loader/sharded_state_loader.py
53 - vllm/model_executor/models/
54 - vllm/model_executor/layers/
@@ -60,8 +67,9 @@ steps:
67 HIP_VISIBLE_DEVICES=0,1 pytest -v -s model_executor/model_loader/test_sharded_state_loader.py -m '(not slow_test)'
68 ;;
69 1)
63 - pytest models/transformers/test_backend.py -v -s -m 'distributed(num_gpus=2)'
64 - pytest models/language -v -s -m 'distributed(num_gpus=2)'
70 + pytest models/transformers/test_backend.py -v -s -m 'distributed(num_gpus=2)' &&
71 + pytest models/language -v -s -m 'distributed(num_gpus=2)' &&
72 + VLLM_ROCM_USE_AITER=1 pytest -v -s models/test_hyv4_rocm.py -m 'distributed(num_gpus=2)'
73 ;;
74 2)
75 pytest models/multimodal -v -s -m 'distributed(num_gpus=2)' --ignore models/multimodal/generation/test_whisper.py --ignore models/multimodal/generation/test_phi4siglip.py
tests/models/test_hyv4_rocm.py new
+137
@@ -0,0 +1,137 @@
1 +# SPDX-License-Identifier: Apache-2.0
2 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 +
4 +import math
5 +
6 +import pytest
7 +
8 +from tests.utils import multi_gpu_marks
9 +from vllm import SamplingParams
10 +from vllm.config import CompilationConfig
11 +from vllm.config.compilation import CompilationMode, CUDAGraphMode
12 +from vllm.platforms import current_platform
13 +from vllm.v1.metrics.reader import Counter
14 +
15 +pytestmark = pytest.mark.skipif(
16 + not current_platform.is_rocm(), reason="ROCm-specific tests"
17 +)
18 +
19 +
20 +def _small_hyv4_config(config):
21 + # Apply to both target and MTP draft while retaining MLA/indexer dimensions.
22 + config.update(
23 + {
24 + "hidden_size": 512,
25 + "num_hidden_layers": 2,
26 + "num_attention_heads": 64,
27 + "q_lora_rank": 128,
28 + "intermediate_size": 512,
29 + "moe_intermediate_size": 256,
30 + "n_routed_experts": 4,
31 + "num_experts_per_tok": 2,
32 + "n_shared_experts": 1,
33 + "enable_ihc": True,
34 + "index_n_heads": 32,
35 + "index_topk": 2048,
36 + "layer_types": ["deepseek_sparse_attention"] * 2,
37 + "indexer_types": ["full", "shared"],
38 + "num_nextn_predict_layers": 1,
39 + "vocab_size": 256,
40 + "bos_token_id": 1,
41 + "eos_token_id": 2,
42 + "pad_token_id": 0,
43 + }
44 + )
45 + return config
46 +
47 +
48 +def _num_captured_graphs(_worker):
49 + from vllm.compilation.counter import compilation_counter
50 +
51 + return compilation_counter.num_cudagraph_captured
52 +
53 +
54 +@pytest.mark.parametrize(
55 + "tp,enforce_eager,mtp,dtype,kv_cache_dtype",
56 + [
57 + pytest.param(1, True, False, "bfloat16", "auto", id="eager-tp1"),
58 + pytest.param(1, True, False, "float16", "auto", id="eager-fp16"),
59 + pytest.param(1, True, False, "bfloat16", "fp8", id="eager-fp8-kv"),
60 + pytest.param(
61 + 2,
62 + False,
63 + False,
64 + "bfloat16",
65 + "auto",
66 + id="graphs-tp2",
67 + marks=multi_gpu_marks(num_gpus=2),
68 + ),
69 + pytest.param(1, True, True, "bfloat16", "auto", id="eager-mtp"),
70 + ],
71 +)
72 +def test_hyv4_dummy_generation(
73 + vllm_runner,
74 + enable_pickle,
75 + tp: int,
76 + enforce_eager: bool,
77 + mtp: bool,
78 + dtype: str,
79 + kv_cache_dtype: str,
80 +) -> None:
81 + """Exercise prefill, decode, and batch consistency with dummy HY weights."""
82 + with vllm_runner(
83 + "tencent/Hy4-preview",
84 + trust_remote_code=True,
85 + skip_tokenizer_init=True,
86 + load_format="dummy",
87 + disable_log_stats=not mtp,
88 + dtype=dtype,
89 + kv_cache_dtype=kv_cache_dtype,
90 + hf_overrides=_small_hyv4_config,
91 + max_model_len=256,
92 + max_num_batched_tokens=128,
93 + max_num_seqs=8,
94 + enable_chunked_prefill=True,
95 + enable_prefix_caching=False,
96 + kv_cache_memory_bytes=128 * 1024 * 1024,
97 + enforce_eager=enforce_eager,
98 + tensor_parallel_size=tp,
99 + speculative_config={"method": "mtp", "num_speculative_tokens": 2}
100 + if mtp
101 + else None,
102 + seed=17,
103 + # Exercise supported decode graphs independently of default graph policy.
104 + compilation_config=CompilationConfig(
105 + mode=CompilationMode.NONE,
106 + cudagraph_mode=CUDAGraphMode.NONE
107 + if enforce_eager
108 + else CUDAGraphMode.FULL_DECODE_ONLY,
109 + cudagraph_capture_sizes=[] if enforce_eager else [1, 2, 4],
110 + ),
111 + ) as model:
112 + if not enforce_eager:
113 + assert model.collective_rpc(_num_captured_graphs) == [3] * tp
114 + prompts = [
115 + {"prompt_token_ids": [11, 12, 13, 14]},
116 + {"prompt_token_ids": list(range(20, 84))},
117 + ]
118 + params = SamplingParams(
119 + temperature=0, max_tokens=4, ignore_eos=True, logprobs=1
120 + )
121 + outputs = model.llm.generate(prompts, params)
122 + assert len(outputs) == len(prompts)
123 + for prompt, output in zip(prompts, outputs):
124 + completion = output.outputs[0]
125 + assert len(completion.token_ids) == 4
126 + assert completion.cumulative_logprob is not None
127 + assert math.isfinite(completion.cumulative_logprob)
128 + single = model.llm.generate([prompt], params)[0].outputs[0]
129 + assert single.token_ids == completion.token_ids
130 +
131 + if mtp:
132 + assert any(
133 + isinstance(metric, Counter)
134 + and metric.name == "vllm:spec_decode_num_drafts"
135 + and metric.value > 0
136 + for metric in model.llm.get_metrics()
137 + ), "MTP drafter did not run"