> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# Transformers 现在能直接跑 llama.cpp 的 GGUF 量化模型了
- URL: https://www.hubwiz.com/blog/transformers-runs-llama-cpp-gguf-quants/
- Published: 2026-10-14T17:10:33.000Z
- Updated: 2026-10-14T17:14:50.000Z
- Description: 本地推理最常用的 GGUF 量化格式，现在可以在 transformers 里直接加载了。Hugging Face 复用 llama.cpp 的 ggml Metal 内核并优化生成循环，在 MacBook Pro M2 Max 上把性能做到接近 llama.cpp——本文完整编译：三行加载代码、OpenAI 兼容服务、实测数字与当前限制。
- Author: admin
- Tags: 本地 LLM, GGUF, 量化, Transformers, PyTorch

**一句话结论**：**GGUF 量化模型现在可以在 transformers 里高效运行了。** 从 Hub 上挑一个 GGUF，用熟悉的 `from_pretrained` 加载，就能在自己的机器上生成——Hugging Face 通过复用 llama.cpp 的 **ggml 内核**并优化 `generate` 循环，把性能做到了**接近 llama.cpp**，目前优先支持 **Apple Silicon 上的 Qwen3.5 架构**。

本文完整编译自 Hugging Face 博客《Transformers now runs llama.cpp quants》（2026-09-22），并做中文整理。

---

## 一、GGUF 是什么，为什么本地推理离不开它

在本地跑模型这件事上，[llama.cpp](https://github.com/ggml-org/llama.cpp?ref=hubwiz.com) 是关键推手——**Ollama、LM Studio、Jan 的推理引擎都是它**。它和 MLX 一起，让本地推理成了普通用户日常可用的选项。

**GGUF 是 llama.cpp 团队开发的格式**，把一个模型所需的**权重和元数据（包括 tokenizer 信息、可选的对话模板）打包在单个文件里**，并支持不同的量化等级，用少量精度换更小的内存占用。以 `Q4_K_M` 这类变体为例：**大部分张量用 4 bit，敏感张量保留更高精度**。

量化对文件大小的影响（以 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`；更激进的量化能塞下更大的模型，但质量取舍取决于模型和任务——**要在你真正要做的工作上评估**。GGUF 在 Hub 上的下载量已达数百万次，ggml-org、Unsloth、LM Studio Community、bartowski 等都在持续发布各种量化版本。

## 二、在 transformers 里加载 GGUF

前置条件：

- 一台 **Apple Silicon Mac**；
- 一个被已发布的 [ggml-quantization 内核构建](https://huggingface.co/kernels/ggml-org/ggml-quantization?ref=hubwiz.com)支持的 PyTorch 版本（通常是最近两个 release）；
- 最新版 transformers（当下需要 main 分支，直到下个 release）与兼容版本的 `kernels`。

```bash
pip install -U "git+https://github.com/huggingface/transformers.git" kernels

```

加载 GGUF 模型，只需给 `from_pretrained` 传入 Hub 的 `model_id` 和文件名 `gguf_file`：

```python
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
)

```

**不需要额外配置**：当权重在 Metal 上保持打包状态时，transformers 会自动加载兼容的 ggml/Metal 层内核，并用 `ggml-org/ggml-attn` 作为注意力实现。如果这个内核拉不下来，模型会带警告回退到 `"sdpa"`；也可以显式传 `attn_implementation="sdpa"` 强制回退。

之后的一切都是标准 transformers API：

```python
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))

```

> 注意：如果没有兼容的量化内核，加载器会回退到**反量化**路径，内存占用会变高。

## 三、起一个 OpenAI 兼容服务，接到任何客户端

同一份 checkpoint 也可以用 `transformers serve` 起成 OpenAI 兼容 API：

```bash
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 仓库，冒号后是要加载的文件，用于在一个仓库的多个量化版本中指定一个。

对话模板支持 thinking 的模型，可以加 `--reasoning off` 跳过、`--reasoning on` 启用；默认 `--reasoning auto` 跟随模板默认行为。

然后在客户端（如 Jan 或 Pi）里添加自定义 OpenAI 兼容提供方：

| 设置项      | 值                                                |
| -------- | ------------------------------------------------ |
| Base URL | http://localhost:8000/v1                         |
| Model ID | unsloth/Qwen3.5-4B-GGUF:Qwen3.5-4B-Q4\_K\_M.gguf |

**transformers 在你的 Mac 上运行模型，客户端只提供对话界面。** 任何支持该 API 的客户端都能接到同一个端点。

## 四、和 llama.cpp 比：几乎追平

参考基准是 llama.cpp 的 [llama-bench](https://github.com/ggml-org/llama.cpp/tree/master/tools/llama-bench?ref=hubwiz.com)（build `5f55650a7`，release b10200，ggml 0.18.0 的 Metal 后端），命令为 `llama-bench -m <file> -p 0 -n 128 -r 3`，报告的是 **tg128**（解码 128 个 token 的生成速率，三次平均，不含 prompt 处理）。transformers 一列是同为 128 token 的 `generate`，从 12 token 的提示开始，三次热身后取最好成绩，**包含 prefill**。

测试环境：**MacBook Pro M2 Max，32 GB 统一内存，macOS 26.6，PyTorch 2.12.1，kernels 0.17.0，插电状态。**

| 模型（量化）                              | Transformers   | llama.cpp        |
| ----------------------------------- | -------------- | ---------------- |
| Qwen3.5-4B Q4\_K\_M（2.74 GB）        | 70.4 tok/s     | 71.8 ± 0.4 tok/s |
| Qwen3.8-27B UD-Q4\_K\_M（16.5 GB）    | **15.9 tok/s** | 13.4 ± 0.9 tok/s |
| Qwen3.5-35B-A3B UD-IQ4\_XS（16.3 GB） | 60.2 tok/s     | 61.3 ± 0.5 tok/s |

![GGUF 生成吞吐：Transformers vs. llama.cpp](https://www.hubwiz.com/blog/content/images/2026/10/img_1ee050f2a680e9c06fb73709142203c7.png)

**transformers 在三种 checkpoint 上都追得很近**——4B 几乎打平，27B 因为包含 prefill 反而更快，MoE 的 35B 只差一个多百分点。官方也提醒：两者**并非完全相同的基准条件**（transformers 含 prefill，llama-bench 只算解码），所以不要把它当作严格的同条件对比。

但结论是清楚的：**你可以在 Python/PyTorch 里直接跑 GGUF 量化模型，而不必切换运行时。**

## 五、加速从哪来（一）：复用 ggml 的 Metal 内核

内核（kernel）是在 GPU 上执行运算的小程序。PyTorch 给的是通用实现；专用内核可以少干活、合并多个运算，或者**直接以存储格式读取量化权重**。`kernels` 库让 ggml 的 Metal 内核可以发布在 Hub 上并从 transformers 调用——**把 ggml 的成果带进 PyTorch 模型，而不是把模型换成一个独立推理运行时。**

| 内核                                                                                                  | 作用                                                                   |
| --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| [ggml-quantization](https://huggingface.co/kernels/ggml-org/ggml-quantization?ref=hubwiz.com)       | 以打包的量化权重直接做矩阵运算，包括 MoE 模型中被选中的专家；避免每次解码前展开整个权重矩阵                     |
| [ggml-norm](https://huggingface.co/kernels/ggml-org/ggml-norm?ref=hubwiz.com)                       | 融合归一化运算，包括 Qwen3.5 / Qwen3.8 使用的 zero-centered RMSNorm               |
| [ggml-attn](https://huggingface.co/kernels/ggml-org/ggml-attn?ref=hubwiz.com)                       | 提供 ggml 的 Metal flash attention，用于 prompt 处理与 token 解码               |
| [ggml-gated-delta-net](https://huggingface.co/kernels/ggml-org/ggml-gated-delta-net?ref=hubwiz.com) | 加速 Qwen3.5 / Qwen3.8 混合架构线性注意力层的门控 delta 网络                          |
| [topk](https://huggingface.co/kernels/transformers-community/topk?ref=hubwiz.com)                   | MoE 中为每个 token 选择专家，融合 softmax 与 top-k 路由（transformers 自己的 Metal 实现） |

前四个基于 ggml 内核，第五个 top-k 解决 MoE 路由的另一个瓶颈。它们共同减少了每个生成 token 所需的 GPU 工作量。官方对比了"同样打包的 GGUF checkpoint，带与不带这些层内核"（两种配置都保持量化内核启用）：

![层内核的贡献](https://www.hubwiz.com/blog/content/images/2026/10/img_19d484c7f7a098aaa87d97c0d71c7df4.png)

- Qwen3.5-4B：44.2 → **70.4 tok/s（1.59×）**
- Qwen3.8-27B：10.5 → **15.9 tok/s（1.51×）**
- Qwen3.5-35B-A3B：28.8 → **60.2 tok/s（2.09×）**

**MoE 模型的提升最大（2 倍以上）**——这与"避免展开整个权重矩阵、只读被选中的专家"的设计直接相关。

## 六、加速从哪来（二）：让 CPU 和 GPU 不互相等

内核再快，也得让 GPU 一直有活干。生成过程中，**CPU 负责调度 GPU 操作、控制产出下一个 token 的循环**；而把结果从 GPU 读回会迫使 CPU 等队列里的操作完成——**哪怕每个 token 只等一点点，吞吐也会明显下降。**

`generate` 里做了两处修改（对**所有** transformers 模型都有收益，不只是 GGUF）：

- **提前丢弃多余的注意力掩码**（[PR #48814](https://github.com/huggingface/transformers/pull/48814?ref=hubwiz.com)）：对没有 padding 的 decoder-only 输入，生成开始时就把全 1 的 padding mask 去掉，下游注意力代码不必反复检查能否跳过它；因果注意力仍然保留。
- **延迟停止判断**（[PR #47975](https://github.com/huggingface/transformers/pull/47975?ref=hubwiz.com)）：在支持的路径上，`generate` 异步复制停止决策、在下一步消费。CPU 可以在 GPU 运行时继续调度；流式输出采用同样做法，超出停止条件的多余一步会从结果中移除。

![生成循环的贡献](https://www.hubwiz.com/blog/content/images/2026/10/img_74d76e20cb40358151538f5286c637bc.png)

保持所有层内核启用，单独隔离生成循环的变化：

- Qwen3.5-4B：49.6 → **70.4 tok/s（1.42×）**
- Qwen3.8-27B：13.7 → **15.9 tok/s（1.16×）**
- Qwen3.5-35B-A3B：33.7 → **60.2 tok/s（1.79×）**

**内核减少单个运算的成本，更少的同步点让 CPU 调度与 GPU 执行重叠**——两者互补。官方还特意强调：**这些优化不需要 `torch.compile`**，交互式使用没有编译停顿，输入形状变化也不会触发重编译。

## 七、GGUF 之外：把 ggml 内核带给更多模型

更大的机会在于：**把 ggml 的性能带给 llama.cpp 不支持的模型。**

transformers 已经有这些架构的 PyTorch 实现。有了 ggml 内核与 PyTorch 里的量化方案，就可以在不把整个模型移植进 llama.cpp 的前提下，先加速它们支持的那些运算——**这对新架构、研究模型和可能永远不会有 llama.cpp 实现的定制变体尤其有用。**

这条路径并不限于 GGUF 格式本身：**内核操作的是张量，并不要求整个模型来自 GGUF 文件**。同一套构建块可以整合进其他 transformers 模型和加载流程，也为**计算机视觉、音频、多模态模型**复用注意力、归一化、矩阵乘法内核铺了路。当然，每个架构仍需要集成与验证，目前的 GGUF 示例只覆盖文本生成。

## 八、当前限制与下一步

初始目标场景是 **Apple Silicon 上的单轮交互式对话**，边界需要说清楚：

- **打包推理路径目前仅限 MPS**。通过反量化的 GGUF 导入是另一条独立路径——**支持 GGUF 文件格式，不意味着所有设备都有打包内核**；
- **padding 与批处理仍需完善**。无 padding 的输入能吃到掩码优化的红利；有 padding 的批次没有这个捷径，性能可能更低。官方计划把工作扩展到 MPS 上的 `generate_batch`；
- **架构覆盖有限**。打包加载器目前覆盖 Qwen3.5 的 dense 与 MoE 架构（含兼容的 Qwen3.8 checkpoint），新增架构支持"相对直接"，会逐步扩大。

想让某个 GGUF 模型在 transformers 里可用，可以带上 checkpoint 和用例去 [transformers 仓库提 issue](https://github.com/huggingface/transformers/issues?ref=hubwiz.com)，帮助官方排优先级。

> 想了解 GGUF 文件名里的量化标记怎么读，可以看本站的 [GGUF 文件名解析](https://www.hubwiz.com/blog/gguf-filename-explained/)；量化对精度的影响见 [拯救量化 LLM 的准确性](https://www.hubwiz.com/blog/stop-losing-accuracy-after-llm-quantization/)。

---

## 参考来源

- Hugging Face Blog：《Transformers now runs llama.cpp quants》（2026-09-22）https://huggingface.co/blog/transformers-llama-cpp-quants
- 文章源码（GitHub）：https://github.com/huggingface/blog/blob/main/transformers-llama-cpp-quants.md
- GGUF 量化类型文档：https://huggingface.co/docs/hub/gguf#quantization-types

## 延伸阅读（本站）

- [本地 & 自托管 LLM 完全指南](https://www.hubwiz.com/blog/local-llm-stack/)
- [GGUF 文件名解析](https://www.hubwiz.com/blog/gguf-filename-explained/)
- [Ollama vs. llama.cpp 实测对比](https://www.hubwiz.com/blog/ollama-vs-llama-cpp-performance-comparison/)
- [生产环境别用 Ollama](https://www.hubwiz.com/blog/stop-using-ollama-in-production/)

*本文由汇智网编译整理，转载请注明出处。*