GGUF
GGUF(GGML Universal File)是面向 GGML 及其执行器的模型存储格式。它把张量、模型结构参数和分词器信息组织在同一套二进制容器中,重点解决推理模型的分发、快速加载和跨语言读取问题。
GGUF 常见于 llama.cpp、Ollama 和桌面推理工具;如果目标是训练框架中的安全权重交换,应优先了解 Safetensors。
定位
GGUF 的核心目标不是“把任意训练状态完整保存下来”,而是让推理执行器获得加载模型所需的信息:
Hugging Face 模型目录
├── config.json
├── tokenizer.json
└── *.safetensors
↓ 转换
GGUF
├── 模型与分词器元数据
├── Tensor Info
└── Tensor Data
↓
llama.cpp / GGML-based executor这带来四个直接特征:
- 自包含:模型架构、超参数、分词器和张量可以放在同一文件中。
- 可扩展:元数据采用带类型的键值对,新字段不需要改变固定头部结构。
- 支持 mmap:张量数据按对齐后的偏移连续存放,执行器可以映射文件后按需访问。
- 面向推理:张量类型包含 GGML 使用的浮点和块量化编码。
GGUF 支持分片,因此“单文件”是最常见的分发形态,而不是格式的硬性限制。
文件结构
GGUF v3 可以概括为四个连续区域:
┌──────────────────────────────────────────────┐
│ Header │
│ magic / version / tensor_count / kv_count │
├──────────────────────────────────────────────┤
│ Metadata KV │
│ general.* / <architecture>.* / tokenizer.* │
├──────────────────────────────────────────────┤
│ Tensor Info │
│ name / dimensions / ggml_type / offset │
├──────────────────────────────────────────────┤
│ Alignment Padding │
├──────────────────────────────────────────────┤
│ Tensor Data │
│ aligned raw or quantized tensor blocks │
└──────────────────────────────────────────────┘Header
Header 以字节序列 GGUF 开始,随后记录格式版本、张量数量和元数据键值对数量。GGUF v3 规范中的逻辑结构为:
struct gguf_header_t {
uint32_t magic;
uint32_t version;
uint64_t tensor_count;
uint64_t metadata_kv_count;
gguf_metadata_kv_t metadata_kv[metadata_kv_count];
};version 只在文件结构发生不兼容变化时递增;模型能力和架构差异通常通过元数据表达。
Metadata KV
元数据键采用分层命名,例如:
general.architecture = "llama"
general.name = "Example Model"
llama.context_length = 131072
llama.embedding_length = 4096
llama.block_count = 32
tokenizer.ggml.model = "gpt2"
tokenizer.ggml.tokens = [...]
tokenizer.ggml.merges = [...]值带有明确类型,可表示整数、浮点数、布尔值、字符串和数组。执行器先读取 general.architecture,再按对应架构的元数据约定构建模型。
Tensor Info 与 Tensor Data
每个 Tensor Info 记录名称、维度、ggml_type 和数据偏移。偏移相对于 Tensor Data 区域,并且必须满足全局 ALIGNMENT:
struct gguf_tensor_info_t {
gguf_string_t name;
uint32_t n_dimensions;
uint64_t dimensions[n_dimensions];
ggml_type type;
uint64_t offset;
};Tensor Info 是目录,Tensor Data 才保存实际权重。加载器可以先解析较小的目录,再根据 offset 定位所需张量。
张量编码与量化
GGUF 容器记录的是 ggml_type。该类型既包括 F32、F16、BF16 等浮点编码,也包括 Q4_0、Q4_K、Q6_K、IQ4_XS、MXFP4 等块量化编码。
需要区分三个概念:
- GGUF:定义元数据、张量目录和数据区域如何组织。
- GGML tensor type:定义 Tensor Data 中每种编码的块布局。
- 量化策略:决定不同张量选用什么编码,例如文件名中的
Q4_K_M通常表示一组混合选择,而不是单一ggml_type。
具体块结构和 K-Quant、I-Quant 的差异见 llama.cpp 量化格式。
mmap 加载
GGUF 的布局允许执行器将文件映射到虚拟地址空间:
- 读取 Header 与 Metadata,确定模型架构和运行参数。
- 读取 Tensor Info,建立张量名称到
(type, shape, offset)的索引。 - 将 Tensor Data 映射到内存。
- 根据后端能力直接读取映射区域,或把目标张量复制、变换到 GPU 等设备。
mmap 减少了显式读取整文件和额外 CPU 缓冲区的需求,但不代表 GPU 推理完全“零拷贝”;权重是否需要上传或转换仍取决于执行后端。
从 Hugging Face 模型转换
llama.cpp 的 convert_hf_to_gguf.py 会读取模型配置、分词器和权重,再写入 GGUF。常见流程是先生成高精度 GGUF,再单独量化:
python convert_hf_to_gguf.py ./model \
--outfile model-f16.gguf \
--outtype f16
llama-quantize model-f16.gguf model-q4_k_m.gguf Q4_K_M
llama-server -m model-q4_k_m.gguf转换不是简单修改扩展名:脚本需要识别模型架构、重命名张量,并把配置与分词器信息映射到 GGUF 元数据。新架构只有在转换器和执行器都实现后才能使用。
适用边界
GGUF 适合:
- 使用 llama.cpp 或 GGML 生态执行推理。
- 需要一个便于复制和分发的部署产物。
- 需要 GGML 的块量化编码和 CPU、Apple Silicon 等本地执行路径。
- 希望通过 mmap 降低模型启动时的显式拷贝开销。
GGUF 不等于通用训练检查点。优化器状态、梯度、训练框架对象以及任意自定义 Python 状态通常不属于它的目标范围。