量化五个参数,以及 NPU 场景为什么要关掉 `double_quantization`

2026-08-09

本文所有事实以 hiyouga/LlamaFactory 官方仓库 2026-08-09 的内容为准。我们没有安装、训练或部署过任何模型,文中数字均为仓库源码与文档里写着的值。

很多人以为 LlamaFactory 的量化配置是一大坨,实际上在 src/llamafactory/hparams/model_args.py 里,量化这一组只有五个字段。真正让人踩坑的不是字段多,而是它们和导出侧那几个同前缀的字段长得太像,以及其中一个字段的默认值恰好是 True——README 在 Ascend NPU 那节让你显式写一行关掉它,原因就出在这个默认值上。

五个参数,一次列全

以下每个默认值都来自 model_args.pyfield(default=...),逐字照抄:

参数默认值
quantization_methodQuantizationMethod.BNB
quantization_bitNone
quantization_type"nf4"
double_quantizationTrue
quantization_device_mapNone

五个里有两个默认是 None,一个默认是字符串 "nf4",一个默认是布尔 True,还有一个默认是枚举成员 QuantizationMethod.BNB

枚举这件事值得多看一眼。model_args.py 里不止这一处用枚举成员当默认:注意力那组的 flash_attn 默认是 AttentionFunction.AUTO,推理后端的 infer_backend 默认是 EngineName.HF。而在示例配置那一侧,examples/inference/qwen3_lora_sft.yamlinfer_backend 写的是字符串 huggingface,注释里给的四个取值是 [huggingface, vllm, sglang, ktransformers]。同一个字段,源码默认值记成枚举成员、YAML 里写成小写字符串,两处的字面形态本来就不是一套——所以核对默认值时看源码,写配置时照示例注释里给的取值抄。至于源码怎么把两者对上,那要读实现,我们没读,也不在这儿猜。

它们坐在哪一层:三处最容易混的地方

第一处:这五个字段全部在 model_args.py,不在 finetuning_args.py。仓库把超参按数据、模型、微调、生成、评测、训练、Megatron 桥接分成了 8 个文件放在 src/llamafactory/hparams/ 下,量化归”模型加载”这一层。所以它约束的是模型怎么被载进来,而不是训练用什么方法——finetuning_type(默认 "lora")、lora_rank(默认 8)那一批是另一层的事。

第二处,也是最容易写错配置的一处:quantization_bitexport_quantization_bit两个不同的字段。后者属于导出那一组,默认同样是 None,同组还有 export_quantization_dataset(默认 None)、export_quantization_nsamples(默认 128)、export_quantization_maxlen(默认 1024)。前缀带不带 export_,决定了这个值作用在加载模型的时候还是 llamafactory-cli export 的时候。复制别人配置片段时如果把前缀吃掉了,YAML 本身不会报你抄错了。

第三处quantization_device_map(默认 None)和模型加载那组的 device_map(默认也是 None)是两个字段,名字只差一个前缀。README 的 Optional 依赖表里 bitsandbytes 一行标的是 Minimum 0.39.0、Recommend 0.43.1,量化这条路径上的依赖版本以那张表为准。

还有一处不在 model_args.py 里、但名字里同样带 quantization_bit 的:finetuning_args.py 的偏好对齐那一组有 ref_model_quantization_bitreward_model_quantization_bit,默认都是 None,它们各自跟着 ref_model / reward_model(默认都是 None)和对应的 *_adapters 字段走。换句话说,“量化位数”这个概念在这个仓库里一共出现在四个字段上:主模型、导出、参考模型、奖励模型。四个默认值全是 None,四个作用对象各不相同。

真要确认自己写的某一项落在哪一层,最省事的判定动作是回 src/llamafactory/hparams/ 下按文件名找:模型加载相关的去 model_args.py,训练方法相关的去 finetuning_args.py,生成相关的去 generating_args.py,评测相关的去 evaluation_args.py。找不到,说明你记的那个名字在当前版本里可能压根不存在,别继续照着改配置。

quantization_bit 默认 None:和 quantization_method 分开看

这一项默认 None,意思很朴素:源码没有给它预设任何位数,你不显式写,配置里就没有位数值。而同一组里的 quantization_method 默认已经是 QuantizationMethod.BNB,是个有具体落点的枚举成员。两件事得分开看——“方法这一项有默认值”和”位数这一项也有默认值”不是一回事。至于 quantization_bitNone 时代码具体怎么走,那要读实现,我们没读,不推断。

顺带把 README 那边的口径对上。README 的 Features 里,Scalable resources 一条写的是 16-bit 全参微调、freeze-tuning、LoRA,以及通过 AQLM、AWQ、GPTQ、LLM.int8、HQQ、EETQ 实现的 2/3/4/5/6/8-bit QLoRA。也就是说,README 层面枚举了多种量化后端,而源码里 quantization_method 的默认落点是 BNB 这一个。这两句都是各自出处的原话,我们只做并列陈述,不推断哪种后端对应哪个参数组合,也不推断为什么默认选它——那需要读实现,我们没读。

仓库的 examples/ 下确实单列了一个 examples/train_qlora/ 目录,README 在 NPU 那节点名的 qwen3_lora_sft_bnb_npu.yaml 就是这个路径下的文件。examples/README.md 的 QLoRA Fine-Tuning 一节列了五条配方,其中只有”4/8-bit Bitsandbytes/HQQ/EETQ 量化下的监督微调”那一条被 README 标了 (Recommended),GPTQ、AWQ、AQLM 三条没有这个标注——这是 README 自己的标注,不是我们的判断,也别把它读成”其余三条不能用”。

NPU 那条提示:README 让你写的那一行,和源码默认值的关系

README 的折叠块里给 Ascend NPU 用户的提示只有一句:在配置里设 double_quantization: false,并给了参考示例 examples/train_qlora/qwen3_lora_sft_bnb_npu.yaml

把这句话和上面那张表放在一起看,事情就清楚了一半:

double_quantization: false

double_quantization源码默认值是 True。这意味着如果你什么都不写,它就是开着的。所以 README 那条提示不是”NPU 上多加一个开关”,而是”NPU 上需要显式把一个默认开着的东西关掉”——不写这一行,等于选择了默认值 True。这是本篇唯一一处可以确定的因果:那条提示之所以必须存在,是因为默认值不是 false

至于”为什么在 NPU 上要关”,README 没有给出理由,我们也没有在 NPU 上跑过任何训练,所以这里就停在这儿,不去推断是内核实现、算子支持还是别的什么。任何声称知道原因的说法,都需要有能核对的出处,而这条提示本身没提供。

有一点要提醒:这条提示的适用范围就是 README 写明的那个场景(Ascend NPU)。它不是一条通用建议,别把 double_quantization: false 当成默认该写的一行抄进所有配置里。

显存表里和量化直接相关的三行

README 有一张 Hardware Requirement 表,整张表另有一篇专门讲,这里只取与量化直接相关的三行——因为它们是这五个参数在文档侧唯一对应得上的量化档位:

方法Bits7B14B30B70BxB
QLoRA / QOFT810GB20GB40GB80GBxGB
QLoRA / QOFT46GB12GB24GB48GBx/2GB
QLoRA / QOFT24GB8GB16GB24GBx/4GB

读这三行有两个硬限定,缺一条都会读歪。

第一,这张表在表头上方被 README 自己标了 * estimated(估算)。它不是实测占用,我们也没有跑过任何一次训练,所以这里只转述表里写的数字,不推导”你那张卡够不够”。

第二,2-bit 那行的 70B 格子写的是 24GB,而同一行通用列给的系数是 x/4,按系数算是 17.5GB。两处对不上。这是表里可核实的差异,如实指出到这一句为止——哪个数是对的、为什么会这样,我们不推断,也不拿它评价什么。

合并 LoRA 时那句全大写的 DO NOT

量化这一组还牵着一条明确的操作禁令。examples/merge_lora/qwen3_lora_sft.yaml 顶部有一行原文注释:

### Note: DO NOT use quantized model or quantization_bit when merging lora adapters

翻成中文就是:合并 LoRA 适配器时,不要使用量化模型或 quantization_bit。这句话是仓库自己用全大写写的,属于示例文件里少见的强措辞,也是这五个参数中 quantization_bit 唯一一处被明文限制使用场景的地方。同一个示例文件里,export_size5export_devicecpu(注释里写了可选 [cpu, auto])、export_legacy_formatfalse,这三项与源码默认值一致。

那到底该不该开、开几 bit

不写。该不该量化、选哪种 quantization_methodquantization_bit 填几,取决于你的模型、数据和硬件,官方没给通用值,我们也没有任何本机运行依据可以支撑一个推荐值。这一篇能给你的确定性只有三条:五个字段的确切名字和默认值、它们和导出侧同前缀字段的分界、以及 NPU 那条提示与 double_quantization 默认 True 之间的对应关系。

真要动手,先用 llamafactory-cli train -h 把当前版本的实际参数列表打出来对一遍。源码默认值会随版本变,本文的核对日是 2026-08-09。


本文依据 LlamaFactory 官方仓库(github.com/hiyouga/LlamaFactory)的 README、data/README.mdexamples/ 下的配置与 src/llamafactory/hparams/ 的参数定义整理,核对日 2026-08-09。本文内容为仓库源码与文档口径,我们没有安装、训练或部署过任何模型,文中显存数字均为官方标注的估算值(README 原文标 * estimated)而非实测占用。参数与默认值随版本变动,请以 llamafactory-cli train -h 的实际输出为准。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。