[Test][Determinism] Cover VLM batch invariance in default execution mode (#56528)
Signed-off-by: Shenglei Fu <sfu@confluent.io> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Shenglei Fu committed
Sep 13, 2026 at 07:22 UTC
8cf9de9080ea5cded1c93e3d9a5ac531da0c93b6
1 file changed
+41
-7
tests/v1/determinism/test_batch_invariance_vlm.py
+41
-7
@@ -59,15 +59,22 @@ def _assert_batch_invariant(llm: LLM, inputs: list[dict], sampling) -> None:
59
_extract_step_logprobs(llm.generate([inp], sampling, use_tqdm=False)[0])
60
for inp in inputs
61
]
62
- bsN = [_extract_step_logprobs(out) for out in llm.generate(inputs, sampling)]
62
+ bsN_outputs = llm.generate(inputs, sampling, use_tqdm=False)
63
+ assert len(bs1) == len(inputs)
64
+ assert len(bsN_outputs) == len(inputs)
65
+ bsN = [_extract_step_logprobs(out) for out in bsN_outputs]
66
67
failures = []
68
for i, ((lp1, t1), (lpN, tN)) in enumerate(zip(bs1, bsN)):
69
if lp1 is None or lpN is None:
67
- pytest.skip(
68
- "Logits are not available on RequestOutput; "
69
- "enable logprobs return to run this test."
70
+ failures.append(f"req {i}: selected-token logprobs are unavailable")
71
+ continue
72
+ if len(t1) != sampling.max_tokens or len(tN) != sampling.max_tokens:
73
+ failures.append(
74
+ f"req {i}: expected {sampling.max_tokens} tokens, "
75
+ f"got bs1={len(t1)} bsN={len(tN)}"
76
)
77
+ continue
78
if t1 != tN:
79
failures.append(f"req {i}: token mismatch bs1={t1} bsN={tN}")
80
elif not torch.equal(lp1, lpN):
@@ -84,16 +91,43 @@ def _assert_batch_invariant(llm: LLM, inputs: list[dict], sampling) -> None:
91
@skip_if_not_cuda
92
@pytest.mark.parametrize("input_type", ["image", "video"])
93
@pytest.mark.parametrize("mm_encoder_attn_backend", ["FLASH_ATTN", "TORCH_SDPA"])
87
-def test_vlm_batch_invariance_bs1_vs_bsN(input_type: str, mm_encoder_attn_backend: str):
94
+def test_vlm_batch_invariance_bs1_vs_bsN(
95
+ input_type: str,
96
+ mm_encoder_attn_backend: str,
97
+ monkeypatch: pytest.MonkeyPatch,
98
+):
99
+ monkeypatch.setenv("VLLM_USE_FLASHINFER_SAMPLER", "0")
100
+ _run_vlm_batch_invariance(input_type, mm_encoder_attn_backend, enforce_eager=True)
101
+
102
+
103
+@skip_if_not_cuda
104
+def test_vlm_batch_invariance_default_execution(monkeypatch: pytest.MonkeyPatch):
105
+ monkeypatch.setenv("VLLM_USE_FLASHINFER_SAMPLER", "0")
106
+ _run_vlm_batch_invariance("image", "FLASH_ATTN", enforce_eager=False)
107
+
108
+
109
+def _run_vlm_batch_invariance(
110
+ input_type: str, mm_encoder_attn_backend: str, enforce_eager: bool
111
+) -> None:
112
inputs = _make_inputs(input_type, num_reqs=4)
89
- sampling = SamplingParams(temperature=0.0, max_tokens=8, seed=1234, logprobs=5)
113
+ sampling = SamplingParams(
114
+ temperature=0.0,
115
+ max_tokens=8,
116
+ seed=1234,
117
+ ignore_eos=True,
118
+ logprobs=5,
119
+ )
120
121
llm = LLM(
122
model=VLM_TEST_MODEL,
123
dtype="bfloat16",
94
- enforce_eager=True,
124
+ enforce_eager=enforce_eager,
125
max_num_seqs=16,
126
+ max_model_len=4096,
127
+ max_num_batched_tokens=2048,
128
gpu_memory_utilization=0.85,
129
+ enable_prefix_caching=False,
130
+ mm_processor_cache_gb=0,
131
mm_encoder_attn_backend=mm_encoder_attn_backend,
132
)
133
try: