Skip to content

fix(gemma4): load mixed-quant GGUF checkpoints - #494

Closed
Poyo-Yon wants to merge 1 commit into
FlashML-org:mainfrom
Poyo-Yon:codex/gemma4-mixed-gguf
Closed

Poyo-Yon wants to merge 1 commit into
FlashML-org:mainfrom
Poyo-Yon:codex/gemma4-mixed-gguf

Conversation

@Poyo-Yon

@Poyo-Yon Poyo-Yon commented Sep 16, 2026 •

Copy link
Copy Markdown

Summary

  • read embedding, dense projection, and per-layer expert GGML types from the GGUF tensor table instead of assuming Q6_K/Q4_0
  • store heterogeneous routed experts in fixed-width byte slots and pass the real expert stride through every vendored MMVQ quant type
  • expose all 19 MMVQ block layouts to the native GGUF dense-layer dispatch
  • keep the existing uniform Q4_0 path compatible and reject unsupported mixed-type CPU/hybrid or FTW conversion paths explicitly

Fixes #188.

The fixed-stride expert-bank approach is consistent with the design explored in the closed #102.

Tested on

  • FreeToken base: cac247a (v0.1.3)
  • GPU: NVIDIA GeForce RTX 5060 Ti 16 GB
  • Driver: 616.92
  • CPU: Intel Core i7-12700F
  • RAM: 64 GB
  • OS: WSL2 Ubuntu 24.04, Linux 6.18.33.2
  • Python 3.12.3, PyTorch 2.11.0+cu130, CUDA 13.0

Checkpoints:

  • unsloth/gemma-4-26B-A4B-it-GGUF
    • gemma-4-26B-A4B-it-UD-IQ4_XS.gguf
    • gemma-4-26B-A4B-it-UD-Q3_K_XL.gguf
  • mradermacher/gemma-4-26B-A4B-it-qat-q4_0-unquantized-uncensored-heretic-v2-i1-GGUF
    • gemma-4-26B-A4B-it-qat-q4_0-unquantized-uncensored-heretic-v2.i1-IQ4_XS.gguf

Exact serve command (repeated with each checkpoint path):

ft serve \
  --model <checkpoint.gguf> \
  --host 127.0.0.1 \
  --port 1919 \
  --attention-backend triton \
  --moe-backend offload \
  --moe-cache-rate 0.2 \
  --memory-ratio 0.8 \
  --max-running-requests 1 \
  --max-seq-len-override 4096 \
  --max-prefill-length 512 \
  --num-tokens 4096 \
  --kv-reserve-tokens 4096 \
  --cuda-graph-max-bs 1

All three checkpoints loaded, captured the CUDA graph, completed prefill warm-up, and served an OpenAI-compatible chat completion. The deterministic prompt 17x23 returned 391 on each checkpoint.

Focused tests:

pytest -q tests/models/test_gemma4_gguf_quant.py tests/models/test_gemma4_gguf_rope.py
6 passed, 1 skipped

pytest -q \
  tests/moe/test_offload.py::test_dummy_expert_banks_follow_the_kernel_layout \
  tests/moe/test_offload.py::test_offload_cache_rebuild_resizes_and_preserves_sources \
  tests/moe/test_offload.py::test_set_bank_sources_locked_layer_requires_cpu_layer_ids \
  tests/moe/test_offload.py::test_copy_plan_skips_locked_layers_and_keeps_fused_path
4 passed

The full tests/moe/test_offload.py result was 23 passed and 1 environment-only failure: the isolated POC environment does not have FlashInfer installed, while that existing test explicitly selects the fi attention backend.

KarrAcaRn pushed a commit to KarrAcaRn/FreeToken-ByAI that referenced this pull request Oct 3, 2026
… checkpoints

Conflict: main added the NVMe disk-tier fields to ExpertBanks (FlashML-org#337); kept both those and
the per-layer gguf_quant_types.

Assisted-by: Claude Opus 5.5
KarrAcaRn pushed a commit to KarrAcaRn/FreeToken-ByAI that referenced this pull request Oct 3, 2026
… GGUF checkpoints

Conflict with FlashML-org#494's per-tensor quant layout: took the PR's dense-capable
expert fields and kept FlashML-org#494's gguf_quant_types. That layout demanded expert
tensors in every layer and divided by num_experts, so a dense GGUF would
still fail; it now lays out experts only when the checkpoint has them.

Assisted-by: Claude Opus 5.5
KarrAcaRn pushed a commit to KarrAcaRn/FreeToken-ByAI that referenced this pull request Oct 3, 2026
…d past the 65535 cap

Conflict with FlashML-org#494 (expert_stride_bytes for padded mixed-quant banks): took
the PR's generated launchers and threaded the expert stride through the
kernel, moe_vec_launch and the launcher macro in the position next's
gguf_kernel.cu call sites pass it. Checked: the PR's >65535-row test passes
and a padded-stride q8_0 bank still matches the contiguous one bit for bit.

Assisted-by: Claude Opus 5.5
@jason-fxz

Copy link
Copy Markdown
Collaborator

Thanks for the detailed work and testing. #690 replaces the GGUF path this PR builds on: kernel/csrc/gguf/, layers/gguf.py, moe/fused_q4_0.py and models/gguf/dequant.py are removed, and models/gemma4/gguf.py is rewritten. Each tensor's ggml type is read from the file, and with offload, expert layers of different types go to separate slot pools. The Gemma-4 26B-A4B checkpoints from google (QAT Q4_0), ggml-org (BF16) and unsloth (UD-Q8_K_XL: Q8_0, plus one BF16 layer) run end to end with fused and offload. We did not run the three checkpoints listed here; the headers of the two unsloth files (UD-IQ4_XS, UD-Q3_K_XL) only list tensor types #690 supports.

#690 is the new GGUF infrastructure. Since it covers this and replaces the old path this PR builds on, we are not planning to merge this PR, and it can be closed.

@jason-fxz jason-fxz closed this Oct 15, 2026
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.

gemma4 GGUF: embedding quant type hardcoded to Q6_K, so a Q4_0-embedding GGUF fails to load with a bare AssertionError

2 participants