GGUF and Quantisation Types
By the end of this lesson you will be able to open a model repository, read a list of forty files
with names like Qwen3-8B-UD-Q4_K_XL.gguf, and choose the right one for your machine in about ten
seconds; explain what the letters mean and roughly what each costs in bytes per weight; say what an
importance matrix does and why it appears in some names and not others; check that what you
downloaded is what the publisher published; and produce a GGUF file yourself from a safetensors
checkpoint.
What is inside the file
Section titled “What is inside the file”GGUF is defined in the ggml repository, and it is a deliberately boring format: a header, a table of metadata, a table of tensor descriptions, then the tensor data.
A GGUF file, from the start of the file downwards
- Magic number and versionThe four bytes GGUF, then a version number. Version 3 added big-endian support.
- CountsHow many tensors and how many metadata entries follow.
- Metadata key-value pairsTyped, snake_case keys: general.architecture, general.quantization_version, general.alignment, then per-architecture keys such as llama.context_length, llama.block_count and llama.attention.head_count_kv, and the tokeniser under tokenizer.ggml.*.
- Tensor informationFor each tensor: its name, its dimensions, its ggml type, and its offset into the data section.
- Padding to general.alignmentDefault 32 bytes, so the data section starts on a boundary the loader can map directly.
- Tensor dataThe weights. Memory-mapped rather than read, which is why a large model starts answering before the whole file has been pulled from disk.
Two consequences matter in practice. The metadata is why a GGUF file needs no config.json,
tokeniser file or chat template beside it: the specification’s stated goal is that “all information
needed to load a model is contained in the model file”. And the alignment and layout are why the
file is memory-mapped, which is why --no-mmap is a flag you will meet later, and why a model can
appear to load instantly and then be slow on its first few tokens while the pages are actually read.
The specification also defines a file-naming convention,
[Sidecar]-BaseName-SizeLabel-FineTune-Version-Encoding-Type-Shard.gguf, with examples such as
Grok-100B-v1.0-Q4_0-00003-of-00009.gguf. Publishers follow it loosely, but two parts are always
there: the size label and the encoding. The encoding is the thing this lesson is about.
The families, in the order they were invented
Section titled “The families, in the order they were invented”The names look arbitrary. They are three generations of the same idea.
The legacy types: Q4_0, Q5_0, Q8_0. The original scheme. Weights are grouped into small
blocks; each block stores its values at the stated bit width plus one scale factor for the block.
The number is the bits per weight before the scale is counted, and the _0 is the block layout.
Q8_0 is still in wide use because at eight bits the quality question effectively disappears;
Q4_0 has been superseded.
The K-quants: Q2_K to Q6_K, with _S, _M and _L variants. The insight is that not every
tensor deserves the same precision. A K-quant file is a mixture: attention and feed-forward
tensors are quantised at different widths, with the tensors that hurt most when damaged kept wider.
Q4_K_M means “the four-bit K-quant mixture, medium”, and _S and _M and _L are progressively
more generous mixtures at the same nominal width. This is why the file sizes do not line up with the
arithmetic: a “four-bit” model is not four bits per weight.
The IQ types: IQ1_S through IQ4_XS and IQ4_NL. These use a codebook rather than a plain
scale, which extracts more quality per bit at the low end, and they are normally built with an
importance matrix. They are the reason a very large model can be squeezed onto a machine that
should not fit it, and they are the types where the quality question is real rather than academic.
MXFP4. Not a llama.cpp invention: a four-bit floating-point format with a shared scale per
block, used as a model’s native format rather than as a post-training compression. gpt-oss is the
course’s example; its card describes MXFP4 quantisation of the mixture-of-experts weights and says
that is how the model was evaluated. Quantising it further would be quantising a quantised model.
What the letters actually cost
Section titled “What the letters actually cost”The llama-quantize README publishes a table of bits per weight and file size for every type,
measured on Llama 3.1 8B. These are the project’s own published figures for that one model, so
treat them as a shape rather than as your model’s exact sizes.
| Type | Bits per weight | File size, GiB |
|---|---|---|
| IQ1_S | 2.0042 | 1.87 |
| IQ2_XXS | 2.3824 | 2.23 |
| Q2_K | 3.1593 | 2.95 |
| IQ3_XXS | 3.2548 | 3.04 |
| Q3_K_M | 3.9960 | 3.74 |
| IQ4_XS | 4.4597 | 4.17 |
| Q4_K_S | 4.6672 | 4.36 |
| Q4_K_M | 4.8944 | 4.58 |
| Q5_K_M | 5.7036 | 5.33 |
| Q6_K | 6.5633 | 6.14 |
| Q8_0 | 8.5008 | 7.95 |
| F16 | 16.0005 | 14.96 |
Read the first column twice. IQ1_S, the “one-bit” type, is two bits per weight. Q4_K_M is nearly
five. Q8_0 is eight and a half. The overhead is the block scales plus the tensors each mixture
keeps at higher precision, and it is why the memory arithmetic from Part 4 uses about 0.55 to 0.6
bytes per parameter for a four-bit model rather than 0.5.
Importance matrices
Section titled “Importance matrices”Quantisation rounds every weight. An importance matrix decides which weights can least afford it.
llama-imatrix runs a calibration text through the unquantised model and collects the squared
activations for each tensor, producing a score per weight group. llama-quantize then reads that
file with --imatrix and spends its bit budget accordingly, protecting the weights that carry the
most signal on that text.
RunnableAll tracks
~/llama.cpp/build/bin/llama-imatrix \ -m ~/models/gguf/Qwen3-8B-BF16.gguf \ -f calibration.txt \ -ngl 99
~/llama.cpp/build/bin/llama-quantize \ --imatrix imatrix.gguf \ ~/models/gguf/Qwen3-8B-BF16.gguf \ ~/models/gguf/Qwen3-8B-IQ4_XS.gguf \ iq4_xs 8Two honest caveats. The matrix is computed on a particular text, so it encodes an assumption about
what the model will be asked to do; a matrix from English prose is a bet that you will use English
prose. And the improvement is largest where the bit budget is tightest: at Q6_K or Q8_0 there is
little left to protect. The llama-quantize README puts it plainly, saying that quantisation “may
introduce some accuracy loss” which “can be minimized by using a suitable imatrix file”.
Reading a provider’s table
Section titled “Reading a provider’s table”Very few model publishers ship GGUF files themselves. Most GGUF files come from a handful of people who convert and quantise every notable release within a day or two, and their repositories look like a wall of names.
The course’s model reference records one GGUF source per model, and they are of three kinds:
- The publisher’s own, where it exists.
ggml-org/gpt-oss-20b-GGUFis maintained by the llama.cpp organisation itself, which is as close to first-party as GGUF gets. - unsloth, which the course uses for the Qwen3 family. Their repositories carry the standard
types plus their own
UD-variants, described on the card as “Unsloth Dynamic” quantisation, which are their own mixture choices. - bartowski, which the course uses for Llama 3.1 8B, the cross-engine comparison model.
Faced with a list, three questions settle it.
Does it fit? Take the file size, add your KV cache, compare with your memory. This eliminates most of the list immediately.
Is it a mixture you recognise? Prefer Q4_K_M, Q5_K_M, Q6_K and Q8_0 for ordinary use.
Reach for IQ4_XS or lower only when the model would not otherwise fit, and expect to have to check
the quality rather than assume it.
Is it split? Large models are published as shards named -00001-of-00009 and so on. Download
all of them into the same directory and point the tool at the first; llama.cpp opens the rest. A
common mistake is downloading only the first shard because it is the one named in an example.
Qwen3-32B at Q4_K_M on a 24 GB machine, with 8k of context — an estimate, not a measurement
- Weights, Q4_K_M
- 19.8 GB
- KV cache, 8k tokens at FP16
- 2.1 GB
- Free
- 2.1 GB
- Total
- 24 GB
Downloading, and checking what you got
Section titled “Downloading, and checking what you got”Part 4 established the model library at ~/models and the habit of verifying a download against the
checksum the Hub publishes for the file. GGUF files are where that habit earns its keep, because
they are large, because a truncated download often produces a file that loads and then behaves
strangely, and because you will collect a lot of them.
RunnableAll tracks
hf download unsloth/Qwen3-8B-GGUF Qwen3-8B-Q4_K_M.gguf \ --local-dir ~/models/unsloth/Qwen3-8B-GGUFTo fetch a sharded model, ask for the pattern rather than each file:
RunnableAll tracks
hf download unsloth/Qwen3-235B-A22B-GGUF --include "*IQ4_XS*" \ --local-dir ~/models/unsloth/Qwen3-235B-A22B-GGUFPart 4’s fetch-model.sh does the same thing and then verifies the SHA-256 against the value the
Hub publishes for that file, writing the checksum beside the file. Use it for anything large enough
that re-downloading would annoy you.
Making your own
Section titled “Making your own”Sometimes there is no GGUF: a model published this morning, a fine-tune of your own from Part 13, or a quantisation mixture nobody published. Two steps produce one.
Step one: convert the checkpoint to GGUF at full precision. convert_hf_to_gguf.py lives at the
root of the llama.cpp checkout and reads a Hugging Face model directory. Its --outtype accepts
f32, f16, bf16, q8_0, tq1_0, tq2_0 and auto, where auto is described as “the
highest-fidelity 16-bit float type”. The script needs its own Python dependencies, listed in the
checkout’s requirements.txt.
RunnableAll tracks
uv venv ~/llama.cpp/.venvsource ~/llama.cpp/.venv/bin/activateuv pip install -r ~/llama.cpp/requirements.txt
python3 ~/llama.cpp/convert_hf_to_gguf.py \ ~/models/Qwen/Qwen3-8B \ --outfile ~/models/gguf/Qwen3-8B-BF16.gguf \ --outtype bf16Step two: quantise it. llama-quantize takes the input file, the output file, a type name and
optionally a thread count.
RunnableAll tracks
~/llama.cpp/build/bin/llama-quantize \ ~/models/gguf/Qwen3-8B-BF16.gguf \ ~/models/gguf/Qwen3-8B-Q4_K_M.gguf \ q4_k_m 8The options worth knowing, all from the tool’s README: --imatrix to use an importance matrix,
--include-weights and --exclude-weights to limit which tensors it applies to,
--output-tensor-type and --token-embedding-type to pin those two tensors to a type of your
choosing, --leave-output-tensor to skip quantising the output tensor at all, --pure to disable
the K-quant mixtures and use one type everywhere, --allow-requantize to quantise something that is
already quantised, and --keep-split to preserve a sharded input’s shard structure.
--allow-requantize deserves a warning rather than a tip: going from Q8_0 to Q4_K_M applies rounding
error twice, and the result is worse than quantising once from the full-precision file. It exists
for cases where the original is unavailable, not as a shortcut.
Compare representations without changing the experiment
Section titled “Compare representations without changing the experiment”Choose one high-precision source checkpoint and derive the quantised variants from it. Record the converter revision, quantiser settings and calibration data where applicable. Downloading unrelated community conversions with similar filenames may compare conversion choices or different base revisions as well as precision.
Evaluate three properties separately: file size, runtime memory at fixed context and task quality. File size does not include the cache. Runtime memory may change in steps because the engine allocates buffers in blocks. Quality loss can be concentrated in unusual identifiers, arithmetic or structured-output edge cases even when conversational answers remain fluent.
For a worked decision, suppose the smaller representation fits fully on the GPU while the larger one offloads. The smaller model may produce a faster end-to-end answer because placement changed. That is a valid deployment result, but it does not isolate the quantised kernel’s speed. Report both the representation and the residency so readers can tell why the useful outcome changed.
A GGUF file is a header, a metadata table, a tensor table and the weights, laid out to be
memory-mapped and carrying everything needed to load the model, which is why it is one file rather
than a directory. Quantisation names come in three generations: the legacy _0 types, the K-quant
mixtures that spend different precision on different tensors, and the IQ codebook types built with
an importance matrix for the low bit widths. The bits per weight are always higher than the name
suggests, by enough to matter to your memory budget: a four-bit K-quant is closer to five bits.
Choose by fitting first, leaving room for the KV cache, then by measuring quality if the choice is
tight. Download from a repository you can name, verify the checksum, and where no GGUF exists,
convert_hf_to_gguf.py and llama-quantize will make one in two commands.
Check your understanding
Sources for this lesson
7 verified · checked 2026-09-09
- 01GGUF specification§ Design goals; File structure; Metadata; Naming conventiongithub.com/ggml-org/ggml/blob/master/docs/gguf.md2026-09-09
- 02llama.cpp — llama-quantize README§ Options; quantisation types and bits per weightgithub.com/ggml-org/llama.cpp/blob/master/tools/quantize/README.md2026-09-09
- 03llama.cpp — llama-imatrix README§ Usage; examplesgithub.com/ggml-org/llama.cpp/blob/master/tools/imatrix/README.md2026-09-09
- 04llama.cpp — convert_hf_to_gguf.py§ parse_argsgithub.com/ggml-org/llama.cpp/blob/master/convert_hf_to_gguf.py2026-09-09
- 05unsloth/Qwen3-8B-GGUF model repository§ Files and quantisationshuggingface.co/unsloth/Qwen3-8B-GGUF2026-09-09
- 06ggml-org/gpt-oss-20b-GGUF model repositoryhuggingface.co/ggml-org/gpt-oss-20b-GGUF2026-09-09
- 07openai/gpt-oss-20b model card§ Model description; quantisationhuggingface.co/openai/gpt-oss-20b2026-09-09
Every technical claim on this page was checked against the official documentation of the tool, vendor or model publisher on the date shown, at the version pinned for the course. Where the course disagrees with folklore, the source is how you can tell which one to trust.