Containers · .gguf

GGUF (GGML Universal File)

Single-file, mmap-friendly container used by ggml / llama.cpp / whisper.cpp and derivatives. Fixed header, typed key/value metadata section, tensor-info table, zero-padding to an alignment boundary, then a tensor data blob. Tensors may use plain element types (F32/F16/BF16/I8..I64/F64) or ggml block-quantized types (Q4_0, Q8_0, K-quants, IQ-quants, TQ, MXFP4, NVFP4, Q1_0, Q2_0). Dimension order is ggml order: ne[0] is the innermost (fastest-varying, contiguous) dimension, i.e. the REVERSE of numpy/PyTorch shape order.

.gguf

What it is
many tensors
Byte order
undeclared default little
Dimension order
innermost first (ggml ne[])
Compression
none
Metadata
typed kv
Loading
Loading it into a library does not execute code.

How to read it

header (incl. all metadata KV) | tensor_info[tensor_count] | zero padding to ALIGNMENT (absolute file offset) | tensor_data. Every field is packed (no implicit alignment) except the padding before tensor_data and between tensors. ALIGNMENT is only known after parsing metadata (general.alignment).

header
gguf_header
tensor_infos
gguf_tensor_info[header.tensor_count]
padding
u8[align_up(pos, ALIGNMENT) - pos]. ggml only seeks to the aligned offset when tensor_count > 0
tensor_data
bytes. each tensor at data_start + info.offset; gap between tensors zero-padded to ALIGNMENT
0        4        8                16               24
+--------+--------+----------------+----------------+-----------------------------+
| "GGUF" | ver u32| tensor_cnt u64 | kv_count u64   | kv[0] kv[1] ... (packed)    |
+--------+--------+----------------+----------------+-----------------------------+
| tensor_info[0] ... tensor_info[n-1] (packed)                                    |
+----------------------------------------------------------------------------------+
| 0x00 padding up to multiple of ALIGNMENT (absolute file offset)                  |
+----------------------------------------------------------------------------------+  <- data_start
| tensor 0 data | pad | tensor 1 data | pad | ...                                  |
+----------------------------------------------------------------------------------+

One tensor

name
tensor_info.name (UTF-8)
dtype
tensor_info.type (ggml_type) -> dtypes[].canonical
shape
reversed(tensor_info.dimensions) # canonical row-major shape
data_offset
data_start + tensor_info.offset (absolute)
nbytes
see nbytes_formula
order
row-major (C) in canonical shape terms; no strides

Example

The specs test vector. Shapes are outermost first: the file stores that list reversed, fastest dimension first. w_q8_0 is the Q8_0 blocks for w_f32. e_bf16 is in this file. s_f32 is not: a scalar is stored as one dimension of length 1, and that stored shape must not replace the canonical shape [].

small.gguf1,792 bytes

Version
3
general.architecture
llama
test.answer
42
test.note
tensor-format-specs
NameDtypeShapeStored orderBytes
w_f32F32float324 × 6464 × 41,024
b_f16F16float168816
i_i32I32int323 × 22 × 324
e_bf16BF16bfloat162 × 33 × 212
w_q8_0Q8_0ggml_q8_04 × 6464 × 4272

Number formats

The name in the file, and the canonical dtype it maps to.

In the fileCanonicalBits
F32float3232
F16float1616
BF16bfloat1616
F64float6464
I8int88
I16int1616
I32int3232
I64int6464
Q4_2none—
Q4_3none—
Q4_0_4_4none—
Q4_0_4_8none—
Q4_0_8_8none—
IQ4_NL_4_4none—
IQ4_NL_4_8none—
IQ4_NL_8_8none—
Quantized block types (27)
In the fileCanonicalBits
Q4_0ggml_q4_04.5
Q4_1ggml_q4_15
Q5_0ggml_q5_05.5
Q5_1ggml_q5_16
Q8_0ggml_q8_08.5
Q8_1ggml_q8_19
Q2_Kggml_q2_k2.625
Q3_Kggml_q3_k3.4375
Q4_Kggml_q4_k4.5
Q5_Kggml_q5_k5.5
Q6_Kggml_q6_k6.5625
Q8_Kggml_q8_k9.125
IQ2_XXSggml_iq2_xxs2.0625
IQ2_XSggml_iq2_xs2.3125
IQ2_Sggml_iq2_s2.5625
IQ3_XXSggml_iq3_xxs3.0625
IQ3_Sggml_iq3_s3.4375
IQ1_Sggml_iq1_s1.5625
IQ1_Mggml_iq1_m1.75
IQ4_NLggml_iq4_nl4.5
IQ4_XSggml_iq4_xs4.25
TQ1_0ggml_tq1_01.6875
TQ2_0ggml_tq2_02.0625
MXFP4ggml_mxfp44.25
NVFP4ggml_nvfp44.5
Q1_0ggml_q1_01.125
Q2_0ggml_q2_02.25

Sources

Nick Reynolds · @goldnode · nicks.net · rev 0.1