[Gemma4] vision-path A/B knobs for the 12B loop defect (bidi-on-full-layers, fp32 embedder) + NaN-safe softcap - #1
Conversation
Signed-off-by: yewentao256 <zhyanwentao@126.com>
…tion select max hidden dim of target and draft model (vllm-project#52193) Signed-off-by: khushali9 <khushali.desai9@gmail.com>
…aths (vllm-project#53561) Signed-off-by: jperezde <jperezde@redhat.com>
Signed-off-by: Giancarlo Delfin <gdelfin@inferact.ai>
Signed-off-by: Randall Smith <Randall.Smith@amd.com>
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Co-authored-by: Xianbao QIAN <xianbao.qian@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Andrey Talman <atalman@fb.com>
…filing (vllm-project#53593) Signed-off-by: Nick Hill <nickhill123@gmail.com>
…m-project#53456) Signed-off-by: Mikhail Kostryukov <mike@triptrack.net> Co-authored-by: Claude <noreply@anthropic.com>
vllm-project#52676) Signed-off-by: kiroxu <148877251+BabyDrangoner@users.noreply.github.com> Co-authored-by: OpenAI Codex <codex@openai.com>
…llm-project#53618) Signed-off-by: Kevin Luu <51931015+khluu@users.noreply.github.com> Co-authored-by: Codex <codex@openai.com>
…llm-project#53519) Signed-off-by: Zupeng Wang <71580390+zupengwang@users.noreply.github.com>
Signed-off-by: Libin Tang <libin.tang@intel.com> Co-authored-by: Kunshang Ji <kunshang.ji@intel.com>
…llm-project#53604) Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…project#53625) Signed-off-by: mhuzaifa3 <mhuzaifa3@outlook.com>
…vllm-project#49636) Signed-off-by: Md Saidul Hoque Anik <mhoqueanik@nvidia.com> Signed-off-by: Anerudhan Gopal <agopal@nvidia.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Anerudhan Gopal <agopal@nvidia.com>
…project#53530) (vllm-project#53530) Signed-off-by: Minjang Kim <minjang@meta.com> Co-authored-by: Autopilot Bot <noreply+1608173377072046@fb.com> Co-authored-by: OpenAI Codex <codex@openai.com>
Co-authored-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Signed-off-by: Connor Carpenter <connorc@nvidia.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
…lts for omitted language_config fields (vllm-project#51302) Signed-off-by: Seunghyuk Park <separk@habana.ai>
… modeling backend (vllm-project#53615) Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Signed-off-by: Cyrus Leung <tlleungac@connect.ust.hk> Co-authored-by: Xianbao QIAN <xianbao.qian@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Signed-off-by: louie-tsai <louie.tsai@intel.com>
…lm-project#53407) Signed-off-by: Xiaohu Guo <Xiaohu.Guo@amd.com> Signed-off-by: Lucas Wilkinson <lwilkins@redhat.com> Signed-off-by: xiaohuguo2023 <149615094+xiaohuguo2023@users.noreply.github.com> Co-authored-by: Lucas Wilkinson <lwilkins@redhat.com> Co-authored-by: Lucas Wilkinson <LucasWilkinson@users.noreply.github.com>
…llm-project#53659) Signed-off-by: wang.yuqi <yuqi.wang@daocloud.io>
Signed-off-by: JiataiWang <wangjiatai@proton.me> Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Thien Tran <gau.nernst@yahoo.com.sg> Co-authored-by: Codex <codex@openai.com>
…#50431) Signed-off-by: Andy Xie <andy.xning@gmail.com>
…ring (vllm-project#51262) Signed-off-by: jiahaoliang <gzliangjiahao@gmail.com> Signed-off-by: Jiahao Liang <gzliangjiahao@gmail.com> Co-authored-by: Chauncey <chaunceyjiang@gmail.com>
Signed-off-by: Tianyu Guo <guoty@inferact.ai>
…t#52783) Signed-off-by: mgoin <mgoin64@gmail.com>
…f 500 (vllm-project#53744) Signed-off-by: mhuzaifa3 <mhuzaifa3@outlook.com>
Signed-off-by: mgoin <mgoin64@gmail.com> Co-authored-by: OpenAI Codex <codex@openai.com>
…ol (vllm-project#53682) Signed-off-by: Nick Hill <nickhill123@gmail.com>
…E latency reduction (vllm-project#53649) Signed-off-by: yewentao256 <zhyanwentao@126.com>
…ust be precomputed` (vllm-project#53766) Signed-off-by: yewentao256 <zhyanwentao@126.com>
…erministic under TP) (vllm-project#51292) Signed-off-by: Don Tolley <tolleybot@gmail.com> Signed-off-by: tolleybot <tolleybot@gmail.com> Co-authored-by: yewentao256 <yewentao256@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
… keys (vllm-project#53329) Signed-off-by: almogtavor <almogtavor@gmail.com>
…llm-project#53534) Signed-off-by: Canlin Guo <canlinguosdu@gmail.com>
…ry access was encountered (vllm-project#53773) Signed-off-by: yewentao256 <zhyanwentao@126.com>
Signed-off-by: Thien Tran <gau.nernst@yahoo.com.sg> Co-authored-by: Codex <codex@openai.com>
…M103 (vllm-project#53606) Signed-off-by: Jee Jee Li <jeejeelee@inferact.ai>
…ct#53557) Signed-off-by: linitra24 <Joy25810@foxmail.com>
Signed-off-by: Simon Veitner <sveitner@redhat.com>
Signed-off-by: yewentao256 <zhyanwentao@126.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
…ges API (vllm-project#45803) Signed-off-by: HyunKyun Moon <mhg5303@gmail.com>
…llm-project#53819) Signed-off-by: nizhang1 <nizhang1@coupang.com> Co-authored-by: nizhang1 <nizhang1@coupang.com> Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…rser engines (vllm-project#52830) Signed-off-by: sfeng33 <4florafeng@gmail.com>
…tcap 1. VLLM_GEMMA4_BIDI_FULL_LAYERS=1 keeps the bidirectional image spans on full-attention layers instead of clearing them (_clear_mm_prefix_for_full_attn_layers). llama.cpp — the engine that serves gemma-4-12B vision cleanly — applies non-causal image attention on BOTH its SWA and full KV caches (mtmd path), while HF transformers documents 'causal only' for Gemma 4 global layers and vLLM follows HF. The knob makes the divergence testable: gemma-4-12B loops to the token cap on 4/5 dense screenshot prompts under stock vLLM GPU serving while identical weights on llama.cpp are clean, and text-only prompts on the same vLLM server do not loop — isolating the defect to the image-path mask semantics. Default off: stock behavior unchanged. 2. apply_softcap (triton_attention_helpers) clamps S/cap to +-30 before the exp-form tanh: fp32 exp overflows to inf at ~88.7, giving inf/inf = NaN and poisoning the softmax row. tanh(+-30) is exactly +-1.0 in fp32, so the clamp is lossless. Shared by triton_unified_attention and int4_per_token_head. Evidence: pieces-app global-cloud-runtime docs/BENCH_RESULTS.md 'gemma12b GPU backend-isolation round (2026-08-26)' and docs/upstream-draft-vllm-gemma12b.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR SummaryMedium Risk Overview CUDA / MoE: Extends libtorch-stable SITU activations with optional Rust frontend: gRPC Control gains LoadLora / UnloadLora / ListLoras; Generate accepts DeepSeek V4 chat rendering: System (and trailing system) turns now emit the same assistant transition tokens as user turns in chat and thinking modes. CI / Buildkite: Best-effort CRCR nightly job reporting (shell + Python JSON payloads, soft-fail). ROCm large-model lm-eval switches to Other: Docker rust-build split into cache (pretend version) + relink stage; Reviewed by Cursor Bugbot for commit 226145d. Configure here. |
…full-fp32 upper bound)
Ports pieces-app/tpu-inference 2e4fed6f (fp32 LayerNorm STATISTICS only, no
re-derivation of upstream's embedder forward / ColumnParallelLinear plumbing)
to the vLLM GPU path, plus a full-fp32-embedder arm as the upper bound.
VLLM_GEMMA4_VISION_LN_FP32=1 three embedder LayerNorms compute mean/var
in fp32 (the TPU fix, as a GPU control)
VLLM_GEMMA4_VISION_FP32=1 whole embedder in fp32 (params upcast,
input cast in, output cast back)
Both default off. Motivation is a CPU stage-diff vs an fp32 eager reference
on a real screenshot (tpu-inference tools/diagnostics/gemma4_unified_vision_diff):
at the soft-token output, torch-eager bf16 rel 3.1e-3 / cos 1.0000 vs torchax
bf16 rel 4.4e-2 / cos 0.9944, error concentrated on near-flat patches whose
std is the order of the bf16 quantization step (LayerNorm amplifies a bad
rstd by ~1/std).
Expectation being tested on GPU: PyTorch eager on CUDA ALREADY accumulates
LayerNorm statistics in fp32 for bf16 inputs, so the LN-only knob should be a
near-no-op here — it is the control proving the GPU path does not share the
TPU's torchax defect. The full-fp32 knob tests whether the residual
torch-eager-bf16 embedder error is enough to tip borderline prompts into
gemma-4-12B's documented ~40% loop attractor.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Update: vision-embedder precision arms added (both negative)Second commit adds two env-gated knobs on Background. A JAX/TPU deployment of this same Result: it does not transfer, and neither does the stronger version.
Arm I is a no-op by construction: PyTorch eager on CUDA already accumulates Arm J closes even that residual 3.1e-3 and still does not help. Its seed-42 run Engine logs confirm both knobs applied ( Net for triage: bf16 arithmetic in the vision embedder is not what drives Knobs default off; stock behavior unchanged. They are kept because this A/B is |
Update 2: the defect scales with image-block size —
|
| Arm | Config | loops (cap-hits) | parsed |
|---|---|---|---|
| baseline | max_soft_tokens=1120 (~1094-token image block) |
4/5, and 3-4/5 across six independent earlier arms | 1/5 |
| K | max_soft_tokens=560 (~534-token block) |
0/20 case-runs | 9/10 |
| L | 1120 + sliding_window 1024→2048 |
10/10 — worse | 0/10 |
Arm K checks (seed 42 / 43): chrome-firebase 20/20 · 20/20, cursor-repo 19/20 ·
19/20, gdoc-wpe 15/22 · (stray \escape, not a loop), google-chat 22/22 ·
20/22, x-social 18/19 · 17/19. The one non-parse in ten is a bad escape
character in otherwise complete, fence-terminated JSON.
The obvious mechanism is wrong. text_config.sliding_window is 1024, which
sits neatly between the two block sizes, so "the block is wider than the window
and the within-block bidirectional attention gets clipped" is the natural
story. Arm L falsifies it: holding the block at 1094 and widening the window to
2048 — so the block fits — made the model strictly worse (10/10 loops).
Gemma-4's sliding layers are trained at 1024 and degrade off-distribution.
A source check says the same thing independently: llama.cpp's
LLAMA_SWA_TYPE_STANDARD masks iff p1 - p0 >= n_swa — one-sided, future KV
never masked — and this repo's gemma-4 clamp is (query_abs_pos - seq_offset) < SLIDING_WINDOW. Same rule; the window/block composition is not where the
engines differ.
Two reproduction constraints worth knowing. The HF processor accepts only
max_soft_tokens in (70, 140, 280, 560, 1120) — a 960 arm dies at startup with
an explicit ValueError — so there is no rung between 534 and 1094 tokens and
the transition cannot be bracketed tighter by budget. And it upscales
under-budget images to fill the budget: two case sets 6% apart in linear
resolution returned byte-identical prompt-token counts. Block width is a
function of max_soft_tokens alone, never of input resolution.
Where that leaves the bug. Image-conditional (text-only prompts are clean),
scales with block size, not the window, not the mask scope, not preprocessing,
not embedder precision. The remaining candidate is an error in the
bidirectional mm_prefix range construction whose cost grows with block size.
The decisive probe — which I have not run — is to disable mm_prefix
bidirectional attention entirely at budget 1120: if pure-causal is clean there,
the bug is in that mask path.
Practical upshot: anyone hitting gemma-4-12B degeneration on vision should
try max_soft_tokens=560 first. And any fix for the underlying bug must be
validated at 1120 specifically — 560 will hide it.
There was a problem hiding this comment.
Pull request overview
This PR primarily hardens GPU attention softcapping against NaNs and extends speculative/adaptive verification logprobs plumbing (including device-only request-boundary handling). However, the diff also includes substantial additional refactors and feature work (e.g., new LoRA lifecycle gRPC API, CLI/entrypoint reshuffles, model/quantization cleanups, and many test/documentation updates), making the effective scope significantly broader than the PR description.
Changes:
- Make Triton
apply_softcapNaN-safe by clamping the exponent argument to a safe fp32 range. - Enable logprobs with adaptive verification by carrying per-request boundaries as a tensor (device → async D2H) and threading that through logprobs tensors/lists.
- Add/extend parallelism features and supporting hooks (e.g.,
compute_logits_local/skip_gatherpath for batch-sharded sampling) plus a broad set of refactors, API, docs, and test updates across Python + Rust.
Reviewed changes
Copilot reviewed 224 out of 301 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| vllm/v1/worker/gpu/spec_decode/rejection_sampler.py | Plumbs adaptive-verification-aware request boundaries into logprobs computation. |
| vllm/v1/worker/gpu/spec_decode/adaptive_verification.py | Narrows backend/CG-support checks to selected layers and adds targeted CG-support querying. |
| vllm/v1/worker/gpu/sample/sampler.py | Factors logprobs dimension computation into a helper used by sharded gather paths. |
| vllm/v1/worker/gpu/sample/logprob.py | Allows cu_num_logits to be tensor-backed and stores device-only boundaries in outputs. |
| vllm/v1/worker/gpu/model_states/mamba_hybrid.py | Propagates aligned Mamba state indices to metadata builders when available. |
| vllm/v1/worker/gpu/model_states/encoder_decoder.py | Updates model-state docstring to reflect supported models. |
| vllm/v1/worker/gpu/attn_utils.py | Refactors cudagraph support detection into get_attn_cg_support and adds layer filtering. |
| vllm/v1/worker/gpu_worker.py | Updates import path for batch-invariance initialization. |
| vllm/v1/worker/gpu_model_runner.py | Adjusts logprobs tuple unpacking to tolerate extra returned fields. |
| vllm/v1/utils.py | Redacts sensitive args when logging Rust frontend launch command. |
| vllm/v1/outputs.py | Adds tensor-backed cu_num_generated_tokens and CPU materialization logic. |
| vllm/v1/engine/logprobs.py | Adjusts prompt logprobs tuple unpacking to tolerate extra returned fields. |
| vllm/v1/engine/core.py | Uses get_args(PauseMode) for pause-mode validation. |
| vllm/v1/core/sched/scheduler.py | Threads XD-RoPE flag into request scheduling and logs pause-state transitions. |
| vllm/v1/core/sched/output.py | Carries XD-RoPE flag through scheduler output request data. |
| vllm/v1/attention/ops/triton_attention_helpers.py | Clamps S/x before exp-form softcap to prevent fp32 inf/inf NaNs. |
| vllm/v1/attention/backends/mla/xpu_mla_sparse.py | Adds required decode/prefill counters to XPU sparse MLA metadata. |
| vllm/v1/attention/backends/mla/flashinfer_mla_sparse.py | Adds TRT-LLM metadata builder and declares cudagraph support for SM100 sparse MLA. |
| vllm/v1/attention/backends/flash_attn_diffkv.py | Initializes fa4_hd256 flag. |
| vllm/utils/b12x.py | Makes optional b12x module access more compile-safe via cached submodule imports. |
| vllm/utils/argparse_utils.py | Adds --task hinting for serve and overrides argparse error messaging. |
| vllm/triton_utils/importing.py | Excludes Triton “cpu” backend when counting active drivers to avoid false multi-driver detection. |
| vllm/transformers_utils/processors/cheers.py | Removes Cheers processor implementation. |
| vllm/transformers_utils/processors/init.py | Removes Cheers/FireRedLID processors from registry exports. |
| vllm/transformers_utils/processor.py | Simplifies compatibility docstring text. |
| vllm/transformers_utils/model_arch_config_convertor.py | Removes “umm” and MPT convertor wiring. |
| vllm/transformers_utils/configs/hyperclovax.py | Removes vendored HCXVisionConfig shim and related import. |
| vllm/transformers_utils/configs/fireredlid.py | Removes FireRedLID config class. |
| vllm/transformers_utils/configs/deepseek_vl2.py | Fixes DeepSeek-VL2 text config default vocab_size and aligns kv_lora_rank. |
| vllm/transformers_utils/configs/init.py | Removes multiple config registrations (e.g., Arctic/Cheers/FlexOlmo/HunYuan/HCXVision/FireRedLID). |
| vllm/transformers_utils/config.py | Removes config registry entries for removed model types. |
| vllm/transformers_utils/chat_templates/registry.py | Removes chameleon chat template fallback mapping. |
| vllm/tokenizers/deepseek_v4_encoding.py | Replaces asserts with ValueErrors and updates system-message generation transitions. |
| vllm/sampling_params.py | Lifts prior restriction disallowing output logprobs with adaptive verification. |
| vllm/profiler/wrapper.py | Fixes auto-stop to call public stop() so state fully resets; adds restart coverage. |
| vllm/parser/parser_manager.py | Simplifies parser composition logic (removes shared-engine shortcut behavior). |
| vllm/parser/gemma4.py | Expands tool-call parsing transitions to support parenthesis and tool-end transitions. |
| vllm/multimodal/utils.py | Preserves MM CPU metadata for XD-RoPE in prefix-cache stripping path. |
| vllm/multimodal/media/audio.py | Enforces strict base64 decoding and pre-checks local-file audio size before decode. |
| vllm/models/minimax_m3/nvidia/model.py | Adds compute_logits_local passthrough for local-logits path. |
| vllm/models/kimi_k3/nvidia/kda_metadata.py | Adds aligned Mamba indices field and uses it for “align” cache mode. |
| vllm/models/inkling/nvidia/logits_processor.py | Adds skip_gather plumbing; supports returning local logits without TP gather. |
| vllm/models/inkling/amd/logits_processor.py | Same as NVIDIA path: adds skip_gather support. |
| vllm/model_executor/models/transformers/utils.py | Adds maybe_per_layer helper for per-layer config fields. |
| vllm/model_executor/models/transformers/multimodal.py | Wraps image tokens with start/end markers for processors that require them. |
| vllm/model_executor/models/transformers/moe.py | Adds per-layer MoE config selection (top-k/intermediate/renorm) using extracted layer index. |
| vllm/model_executor/models/qwen3_omni_moe_thinker.py | Marks support for tower-connector LoRA. |
| vllm/model_executor/models/qwen3_dflash.py | Allows overriding decoder-layer class; uses class attr in layer construction. |
| vllm/model_executor/models/qwen3_5.py | Adds compute_logits_local (and wrapper passthrough) for local-logits path. |
| vllm/model_executor/models/llama.py | Updates doc comment and adds compute_logits_local. |
| vllm/model_executor/models/lfm2_vl.py | Marks support for tower-connector LoRA. |
| vllm/model_executor/models/jina_vl.py | Reworks Jina VL processing to keep cached MM ordering/hashes consistent with prompt template. |
| vllm/model_executor/models/granitemoehybrid.py | Tightens weight-loader expectations and types rotary-emb field. |
| vllm/model_executor/models/granite4_vision.py | Adds assertions/typing for multimodal embeddings in embed path. |
| vllm/model_executor/models/granite_speech.py | Strengthens audio dummy/options typing and audio input validation paths. |
| vllm/model_executor/models/gpt_neox.py | Adds assertion for intermediate tensors when provided path is taken. |
| vllm/model_executor/models/gpt_j.py | Adds assertion for intermediate tensors when provided path is taken. |
| vllm/model_executor/models/glmasr.py | Strengthens audio data handling and typing; avoids None/list ambiguity. |
| vllm/model_executor/models/glm4v.py | Makes MM grid extraction more defensive and fixes embed_input_ids signature forwarding. |
| vllm/model_executor/models/glm4_moe.py | Adds explicit moe_mlp_layers type annotation. |
| vllm/model_executor/models/glm4_moe_mtp.py | Asserts parallel_config is present before use. |
| vllm/model_executor/models/glm4_moe_lite.py | Cleans up q_lora_rank access, refactors mapping unpacking, and removes unused empty-tensor factory. |
| vllm/model_executor/models/glm4_moe_lite_mtp.py | Adds asserts for speculative config presence; adjusts overrides and mapping unpacking. |
| vllm/model_executor/models/glm_ocr.py | Accepts encoder_metadata and explicitly ignores it for compatibility. |
| vllm/model_executor/models/glm_ocr_mtp.py | Adds asserts for speculative config presence and refines KV-scale remap handling. |
| vllm/model_executor/models/gemma4_mtp.py | Adds speculative-config asserts and masked_embedding nullability assertions. |
| vllm/model_executor/models/gemma4_dspark.py | Adds assertion ensuring v_proj exists when k!=v path is used. |
| vllm/model_executor/models/gemma3n.py | Makes quant_config optional in signature. |
| vllm/model_executor/models/gemma3_mm.py | Adds path arg and asserts image input exists in eager encoder path. |
| vllm/model_executor/models/gemma.py | Adds assertion for intermediate tensors when used. |
| vllm/model_executor/models/deepseek_v2.py | Makes q_lora_rank optional and aligns projection dimension usage. |
| vllm/model_executor/models/conformer_encoder.py | Updates module docstrings to remove FireRedLID references. |
| vllm/model_executor/models/bailing_moe_v3.py | Handles missing mamba-family metadata during warmup/profile runs. |
| vllm/model_executor/models/apertus.py | Updates doc comment on bidirectional attention usage. |
| vllm/model_executor/layers/vocab_parallel_embedding.py | Moves batch-invariant import to determinism module path. |
| vllm/model_executor/layers/quantization/utils/w8a8_utils.py | Removes unused CUTLASS FP8 constant. |
| vllm/model_executor/layers/quantization/quark/schemes/quark_ocp_mx.py | Removes unused attribute assignments; keeps derived dtype logic. |
| vllm/model_executor/layers/quantization/quark/quark_moe.py | Removes unused float4 dtype probe. |
| vllm/model_executor/layers/quantization/inc/schemes/inc_scheme.py | Removes unused KV-cache quantization method stub and import. |
| vllm/model_executor/layers/quantization/fp8.py | Removes unused cutlass-block-fp8 support caching. |
| vllm/model_executor/layers/quantization/compressed_tensors/schemes/compressed_tensors_w8a8_fp8.py | Removes unused cutlass-block-fp8 support caching/import. |
| vllm/model_executor/layers/logits_processor.py | Adds skip_gather flag to allow returning local logits before TP gather. |
| vllm/model_executor/layers/linear.py | Moves batch-invariant import to determinism module path. |
| vllm/model_executor/layers/layernorm.py | Moves batch-invariant import to determinism module path. |
| vllm/model_executor/layers/fused_moe/routed_experts.py | Docstring formatting/indentation cleanup. |
| vllm/model_executor/layers/fused_moe/prepare_finalize/deepep_v2.py | Carries prefix-sum metadata for cudagraph decode to support padding-row skipping. |
| vllm/model_executor/layers/fused_moe/modular_kernel.py | Allows missing expert counts and introduces valid_rows plumbed activation support. |
| vllm/model_executor/layers/fused_moe/experts/fused_batched_moe.py | Asserts expert counts are present for fused batched MoE apply path. |
| vllm/model_executor/layers/fused_moe/deep_gemm_utils.py | Falls back to local counting if expert counts are absent (carrier-only metadata). |
| vllm/model_executor/layers/fused_moe/activation.py | Adds valid_rows option and introduces fused SITU+FP8-quant helper wrapper. |
| vllm/model_executor/determinism/batch_invariant.py | Updates imports to new determinism config module path. |
| vllm/model_executor/determinism/init.py | Adds determinism package init. |
| vllm/lora/layers/logits_processor.py | Adds skip_gather arg and explicitly rejects skipping gather for lm_head LoRA. |
| vllm/envs.py | Clarifies audio filesize env var scope and enforcement points. |
| vllm/entrypoints/serve/utils/api_utils.py | Moves CLI args import, adds hf_token redaction, and exports redact_sensitive_args. |
| vllm/entrypoints/serve/dev/sleep/api_router.py | Removes stale FIXME comments about frontend multiprocessing behavior. |
| vllm/entrypoints/scale_out/render/serving.py | Adds Anthropic Messages render path converting to OpenAI chat before tokenization. |
| vllm/entrypoints/scale_out/render/api_router.py | Adds /v1/messages/render endpoint for Anthropic Messages requests. |
| vllm/entrypoints/launchers/run_batch.py | Fixes local imports for launcher entrypoint components. |
| vllm/entrypoints/launchers/render/entry.py | Switches to launcher CLI args module and reorders imports. |
| vllm/entrypoints/launchers/dp_supervisor.py | Fixes imports to use relative launcher modules. |
| vllm/entrypoints/launchers/cli_args.py | Rebrands CLI args module as “online server” and fixes import paths/constants. |
| vllm/entrypoints/launchers/api_server/entry.py | Switches to launcher CLI args module and reorders imports. |
| vllm/entrypoints/cohere/protocol.py | Bounds stop_sequences length via env limit using Pydantic Annotated Field. |
| vllm/entrypoints/cli/serve.py | Switches serve CLI to launcher CLI args and dp_supervisor module. |
| vllm/entrypoints/cli/launch.py | Switches launch CLI to launcher CLI args and reorders imports. |
| vllm/entrypoints/anthropic/serving.py | Renames conversion method to to_chat_completion_request and updates call sites. |
| vllm/engine/arg_utils.py | Adds --enable-batch-sharded-sampling plumbing into EngineArgs and config creation. |
| vllm/distributed/kv_transfer/kv_connector/v1/nixl/push_scheduler.py | Moves Mamba truncation hook out of cache-lookup path. |
| vllm/distributed/kv_transfer/kv_connector/v1/nixl/pull_scheduler.py | Same: moves Mamba truncation hook out of cache-lookup path. |
| vllm/distributed/kv_transfer/kv_connector/v1/nixl/base_scheduler.py | Truncates Mamba requests on request admission (on_new_request). |
| vllm/distributed/device_communicators/all_reduce_utils.py | Adds FI/MNNVL allreduce max size for (103, 8, 1). |
| vllm/config/parallel.py | Adds enable_batch_sharded_sampling config field and documentation. |
| vllm/config/model.py | Adds uses_xdrope boolean property. |
| vllm/compilation/passes/fusion/allreduce_rms_fusion.py | Sizes FlashInfer allreduce+RMS workspace for max hidden dim across target+draft. |
| tools/pre_commit/mypy.py | Adjusts mypy exclusions to include more model files. |
| tests/weight_loading/models.txt | Removes deleted dummy model entry; keeps FP8 model. |
| tests/v1/worker/test_gpu_rejection_sampler_chunking.py | Sets new enable_adaptive_verification attribute in test fixture. |
| tests/v1/worker/test_gpu_profiler.py | Adds regression tests for restart after max-iterations auto-stop. |
| tests/v1/worker/test_gpu_model_runner_v2_eplb.py | Adds enable_batch_sharded_sampling to runner parallel config stub. |
| tests/v1/test_outputs.py | Adds coverage for tensor-backed request boundaries in LogprobsTensors.tolists. |
| tests/v1/spec_decode/test_adaptive_verification.py | Adds tests for layer-scoped backend/CG checks without weakening runner CG mode. |
| tests/v1/kv_connector/unit/test_nixl_push_connector.py | Adds test ensuring P-side Mamba truncation happens before cache lookup. |
| tests/v1/kv_connector/unit/test_nixl_connector_hma.py | Updates truncation test to use on_new_request and checks idempotency. |
| tests/v1/engine/test_output_processor.py | Adjusts unpacking for changed prompt-logprobs tensor shape/fields. |
| tests/v1/determinism/test_rms_norm_batch_invariant.py | Updates import path for determinism batch-invariant RMSNorm. |
| tests/v1/determinism/test_matmul_batch_invariant.py | Updates import paths and expands test to transposed-B cases. |
| tests/v1/core/utils.py | Ensures EC producer role enables minimal multimodal config in scheduler fixture. |
| tests/v1/core/test_output.py | Adds XD-RoPE coverage for strip_covered_mm_data. |
| tests/utils_/test_tensor_schema.py | Replaces removed HCX schema with a minimal local double-nested schema. |
| tests/tools/test_docker_build_metadata_args.py | Verifies rust build cache excludes .git in cached stage and relinks for exact version. |
| tests/tokenizers_/test_detokenize.py | Removes reference to deleted MPT model. |
| tests/test_triton_utils.py | Adds tests covering cpu backend behavior in Triton driver detection. |
| tests/test_audio_media_size_precheck.py | Adds load_bytes/load_file oversize checks and fixes header case for Content-Length. |
| tests/renderers/test_hf.py | Removes chameleon from HF content-format resolve test list. |
| tests/plugins_tests/test_endpoint_plugins.py | Updates import path for launcher CLI args. |
| tests/parser/engine/test_parser_engine.py | Updates expectations around parser manager behavior and reasoning wiring. |
| tests/multimodal/media/test_audio.py | Adds test that malformed base64 is rejected with ValueError. |
| tests/models/test_registry.py | Adjusts terratorch-only gating. |
| tests/models/test_initialization.py | Adjusts terratorch-only gating. |
| tests/models/multimodal/processing/test_qwen2_vl.py | Adds Jina VL processing order/cache alignment regression test. |
| tests/models/multimodal/processing/test_common.py | Removes prior skip for jina-reranker-m0 processing correctness. |
| tests/models/multimodal/generation/test_common.py | Removes chameleon VLM test entries. |
| tests/models/language/pooling_mteb_test/test_modernbert_fp8.py | Refines ROCm FP8 skip logic based on GPU kernel availability. |
| tests/model_executor/kernels/test_b12x_linear.py | Adds dynamo/compile safety test for b12x submodule lookup. |
| tests/kernels/moe/test_moe.py | Updates activation test call to pass new valid_rows arg. |
| tests/evals/gsm8k/configs/humming/Qwen3-30B-A3B-MXFP4A16-humming-act-fp8-block.yaml | Adds new eval config for block-FP8 activation quant. |
| tests/evals/gsm8k/configs/humming/config-act-fp8.txt | Registers new humming eval config. |
| tests/entrypoints/serve/utils/test_api_utils.py | Adds hf_token redaction coverage and updates redaction API name. |
| tests/entrypoints/pooling/scoring/test_cross_encoder_online_vision.py | Updates expected FLEX_ATTENTION threshold. |
| tests/entrypoints/launchers/test_dp_supervisor.py | Updates import path to launcher dp_supervisor module. |
| tests/entrypoints/launchers/test_cli_args.py | Updates import paths and test utilities import location. |
| tests/entrypoints/launchers/api_server/test_api_server_process_manager.py | Adds test ensuring Rust frontend launch logs redact credentials. |
| tests/entrypoints/cohere/test_registry_and_args.py | Updates import path to launcher CLI args. |
| tests/entrypoints/cohere/test_protocol.py | Adds stop_sequences limit validation test. |
| tests/entrypoints/anthropic/test_anthropic_messages_conversion.py | Updates docs/tests to use to_chat_completion_request rename. |
| tests/engine/test_arg_utils.py | Updates dp_supervisor import paths. |
| tests/distributed/test_pipeline_parallel.py | Removes deleted Arctic/MPT and chameleon entries. |
| tests/distributed/test_comm_ops.py | Updates expected mnnvl workspace size for (103, 8, 1). |
| tests/config/test_multimodal_config.py | Adds test: EC producer-only enables mm_encoder_only. |
| tests/config/test_model_arch_config.py | Removes commented reference to deleted MPT model. |
| tests/config/base_model_arch_groundtruth.json | Removes groundtruth entry for deleted mosaicml/mpt-7b. |
| tests/compile/passes/distributed/test_fusion_all_reduce.py | Adds tests for _fused_ar_workspace_hidden_dim sizing across target/draft. |
| rust/src/server/src/state.rs | Adds LoRA-enabled checks and exposes list/load/unload operations for lifecycle API. |
| rust/src/server/src/routes/tests.rs | Adds ready-response customization helper for admin app tests. |
| rust/src/server/src/grpc/inference.rs | Threads lora_name through spans and resolves/validates LoRA for gRPC inference requests. |
| rust/src/server/Cargo.toml | Adds thiserror dependency. |
| rust/src/engine-core-client/src/protocol/lora.rs | Makes LoraRequest::new validated (Result-returning) with typed errors. |
| rust/src/chat/src/renderer/deepseek_v4/tests.rs | Adds system→assistant transition tests for thinking/chat modes. |
| rust/src/chat/src/renderer/deepseek_v4/encoding.rs | Allows assistant transition after system messages where appropriate. |
| rust/proto/inference.proto | Adds lora_name field to GenerateRequest. |
| rust/proto/control.proto | Adds LoRA lifecycle RPCs and messages to Control service. |
| rust/Cargo.lock | Records thiserror dependency addition. |
| requirements/test/nightly-torch.txt | Updates einops comment after MPT removal. |
| examples/rl/rlhf_async_new_apis.py | Updates batch-invariant import path. |
| examples/generate/multimodal/vision_language_multi_image_offline.py | Removes HyperCLOVAX seed-vision example and registry entry. |
| examples/generate/multimodal/encoder_decoder_multimodal_offline.py | Removes FireRedLID example wiring. |
| examples/generate/multimodal/audio_language_offline.py | Removes FireRedLID example wiring. |
| docs/usage/security.md | Clarifies audio filesize limit enforcement across input types. |
| docs/models/pooling_models/embed.md | Removes GritLM entry. |
| docs/mkdocs/gen_files/generate_argparse.py | Updates argparse generator to mock launcher cli_args module. |
| docs/features/speculative_decoding/adaptive_verification.md | Updates limitations: removes “output logprobs not supported” note. |
| docs/design/attention_backends.md | Documents Blackwell FA4 head_size=256 constraints and fallbacks. |
| docs/contributing/model/multimodal.md | Removes chameleon reference from examples. |
| docker/Dockerfile.xpu | Splits Rust build into cached stage + relink stage for exact git-derived versioning. |
| docker/Dockerfile.cpu | Same: Rust build cache stage + relink stage for exact versioning. |
| docker/Dockerfile | Same: Rust build cache stage + relink stage for exact versioning. |
| csrc/libtorch_stable/torch_bindings.cpp | Extends situ op signature and registers new situ_and_mul_quant op. |
| csrc/libtorch_stable/quantization/w8a8/cutlass/c3x/scaled_mm.cuh | Removes unused/obsolete SM100 gemm template specialization. |
| csrc/libtorch_stable/quantization/machete/machete_prepacked_layout.cuh | Removes unused NKL layout helper. |
| csrc/libtorch_stable/quantization/gptq/qdq_util.cuh | Removes unused dq_scale helper. |
| csrc/libtorch_stable/quantization/gptq/matrix_view.cuh | Removes unused half2 helpers and q4 column view. |
| csrc/libtorch_stable/quantization/gptq_allspark/allspark_utils.cuh | Removes unused cp_async_ca helper. |
| csrc/libtorch_stable/ops.h | Updates situ signatures and declares situ_and_mul_quant. |
| cmake/external_projects/vllm_flash_attn.cmake | Bumps flash-attention submodule GIT_TAG. |
| .github/CODEOWNERS | Updates batch-invariant ownership path to determinism module directory. |
| .buildkite/test-amd.yaml | Moves MTEB lane to MI300; updates lm-eval config list filename. |
| .buildkite/test_areas/model_runner_v2.yaml | Increases timeout and adds sharded sampling e2e tests to MRv2 distributed lane. |
| .buildkite/test_areas/entrypoints.yaml | Increases entrypoints unit timeout. |
| .buildkite/test_areas/crcr_report.yaml | Adds CRCR nightly report step group. |
| .buildkite/lm-eval-harness/test_lm_eval_correctness.py | Adds tokenizer_mode passthrough into lm-eval harness args. |
| .buildkite/lm-eval-harness/configs/models-large-rocm-tp4.txt | Adds DeepSeek-V4-Flash MXFP4 eval config. |
| .buildkite/lm-eval-harness/configs/DeepSeek-V4-Flash-MXFP4.yaml | Adds ROCm TP4 eval config including deepseek tokenizer mode and required arch gating. |
| .agents/skills/kernel-microbenchmark/benchmarks/cupti_microbenchmark.py | Adds CUPTI timing microbenchmark template. |
| .agents/skills/kernel-microbenchmark/agents/openai.yaml | Registers kernel microbenchmark skill metadata. |
| .agents/skills/debug-ima/SKILL.md | Adds debug-ima skill documentation stub. |
| .agents/skills/debug-ima/agents/openai.yaml | Registers debug-ima skill metadata. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| skip_gather: bool = False, | ||
| ) -> torch.Tensor | None: | ||
| # The LoRA delta is accumulated into the full gathered logits, so the | ||
| # TP gather cannot be skipped here. | ||
| if skip_gather: | ||
| raise NotImplementedError( | ||
| "Skipping the logits TP gather is not supported with an lm_head LoRA." | ||
| ) |
| service Control { | ||
| // Server and model discovery. | ||
| rpc GetServerInfo (GetServerInfoRequest) returns (ServerInfo) {} | ||
| rpc GetModelInfo (GetModelInfoRequest) returns (ModelInfo) {} | ||
|
|
||
| // Request lifecycle. | ||
| rpc Abort (AbortRequest) returns (AbortResponse) {} | ||
|
|
||
| // LoRA lifecycle. | ||
| rpc LoadLora (LoadLoraRequest) returns (LoadLoraResponse) {} | ||
| rpc UnloadLora (UnloadLoraRequest) returns (UnloadLoraResponse) {} | ||
| rpc ListLoras (ListLorasRequest) returns (ListLorasResponse) {} | ||
|
|
||
| // KV event discovery. |
|
Final confirmation probe (2026-08-27), closing the investigation: grammar-constrained decoding does not mitigate the 1120 loops. xgrammar + `disable_any_whitespace` at `max_soft_tokens=1120`: 15/20 loops vs 4/5 free-form control, same revision, same image digest (nightly-46638857) as the arm-K 560 validation. Mechanism: the repetition lives inside JSON string literals (escaped-`\n` runs, `☺` spam, phrase repetition) — grammar-legal until the token cap truncates. The defect is in the vision-conditioned next-token distribution, below the decode-constraint layer; no grammar/sampler/mask/KV/backend knob reaches it. Production recommendation unchanged and now final: `max_soft_tokens=560` on GPU. Full table in the bench repo (BENCH_RESULTS.md, 2026-08-27). 🤖 Generated with Claude Code |
Gemma-4-12B generates degenerate repetition loops on vLLM GPU when given images.
This PR carries the two code changes that came out of a 13-arm investigation, plus
the full evidence trail. Both knobs default off; stock behavior is unchanged.
What's in the diff
VLLM_GEMMA4_BIDI_FULL_LAYERS=1— keep bidirectional image spans onfull-attention layers instead of clearing them. llama.cpp applies non-causal
image attention on both its SWA and full KV caches; HF (and vLLM) document
"causal only" for Gemma-4 global layers. Negative result — kept because
reconstructing the A/B is a full fork-build-deploy cycle.
VLLM_GEMMA4_VISION_LN_FP32=1/VLLM_GEMMA4_VISION_FP32=1— fp32LayerNorm statistics, or the whole vision embedder in fp32. Ported narrowly
from a sibling TPU stack's shipped fix. Negative result on CUDA (see below).
apply_softcap— a genuine hardening fix, unrelated to the loopdefect. The helper computes
x*tanh(S/x)via the exp form; fp32expoverflows to inf past |S/x| ≈ 88.7, so the expression becomes
inf/inf= NaNand poisons the whole softmax row. Now clamps
S/xto ±30 first —tanh(±30)is exactly ±1.0 in fp32, so it is lossless. Shared bytriton_unified_attentionandint4_per_token_head. This one is worthtaking on its own merits.
The finding that actually matters:
max_soft_tokens=560The defect scales with image-block size and disappears entirely below ~1024
soft tokens.
max_soft_tokens=1120max_soft_tokens=560At 560, per-case checks reach 20/20 and 22/22 — better reliability than the
llama.cpp reference (3/5 valid) on the same frames. The cost is fine-text
resolution: long URL ids and small headings degrade (one case 15/22).
Recommendation: anyone hitting gemma-4-12B degeneration on vision should set
max_soft_tokens=560first. Any real fix must be validated at 1120specifically — 560 hides the defect completely.
What was ruled out (13 arms)
Text-side, each by its own arm: attention backend, KV dtype (fp8 vs auto),
sampler (incl.
min_pparity with llama-server), tokenizer/BOS/stop-set,final_logit_softcapping, proportional RoPE. Decisive control: the sameserver, weights, sampler and seed, given each case's content as OCR text
instead of a screenshot, produces zero loops in 5/5. The defect is
image-conditional.
Image-side, each patched, built, deployed and measured:
mm_prefixentirely)Two of these deserve comment:
sliding_windowis 1024,sitting exactly between the two block sizes, so "the block is wider than the
window and within-block bidirectional attention gets clipped" is the obvious
story. Widening the window so the block fits made it worse — Gemma-4's
sliding layers are trained at 1024 and degrade off-distribution. A source
check agrees the composition isn't where engines differ: llama.cpp's
LLAMA_SWA_TYPE_STANDARDmasks iffp1 - p0 >= n_swa(one-sided, future KVnever masked); this repo's Gemma-4 clamp is
(query_abs_pos - seq_offset) < SLIDING_WINDOW. Same rule.(absent 7/10, stock 4/5, extended to all layers 4/5, window-widened 10/10) and
none loops at 534. Note when reproducing: disabling
mm_prefixmakesFlashInfer eligible, so the backend silently changes unless you pin
--attention-backend=TRITON_ATTN(and--disable-chunked-mm-input, which isotherwise auto-forced only when mm-prefix is on).
Where it stands: mask and numerics dimensions are exhausted; block size is
the only variable that moves the outcome. The untested remainder is
position-embedding / patch-ordering behavior at scale — the factorized 2D
posemb table and the patchify/space-to-depth ordering are the only vision-path
components whose behavior is a function of block geometry and that were never
varied independently of it.
Two reproduction constraints
max_soft_tokens ∈ (70, 140, 280, 560, 1120).A 960 arm dies at startup with an explicit
ValueError, so there is no rungbetween 534 and 1094 tokens and the transition cannot be bracketed tighter.
in linear resolution returned byte-identical prompt-token counts. Block width
is a function of
max_soft_tokensalone, never of input resolution.Environment / methodology note
vLLM nightly
46638857(andf94666b6), RTX PRO 6000 (sm_120), BF16 and QATW4A16 checkpoints, 5 dense-screenshot cases, v6-mini free-form JSON,
temp 1.0 / top_p 0.95 / top_k 64, ≥2 seeds per arm.
Two measurement traps worth passing on, both of which nearly manufactured false
results:
eval silently measures the old config. A 960-budget arm failed its startup
probe and its "clean" numbers were really a third 560 run — caught only
because the prompt-token counts were byte-identical. Gate every config arm on
a value read back from the live response, never on "the deploy returned".
VLLM_ATTENTION_BACKENDis removed upstream and only warns(
Unknown vLLM environment variable detected). Deployments still setting itsilently run auto-selection — ours did for four revisions, invalidating the
backend label on an entire earlier result series. Assert the
Using AttentionBackendEnum.Xstartup line instead.Fork-first: nothing here has been filed upstream.