LLM 量化与 GGUF
把低比特权重与 metadata 封装成可部署模型包
建议阅读:约 18 分钟
学习目标
本章关键词
| 关键词 | 解释 | ESP32 工程类比 |
|---|---|---|
| GGUF | GGML 系执行器使用的模型容器格式。 | 像固件镜像加可扩展的描述区。 |
| Block quantization | 按块共享 scale 等参数的低比特编码。 | 像压缩一批采样值并附带该批量程。 |
| Weight-only | 只量化权重、激活保持较高精度的策略。 | 像压缩固件常量而保留计算工作区精度。 |
| mmap | 将文件映射到虚拟内存按需访问。 | 像按页读取固件资源,减少一次性复制。 |
承上:回顾与定位
上一章已经为逐 token 增长的 KV 状态建立容量账本;本章进一步压缩跨请求复用的权重,并把 GGUF metadata 视为可验证的模型包契约。
历史发展脉络
低比特模型的历史并不是把 float 简单截成整数。早期压缩研究已经把剪枝、量化与编码视作不同层次;LLM 时代又暴露出离群通道、层敏感度和专用 kernel 的问题。GGUF 则解决另一个维度:怎样把张量、量化类型和解释模型所需的元数据可靠装进一个可快速读取的容器。
Deep Compression 将量化放进系统化模型压缩流程
Deep Compression 把剪枝、训练后量化与 Huffman 编码组合起来,说明“位宽降低”只是压缩链路的一环。它也确立了重要工程习惯:压缩后必须回到任务精度与实际存储收益验证,而不能只报告理论 bit 数。
Deep Compression 原始论文 ↗LLM.int8 揭示大模型离群特征的代价
LLM.int8 观察到部分隐藏维度出现系统性大幅值,并以混合精度路径保留这些离群计算。这推动量化从“所有权重统一降位”走向按统计特征分流,也解释了为何同为 int8,不同算法的质量和 kernel 要求会明显不同。
LLM.int8 原始论文 ↗GPTQ 让超大模型的一次性权重量化更实用
GPTQ 使用近似二阶信息逐层量化权重,在无需完整重新训练的条件下把大模型压到 3 至 4 bit 区间。它强化了“误差需按权重相互作用补偿”的认识,也让校准样本与量化顺序成为部署产物的一部分。
GPTQ 原始论文 ↗GGUF 统一张量容器与可扩展元数据
GGUF 作为 GGML、GGMF、GGJT 的后继格式,用类型化键值元数据、对齐的 tensor 区和版本字段降低歧义,并面向 mmap 读取。它并不规定模型必须采用哪一种量化;同一容器中可以存放不同类型的张量。
GGUF 官方规范 ↗混合量化配方成为面向目标硬件的构建步骤
llama.cpp 的量化工具支持 K-quants、importance matrix 与按 tensor 覆盖类型,实践由选择单个“Q4”标签转向保留敏感张量、匹配 kernel、检查困惑度代理并在目标硬件测量。重新量化低比特文件也被明确视为高风险操作。
llama.cpp Quantize 官方文档 ↗类比图解
把量化模型想成装进航运集装箱的压缩调色板
原始 FP16 权重像画室里几万种细微颜料。量化时不是随手丢掉颜色,而是把相近色按一小块分组,为每块制作有限色卡;整数码是色卡编号,scale 与最小值是还原说明。敏感层像人物眼睛,可留用更细色卡。GGUF 则是带清单的集装箱:箱头记录架构、tokenizer 和对齐规则,货位表指明每块张量在哪里、用哪种编码,runtime 才能直接搬到正确 kernel。
类比的边界: 颜料类比没有体现矩阵乘 kernel:压缩率高并不自动加速,若硬件缺少对应解码与乘法实现,运行时可能先反量化再计算。感知上的“颜色接近”也不是语言模型质量;最终仍需困惑度或任务集、长文本稳定性和目标设备基准来判断。
本章讲解
先算真实 BPW,不要被 Q4 名字迷惑
块量化除低比特码值外,还要保存每块的 scale、min、对齐填充,有些格式又混用不同 tensor 精度,所以文件平均 bits per weight 通常不等于名称中的数字。验算时读取 GGUF tensor 类型和元素数,分别汇总数据字节与元数据开销,再与 FP16 基线比较。容量预算还要另加 tokenizer、KV cache 和 runtime workspace,模型文件大小不是峰值 RAM。
块大小决定压缩与局部适应能力
一组权重共享量化参数时,块越大,scale 开销占比越低,却越难同时覆盖小值和离群值;块越小,更能贴合局部范围,但额外参数、索引与 kernel 处理成本上升。per-tensor、per-channel 与 block-wise 不是抽象标签,而是在统计适配和存储访问之间选粒度。应查看目标格式的准确布局,不能拿通用公式硬套所有 Q4。
混合精度要由敏感度与 kernel 共同决定
嵌入、输出投影、注意力或某些 MoE tensor 对误差的敏感度并不一致,K-quants 的后缀往往表示一套混合配方。选择时从高精度 GGUF 生成多个候选,使用相同校准样本与任务集比较,并确认 backend 对其中每种 tensor type 都有高效 kernel。若少数层频繁回退或反量化,省下的带宽可能被边界转换抵消。
GGUF 是自描述容器,不是质量证书
加载器依据 magic、版本、alignment、tensor shape/type 和架构 metadata 解释文件,tokenizer 与 chat template 相关字段还决定输入语义。格式合法只说明字节可解析,不证明权重来源、量化过程或模型输出正确。部署前应保存源模型修订号、转换器 commit、量化命令与哈希,并用 dump 工具核对关键 metadata,防止“能打开但稳定答错”的静默故障。
建立不可逆转换的单向发布链
量化会丢失信息,从 Q4 再量化到 Q5 并不会恢复精度,反而加入第二轮舍入误差。工程仓库应保留可信 FP16/BF16 或官方原始权重,把转换和量化做成可重放构建:输入哈希固定、工具版本固定、产物另名输出。验收同时测文件大小、峰值常驻内存、PP/TG 速度、任务正确率和长输出异常,任一项退化都能追溯到配方。
动态过程演示
一份高精度权重如何变成可验证的 GGUF
动画把“转换容器”和“量化张量”分开显示,避免将格式、算法和最终部署性能混为一步。
冻结基线 · BF16/FP16 weights + tokenizer + revision
记录来源、许可证、哈希与基线输出
后续任何低比特产物都应可回溯到同一高精度起点
循环 / 返回条件: 若质量超限,回到“采集敏感度”扩大代表性样本或提高敏感 tensor 精度;若速度不升,回到“分块量化”检查 kernel 支持与反量化边界。始终从高精度基线重新生成,禁止串行重复量化。
查看静态全景图
FP16 tensor → blocks → quantized values + scales/mins → GGUF tensor + metadata → runtime kernel
代码或命令示例
python convert_hf_to_gguf.py ./model --outfile model-f16.gguf
llama-quantize model-f16.gguf model-q4_k_m.gguf Q4_K_M
llama-cli -m model-q4_k_m.gguf -p "hello"动手实验
实验记录与导出
工程陷阱
核心测试
完成 3 道单选题后提交;提交前不会显示答案。
在 GitHub 上讨论本章
登录 GitHub 后提问、补充实测或分享你的实现;评论会保存在本课程的 GitHub Discussions 中。
评论区需要 JavaScript;也可以直接打开 GitHub 讨论区: 打开 GitHub 讨论区 ↗
延伸阅读
启下:下一章如何使用本章能力
下一章把模型包真正交给 runtime 和端侧推理框架,检查加载、采样、调度、backend 分区、fallback 与取消路径。
下一天: Day 13 · LLM Runtime