Gemma 4 E4B QAT Q4_0 assistant (MTP head), GGUF
Google publishes the QAT Q4_0 model google/gemma-4-E4B-it-qat-q4_0-gguf
as GGUF, but its multi-token-prediction (MTP) assistant only as safetensors
(google/gemma-4-E4B-it-qat-q4_0-unquantized-assistant).
There was no GGUF MTP head for the QAT GGUF, so this repository is that assistant converted to GGUF, nothing else:
no training or fine-tuning. Use it together with google/gemma-4-E4B-it-qat-q4_0-gguf for speculative decoding in llama.cpp.
The Google model card asks for exactly this pairing: "When using multi-token prediction (speculative decoding) with an
assistant model alongside a QAT target model, the assistant model must also be a QAT checkpoint with the same precision."
| file |
size |
sha256 |
gemma-4-E4B-it-qat-q4_0-assistant.gguf |
77 MB |
1542462b3316d5646b3379d62c96945141b163d57788705f851a9ceede9957c6 |
Use (llama.cpp)
hf download google/gemma-4-E4B-it-qat-q4_0-gguf --local-dir qat
hf download ensky0/gemma-4-E4B-it-qat-q4_0-gguf-assistant --local-dir qat
llama-server -m qat/gemma-4-E4B_q4_0-it.gguf --mmproj qat/gemma-4-E4B-it-mmproj.gguf \
-md qat/gemma-4-E4B-it-qat-q4_0-assistant.gguf --spec-type draft-mtp --spec-draft-n-max 3
How it was made
llama.cpp at commit 0c1e570
(Gemma4AssistantForCausalLM → GGUF architecture gemma4-assistant):
hf download google/gemma-4-E4B-it-qat-q4_0-unquantized-assistant --local-dir assistant
python convert_hf_to_gguf.py assistant --outtype bf16 --outfile assistant-BF16.gguf
llama-quantize assistant-BF16.gguf gemma-4-E4B-it-qat-q4_0-assistant.gguf Q4_0
llama-quantize's Q4_0 keeps token_embd.weight at Q6_K and puts the other weights at Q4_0, the same layout as Google's
QAT target GGUF (its token_embd.weight is Q6_K too). 49 tensors, same names and shapes as ggml-org's non-QAT mtp-gemma-4-E4B-it-Q4_0.gguf.
Verification
Text, with the QAT target
gemma-4-E4B_q4_0-it.gguf + this file, llama.cpp 0c1e570 (llama-completion without, llama-speculative-simple --spec-type draft-mtp
--spec-draft-n-max 3 with the head), greedy, 96 tokens, 5 prompts (3 Japanese → Korean translations, 2 English questions),
NVIDIA A100:
| accepted / drafted |
output identical to no drafting |
| 141/251 = 56% |
3/5 |
Where the outputs differ they agree for the first words and then part at one token: checking several drafted tokens in
one batch changes the floating-point order slightly, and greedy decoding can then pick a different token. In the E4B
speech test (see the E4B repository) the non-QAT ggml-org head gives exactly as many differing outputs as this conversion,
so the differences come from the batched verification, not from the converted weights.
Speech translation (Japanese audio → Korean), the use case this was made for
Target gemma-4-E4B_q4_0-it.gguf + gemma-4-E4B-it-mmproj.gguf, Google's speech-translation prompt, greedy, 110 segments of
a live recording (short, noisy conversational Japanese), chrF against Gemini-written, twice-verified Korean references, NVIDIA A100:
| MTP head |
drafted tokens |
identical output to no drafting |
accepted / drafted |
first Korean character |
done |
chrF |
| none |
- |
- |
- |
0.149 s |
0.203 s |
14.9 |
| this file |
2 |
79/110 |
998/2270 = 44% |
0.137 s |
0.184 s |
15.0 |
| this file |
3 |
79/110 |
1078/3120 = 35% |
0.141 s |
0.191 s |
15.0 |
| this file |
4 |
79/110 |
1120/3820 = 29% |
0.139 s |
0.189 s |
15.0 |
ggml-org mtp-gemma-4-E4B-it-Q4_0.gguf (non-QAT head) |
3 |
79/110 |
1070/3141 = 34% |
0.142 s |
0.191 s |
15.0 |
Gemma 4 12B QAT vs E4B QAT for speech translation (the targets, without MTP)
Japanese audio → Korean, Google's speech-translation prompt, greedy, NVIDIA A100. chrF against Korean references that Gemini
wrote from the audio, checked in two verification rounds. 12B is better on clean or conversational speech and much worse on short, band-limited live-recording segments:
| set |
clips (speech) |
median length |
12B QAT |
E4B QAT |
| read speech: Common Voice 8.0 ja test (first 150 of 200 random utterances, seed 0) |
150 |
4.8 s |
53.5 |
52.1 |
| conversation: HTH japanese-casual-conversational-speech-golden-dataset-preview |
68 |
2.6 s |
38.6 |
35.6 |
| live recording (our own, not published; cut by a VAD into segments of at most 3 s) |
107 |
1.6 s |
5.8 |
14.9 |
| first Korean character / done (live recording) |
0.244 s / 0.345 s |
0.149 s / 0.203 s |
On the live-recording set 12B answers 43 of 110 segments with a refusal ("I'm sorry, I can't help with that") instead of a
transcription. Google's original google/gemma-4-12B-it (BF16, transformers 5.18) and llama.cpp's llama-mtmd-cli fail on
the same segments the same way, so it is the model, not the GGUF or llama.cpp; clean synthetic speech is transcribed
correctly by both models. What makes it fail (12B QAT, refusals on the conversation set made live-recording-like):
| change |
refusals |
chrF |
| as is |
6/68 |
38.6 |
| low-pass 4 kHz |
9/68 |
36.4 |
| low-pass 2 kHz |
16/68 |
36.1 |
| first 1.5 s only |
18/68 |
| live-recording set as is / two neighbouring segments joined |
43/110 / 18/55 |
Short segments matter most, missing high frequencies next (energy above 4 kHz: live recording 0.3%, conversation 1.7%, read
speech 0.9%). 12B is encoder-free (raw 40 ms waveform frames projected straight into the language model), E4B has a
dedicated ~300M audio encoder; for low-latency subtitles cut into short segments, E4B is the better choice.
License
Apache 2.0, as the original Gemma 4 weights.
Converted for a realtime speech-translation subtitle app (llama.cpp, Japanese audio → Korean subtitles).