权重格式

safetensors 与 pickle 的安全差异、GGUF 是什么、以及各种量化格式怎么选。

作者 David更新于 第 3 篇(共 19 篇)

同一个模型在 Hub 上常有四五种格式。选错了要么下白工,要么跑不起来。这一篇把它们的关系理清。

两个正交的维度

          序列化格式                   数值精度
   ┌──────────────────────┐   ×   ┌────────────────────┐
   │ safetensors / .bin   │       │ fp32 / bf16 / fp16 │
   │ GGUF / ONNX          │       │ int8 / int4 / …    │
   └──────────────────────┘       └────────────────────┘
        「文件怎么存」                「数字有多精细」

这两件事经常被混为一谈。「GGUF」是格式,「Q4_K_M」是量化方案,一个 GGUF 文件里可以是 fp16 也可以是 int4。

序列化格式

safetensors —— 默认选它

[8 字节 header 长度][JSON header][紧密排列的张量数据]

设计目标只有两个:安全与快。

特性说明
不执行代码纯数据格式,加载时不可能运行任何东西
零拷贝加载可以 mmap,大模型加载明显更快
可部分读取能只读某几个张量而不加载整个文件

pytorch_model.bin —— 能避就避

它是 Python pickle。pickle 在反序列化时会执行代码——这不是 bug,是设计。

# 一个恶意的 .bin 文件可以在你 load 的瞬间做任何事
torch.load("innocent_looking.bin")     # 可能已经中招

这不是理论风险。 Hub 上出现过投毒的 pickle 权重,HuggingFace 因此专门做了扫描(模型页会显示 pickle 安全扫描结果)。

实践纪律:

  1. 有 safetensors 就绝不下 .bin。
  2. 万不得已要加载 .bin,用 torch.load(..., weights_only=True)(PyTorch 2.6+ 已默认如此)。
  3. 来源不明的仓库,别碰 pickle 权重。

这也是 safetensors 被造出来的全部原因。

GGUF —— llama.cpp 生态

单文件、自包含(权重 + tokenizer + 元数据全在一个文件里),为 CPU / Apple Silicon 推理优化。

Qwen3-8B-Q4_K_M.gguf     ← 一个文件,拷走就能跑

特点:

  • 一个文件搞定,不用管分片索引和 tokenizer 配置。
  • CPU 上快,支持部分层卸载到 GPU(-ngl)。
  • 通常由社区转换,常见发布者:unsloth、bartowski、Qwen 官方等。
  • 训练用不了——它是纯推理格式。

用法见 GGUF 路线。

其他

格式用途
ONNX跨框架部署、ONNX Runtime、移动端
MLXApple Silicon 专用(mlx-community/ 下有很多)
TensorRT-LLM engineNVIDIA 极致推理性能,需自己编译

数值精度

未量化

dtype字节/参数说明
float324训练精度,推理很少用
float162老卡(Turing 之前)用它
bfloat162现在的事实标准,动态范围大,不易溢出

fp16 与 bf16 都是 2 字节,但 bf16 更稳——它牺牲精度换指数范围,训练时不容易出 NaN。Ampere(RTX 30 系)及以后的卡都支持。

model = AutoModelForCausalLM.from_pretrained("org/model", torch_dtype="auto")

"auto" 会读 config.json 里的 torch_dtype,这是最省心的写法——比自己写死 torch.float16 好。

量化

把权重压到更少的位数,用精度换显存。

方案位数特点
bitsandbytes NF44transformers 里加两行就能用,微调(QLoRA)必备
GPTQ4 / 8需要校准数据,推理快
AWQ4激活感知,同位数下质量常优于 GPTQ
GGUF Q4_K_M 等混合llama.cpp 生态,CPU 友好

GGUF 的量化命名怎么读:

Q4_K_M
│ │ └── 尺寸档:S(小)/ M(中)/ L(大)
│ └──── K-quant 方法(比老的 Q4_0 质量好)
└────── 4 bit

不知道选哪个就选 Q4_K_M——它是体积与质量平衡得最好的一档,社区默认推荐。

显存充裕想要更好质量:Q5_K_M 或 Q6_K。极度受限:Q3_K_M,但质量下降开始明显。Q2 系一般不值得——省下的显存不多,质量损失很大。

量化损失有多大

粗略经验:

bf16  →  Q8     几乎无损
      →  Q6_K   损失很小
      →  Q5_K_M 轻微
      →  Q4_K_M 可察觉但通常可接受   ← 甜点
      →  Q3_K   明显
      →  Q2_K   严重

模型越大,量化越抗损。 70B 的 Q4 常常比 8B 的 bf16 更好用——同样的显存下,优先选「更大的模型 + 更狠的量化」,这是社区反复验证过的经验。

怎么选

你的目标是?
├── 在 GPU 上跑推理
│   ├── 显存够 → safetensors + bf16
│   └── 显存紧 → safetensors + AWQ/GPTQ 4bit,或 GGUF
├── 在 CPU / Mac 上跑 → GGUF(Q4_K_M 起步)
├── 要微调 → safetensors + bf16(QLoRA 时配 bitsandbytes 4bit)
└── 要部署成服务、追吞吐 → safetensors + AWQ,配 vLLM

GGUF 不能用来训练。 想微调就必须下原始的 safetensors 权重——见到有人下了 GGUF 再问「怎么微调」,答案是重新下。

反过来,微调完想在 CPU 上跑,需要合并 LoRA 后转换成 GGUF(llama.cpp 仓库里有 convert_hf_to_gguf.py)。

一个实际的例子

同一个 8B 模型,四种选择的对比:

选择体积能跑的硬件质量
safetensors bf16~16 GB24 G 显卡基准
AWQ 4bit~5.5 GB8 G 显卡轻微下降
GGUF Q4_K_M~5 GB纯 CPU 也行(慢)轻微下降
GGUF Q8_0~8.5 GBCPU / 小显卡几乎无损

8 G 显卡跑 8B 模型,靠的就是量化。 具体选型见按显存选模型。

小结

  • 格式与精度是两个维度,别混为一谈。
  • safetensors 优先——pickle(.bin)加载时会执行代码,是真实风险。
  • GGUF 是单文件推理格式,CPU/Mac 首选,不能训练。
  • dtype 写 torch_dtype="auto" 最省心;bf16 是现在的标准。
  • 量化不知道选什么就 Q4_K_M。
  • 同等显存下,大模型 + 重量化 通常优于 小模型 + 轻量化。

下一篇:命令行与登录。

本页目录