[控场AI]
· 8 分钟阅读· 4,311 字

GGUF vs safetensors:格式不决定一切,运行时才是关键

GGUF vs safetensors:格式不决定一切,运行时才是关键

GGUF 与 safetensors 之争本质是运行时门禁选择,而非速度对决。

文章指出,GGUF 与 safetensors 的对比常被误读为性能竞赛,实则是一场“门禁检查”:格式决定你能使用哪些运行时。GGUF 是单文件量化容器,内嵌权重、分词器和聊天模板,适配 llama.cpp、Ollama、LM Studio 等;safetensors 是纯序列化容器,承载全精度张量,主打安全免 pickle 攻击,适配 transformers、vLLM、ComfyUI。同一 Qwen3-0.6B 模型,Q4_K_M GGUF 仅 397MB,BF16 safetensors 为 1.50GB。文章强调字节数可免费验证,但速度与质量需匹配基准,本文不提供。结论:先选运行时,格式自然确定;转换几乎不值得。

在模型部署的讨论中,GGUF 与 safetensors 的对决常常被简化为一场文件扩展名的擂台赛。但事实并非如此——这更像是一次门禁检查。选择 GGUF,llama.cpp、Ollama、LM Studio、Jan 等运行时的大门会为你打开;选择 safetensors,transformers、vLLM、ComfyUI 则成为你的舞台。格式本身只是决定哪些门会开启,而其余的一切都随之而来。

GGUF vs safetensors 文章截图

本文拒绝一个常见的谎言:即这场较量是由那些从未在同一台机器上验证过的速度数字决定的。我们真正能够免费获取、且多数争论所忽略的,是每种容器自身的重量,以及它们各自能在哪里被打开。

你究竟在选择什么?

GGUF 是由 llama.cpp 作者构建的单文件容器,量化以张量为单位直接嵌入其中——大家争论不休的量化阶梯只存在于这个格式内部。一个文件同时携带权重、分词器和聊天模板:文件本身就是分发单元。

Safetensors 则是一种序列化容器——一个 JSON 头部加上原始的字节张量——它承载训练仓库发布时的精度,通常是 BF16 或 FP16。它不进行量化,只负责存储。其命名源于唯一使命:确保在模型加载时不会被 pickle 反序列化攻击。Python 的 pickle 会在解包时执行代码;safetensors 不执行任何操作——这就是其全部安全主张,也是 Hugging Face 生态将其标准化原因。

用两种容器分别称量同一个模型,设计哲学便会在字节中显现。同一个 Qwen3-0.6B 模型,以不同格式发布时:Q4_K_M GGUF 为 396,705,472 字节(397 MB);BF16 GGUF 为 1,198,182,848 字节(1.20 GB);BF16 safetensors 为 1,503,300,328 字节(1.50 GB)。 量化容器的大小仅为全精度容器的四分之一,因为它只承载了四分之一的精度。而这些数字,只需一个 curl -I 命令就能在你的终端中验证,无需任何基准测试装备。缺失的精度是否会影响质量,则是一个字节无法回答的保真度问题。

格式不是一种偏好,而是能够打开你文件的运行时列表。

量化(Quantization) 是指将模型权重从高精度浮点数(如 FP16、BF16)压缩为低位宽表示(如 4位、8位整数),从而大幅缩小模型体积和内存占用。GGUF 格式中的 Q4_K_M 是一种混合量化方案:K 代表 k-quant 分块量化,M 代表中等质量档位,它在关键权重层保留较高精度、其他层使用 4 位,以在压缩率与输出质量之间取得平衡。量化通常在模型训练完成后进行(post-training quantization),因此不可避免地带来一定精度损失,具体影响取决于模型规模、任务类型和量化粒度。一个 0.6B 的小模型在 Q4 下质量下降可能比 70B 模型更明显,因为小模型本身冗余更少。

Pickle 反序列化攻击 是 Python 生态中长期存在的安全漏洞:pickle 格式在反序列化时可以执行任意代码,因此加载来自不可信来源的 .pt 或 .bin 模型文件等同于运行未知脚本。Hugging Face 曾发现过嵌入恶意 pickle 代码的模型仓库。Safetensors 的设计从根本上消除了这一攻击面——它只存储张量元数据和原始字节,加载时仅做内存映射,不执行任何代码。这也是 Hugging Face 将 safetensors 设为默认格式的核心动因之一,而非仅仅为了加载速度。

字节揭示了什么?

对于一个只读取记录的文章,诚实的规则是:只陈述记录中注明的数字,并注明出处,不做基准测试的伪装。下表是同一模型、三种容器的实际字节大小——在信任任何数据之前,请自行核实。

容器精度发布字节数占全精度比例
GGUF Q4_K_M4位量化396,705,472 (397 MB)26%
GGUF BF16全精度,llama.cpp 打包1,198,182,848 (1.20 GB)80%
safetensors BF16全精度,原始张量1,503,300,328 (1.50 GB)100%

无需基准测试装备,自行验证:

curl -sIL https://huggingface.co/unsloth/Qwen3-0.6B-GGUF/resolve/main/Qwen3-0.6B-Q4_K_M.gguf | grep -i content-length

对 BF16 和 safetensors 文件使用同样的命令——无论何时,字节数都清晰可查。

以诚实的方式解读表格:26% 是量化阶梯的全部承诺——用四位替代十六位,在磁盘和内存中都是如此。两行全精度数据之间的差距(1.20 GB 对 1.50 GB)是打包开销,而非物理定律:llama.cpp 的 BF16 打包比原始张量转储更精简地存储了相同的张量。然而,字节无法说明速度或质量;一个没有匹配基准环境的每秒令牌数列只是论坛噪音,本文拒绝提供这样的数据。

三道明确的墙:其一,质量——Q4 与 BF16 之间是保真度权衡,字节数无法衡量。其二,速度——加载时间和每秒令牌数属于在指定机器上匹配的基准测试,本文没有这样的条件,因此不提供任何数字。其三,规模——0.6B 模型的字节比例在 70B 模型上形态相似,但在 70B 上你将感受到的绝对等待时间,是在不同硬件上的另一篇文章。

打包开销(Packing Overhead) 指的是模型权重在存储时因对齐、元数据、张量布局等非精度因素产生的额外字节。GGUF BF16 比 safetensors BF16 小约 20%,原因是 llama.cpp 对张量进行了更紧凑的序列化打包,而 safetensors 保留了训练框架原始的张量布局和 JSON 头部。这种差异不影响模型精度,仅反映两种容器在存储效率上的设计取舍:GGUF 倾向单文件自包含与紧凑,safetensors 倾向与训练生态无缝对接。

每种格式实际上在哪里运行?

这才是真正起决定作用的部分。GGUF 可在 llama.cpp、Ollama、LM Studio、Jan 中打开——这是单文件本地生态系统。vLLM 通过其插件,也能在 GPU 上读取 GGUF,但存在一些注意事项。safetensors 可在 transformers、vLLM 原生环境、ComfyUI 以及 Apple 的 MLX 工具链中打开。边缘处的重叠颇具启发性:Ollama——这个基于 GGUF 引擎构建的应用程序——仍然提供 MLX 运行器,以便 Apple Silicon 用户加载源自 safetensors 的权重。即使是应用本身也在对冲赌注。

你已在运行格式自动选定原因
Ollama、LM Studio 或 llama-serverGGUF其引擎原生支持 GGUF;量化文件适合小磁盘
Python/transformers 流水线safetensorsfrom_pretrained 是原生路径;无需维护转换步骤
GPU 服务器上的 vLLMsafetensors原生支持,无需插件,无 GGUF 注意事项
ComfyUI 或图像流水线safetensors扩散生态系统使用 safetensors 检查点
小磁盘和小型设备GGUF Q4_K_M相同权重下 397 MB 对 1.50 GB

GGUF 将量化作为默认选项;safetensors 将全精度作为默认选项。这个默认值就是决策的大部分。

vLLM 的 GGUF 插件 允许 vLLM 在 GPU 上加载 GGUF 量化模型,但存在若干限制:并非所有量化类型都被支持,某些情况下需要手动指定 --quantization 参数,且性能表现与原生 safetensors 路径可能存在差异。该插件主要面向希望在 vLLM 高吞吐推理框架中使用量化模型的用户,但官方仍推荐 safetensors 作为 vLLM 的首选格式。理解这一区别有助于避免在 GPU 服务器上因格式选择不当而遭遇兼容性问题。

你应该部署哪一个?

在查看任何表格之前,先检查已安装的内容。如果机器能响应 ollama run,你就生活在 GGUF 的国度——选择 Q4_K_M 文件,别再阅读论坛。如果你的日常工作是 Python,或者你的服务层是 vLLM,那么 safetensors 从来就不是一个真正的选项;它是生态系统的母语。两种格式之间的转换是可能的,但几乎从不值得:每次转换都是权重可能悄然出现差异的新契机。

诚实原则:我已阅读记录,但未实际运行。 以上所有数字均来自本文发布当天拉取的已发布文件——没有基准测试装备,没有每秒令牌数的伪装。记录所确立的是权衡的形态——量化容器使用四分之一的字节,两个几乎不重叠的运行时,以及每一侧默认精度都在悄悄为大多数人做出决定。

没有人会因为速度而切换格式。他们为了某个功能而切换运行时,格式则作为入场券随之改变。

轮到你了

这是一次讨论优先的旅程,因此争论将转移到评论区。我的立场已摆在桌面上:先选择运行时,让格式随之而来。我预计会受到的反驳——即公平的比较需要先有一个具体的测试环境,然后才能有观点,以及大多数格式争论只是穿着伪装的运行时争论。

因此,有两件事值得争论:你的日常工具实际上是从哪个货架打开的?有没有人在真实任务中感受到 Q4 的质量下降,还是这只是论坛传说? 请说出运行时和模型名称;最有据可查的答案将决定下一篇文章的条款。

分享:

相关推荐