☰
Transformers直接加载GGUF:本地模型不再二选一
2026/10/1 13:09:53 网站建设 项目流程

如果你这两年搞过本地模型,大概率经历过这种纠结:下载模型之前先得问自己一句,我到底走哪条路?想用 Ollama 或者 llama.cpp,那就得认 GGUF;想用 Transformers 做开发、接 Agent、玩 Hugging Face 整套生态,又得老老实实去下 safetensors 格式。明明是同一个模型,硬生生被拆成两个阵营,本地党经常得“二选一”。这个局面最近终于被撕开了一道口子——Transformers 已经能直接加载 GGUF 了。

说“直接”可能还不够准确,准确说是from_pretrained一个带.gguf后缀的文件就能把模型跑起来,不用先转格式,不用单独跑去 llama.cpp 那边推理。这篇博文我就从原理、实操、踩坑到场景组合,把这个更新的来龙去脉说明白,适合那些既想用 Transformers 生态、又不想放弃量化模型低占用优势的人。不管是研究代码、跑本地 Agent,还是想让 Cursor、Claude Code 接上本地模型,这个改动都能让你省掉一大圈折腾。

1. 为什么以前 GGUF 和 Transformers 一直“互相看不见”

1.1 GGUF 是怎么变成本地模型“通用语言”的

GGUF 的诞生和 llama.cpp 的崛起分不开。早期 llama.cpp 用的是 GGML 格式,但那套格式扩展性差,加一点元数据都费劲,后来官方直接推倒重来,设计了 GGUF。和普通权重文件最大的区别是,GGUF 把模型的所有信息都塞进一个文件里:张量数据、超参数、tokenizer 词表、特殊 token、甚至一些自定义的 metadata,全给你打包好了。

打个不严谨的比方,safetensors 更像一个“零件盒”,里面是纯权重,你需要另外拿一份 config 才知道怎么组装;GGUF 更像一个“自动安装包”,下载下来就能用。再加上 GGUF 原生支持 llama.cpp 那套 K-quant 分块量化方案(Q4_K_M、Q5_K_M 这种),同样一个 7B 模型,原始 fp16 要 14GB 左右,压成 Q4_K_M 只有 4GB 出头,显存压力直接小了三分之二。这就是为什么本地模型圈快速把 GGUF 当成了事实标准:文件小、单文件分发、拿到就能跑。

1.2 Transformers 之前不认 GGUF 的真正原因

不是人家看不起 GGUF,纯粹是两套生态的底层设计差异。Transformers 的模型加载流程很固定:读 config 文件,构建模型骨架,然后往骨架里塞 PyTorch 的state_dict或者 safetensors 的权重张量。它对“权重”的假设是字典结构,state_dict里每个键对应一个 torch 张量,模型类按名取参。而 GGUF 是另一种二进制布局,张量按顺序存储在文件里,还内嵌了量化信息,一个小数要拆成几个字节来编码。

Transformers 没有能力直接反序列化这玩意儿。更麻烦的是,GGUF 文件的量化权重需要特殊的反量化算子才能在 GPU 上跑,Transformers 的核心逻辑是抽象成nn.Module,它并不关心底层量化方案。所以在过去很长一段时间,你的选择只有两条路:要么用 llama.cpp/Ollama 跑 GGUF,享受低显存和高效 CPU 推理;要么用 Transformers 跑原始权重,换取完整的生态工具链,比如微调、评估、Agent 集成。两边就像 iOS 和 Android,明明都是手机,应用却不通用。

2. 现在到底怎么“直接跑”:GGUF 加载实操

2.1 装对版本,写出最小加载代码

Transformers 大概是 4.45 版本正式加入的 GGUF 加载支持,所以第一件事是把环境升上去,顺便装一个ggufPython 库,它是用来解析 GGUF 文件元数据的。

pip install -U transformers pip install gguf torch

然后,奇迹发生了。代码长这样:

from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen2-7B-Instruct-GGUF", gguf_file="qwen2-7b-instruct-q4_k_m.gguf" ) tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-7B-Instruct")

其中gguf_file这个参数是关键。它告诉 Transformers:这个 repo 里可能有普通权重,但我只想加载这一个指定名字的 GGUF 文件。如果没有传gguf_file,而 repo 里恰好只有一个.gguf文件,Transformers 也会自动识别;但绝大多数 GGUF 仓库里都有好几个量化版本,所以老老实实指定文件名最稳妥。

加载完之后,模型就是一个正常的AutoModelForCausalLM对象,后面你想.generate()、想接pipeline、想塞进自己的推理封装都行,和以前用 safetensors 加载没有任何区别。这就是“不用二选一”的含义:量化模型的体积优势保住了,Transformers 生态的工具链也保住了。

2.2 用本地 GGUF 文件加载,不一定要走 Hugging Face

有人可能说,我不走 Hugging Face,我自己下载了一个qwen1.5-0.5b-chat-q4_k_m.gguf放在磁盘上,怎么加载?直接指向本地目录就行:

model = AutoModelForCausalLM.from_pretrained( "/path/to/local/gguf_dir", gguf_file="qwen1.5-0.5b-chat-q4_k_m.gguf" ) tokenizer = AutoTokenizer.from_pretrained("/path/to/local/gguf_dir")

但这里有一个非常容易踩的坑:Transformers 可以读 GGUF 的权重,但 tokenizer 的加载逻辑仍然是原来的逻辑。tokenizer 需要tokenizer.json、vocab.json、tokenizer_config.json这些标准文件,不会从 GGUF 里自动提取(至少当前版本还没有完全做到)。如果你本地只有一个光秃秃的.gguf文件,AutoTokenizer.from_pretrained一定会报错。

解决方式有三个:第一,去模型原仓库把 tokenizer 相关文件一并下下来,放进同一个目录;第二,如果模型在 Hugging Face 上有原始仓库,tokenizer 直接指向原始仓库名字,像我上面的例子就是权重指向 GGUF 仓库、tokenizer 指向原始仓库;第三,实在找不到,网上有很多将 GGUF 模型重新导出 tokenizer 的工具脚本,但没必要,直接下载原版几个小文件就行。

2.3 量化格式和推理精度的关系,别被文件大小骗了

Transformers 加载 GGUF 时,其实并不是“直接运行 GGUF”,而是先把 GGUF 文件里的权重读出来,还原成 torch 张量,再装进常规模型结构里。这个逻辑很重要,很多人误解它能像 llama.cpp 一样把 Q4 量化模型直接塞进显存跑。

现阶段支持的量化格式主要在常见几种里面:

量化格式说明适合场景
F32 / F16未量化或半精度追求质量,不在乎体积
Q4_04bit,基础量化显存极小,质量损失大
Q4_K_S4bit,K-quant 小型质量/体积平衡
Q4_K_M4bit,K-quant 中型目前本地模型的“甜点位”,兼顾体积和质量
Q5_0 / Q5_K_S / Q5_K_M5bit 量化比 Q4 质量更好,文件稍大

K-quant 是 llama.cpp 提出的一套量化策略,核心思路是:模型里不同张量的重要性不同,重要的张量保留更多 bit,不重要的压得更狠。所以 Q4_K_M 虽然还是 4bit 量级,但实际效果往往比最早的 Q4_0 好不少。

这里必须提醒一句:Transformers 加载 GGUF 之后,模型的推理精度取决于你加载时有没有配置额外的量化方案。如果你只是普普通通from_pretrained了一个Q4_K_M.gguf,那么权重会被解压回 fp16 或 fp32(取决于模型 config 默认值),显存占用并不会等于那个 4GB 的文件大小,可能还是接近原始模型的体量。

想要真正低显存运行,还需要配合bitsandbytes做二次量化:

from transformers import BitsAndBytesConfig import torch quant_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_compute_dtype=torch.float16 ) model = AutoModelForCausalLM.from_pretrained( "...", gguf_file="...gguf", quantization_config=quant_config )

这样做,模型加载后在显存里就是 4bit 状态,这才是真正冲着小显存去的玩法。官方文档里还支持直接传GGUFConfig,它能从 GGUF 文件 metadata 推断出原始量化配置,但实际推理时那个配置更多是“告诉模型你本来是什么”,让你心里有个数。

3. 我实际踩过的坑:几个报错和它们的根源

3.1no lm runtime found for model format 'gguf'

这个报错我在好几个帖子里看到过,配合“claude code 调用 lmstudio 的本地模型”这个热搜词特别典型。它不是 Transformers 本身抛的错误,而是你用的 AI 编程工具或者 Agent 框架去连本地推理服务时,后端运行时没有正确响应。

我遇到的具体场景是这样的:Claude Code 里配置了本地模型地址,指向 LM Studio 暴露的 OpenAI 兼容服务,但 LM Studio 那个服务里根本没加载模型,或者加载的是一个模型目录而不是具体的 GGUF 文件,于是一调用就报no lm runtime found for model format 'gguf'。翻译成人话就是:调用方说“我要跑 GGUF”,但服务端压根没有能处理 GGUF 的运行时。

排查思路很简单,按顺序来:第一步,打开 LM Studio / Ollama / llama.cpp server,手动确认这个 GGUF 文件能被直接加载跑通;第二步,检查你配的 base URL,确认端口和路径正确,比如 LM Studio 默认是http://localhost:1234/v1,Ollama 是http://localhost:11434/v1;第三步,把 AI 工具那边的模型名和 server 里实际加载的模型名对齐,这个最容易忽视,名字对不上就是找不到 runtime。

3.2'aimv2' is already used by a transformers config, pick another name

这个报错是 Transformers 加载 GGUF 时比较有代表性的一个,说明 Transformer 在解析模型配置时发现命名冲突。通常发生在两种情况下:一是你使用的 repo 里既有原始 Transformers config,又带了 GGUF 文件,加载时 GGUF 的 metadata 和 config 里预注册的模型结构名撞了;二是某些多模块模型(比如带视觉塔的 VLM)里,内部模块的名字和已注册的 config 名重复。

解决办法也不复杂。优先试试不去手动传 config,只传gguf_file,让 Transformers 自己从 GGUF 文件读架构;如果还是要报错,就把冲突的 config 备份移走,只留一个;再不行,下载最新版 transformers,因为 GGUF 支持迭代很快,很多命名冲突是早期版本对某些架构解析不完善导致的,升级之后就消失了。我当时加载某个 Qwen2-VL 量化版时遇到类似问题,就是升级版本解决的,没有任何魔改。

3.3 加载成功但显存爆了,或者推理没变快

这是“文件小了,显存没小”的认知误区,前面已经说了一半。如果你按裸from_pretrained加载 GGUF,权重回到 fp16,那么一个 7B 模型照样占 14GB 显存,模型文件才 4GB,你肯定觉得不对劲。这时候先检查模型 dtype,加上quantization_config走 bitsandbytes 才是正道。

另外一部分人抱怨“为什么 Transformers 跑 GGUF 比 Ollama 慢”,这个其实正常。llama.cpp 是纯 C++ 推理引擎,针对量化权重做了大量底层优化,还把 KV cache、采样、并行都揉进了一套代码里;Transformers 是通用框架,加载 GGUF 本身就是“兼容更多场景”的取舍,不是性能竞赛。如果你追求极致的推理速度,继续用 Ollama 或者 llama.cpp 完全没问题,这次更新的意义在于“我不用为了用 Transformers 再去重新下载一份模型”,而不是“Transformers 要取代 llama.cpp”。

4. 本地模型不再二选一之后,场景怎么组合

4.1 Ollama、LM Studio、Transformers 终于可以共用同一个文件

以前我电脑里经常出现同一个模型的三个副本:一份 GGUF 放在 Ollama 里跑聊天,一份 GGUF 放在 LM Studio 里做 OpenAI 兼容服务,还有一份原始 safetensors 放在项目目录里给 Transformers 调。浪费磁盘倒是其次,关键是版本管理混乱,有时候三个副本的量化粒度还不一样,调出来的结果都对比不了。

现在 Transformers 能读 GGUF 之后,理论上你只需要维护一份 GGUF 文件。举例来说,我想把一个本地 GGUF 交给 Ollama 托管,只需要写一个 Modelfile:

FROM /models/qwen2.5-7b-instruct-q4_k_m.gguf

然后执行:

ollama create qwen-local -f Modelfile

Ollama 就会把这个 GGUF 注册成一个新模型。这条命令我以前只能用在“从 Ollama 官方库拉下来”的模型上,现在任何渠道下载的 GGUF 都能注册进去。LM Studio 就更简单了,图形界面里直接选 GGUF 文件就能加载。

于是你可以组成一条很顺滑的链路:用 Hugging Face 下载某个模型的 GGUF 量化版,扔给 Ollama 做本地 server,然后 Cursor、Continue.dev、Claude Code 这类工具统一通过http://localhost:11434/v1调用。你说它是二选一吗?根本不是了,是一套文件多处复用。

4.2 本地小模型在代码重构、日志分析里的实用姿势

热搜里有一条“grep 在本地小模型”,还有“如何使用本地 AI 模型重构 C# 项目代码”,这两个我都实测过,非常能说明本地模型的新玩法。

先说代码重构。以前我用 Cursor 接云模型做 C# 重构,总担心代码片段被传出去。现在直接用 Continue.dev 接 Ollama 里的 Qwen2.5-Coder 量化版,选中一段老代码,让模型给出重构建议,配合本地的grep、rg搜索项目内相似模式,完全离线干活。0.5B 那种小模型做简单注释补全还行,真正做重构建议,建议至少 7B 级别的量化模型,否则经常给出语法不完整的代码。

再说日志分析。本地小模型配合grep可以做成一个半自动排查流程:先用grep把日志里的 ERROR、Exception 行提取出来,丢给本地小模型做分类和根因归纳。以前这个活要么人工看几百行日志,要么把日志粘到网页端 AI 里;现在一条管道命令就搞定,还不用联网。这就是“grep 在本地小模型”的现实意义:检索靠传统工具,理解和归纳靠本地模型,两者互补,效果好得离谱。

4.3 ComfyUI 里的 GGUF 和多模态模型本地化

ComfyUI 也早就支持 GGUF 了,不过走的是专门的第三方节点(比如 comfyui_GGUF),把 GGUF 量化后的视觉语言模型加载进 ComfyUI 里做推理。热搜里那个“comfyui gguf”指的就是这条路。

我尝试过在 ComfyUI 里跑 Qwen2-VL 的 GGUF 量化版,做“图片输入 → 文字描述”的节点,效果挺惊艳的。一个多模态模型量化后体积能压到 4~5GB,放在一张消费级显卡上就能跑,比原来跑 fp16 多模态模型轻松太多。这也说明 GGUF 的支持范围不只是纯文本模型,视觉语言模型同样是重点。至于“本地部署视频模型”,现在主流视频生成模型走的是扩散模型路线,和 GGUF 的关联还不大,但多模态大模型统一量化分发的大方向是明确的,未来视频模型模型如果也进入 LLM + 扩散混合架构,GGUF 或类似的统一格式大概率会成为标配。

5. 这件事对本地模型生态的长期影响

5.1 “不用二选一”之后,工作流可以怎么走

我最喜欢的一个变化是:微调和量化之间不再有壁垒。以前如果你想本地跑一个微调后的模型,常规流程是:用 Transformers 微调出 safetensors,然后转成 GGUF,再放到 llama.cpp 里跑。中间转换工具偶尔会出新问题,比如某些新算子不支持,还要对着报错修半天。

现在 Transformers 能加载 GGUF,虽然目前还不能直接微调 GGUF 文件(加载后转成 torch 权重再做微调是可以的),但至少推理、评估、部署这条链路打通了。你想评估某个 GGUF 量化模型的实际效果,可以直接在 Transformers 里跑一段标准评测脚本,不需要再专门为 llama.cpp 写一套代码;你觉得某个量化模型表现不够好,也可以把它加载后接上 PEFT/LoRA 做轻量微调。这在以前是完全不敢想的操作,涉及两套生态的衔接成本太高了。

5.2 社区迭代速度比你想的快,随时留意新版支持

Transformers 的 GGUF 支持上线之后,社区迭代速度很快。最开始只支持 Llama、Mistral、Qwen 这些主流架构,后面陆续加了不少新模型。我个人的习惯是,每过一两个星期就看一下 release notes,重点看 “GGUF” 关键词出现在哪些模型架构的说明里,说不定你手里的冷门模型哪天就被支持了。

如果你要加载的模型架构还不支持,最简单的办法是继续用 llama.cpp 或者把 GGUF 转换回 safetensors(Hugging Face 官方有转换脚本)。但说实话,如果模型架构太新,官方转换脚本也未必能转得完美,这种情况就老实排队等支持就行。

从一个从业者的角度说,这次更新的意义不只是“多了一个加载格式”,而是让本地模型从“双轨制”慢慢走向“单文件多端通用”。磁盘上不用再囤好几份不同格式的模型副本,Ollama 用户和 Transformers 开发者讨论时,也不用再先确认对方用的是哪套格式。模型还是那个模型,但工具链的围墙倒了一面。

最后分享一个我现在的选择标准:如果只是纯聊天、追求速度,我直接用 Ollama 拉 GGUF,轻量省心;如果要写代码、接 Agent、做评估,我直接用 Transformers 加载同一份 GGUF,不再额外下载 safetensors。同一个模型、同一个文件、两种用法,这不就是“不用二选一”最大的意义么。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询