Transformers 原生支持 GGUF 格式,实现高效本地推理
Hugging Face 宣布在 transformers 库中增加对 GGUF 模型的高效运行支持。这一更新允许开发者通过熟悉的 Transformers API 加载和使用为笔记本内存优化的量化检查点。用户只需从 Hub 选择 GGUF 文件,使用 from_pretrained 加载,即可在本机开始生成任务。

此前,Ollama、LM Studio 和 Jan 等本地 AI 工具主要依赖 llama.cpp 作为推断引擎。随着 MLX 等项目的加入,本地推理逐渐变得实用化。例如,有用户反馈在 MacBook Pro 上通过 llama.cpp 运行 Qwen3.6 27B 模型处理编码代理任务时,体验已非常接近 Claude Opus。
GGUF 是由 llama.cpp 团队开发的广泛使用的本地推理格式,Hub 上的 ggml-org 以及 Unsloth、LM Studio Community 和 bartowski 等发布者提供了大量预量化的 GGUF 检查点。目前,GGUF 模型的下载量已达数百万次。为了让这些模型在 Transformers 中更易用,Hugging Face 复用了底层的 ggml 内核以减少生成开销。初步重点在于 Apple Silicon 的本地推理,首先支持 Qwen3.5 架构。
GGUF 文件格式与量化权衡
GGUF 文件将模型权重和元数据(包括分词器信息和可选聊天模板)打包在一起。它支持不同的量化级别,以牺牲少量精度换取更小的存储空间。例如,Q4_K_M 变体混合了张量精度,主要使用 4 位权重,同时保留敏感张量的更高精度。
以下是 Unsloth 发布的 Qwen3.5-4B 在不同量化等级下的文件大小对比:
| GGUF 变种 | 文件大小 | 权衡说明 |
|---|---|---|
BF16 |
8.42 GB | 未量化的参考基准 |
Q6_K |
3.53 GB | 比小尺寸变种更精确 |
Q5_K_M |
3.14 GB | 在尺寸和精度之间平衡 |
Q4_K_M |
2.74 GB | 本地推理的实用起点 |
建议从 Q4_K_M 开始尝试,若资源允许可升级至 Q5_K_M 或 Q6_K。更激进的量化虽能让更大模型适配设备,但质量损失取决于具体模型和任务类型。
在 Transformers 中加载 GGUF
要开始使用,需满足以下条件:
- 一台 Apple Mac 电脑。
- 由已发布的 ggml 量化内核构建的 PyTorch 版本(通常为最近两个版本)。
- 最新版本的 transformers(目前为主分支,直至下一个正式版本)及兼容的内核库。
pip install -U "git+https://github.com/huggingface/transformers.git" kernels
加载 GGUF 模型时,将 Hub 的 model_id 和文件名作为 gguf_file 参数传递给 from_pretrained。
无需额外配置:当权重保持在 Metal 设备上时,Transformers 会自动加载兼容的 ggml/Metal 层内核,并使用 ggml-org/ggml-attn 作为注意力实现机制。如果无法获取该内核,模型会发出警告并回退到 "sdpa";也可通过 attn_implementation="sdpa" 强制指定。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "unsloth/Qwen3.5-4B-GGUF"
filename = "Qwen3.5-4B-Q4_K_M.gguf"
tokenizer = AutoTokenizer.from_pretrained(model_id, gguf_file=filename)
model = AutoModelForCausalLM.from_pretrained(
model_id,
gguf_file=filename
)
这是唯一针对 GGUF 的特殊步骤,后续操作均遵循标准 Transformers API:
messages = [{"role": "user", "content": "Explain why the sky is blue in a few sentences."}]
inputs = tokenizer.apply_chat_template(
messages,
tokenize=True,
add_generation_prompt=True,
return_dict=True,
return_tensors="pt",
).to(model.device)
with torch.inference_mode():
outputs = model.generate(**inputs, max_new_tokens=256)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
注意:如果没有兼容的量化内核,加载器将对模型进行反量化,这会导致更高的内存占用。
服务部署与客户端连接
用户可以使用相同的检查点配合 Transformers Serving 暴露 OpenAI 兼容的 API:
pip install -U "transformers[serving] @ git+https://github.com/huggingface/transformers.git" kernels
transformers serve "unsloth/Qwen3.5-4B-GGUF:Qwen3.5-4B-Q4_K_M.gguf"
模型参数格式为 <model_id>:<filename>.gguf,其中冒号前是 Hub 仓库 ID,后是要加载的具体文件。这种语法允许从包含多个量化版本的仓库中选择特定文件。
对于支持思考模式的聊天模板,可添加 --reasoning off 跳过或 --reasoning on 启用,默认值 --reasoning auto 遵循聊天模板设置。
可通过配置自定义 OpenAI 兼容提供商来连接 Jan 或 Pi 等客户端:
| 设置项 | 值 |
|---|---|
| Base URL | http://localhost:8000/v1 |
| Model ID | unsloth/Qwen3.5-4B-GGUF:Qwen3.5-4B-Q4_K_M.gguf |
在此架构下,Mac 负责运行模型,客户端提供对话界面。其他支持此 API 的客户端也可复用同一终端。
性能对比:Transformers vs llama.cpp
以 llama.cpp 为本地推理性能的参考基准,比较涵盖三个 GGUF 检查点:小型密集模型、大型密集模型和混合专家(MoE)模型。
测试环境为 MacBook Pro M2 Max,32 GB 统一内存,macOS 26.6,PyTorch 2.12.1,kernels 0.17.0,接通电源。
- llama.cpp 数据:来自 llama-bench 工具 (build 5f55650a7, release b10200, Metal backend from ggml 0.18.0),命令为
llama-bench -m <file> -p 0 -n 128 -r 3,报告 tg128(128 个解码 token 的生成率,三次重复平均,不含预填充)。 - Transformers 数据:从 12 个 token 提示生成相同的 128 个 token,取三次预热运行的最佳结果,包含预填充时间。
结果显示,Transformers 在所有三个检查点上均接近 llama.cpp 的性能。需注意,两者测量条件不完全一致,因为 Transformers 的数据包含了预填充阶段,而 llama.cpp 仅报告解码吞吐量。
互补定位与应用场景
当 GGML 和 llama.cpp 加入 Hugging Face 生态时,明确了其互补角色:llama.cpp 提供本地推理的基础运行时,而 Transformers 定义模型结构。此次 GGUF 支持进一步拉近了两者的距离。
若首要目标是极致高效的本地推理,llama.cpp 仍是推荐引擎,因其专用运行时、内存管理和广泛的硬件支持均围绕此目标构建。但在 Transformers 中集成 GGUF 为开发者提供了便利:
- Python/PyTorch 实验:利用熟悉的 PyTorch 工具检查中间激活、修改前向传播或原型定制层。
- 模型评估:使用现有的 Transformers 评估工作流测量量化检查点的质量。
- 转换验证:开发者可在 Transformers 中同时加载原始检查点和 GGUF 转换版,以便检查权重转换正确性及量化误差。
- 新解码方法探索:使用自定义 logit 处理器和停止标准,或在 Python 中编写生成循环。
- 微调:对减量权重继续使用标准的 Transformers 训练工作流。
在微调场景下,可使用 GgufConfig(dequantize=True):
import torch
from transformers import AutoModelForCausalLM, GgufConfig
model = AutoModelForCausalLM.from_pretrained(
"unsloth/Qwen3.5-4B-GGUF",
gguf_file="Qwen3.5-4B-Q4_K_M.gguf",
quantization_config=GgufConfig(dequantize=True),
dtype=torch.bfloat16,
)
超越 GGUF:ggml 内核的更广泛应用
更大的机遇在于将 ggml 的高性能带入 llama.cpp 尚未支持的模型架构中。
许多架构已有 PyTorch 实现。通过在 PyTorch 中使用 ggml 内核和量化方案,可以在无需先在 llama.cpp 中实现整个模型的情况下加速关键操作。这对新架构、研究模型及可能永远不会获得专门 llama.cpp 实现的自定义变体尤为有用。
内核作用于张量而非整个模型,因此不要求模型必须来自 GGUF 文件。同样的构件可集成到其他 Transformers 模型和加载工作流中。这也为计算机视觉、音频和多模态模型开辟了道路,使其能复用兼容的注意力、规范化和矩阵乘法内核,而无需在 llama.cpp 中完全实现。目前的初始示例仅涵盖文本生成。
技术细节:内核复用与生成循环优化
为了展示在保持 Python 模型和生成循环的同时能达到多高的性能,团队重点关注了内核效率和生成循环优化。
复用 ggml 的 Metal 内核
内核是在 GPU 上执行操作的小程序。PyTorch 提供通用实现,而专用内核可以减少工作量、融合多个操作或直接读取存储格式的量化权重。kernels 库允许分发 Hub 上兼容的 ggml Metal 内核构建,并从 Transformers 调用它们。这使得 ggml 的工作能在 PyTorch 模型中完成,而无需替换为单独的推理运行时。
| Kernel | 功能描述 |
|---|---|
ggml-quantization |
读取用于矩阵操作的打包量化权重,包括 MoE 模型中选定的专家。避免在每次解码操作前展开整个权重矩阵。 |
ggml-norm |
融合归一化操作,包括 Qwen3.5 和 Qwen3.8 使用的零中心 RMSNorm。 |
ggml-attn |
提供 ggml 的 Metal flash attention,用于提示处理和 token 解码。 |
ggml-gated-delta-net |
加速 Qwen3.5 和 Qwen3.8 混合架构线性注意力层中使用的门控 delta 网络。 |
topk |
为 MoE 模型中的每个 token 选择专家,结合 softmax 和 top-k 路由。这是自研的 Metal 实现。 |
前四个包基于 ggml 内核;top-k 内核解决了 MoE 路由中的另一个瓶颈。它们共同减少了生成每个 token 所需的 GPU 工作量。
CPU 与 GPU 协同工作
更快的内核只有在 GPU 持续忙碌时才有效。在生成过程中,CPU 调度 GPU 操作并控制产生下一个 token 的循环。从 GPU 读回结果可能迫使 CPU 等待队列操作完成。即使是很小的等待,若在每个 token 上重复,也会显著降低吞吐量。
两项更改旨在解决 generate 中的这一问题,且适用于所有 Transformers 模型(不仅限于 GGUF):
- 早期移除不必要的注意力掩码 (#48814):当支持的仅解码器输入没有填充时,其全 1 填充掩码可在生成开始时移除。下游注意力代码不再需要反复检查该掩码以确定是否可跳过。因果注意力仍然保留。
- 延迟停止检查 (#47975):在支持的路径上,
generate异步复制停止决策并在下一步消耗它。CPU 可以在 GPU 运行时继续调度工作。流式 token 使用相同方法,任何超出停止条件的额外步骤将从结果中移除。
这些更改优化了模型周围的生成循环,其效用超出了 GGUF 范围。它们与内核工作相辅相成:内核降低单次操作成本,而减少同步点则允许 CPU 调度和 GPU 执行重叠。
当前限制与未来计划
初始目标是在 Apple Silicon 上进行单个交互式对话。需注意以下边界:
- 打包推理路径目前仅限 MPS。通过反量化导入 GGUF 仍是一个独立选项;文件格式的支持并不意味着打包内核在所有设备上可用。
- 填充和批处理仍需改进。无填充输入受益于上述掩码优化。填充批次无法采用相同的捷径,性能可能较低。团队希望将工作扩展到 MPS 上的
generate_batch。 - 架构覆盖有限。打包加载器目前覆盖 Qwen3.5 密集和 MoE 架构,包括兼容的 Qwen3.8 检查点。添加对其他架构的支持相对直接,覆盖范围将逐步扩大。
如有希望在 Transformers 中使用的 GGUF 模型,请提交 Issue 并附带检查点及使用案例。





