[Misc] Separate adaptive verification config validation (#54108)
Signed-off-by: Nick Hill <nickhill123@gmail.com>
Nick Hill committed
Aug 27, 2026 at 19:03 UTC
8cfba696eef712edbdc4b02aafd5ac73a818736d
1 file changed
+36
-30
vllm/config/vllm.py
+36
-30
@@ -1607,6 +1607,7 @@ class VllmConfig:
1607
self._validate_v1_model_runner()
1608
1609
self._validate_batch_sharded_sampling()
1610
+ self._validate_adaptive_verification()
1611
1612
# Re-compute compile ranges after platform-specific config updates
1613
# (e.g., XPU may lower max_num_batched_tokens when MLA is enabled)
@@ -2444,34 +2445,6 @@ class VllmConfig:
2445
):
2446
unsupported.append("EAGLE3 with pipeline parallelism")
2447
2447
- if (
2448
- speculative_config.enable_adaptive_verification
2449
- and self.lora_config is not None
2450
- ):
2451
- # The per-token LoRA mapping is built from CPU placeholder boundaries,
2452
- # while the trimmed batch's true boundaries are decided on the GPU.
2453
- unsupported.append("adaptive verification with LoRA")
2454
-
2455
- if (
2456
- speculative_config.enable_adaptive_verification
2457
- and self.compilation_config.cudagraph_mode == CUDAGraphMode.NONE
2458
- ):
2459
- # The draft budget divides by step costs profiled from captured
2460
- # cudagraphs; eager execution captures none.
2461
- unsupported.append(
2462
- "adaptive verification with enforce_eager/cudagraph_mode=none"
2463
- )
2464
-
2465
- if (
2466
- speculative_config.enable_adaptive_verification
2467
- and self.parallel_config.pipeline_parallel_size > 1
2468
- ):
2469
- # Cost curves and confidences currently only exist on the last PP rank;
2470
- # earlier ranks would diverge on the trimmed batch shape.
2471
- # TODO: we should be able to support adaptive verification with PP by
2472
- # broadcasting the cost curves and confidences to all ranks.
2473
- unsupported.append("adaptive verification with pipeline parallelism")
2474
-
2448
if self.parallel_config.enable_dbo:
2449
unsupported.append("dual batch overlap")
2450
@@ -2503,8 +2476,11 @@ class VllmConfig:
2476
unsupported.append("prefill context parallel")
2477
2478
# DSpark is implemented only by the V2 GPU model runner.
2506
- if self.speculative_config and self.speculative_config.method == "dspark":
2507
- unsupported.append("dspark speculative decoding")
2479
+ if self.speculative_config:
2480
+ if self.speculative_config.method == "dspark":
2481
+ unsupported.append("dspark speculative decoding")
2482
+ if self.speculative_config.enable_adaptive_verification:
2483
+ unsupported.append("adaptive draft verification")
2484
2485
# Mixed sliding/full DFlash drafts need multiple KV groups (V2 only).
2486
if self._dflash_needs_multi_kv_group():
@@ -2524,6 +2500,36 @@ class VllmConfig:
2500
2501
return unsupported
2502
2503
+ def _validate_adaptive_verification(self) -> None:
2504
+ spec_config = self.speculative_config
2505
+ if not spec_config or not spec_config.enable_adaptive_verification:
2506
+ return
2507
+
2508
+ if self.lora_config is not None:
2509
+ # The per-token LoRA mapping is built from CPU placeholder boundaries,
2510
+ # while the trimmed batch's true boundaries are decided on the GPU.
2511
+ raise ValueError(
2512
+ "Adaptive verification is not currently compatible with LoRA"
2513
+ )
2514
+
2515
+ if self.compilation_config.cudagraph_mode == CUDAGraphMode.NONE:
2516
+ # The draft budget divides by step costs profiled from captured
2517
+ # cudagraphs; eager execution captures none.
2518
+ raise ValueError(
2519
+ "Adaptive verification is not currently compatible with "
2520
+ "enforce_eager/cudagraph_mode=none"
2521
+ )
2522
+
2523
+ if self.parallel_config.pipeline_parallel_size > 1:
2524
+ # Cost curves and confidences currently only exist on the last PP rank;
2525
+ # earlier ranks would diverge on the trimmed batch shape.
2526
+ # TODO: we should be able to support adaptive verification with PP by
2527
+ # broadcasting the cost curves and confidences to all ranks.
2528
+ raise ValueError(
2529
+ "Adaptive verification is not currently compatible "
2530
+ "with pipeline parallelism"
2531
+ )
2532
+
2533
def _validate_batch_sharded_sampling(self) -> None:
2534
"""Validate `enable_batch_sharded_sampling` against the rest of the config."""
2535
if not self.parallel_config.enable_batch_sharded_sampling: