group: Spec Decode
depends_on:
  - image-build
steps:
- label: ":nvidia: (H200 MIG 35GB) V1 Spec Decode"
  device: h200_35gb
  key: v1-spec-decode
  timeout_in_minutes: 40
  source_file_dependencies:
    - vllm/config/
    - vllm/distributed/
    - "!vllm/distributed/kv_transfer/"
    - vllm/inputs/
    - vllm/model_executor/
    - vllm/models/qwen4_exp/
    - vllm/platforms/
    - vllm/sampling_params.py
    - vllm/transformers_utils/
    - vllm/utils/
    - vllm/v1/
    - tests/v1/spec_decode
  commands:
    - export VLLM_WORKER_MULTIPROC_METHOD=spawn
    # TODO: create another `optional` test group for slow tests
    - pytest -v -s -m 'not slow_test' v1/spec_decode
  mirror:
    amd:
      label: ":amd: (MI300) V1 Spec Decode"
      dind: false
      device: mi300_1
      timeout_in_minutes: 50
      depends_on:
      - image-build-amd

- label: ":nvidia: (H200 MIG 35GB) Spec Decode Eagle 1: DeepSeek + Qwen"
  key: spec-decode-eagle-1-deepseek-qwen
  timeout_in_minutes: 25
  device: h200_35gb
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/eagle/ -k "deepseek_eagle or qwen3_eagle3"
  mirror:
    amd:
      label: ":amd: (MI355 DPX) Spec Decode Eagle 1: DeepSeek + Qwen"
      dind: false
      device: mi355_dpx
      timeout_in_minutes: 60
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/model_executor/model_loader/
      - vllm/v1/sample/
      - vllm/model_executor/layers/
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (H200 MIG 35GB) Spec Decode Eagle 2: Llama 3 + Qwen VL + Other"
  key: spec-decode-eagle-2-llama3-qwen-vl-other
  timeout_in_minutes: 25
  device: h200_35gb
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/eagle/ -k "not deepseek_eagle and not qwen3_eagle3"
  mirror:
    amd:
      label: ":amd: (MI355 DPX) Spec Decode Eagle 2: Llama 3 + Qwen VL + Other"
      dind: false
      device: mi355_dpx
      timeout_in_minutes: 60
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/model_executor/model_loader/
      - vllm/v1/sample/
      - vllm/model_executor/layers/
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (B200) Spec Decode Eagle Nightly"
  key: spec-decode-eagle-nightly-b200
  timeout_in_minutes: 25
  device: b200-k8s
  optional: true
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/eagle/

# MTP correctness is one parametrized test split into per-model folders;
# each job below runs whole directories.
- label: ":nvidia: (H200 MIG 35GB) Spec Decode Speculators"
  key: spec-decode-speculators
  timeout_in_minutes: 30
  device: h200_35gb
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - vllm/v1/attention/backends/
    - vllm/transformers_utils/configs/speculators/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/speculators/
  mirror:
    amd:
      label: ":amd: (MI300) Spec Decode Speculators"
      dind: false
      device: mi300_1
      timeout_in_minutes: 40
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/model_executor/model_loader/
      - vllm/v1/sample/
      - vllm/model_executor/layers/
      - vllm/transformers_utils/configs/speculators/
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (H200 MIG 35GB) Spec Decode MTP Gemma4"
  key: spec-decode-mtp-gemma4
  timeout_in_minutes: 30
  device: h200_35gb
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - vllm/v1/attention/backends/
    - vllm/transformers_utils/configs/speculators/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/mtp/gemma4/
  mirror:
    amd:
      label: ":amd: (MI300) Spec Decode MTP Gemma4"
      dind: false
      device: mi300_1
      timeout_in_minutes: 40
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/model_executor/model_loader/
      - vllm/v1/sample/
      - vllm/model_executor/layers/
      - vllm/transformers_utils/configs/speculators/
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (H200 MIG 35GB) Spec Decode MTP DeepSeek + MiMo"
  key: spec-decode-mtp-deepseek-mimo
  timeout_in_minutes: 30
  device: h200_35gb
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - vllm/v1/attention/backends/
    - vllm/transformers_utils/configs/speculators/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/mtp/deepseek/
    - pytest -v -s v1/e2e/spec_decode/mtp/mimo/
  mirror:
    amd:
      label: ":amd: (MI300) Spec Decode MTP DeepSeek + MiMo"
      dind: false
      device: mi300_1
      timeout_in_minutes: 40
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/model_executor/model_loader/
      - vllm/v1/sample/
      - vllm/model_executor/layers/
      - vllm/transformers_utils/configs/speculators/
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (H200 MIG 35GB) Spec Decode MTP Qwen3.5"
  key: spec-decode-mtp-qwen3-5
  timeout_in_minutes: 30
  device: h200_35gb
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - vllm/v1/attention/backends/
    - vllm/transformers_utils/configs/speculators/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/mtp/qwen3_5/
  mirror:
    amd:
      label: ":amd: (MI300) Spec Decode MTP Qwen3.5"
      dind: false
      device: mi300_1
      timeout_in_minutes: 40
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/model_executor/model_loader/
      - vllm/v1/sample/
      - vllm/model_executor/layers/
      - vllm/transformers_utils/configs/speculators/
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (B200) Spec Decode Speculators + MTP Nightly"
  key: spec-decode-speculators-mtp-nightly-b200
  timeout_in_minutes: 30
  device: b200-k8s
  optional: true
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - vllm/transformers_utils/configs/speculators/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/speculators/
    - pytest -v -s v1/e2e/spec_decode/mtp/

- label: ":nvidia: (H200 MIG 35GB) Spec Decode N-Gram + Suffix"
  key: spec-decode-ngram-suffix
  timeout_in_minutes: 20
  device: h200_35gb
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - tests/v1/e2e/spec_decode/
    - tests/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/ngram_suffix/
    - python3 spec_decode/test_custom_proposer.py
  mirror:
    amd:
      label: ":amd: (MI355 DPX) Spec Decode N-Gram + Suffix"
      dind: false
      device: mi355_dpx
      timeout_in_minutes: 35
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/model_executor/model_loader/
      - vllm/v1/sample/
      - vllm/model_executor/layers/
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (H200 MIG 18GB) Spec Decode Draft Model Shard %N"
  key: spec-decode-draft-model
  timeout_in_minutes: 60
  device: h200_18gb
  parallelism: 4
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/draft_model/ --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT --shard-id=$$BUILDKITE_PARALLEL_JOB
  mirror:
    amd:
      label: ":amd: (MI355 DPX) Spec Decode Draft Model Shard %N"
      dind: false
      device: mi355_dpx
      timeout_in_minutes: 60
      parallelism: 2
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/model_executor/model_loader/
      - vllm/v1/sample/
      - vllm/model_executor/layers/
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (B200) Spec Decode Draft Model Nightly"
  key: spec-decode-draft-model-nightly-b200
  timeout_in_minutes: 40
  device: b200-k8s
  optional: true
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/draft_model/

- label: ":nvidia: (H100) Speculators Correctness Nightly"
  key: speculators-correctness
  timeout_in_minutes: 30
  device: h100
  optional: true
  num_devices: 1
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/dflash/
    - vllm/model_executor/models/qwen3_dflash.py
    - tests/v1/spec_decode/test_speculators_correctness.py
  commands:
    - export VLLM_ALLOW_INSECURE_SERIALIZATION=1
    - pytest -v -s v1/spec_decode/test_speculators_correctness.py -m slow_test
  mirror:
    amd:
      label: ":amd: (MI300) Speculators Correctness Nightly"
      dind: false
      device: mi300_1
      timeout_in_minutes: 40
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/_aiter_ops.py
      - vllm/platforms/rocm.py

- label: ":nvidia: (B200) Spec Decode DeepSeek MTP Parallel Load"
  key: spec-decode-deepseek-mtp-parallel-load-2xb200-2xmi300
  timeout_in_minutes: 30
  device: b200-k8s
  optional: true
  num_devices: 2
  source_file_dependencies:
    - vllm/v1/spec_decode/llm_base_proposer.py
    - vllm/v1/spec_decode/eagle.py
    - vllm/v1/worker/gpu/spec_decode/eagle/
    - vllm/model_executor/models/deepseek_mtp.py
    - vllm/model_executor/models/deepseek_v2.py
    - tests/v1/e2e/spec_decode/test_mtp_parallel_load.py
  commands:
    - pytest -v -s v1/e2e/spec_decode/test_mtp_parallel_load.py
  mirror:
    amd:
      label: ":amd: (MI300) Spec Decode DeepSeek MTP Parallel Load"
      dind: false
      device: mi300_2
      timeout_in_minutes: 45
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/distributed/
      - vllm/model_executor/model_loader/
      - vllm/model_executor/layers/
      - vllm/model_executor/models/deepseek_mtp.py
      - vllm/model_executor/models/deepseek_v2.py
      - vllm/v1/attention/
      - vllm/v1/engine/
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/v1/worker/gpu_model_runner.py
      - tests/v1/e2e/spec_decode/test_mtp_parallel_load.py
      - vllm/platforms/rocm.py

- label: ":nvidia: (H200 MIG 35GB) Spec Decode AL DFlash Nightly"
  key: spec-decode-dflash-nightly
  timeout_in_minutes: 90
  device: h200_35gb
  optional: true
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - vllm/model_executor/models/qwen3_dflash.py
    - vllm/model_executor/models/qwen3_dflash2.py
    - vllm/model_executor/models/qwen3_5.py
    - vllm/model_executor/models/laguna_dflash.py
    - tests/v1/e2e/spec_decode/
  commands:
    # DFlash2 NVFP4 (27B) does not fit a 35GB MIG slice; runs on B200 below.
    - pytest -v -s v1/e2e/spec_decode/acceptance_rates/dflash/ -k "not dflash2"
  mirror:
    amd:
      label: ":amd: (MI300) Spec Decode AL DFlash Nightly"
      dind: false
      device: mi300_1
      timeout_in_minutes: 120
      commands:
      - pytest -v -s v1/e2e/spec_decode/acceptance_rates/dflash/ -k "not dflash2"
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/v1/attention/
      - vllm/v1/sample/
      - vllm/model_executor/model_loader/
      - vllm/model_executor/layers/
      - vllm/model_executor/models/qwen2.py
      - vllm/model_executor/models/qwen3.py
      - vllm/model_executor/models/qwen3_dflash.py
      - vllm/model_executor/models/laguna.py
      - vllm/model_executor/models/laguna_dflash.py
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (B200) Spec Decode AL DFlash2 Nightly"
  key: spec-decode-dflash2-nightly-b200
  timeout_in_minutes: 60
  device: b200-k8s
  optional: true
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - vllm/model_executor/models/qwen3_dflash.py
    - vllm/model_executor/models/qwen3_dflash2.py
    - vllm/model_executor/models/qwen3_5.py
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/acceptance_rates/dflash/ -k "dflash2"
  mirror:
    amd:
      label: ":amd: (MI355) Spec Decode AL DFlash2 Nightly"
      dind: false
      device: mi355_1
      num_devices: 1
      timeout_in_minutes: 60
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - .buildkite/test_areas/spec_decode.yaml
      - tests/v1/e2e/spec_decode/
      - tests/evals/gsm8k/
      - tests/utils.py
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/v1/worker/gpu/sample/
      - vllm/v1/worker/gpu/model_runner.py
      - vllm/v1/attention/
      - vllm/model_executor/models/qwen3_dflash.py
      - vllm/model_executor/models/qwen3_dflash2.py
      - vllm/model_executor/models/qwen3_5.py
      - vllm/model_executor/model_loader/
      - vllm/model_executor/layers/quantization/
      - vllm/model_executor/kernels/linear/
      - vllm/platforms/rocm.py

- label: ":nvidia: (H200 MIG 35GB) Spec Decode AL DSpark Nightly"
  key: spec-decode-dspark-nightly
  timeout_in_minutes: 60
  device: h200_35gb
  optional: true
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - vllm/model_executor/models/qwen3_dspark.py
    - vllm/model_executor/models/gemma4_dspark.py
    - tests/v1/e2e/spec_decode/
  commands:
    - pytest -v -s v1/e2e/spec_decode/acceptance_rates/dspark/
  mirror:
    amd:
      label: ":amd: (MI300) Spec Decode AL DSpark Nightly"
      dind: false
      device: mi300_1
      timeout_in_minutes: 90
      depends_on:
      - image-build-amd
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/worker/gpu/spec_decode/
      - vllm/v1/attention/
      - vllm/v1/sample/
      - vllm/model_executor/model_loader/
      - vllm/model_executor/layers/
      - vllm/model_executor/models/qwen2.py
      - vllm/model_executor/models/qwen3.py
      - vllm/model_executor/models/qwen3_dflash.py
      - vllm/model_executor/models/qwen3_dspark.py
      - vllm/model_executor/models/gemma4.py
      - vllm/model_executor/models/gemma4_mm.py
      - vllm/model_executor/models/gemma4_unified.py
      - vllm/model_executor/models/gemma4_mtp.py
      - vllm/model_executor/models/gemma4_dspark.py
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py

- label: ":nvidia: (H200 MIG 35GB) Spec Decode AL MTP + Other Acceptance Nightly"
  key: spec-decode-mtp-other-acceptance-nightly
  timeout_in_minutes: 35
  device: h200_35gb
  optional: true
  parallelism: 3
  source_file_dependencies:
    - vllm/v1/spec_decode/
    - vllm/v1/worker/gpu/spec_decode/
    - tests/v1/e2e/spec_decode/conftest.py
    - tests/v1/e2e/spec_decode/
  commands:
    # Each Gemma4 parametrization is an indivisible ~23m floor. Keep them in
    # separate shards and put the remaining tests in shard 0, where new tests
    # land by default.
    - if [ "$$BUILDKITE_PARALLEL_JOB" = "0" ]; then pytest -v -s v1/e2e/spec_decode/acceptance_rates/mtp_other/ --deselect "tests/v1/e2e/spec_decode/acceptance_rates/mtp_other/test_mtp.py::test_gemma4_mtp_acceptance_lengths[False]" --deselect "tests/v1/e2e/spec_decode/acceptance_rates/mtp_other/test_mtp.py::test_gemma4_mtp_acceptance_lengths[True]"; fi
    - if [ "$$BUILDKITE_PARALLEL_JOB" = "1" ]; then pytest -v -s "v1/e2e/spec_decode/acceptance_rates/mtp_other/test_mtp.py::test_gemma4_mtp_acceptance_lengths[False]"; fi
    - if [ "$$BUILDKITE_PARALLEL_JOB" = "2" ]; then pytest -v -s "v1/e2e/spec_decode/acceptance_rates/mtp_other/test_mtp.py::test_gemma4_mtp_acceptance_lengths[True]"; fi
  mirror:
    amd:
      label: ":amd: (MI355 DPX) Spec Decode AL MTP + Other Acceptance Nightly"
      dind: false
      device: mi355_dpx
      timeout_in_minutes: 55
      depends_on:
      - image-build-amd
      working_dir: /vllm-workspace/tests
      source_file_dependencies:
      - vllm/v1/spec_decode/
      - vllm/v1/sample/
      - vllm/v1/worker/gpu/
      - vllm/v1/worker/gpu_model_runner.py
      - vllm/v1/worker/gpu_worker.py
      - vllm/model_executor/model_loader/
      - vllm/model_executor/models/gemma4.py
      - vllm/model_executor/models/gemma4_mm.py
      - vllm/model_executor/models/gemma4_mtp.py
      - vllm/model_executor/models/llama.py
      - vllm/model_executor/models/llama_eagle3.py
      - vllm/model_executor/models/medusa.py
      - vllm/model_executor/models/registry.py
      - tests/evals/gsm8k/
      - tests/utils.py
      - tests/v1/e2e/spec_decode/
      - vllm/platforms/rocm.py
