Skip to content

Add DiffusionGemma (Gemma-4 MoE block-diffusion) support: MoE imatrix variants, AWQ MoE groups, llama.cpp bump, diffusion eval backend#4

Draft
pearsonkyle wants to merge 1 commit into
mainfrom
claude/nifty-planck-0yni75
Draft

Add DiffusionGemma (Gemma-4 MoE block-diffusion) support: MoE imatrix variants, AWQ MoE groups, llama.cpp bump, diffusion eval backend#4
pearsonkyle wants to merge 1 commit into
mainfrom
claude/nifty-planck-0yni75

Conversation

@pearsonkyle

Copy link
Copy Markdown
Owner

Summary

Adds end-to-end support for DiffusionGemma 26B-A4B (google/diffusiongemma-26B-A4B-it) — a 128-expert (8 active) Gemma-4 MoE block-diffusion LLM — covering the <3bpw quantization methods, bench, and full task-level eval. This is the repo's first MoE and first diffusion architecture.

Answers to the motivating questions

  • Does imatrix work for this model? Yes. llama-imatrix runs a standard forward, and DiffusionGemma's causal encoder mode is exactly that, over the same weights the diffusion decoder uses (encoder/decoder are tied; only the attention mask differs). Two caveats are handled: (1) the UNIFIED graph treats the last canvas_length (256) positions of each chunk as a bidirectional canvas — recipes raise imatrix_ctx to 2048 to keep that fraction small, and quant-vs-quant KLD remains valid; (2) MoE imatrix entries carry per-expert counts and 3D weights, which the variant builders previously dropped silently (which would make llama-quantize refuse IQ2_*). They now normalize and rerank per expert, with an expert-coverage check wired into the pipeline.
  • Can it be tuned with AWQ? Yes. New L{i}_moe scale groups fold into pre_feedforward_layernorm_2, whose only consumer is the fused 3D experts.gate_up_proj. The router reads the raw residual through its own internal norm, so routing logits are exactly invariant under the fold (unit-tested in f32). moe_expert_sample (default 8) caps the α-search cost; Gemma's (1+γ) RMSNorm convention rides the existing rmsnorm_plus_one path.
  • GPTQ on the 128 experts is deferred (badly-conditioned per-expert Hessians × CPU Cholesky on 26B ≈ days); documented in CLAUDE.md.

Submodule bump

vendor/llama.cpp: 9e58d4d6c84e85af, the head of llama.cpp PR #24423 — current master has no DiffusionGemma support; the PR adds the diffusion-gemma arch, converter, llama-diffusion-cli canvas mode, and a persistent logits server. Setup instructions in CLAUDE.md show how to fetch the PR ref; re-pin to master once it merges. calibrate/_iq2_grids.py regenerated against the new pin (grids byte-identical; ksigns parity assertion passed). llama-perplexity still has no --parse-special (re-verified); the imatrix GGUF schema and converter CLI are unchanged.

Task eval without llama-server

llama-server cannot diffusion-decode, so eval/diffusion_server.py provides running_diffusion_server(...): an OpenAI-compatible shim that renders chat prompts (with tools) via the HF tokenizer, generates through a numpy port of llama.cpp's entropy-bound block-diffusion sampler driven by the persistent llama-diffusion-gemma-server (one model load per eval), and parses Gemma-4 <|tool_call>call:NAME{…}<tool_call|> markup into OpenAI tool_calls. The tool-call/MMLU-Pro evals and eval.reps are untouched apart from a server_factory hook; reps scripts gain --backend diffusion --hf-dir <snapshot>. scripts/bench_diffusion_speed.py times llama-diffusion-cli (llama-bench decode tok/s is meaningless for diffusion generation).

New recipes

  • q2_k_diffusiongemma_imatrix — low-resource path (no HF load; llama-imatrix streams the GGUF).
  • iq2_m_diffusiongemma_awq — AWQ + hybrid_custom imatrix stacked, IQ2_S codebook proxy auto-selected.

Testing

  • 353 unit tests pass (33 new: MoE tensor mapping, per-expert imatrix rerank/normalization with real gguf-py round-trips, expert coverage, MoE group discovery on standard + DiffusionGemma trunks, f32 fold/routing invariance, deterministic expert subsampling, Gemma-4 markup parsing, canvas trimming, entropy-bound acceptance rule).
  • ruff and mypy at or better than parity with main (mypy 36 → 28 pre-existing errors; the one ruff finding predates this PR).
  • Not yet run (needs GPU/disk beyond this environment): real 26B end-to-end. The recipe headers carry the resource checklist (≥220 GB disk for the AWQ path, 80GB-class GPU or ≥96 GB RAM; imatrix-only path needs neither) and post-run checks (expert coverage ≥95%, llama-quantize applies imatrix to all ffn_*_exps, manual llama-diffusion-cli sanity generation at F16 vs IQ2_M).

https://claude.ai/code/session_011BaPPBxkVCggmj1McnSC32


Generated by Claude Code

Bump vendor/llama.cpp 9e58d4d6 -> c84e85af (head of llama.cpp PR #24423:
diffusion-gemma arch, converter, llama-diffusion-cli canvas mode, persistent
llama-diffusion-gemma-server); regenerate calibrate/_iq2_grids.py against the
new pin (grids unchanged, ksigns parity holds).

MoE-aware imatrix variants:
- hf_gguf_map: fused 3D expert rules (ffn_gate_up_exps/ffn_down_exps), router
  (ffn_gate_inp), self-conditioning MLP; DiffusionGemma trunk prefixes
  (model.decoder.*, model.encoder.language_model.*) normalized to model.*;
  new is_moe_expert sibling of is_ssm.
- imatrix: per-expert counts normalization in _load_base_imatrix (zero-count
  experts -> neutral ones, mirroring llama-quantize), per-expert reranking in
  the analytic variants (L1 norm must not bleed across experts), per-expert
  E[a^2] passthrough in outlier variants, and a MoE expert-coverage check
  wired into both pipeline calibrate stages.

AWQ MoE extension:
- discover_groups emits L{i}_moe: the fused gate_up stack under
  pre_feedforward_layernorm_2, anchored on the experts module (sees every
  token pre-routing). The router reads the raw residual through its own norm,
  so routing logits are exactly invariant under the fold (unit-tested).
- moe_expert_sample (default 8) caps the alpha-search cost on 128-expert
  stacks; apply() handles 3D members via last-axis broadcasting.
- _hf.load_calibration_model falls back to the concrete arch class when
  AutoModelForCausalLM refuses (DiffusionGemmaForBlockDiffusion);
  _hf.causal_logits runs sanity checks through the causal encoder + tied
  lm_head; forward_no_logits resolves the encoder trunk.

extract: ForBlockDiffusion checkpoints pass through untouched (the llama.cpp
converter owns vision-drop and decoder remapping).

Task eval without llama-server (which cannot diffusion-decode):
eval/diffusion_server.py drives the persistent logits server with a numpy
port of the entropy-bound block-diffusion sampler behind an OpenAI-compatible
shim (Gemma-4 tool-call markup parsed into tool_calls); eval/reps grows a
server_factory hook and the reps scripts a --backend diffusion flag.
scripts/bench_diffusion_speed.py times llama-diffusion-cli (llama-bench
decode tok/s is meaningless for diffusion generation).

Recipes: q2_k_diffusiongemma_imatrix (low-resource, no HF load) and
iq2_m_diffusiongemma_awq (AWQ + hybrid_custom stacked). CLAUDE.md documents
the architecture facts, imatrix caveats (UNIFIED-graph canvas region,
per-expert counts), and the GPTQ-on-experts deferral.

https://claude.ai/code/session_011BaPPBxkVCggmj1McnSC32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants