GGUF 一直是 llama.cpp 的地盘。你想在 Python 里拿 Transformers 跑一个 Q4_K_M 权重,要么先写反量化脚本,要么换掉整条推理链路。现在这堵墙被拆掉一角:Hugging Face 的 Transformers 支持直接读取 GGUF checkpoint,from_pretrained 里多传一个 gguf_file 就能加载,底层复用 ggml 的 Metal 内核——在 Apple Silicon 上,实测吞吐已经贴着 llama.cpp 走。
加载器只是外壳,动刀的地方在内核
传一个 gguf_file,就这么多
调用方式没有任何学习成本。from_pretrained 里多给一个 gguf_file 参数,指向 Hub 上 GGUF 仓库里的具体文件名,或者你本地磁盘的路径,剩下的流程和加载普通 safetensors 权重没有区别。模型能 forward,能 generate,也能直接塞进现有的评测脚本。
这条路以前并非走不通。Transformers 早就能读 GGUF,代价是反量化全部用 PyTorch 实现:前向过程中,每一层低比特权重被现场拆开还原成浮点张量。结果是速度慢,内存峰值也难看,很多人试过一次就放弃了。
Metal 内核被搬进了 Python 进程
这次真正的动作,是把反量化交给 ggml 编译出来的原生内核。在苹果芯片上,那套 Metal 着色器原本只活在 llama.cpp 的可执行文件里,如今 Transformers 能直接调用它。同一条加速路径,两个生态共享。
代价在构建环节。想吃到 GPU 加速,得装带 Metal 后端编译的 ggml 包,构建时把对应开关打开;否则它会安静地回落到 CPU 内核,然后你在 M 系列 Mac 上看到一组让人怀疑人生的 token/s 数字。
吞吐数字,别只看结论
官方给出的实测里,Apple Silicon 上 Transformers 加载 GGUF 后的生成吞吐已经接近 llama.cpp。这类对比图有个通病:prompt 长度、batch size、生成长度、预热次数、模型规模,任何一项变化都能把曲线掰弯。自己复现时,至少保证两边用同一个 GGUF 文件、同一段 prompt、同一组采样参数,否则你比较的是引擎以外的噪音。
各自的地盘,短期内谁也吃不掉谁
llama.cpp 的强项是“当一个服务”
并发请求、连续批处理、KV cache 的精细管理、跨平台后端(CUDA、Metal、Vulkan、ROCm),llama.cpp 是奔着把模型稳定地跑起来设计的。你要的是一个常驻的推理端口,它仍然是默认答案。模型换一个、上下文拉长一倍,它都有自己的调度手段。
Transformers 赢在周围那一圈
评测框架、数据处理管线、自定义 logits processor、PEFT 适配器、和 tokenizer 绑定的预处理逻辑——这些东西在 llama.cpp 里要么没有,要么得自己手搓。GGUF 权重现在可以留在 Transformers 里跑,等于承认了一件事:量化模型也是模型,也该能进训练与评测生态的流水线。
怎么选,判断标准其实很朴素
任务是跑一次 benchmark,比较不同量化等级在同一套 prompt 上的表现,用 Transformers 省事。任务是要压住线上尾延迟、扛住并发流量,llama.cpp 或者别的专用引擎更合适。中间地带是本地 Notebook 里的原型验证——用哪边都行,看你的依赖树能不能忍受一次 C++ 编译。
上手之前,先算三笔账
支持的量化类型是一个有限集
ggml 的量化家族很庞大,从 Q2_K 到 Q8_0,还有 IQ 系列和各种混合精度变体。Transformers 侧并非全盘接收,冷门类型的加载会直接报错。下载权重之前先看一眼模型卡上的量化标签,别等加载到一半才发现不支持。
内存账要重算一遍
GGUF 的卖点是省内存。反量化按需发生,常驻内存里的是低比特形式,峰值取决于一次前向要还原多少层。这条曲线跟加载 fp16 权重完全是两回事,别拿老经验拍数字。M 系列 Mac 的统一内存尤其如此——系统、模型、KV cache 抢的是同一块资源,谁多占一点,别的地方就疼。
tokenizer 和 chat template 容易错配
GGUF 文件里通常打包了 tokenizer 配置和聊天模板。上游模型更新了模板,而量化仓库还停在旧版本,这种错配会让输出变得莫名其妙——格式飘、角色串、停止符不生效。跑之前打印一次 tokenizer 的聊天模板,几秒钟的事,能省掉一小时的 debug。
格式变成接口,才是这事的余波
GGUF 正在脱离单一项目
一个格式只有在被第二个、第三个工具链原生读取之后,才算真正成为基础设施。GGUF 走到这一步花了好几年。现在它既是 llama.cpp 的产物,也是 Transformers 的输入,还成了一个中立的交换层——量化模型可以在工具之间搬来搬去,不必重新导出。
本地推理的分工在变清晰
过去的问题是“我该用哪个引擎”,现在的问题更细:同一份权重,开发阶段交给 Transformers 调参和评测,部署阶段交给 llama.cpp 扛流量,中间不需要重新量化一次。流程拆开之后,两个生态各自优化自己那一段。这比任何一方的性能数字都更有意思。
所以别急着问“谁更快”。先问清楚你要跑的是什么活。

