首页
/ Transformers 的 GGUF 支持:加载量化模型、反量化到 PyTorch 再微调的完整指南

Transformers 的 GGUF 支持:加载量化模型、反量化到 PyTorch 再微调的完整指南

2026-09-05 12:28:29作者:柯茵沙

GGUF 是一种面向 GGML/llama.cpp 生态的单文件模型格式,Transformers 通过在 from_pretrained 中提供 gguf_file 参数,可以直接读取 Hub 上常见的 GGUF 量化检查点:先把配置、分词器元数据和权重从文件中解析出来,再将量化权重反量化(dequantize)为 PyTorch 张量,从而把原本只能在 ggml 运行时中推理的模型带回 Transformers 生态做训练与微调。读完本文,你将掌握 gguf_file 的完整用法、当前支持的反量化类型与模型架构清单、底层“元数据映射 + 张量重排”的源码实现,以及如何把微调结果保存并转回 GGUF。

什么是 GGUF:单文件模型格式

GGUF 是 GGML 推理框架(llama.cpp、whisper.cpp 等项目基于它)使用的模型存储格式。它的核心设计是单文件格式(single-file format)

  • 一个 .gguf 文件通常同时包含模型配置属性分词器词表(token、score、merges 等)以及其他元数据;
  • 同时包含模型全部权重张量,且张量以文件中声明的量化类型存储;
  • 文件支持快速检视(inspection):可以先只读取 KV 元数据而不加载张量,这在 Hub 上用于对 GGUF 仓库做快速扫描。

由于量化存储大幅降低了文件体积,GGUF 成为 Hub 上 LLM 社区分享权重的主流格式之一(例如 Q4_K、Q6_K、IQ2_XXS 等各种量化级别的文件)。

在 Transformers 中加载 GGUF:gguf_file 参数

[!NOTE] 文档明确标注:GGUF 加载功能仍处于高度实验阶段,欢迎社区贡献以覆盖更多量化类型和模型架构(见 docs/source/ar/gguf.md)。

加载 GGUF 文件的方式是在 分词器模型from_pretrained 调用中都传入 gguf_file 参数,两者可以来自同一个 GGUF 文件:

from transformers import AutoTokenizer, AutoModelForCausalLM

model_id = "TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF"
filename = "tinyllama-1.1b-chat-v1.0.Q6_K.gguf"

tokenizer = AutoTokenizer.from_pretrained(model_id, gguf_file=filename)
model = AutoModelForCausalLM.from_pretrained(model_id, gguf_file=filename)

加载完成后,你就拥有了一份未量化(dequantized)的完整模型,可以在 PyTorch 环境中与 Trainer、PEFT 等工具链自由组合。加载路径支持两种位置:

  • gguf_file 指向本地文件:直接以文件路径读取;
  • gguf_file 指向 Hub 上的文件名:走标准的 cached_file 下载/缓存逻辑(与常规检查点下载一致)。

加载的底层调用链

从源码结构看,gguf_file 参数贯穿了分词器、配置、模型三条加载路径:

  1. 分词器侧tokenization_utils_base.py 中,vocab_files_count > 1 的缺失检查对 GGUF 豁免;当检测到 gguf_file 时,直接令 vocab_files["vocab_file"] = gguf_file,即以 GGUF 文件充当词表文件。
  2. 配置侧configuration_utils.py 中,gguf_file 会取代 config.json 成为“配置来源”,通过 load_gguf_checkpoint(resolved_config_file, return_tensors=False)["config"] 只解析元数据(不读张量)来构建 config 字典。
  3. 模型侧modeling_utils.pyfrom_pretrainedgguf_file 做了三件事:
    • 校验约束(下文“限制”一节详述);
    • torch.device("meta") 上实例化一个虚拟(dummy)模型,仅用它的 state_dict 键名生成 GGUF→HF 张量名映射;
    • 调用 modeling_gguf_pytorch_utils.py 中的 load_gguf_checkpoint(..., return_tensors=True, model_to_load=dummy_model, torch_dtype=dtype) 得到张量字典,再按普通 state_dict 流程装入真实模型。

load_gguf_checkpoint 内部的核心步骤:

  • gguf.GGUFReader 打开文件,读取 general.architecture 判断架构(并做若干补丁,例如 llama.cpp 中 Mistral 复用 llama 架构名、T5 系架构识别等);
  • 遍历文件所有 KV 字段,按映射表重命名为 Transformers 配置键;
  • 对每个张量调用 gguf 包的 dequantize(tensor.data, tensor.tensor_type) 反量化(源码位置),随后经过架构专属的 TensorProcessor 做张量重排/拆分,再映射到 HF 参数名;
  • 若传入 torch_dtype(即 from_pretraineddtype 参数),张量会在反量化后立即转换到目标 dtype 以节省显存,例如测试 test_q6_k_fp16dtype=torch.float16 加载 Q6_K 文件并断言 lm_head.weight.dtype == torch.float16

原文档强调“先反量化到 fp32 再加载权重”——从源码看,反量化结果默认为 fp32 张量,但通过 dtype 参数可以在转换时直接落到 float16/bfloat16。

支持的量化类型

文档列出的支持反量化的量化类型如下(初始范围依据 Hub 上常见的共享文件确定):

  • F32
  • F16
  • BF16
  • Q4_0
  • Q4_1
  • Q5_0
  • Q5_1
  • Q8_0
  • Q2_K
  • Q3_K
  • Q4_K
  • Q5_K
  • Q6_K
  • IQ1_S
  • IQ1_M
  • IQ2_XXS
  • IQ2_XS
  • IQ2_S
  • IQ3_XXS
  • IQ3_S
  • IQ4_XS
  • IQ4_NL

[!NOTE] 要支持 GGUF 反量化,必须安装 gguf>=0.10.0。仓库中该门槛定义于 import_utils.pyGGUF_MIN_VERSION = "0.10.0"is_gguf_available 与测试装饰器 require_gguf 均以此为最低版本。

安装方式:pip install "gguf>=0.10.0"(配合已安装的 PyTorch)。若版本不满足,加载会抛出 ImportError(见 modeling_gguf_pytorch_utils.py 中的错误提示)。

支持的模型架构

文档列出的当前受支持架构是 Hub 上最常见的几类:

  • LLaMa
  • Mistral
  • Qwen2
  • Qwen2Moe
  • Phi3
  • Bloom
  • Falcon
  • StableLM
  • GPT2
  • Starcoder2
  • T5

从源码结构看,实际的支持面由 integrations/ggml.py 中的 GGUF_CONFIG_MAPPING 决定:其中除上述架构外,还包含了 qwen3qwen3_moegemma2gemma3gemma4umt5mambanemotrongpt_osslfm2minimax_m2 等架构的元数据映射;modeling_gguf_pytorch_utils.pyGGUF_SUPPORTED_ARCHITECTURES 直接由该映射表的键推导,因此“文档列出的 11 种架构”可视为首批稳定支持的典型,而源码映射表是当前版本更完整的上界。测试文件 tests/quantization/ggml/test_ggml.pyGgufModelTests 类中也给出了各架构对应的 Hub 仓库实例(Mistral、Qwen2、Qwen2Moe、Phi3、Bloom、Falcon、T5、StableLM、GPT2、Starcoder2、Mamba、Nemotron、Gemma2/3、Qwen3 等)。

配置与分词器的元数据映射机制

GGUF 文件把配置和分词器都编码在 KV 字段中(键名形如 llama.context_lengthtokenizer.ggml.merges)。Transformers 需要把它们翻译回自己的配置/分词器格式,核心是两组映射表和一套转换类:

配置映射(GGUF_CONFIG_MAPPING)

ggml.py 中的 GGUF_CONFIG_MAPPING 按架构逐一定义了 GGUF 键到 HF config 键的翻译,例如 llama 架构:

GGUF 键 Transformers config 键
context_length max_position_embeddings
block_count num_hidden_layers
feed_forward_length intermediate_size
embedding_length hidden_size
rope.dimension_count head_dim
rope.freq_base rope_theta
attention.head_count num_attention_heads
attention.head_count_kv num_key_value_heads
attention.layer_norm_rms_epsilon rms_norm_eps
vocab_size vocab_size

不同架构的命名体系差异很大(例如 Bloom 用 n_layer/n_head/layer_norm_epsilon,T5 用 d_model/d_kv/relative_buckets_count),映射表逐架构做了适配。此外 GGUF_CONFIG_DEFAULTS_MAPPING 用于补齐“Transformers 与 llama.cpp 默认值不同”的个别参数(如 qwen3_moenorm_topk_prob)。

解析逻辑本身在 load_gguf_checkpoint:遍历 reader.fields,把 架构.键 拆开查映射表;解析不出来的键会打印 info 日志而不报错。tie_word_embeddings 也不来自元数据,而是根据文件中是否存在 output.weight 张量推断。

分词器映射与 fast tokenizer 重建

GGUF 的分词器字段映射定义在 GGUF_TOKENIZER_MAPPINGggml.tokens/ggml.scores/ggml.merges/ggml.token_type 等字段分别对应词表、分数、BPE merges 与 token 类型,ggml.bos_token_id 等对应特殊 token id;tokenizer_config 部分还会解析 chat_template

GGUF_TO_FAST_CONVERTERS 按架构分派到具体的转换器:

  • llama/deciGGUFLlamaConverter(BPE,含 llama-3 字节级分词器兼容补丁)
  • qwen2/qwen2_moe/qwen3/qwen3_moe/minimax_m2GGUFQwen2Converter
  • phi3GGUFPhi3Converter(补齐 <|system|><|user|> 等特殊 token)
  • bloom/falcon/stablelm/gpt2/starcoder2/mamba/nemotronGGUFGPTConverter(GPT-2 风格 BPE)
  • t5/umt5GGUFT5Converter(Unigram)
  • gemma2/gemma3_text/gemma4_textGGUFGemmaConverter(Unigram,含空白 token 归一化补丁)

值得注意的是 GGUFTokenizerSkeleton:当 GGUF 文件中缺少 merges 字段(部分 LLaMA 系分词器)时,它会在运行时由 tokens 与 scores 重建 BPE merges 表并告警,保证分词器仍可实例化。

张量重排:从 GGUF 布局到 HF 布局

GGUF 的“标准化张量命名”(blk.N.BB.weight/bias)与 HF 的模块路径并不一致,且部分架构在转换时做过布局变换,反向加载时必须做逆变换。仓库为此实现了 TENSOR_PROCESSORS 注册表,按架构分派:

  • LlamaTensorProcessor:对 attn_q/attn_k 权重做逆行转置(_reverse_permute_weights),还原 llama.cpp 转换时的 KV 重排;
  • BloomTensorProcessor:把合并存储的 attn_qkv 按 q/k/v 拆块并逆 reshape(含 bias 的对应处理);
  • GPT2TensorProcessor:对 attn_qkvffn_downffn_upattn_output 等权重做转置,并把 GGUF 的 output.weight 特判映射为 lm_head.weight
  • MambaTensorProcessorssm_alog(-x) 还原指数形式,ssm_conv1d 补回维度;
  • NemotronTensorProcessor / Gemma2TensorProcessor:norm 权重做 -1 平移还原(这类模型 norm 存储的是 weight - 1);
  • Qwen2MoeTensorProcessor / MiniMaxM2TensorProcessor:把 GGUF 中按专家堆叠的 MoE 张量(ffn_gate_exps/ffn_up_exps/ffn_down_exps)拆分并交错写回 HF 的 gate_up_proj实现);
  • GptOssTensorProcessor:处理 128 专家 MoE 张量拆分与合并 gate_up_projs 的交错还原。

名称映射本身复用 gguf 包的 get_tensor_name_map(见 get_gguf_hf_weights_map):先在 meta 设备上构造 dummy 模型拿到 HF 参数名,逐个查表得到 GGUF 名;对一张对多张的 MoE 场景回退到 perform_fallback_tensor_mapping。这个设计意味着新增架构支持 = 在 GGUF_CONFIG_MAPPING 加元数据映射、(如需要)在 TENSOR_PROCESSORS 加处理器、在 GGUF_TO_FAST_CONVERTERS 加分词器转换器。

保存模型并转回 GGUF

完成微调/训练后,标准流程是把 tokenizer 和 model 保存为 HF 格式,再用 llama.cpp 的 convert-hf-to-gguf.py 脚本转回 GGUF:

tokenizer.save_pretrained('directory')
model.save_pretrained('directory')

!python ${path_to_llama_cpp}/convert-hf-to-gguf.py ${directory}

仓库的集成测试 test_q2_k_serialization 验证了这条闭环的前半段:加载 Q2_K 文件 → 生成文本 → save_pretrained → 从本地目录重新加载 → 生成结果一致,说明反量化后的权重可以无损地序列化回 safetensors/PyTorch 格式。

限制与注意事项

以下限制均有源码或测试依据,使用时需留意:

  1. 不支持与量化配置叠加:传入 gguf_file 时若同时带 quantization_config(或从 Hub 加载量化模型),会直接抛 ValueErrormodeling_utils.py)——反量化本身就消除了二次量化的必要。
  2. 不支持 disk offloaddevice_map 中出现 disk 值会抛 RuntimeError,测试 test_gguf_errors_disk_offload 专门验证了这一点;需要 accelerate 可用(检查位置)。
  3. 不支持与 state_dict 同时传入gguf_file 与直接传 state_dict 二选一(modeling_utils.py)。
  4. 版本门槛:需要 gguf>=0.10.0 且已安装 PyTorch,否则抛 ImportError;gguf 包过旧还可能因架构缺失而报 Unknown gguf model_type错误处理)。
  5. 功能仍属实验性:与文档声明一致,量化类型和架构覆盖仍在扩展中。

参考文件

登录后查看全文
热门项目推荐
相关项目推荐