mistral.rs UQFF 格式全解析:从文件布局到分片加载的量化模型格式参考
【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs
UQFF(Universal Quantized File Format)是 mistral.rs 原生的量化模型文件格式,用于持久化预量化权重并实现免运行时转换的直接加载。本文以仓库 UQFF 格式参考文档 为主体,结合mistralrs-quant与mistralrs-core中的读写实现,完整讲解 UQFF 的目录结构、分片(shard)内部布局、混合量化类型的自描述机制、版本兼容规则与张量并行加载语义,帮助你理解 UQFF 文件到底是什么、如何生成、如何校验,以及加载器内部究竟做了什么。
使用提示:日常使用 UQFF 模型并不需要了解本文的底层布局——按 UQFF 使用指南 加载即可;本文面向需要排查问题、二次开发或深度理解格式的读者。
为什么需要 UQFF:设计目标与定位
UQFF 解决的核心问题是:让"量化一次、到处加载"成为可能。普通的 safetensors 模型在每次启动时都要经历 ISQ(in-situ quantization,原位量化)的运行时转换,既耗时又无法保证跨机器一致性;而 UQFF 把量化结果直接落盘,加载时跳过转换步骤。
由此衍生的三个设计约束,贯穿了 UQFF 的全部细节:
- 自描述(self-describing):每个量化层条目都携带格式标签与元数据,加载器无需外部清单即可确定每个张量的反序列化方式——这也是单个文件内可以混合多种量化类型的前提;
- 推理专用(inference-only):UQFF 只保存前向推理所需的权重,不包含优化器状态或训练元数据;
- 目录即分发单位:UQFF 的导出结果是一个自包含目录,单独的 shard 文件无法独立加载。
从实现上看,UQFF 的"规范实现"分处两端:读路径(reader 与张量编码)位于 mistralrs-quant/src/uqff(mod.rs、reader.rs、tensor.rs等),写路径位于 mistralrs-core/src/pipeline/isq.rs(write_uqff_artifacts与write_uqff_type等函数)。
导出目录结构:一份完整的 UQFF 资产包含什么
一个 UQFF 导出结果是一个目录,其中包含三类内容:
- 量化权重分片:一个或多个
<stem>-<shard>.uqff文件,存放量化层权重,例如q4k-0.uqff、q4k-1.uqff; - 残差 safetensors:
residual.safetensors,存放未量化张量,典型代表是各类归一化层(norm)与稠密词嵌入(dense embeddings); - 模型资产副本:从源仓库复制、使目录自包含的 JSON/模板文件,包括
config.json、tokenizer.json、tokenizer_config.json、generation_config.json,以及存在时一并复制的modules.json、chat_template.jinja、processor_config.json、preprocessor_config.json。
加载器(from_uqff)被指向一个或多个 shard 文件;residual.safetensors与上述 JSON 资产通过**同级路径查找(sibling-path lookup)**自动拾取——也就是说,加载器在 shard 文件所在目录内按约定文件名寻找配套文件,这正是"目录是分发单位"的直接体现:单独拷走一个 shard 而没有配套的 residual 与config.json是无法加载的。
Shard 内部布局:自描述层的字节级约定
每个.uqffshard 都是标准 safetensors 文件,其条目(entry)按命名约定组织。每一个量化层都通过一组相邻条目实现自描述:
| 条目名 | 类型 | 含义 |
|---|---|---|
<key>.weight | 原始数据 | 层数据本体:GGML 家族的原始块数据(raw blocks)、AFQ/MXFP4/FP8 的打包张量(packed tensors),或未量化回退层中的原生 safetensors 张量 |
<key>.weight.format | u8 标量 | 量化家族标签,加载器据此分发到对应的反序列化器(deserializer) |
<key>.weight.dtype/<key>.weight.shape | u32 | GGML 类型的附加元数据(块类型码 / 逻辑形状) |
<key>.weight.scales/.bits/.group_size | 依类型而定 | AFQ 家族的附加元数据(缩放、位宽、分组大小) |
<key>.bias | 张量 | 该层存在偏置时出现 |
其中<key>即层的权重路径,例如model.layers.0.self_attn.q_proj。源码 reader.rs 中的load_format读取<key>.weight.format的 u8 标量并转换为QuantizedSerdeType枚举(Gguf、Unquant、Hqq、Fp8、Afq、F8Q8、Mxfp4等),随后load_linear依据该枚举把反序列化分发到GgufMatMul、UnquantLinear、AfqLayer、FP8Linear、HQQLayer、MXFP4Layer等对应的deserialize_uqff实现。
此外,safetensors 的元数据中还包含信息性生产方字段:uqff.producer、uqff.producer.mistralrs.version、uqff.producer.mistralrs.git_revision。这些字段仅用于溯源(provenance),加载器不校验其内容。
MoE 专家层的三个规范键
MoE(Mixture of Experts)模型的专家层使用每个 block 三个规范键:
<...>.experts.gate_proj<...>.experts.up_proj<...>.experts.down_proj
三者各持一份堆叠权重,形状为[num_experts, out, in]。源码 mod.rs 中的QuantizedExpertKeys::new正是按{experts_prefix}.gate_proj/.up_proj/.down_proj构造这三个键名。值得注意的是,堆叠专家权重并非所有量化后端都支持:reader 在加载时若发现三阶(rank-3)堆叠权重搭配 HQQ、FP8 或 F8Q8 格式,会直接报错拒绝——这三种格式不支持"堆叠专家 gather",这一点有专门的单元测试uqff_rejects_stacked_backend_without_gather_on_load覆盖。
版本标量条目
每个 shard 集(shard set)的头部还会写入三个 u32 标量条目:uqff.version.major、uqff.version.minor、uqff.version.patch。这三个条目由 mod.rs 中的uqff_version_tensors()生成,当前仓库的版本常量为UQFF_VERSION_MAJOR = 1、UQFF_VERSION_MINOR = 2、UQFF_VERSION_PATCH = 0(见 mod.rs)。
混合量化:一个文件里为什么可以同时存在多种类型
因为每个层都自描述,单个 UQFF 文件天然允许混合多种量化类型。三种典型来源如下:
- Topology 固定的层:由 topology 配置 显式指定类型的层会保持其固定类型,例如在整体 Q4K 文件中把
lm_head钉在q8_0; - 敏感张量自动提精度:模型声明的语言 token 嵌入与输出头(output head)使用 量化类型参考 中记录的更高精度默认值。例如
afq4shard 集中,这些张量以 AFQ6 存储;q4kshard 集中则以 Q6K 存储。关键在于每个加载器都声明精确的路径,因此仅仅名称相似(如以embed_tokens、word_embeddings或lm_head结尾)的视觉、音频等辅助张量不会被隐式提精度; - 形状不支持的层按层回退:形状无法满足目标类型的层会单独回退。例如输入维度不能被 AFQ 分组大小整除的 AFQ 层,会以未量化形式存储。
混合类型的打包因子(pack factor)计算在 reader 中有一套保守逻辑:pack_factor会对所有层布局聚合取最小值,而pack_factor_for则返回单个键的精确值。相关单元测试(如mixed_uqff_uses_conservative_default_and_exact_per_key_factors)验证了嵌入层以 AFQ6/AFQ8 存储时,全局因子取嵌入层因子、单键因子精确到层的行为。
分片规则:10 GiB 软上限与按类型分片
写路径(writer)把张量流切分为<stem>-0.uqff、<stem>-1.uqff、……,每个 shard 的软上限为 10 GiB。若一次运行指定了多个 ISQ 类型,则每种类型生成一套独立的 shard 集(如q4k-0.uqff、afq4-0.uqff),但共享同一个residual.safetensors与同一批模型资产。
配套的 UQFF 使用指南 进一步说明:约定命名的 shard 共享前缀且以-0、-1结尾,如q4k-0.uqff与q4k-1.uqff,只需选择其中一个,加载器即可发现连续的 shard 集合。当uqff_report.json存在并声明了输出时,其 shard 列表具有权威性,允许使用自定义文件名。
版本兼容机制:major 严格、minor 向前兼容
每个 shard 集携带的三个 u32 版本标量是加载时兼容性判定的依据。UqffReader::open(见 reader.rs)的执行逻辑如下:
- major 不同 → 拒绝:报错并提示用
mistralrs quantize重新生成; - minor 新于当前构建支持 → 拒绝:报错提示文件由更新版本的 mistral.rs 写出,建议升级;
- 同 major 下 minor 更旧 → 接受:向后兼容;
- 完全没有版本条目 → 拒绝:判定为 pre-1.0 的旧文件。
同时open还会做跨 shard 的键一致性校验(validate_shard_tensor_keys):版本标量在所有 shard 中必须一致,任何重复张量键都会被拒绝并指出冲突文件。这些规则均有对应单元测试(uqff_reader_rejects_conflicting_versions_across_shards、uqff_reader_rejects_malformed_version_copies、uqff_reader_rejects_duplicate_tensor_keys_across_shards)。
版本演进的两个里程碑
- UQFF 1.1:引入内联的未量化线性条目(
weight.format = Unquant)。此前形状不支持量化的层权重需要挪进residual.safetensors;1.1 之后这类层可以直接以未量化条目内联在 shard 中,使混合文件保持完整。 - UQFF 1.2:量化后的 token 嵌入改为常规层条目存储,并从
residual.safetensors中省略其原始稠密权重。读者仍然接受 token 嵌入留在 residual 文件中的 UQFF 1.1 文件(向后兼容)。
兼容性红线:UQFF 1.x 与 pre-1.0 版本产出的文件不兼容。旧文件加载时会直接报错,请用
mistralrs quantize重新生成。reader 中甚至专门检测"所有键都形如数字"的旧式文件并给出明确提示(Pre-1.0 UQFF artifacts are no longer supported)。
张量并行下的加载语义:切片还是复制?
UQFF shard 中存储的是完整张量;在张量并行(tensor parallelism)场景下,每个 rank 在加载时切出自己的那部分,而非在文件中预分片。这一点从源码可以确认:
shard_range(mod.rs)把Shard(简单均分或显式偏移区间)解析为(dim, start, len)三元组;load_tensor_sharded(reader.rs)先在 CPU 上narrow出目标切片并contiguous(),再搬运到目标设备,确保设备只看到自己那份数据;- bias 的切分遵循
bias_shard语义:输入维被切分时偏置跳过(归约后由调用方补加),非输入维被切分时则嵌入匹配的偏置切片(BiasShard::Narrow)。
切分打包(packed)输入维需要块对齐(block alignment)。典型模型维度满足此要求;当对齐不成立时(出现在部分专家层),该 rank 会复制完整张量而非切片。块对齐量由shard_alignment(reader.rs)按类型返回:GGML 类型返回块大小、AFQ 返回 group size、MXFP4/F8Q8 返回 32、FP8 与未量化返回 1,而HQQ 明确不支持分片加载。
底层块数据的切片由slice_blocked_data(mod.rs)实现,支持沿末维(打包维,要求 start/len 均为块的整数倍)、外维与中间维切片,并有slice_blocked_last_dim、slice_blocked_outer_dim、slice_blocked_3d_middle_dim等测试覆盖。
从生成到校验:UQFF 的完整工作流
虽然布局参考文档聚焦于格式本身,但配合 UQFF 使用指南 可以拼出完整工作流。
生成 UQFF
# 从 safetensors 模型源量化导出 mistralrs quantize \ -m google/gemma-4-E4B-it \ --isq q4k \ -o gemma-q4k.uqff # 从本地 GGUF 文件量化导出(-f 推断 GGUF,-m 可省略) mistralrs quantize \ -f /path/model-BF16.gguf \ --isq q4k \ -o model-q4k.uqff # 从 GGUF 仓库导出(--quant 选输入产物,--isq 选输出 UQFF 格式) mistralrs quantize \ -m <gguf-repo> \ --quant 8 \ --isq q4k \ -o output/要点:--quant与-f互斥;--isq可重复或逗号分隔以一次生成多个变体(此时-o需传目录,数字简写如--isq 4会同时写出afq4.uqff与q4k.uqff);topology 钉住的层在每一个输出变体中都会保留。从 GGUF 生成的 UQFF 会保留源文件的 Q/K rotary 布局,若该布局为相邻(adjacent)形式,转换后动态 LoRA 与 X-LoRA 仍不受支持。
加载 UQFF
# CLI:-m 提供 tokenizer/基础模型解析,--from-uqff 接受文件名或简写/类型名 mistralrs run -m <repo> --from-uqff q4k-0.uqff# Python:from_uqff 接收 shard 文件名(或列表) from mistralrs import Runner, Which runner = Runner( which=Which.Plain( model_id="<repo>", from_uqff="q4k-0.uqff", ), )// Rust:UqffTextModelBuilder 接收基础仓库与首个 shard use mistralrs::UqffTextModelBuilder; let model = UqffTextModelBuilder::new("<repo>", vec!["q4k-0.uqff".into()]) .build() .await?;UQFF 模型在张量并行下同样可用:每个 rank 只加载量化权重中属于自己的切片。
元数据命令:report / verify / inspect
quantize还会在 UQFF 文件旁写出uqff_report.json,记录生成的变体、shard 名、各层存储格式、生产方版本与回退层。加载器在其存在时会用它解析量化名称与 shard 集合(含自定义文件名);无 report 的约定命名 UQFF 仓库仍可正常加载。
# 为现有产物扫描生成 report mistralrs uqff report -m gemma4_26b_a4b/ \ --write \ --base-model google/gemma-4-26B-A4B-it \ --repo-id mistralrs-community/gemma-4-26B-A4B-it # 对远程 HF 仓库生成 report(--quant 选择分组) mistralrs uqff report -m mistralrs-community/gemma-4-26B-A4B-it --quant afq3 --json # 发布前校验结构 mistralrs uqff verify -m gemma4_26b_a4b/ # 交互式浏览张量 mistralrs uqff inspect -m mistralrs-community/gemma-4-26B-A4B-it --quant afq3uqff report、uqff verify、uqff inspect均为仅元数据操作:对本地路径或已缓存的 Hugging Face 产物只做 seek-read 需要的字节区间;对远程 HF 仓库则使用 HTTP 字节区间请求(byte-range)读取 safetensors 头部与小体积 UQFF 元数据张量,不会下载完整模型权重。
注意事项与边界
- 推理专用:UQFF 不包含优化器状态或训练元数据,不可用于恢复训练;
- 目录即分发单位:
residual.safetensors与config.json是加载的必要配套,单独的 shard 无法加载; - HQQ 的限制:HQQ UQFF 产物不支持分片加载(
shard_alignment直接报错); - 堆叠专家限制:HQQ、FP8、F8Q8 格式不支持三阶堆叠专家权重的 gather,加载时会被拒绝;
- 旧文件不兼容:pre-1.0 文件(无版本标签或旧式键名)必须用
mistralrs quantize重新生成; - 存储扩张检查:reader 会校验各层驻留字节数不超过其稠密估计,否则提示使用等宽或更宽的模型 dtype 或显式设备映射(对应测试
uqff_rejects_storage_expansion_that_a_pack_factor_cannot_represent)。
延伸阅读
- UQFF 使用指南:生成与加载的完整命令手册;
- 量化类型参考:AFQ、Q*K、FP8、NVFP4、MXFP4、HQQ 各家族与敏感张量精度策略;
- 量化指南:格式选型与 imatrix 背景;
- Topology 指南:逐层钉住量化类型;
- 参考实现:mistralrs-quant/src/uqff(reader 与张量编码)、mistralrs-core/src/pipeline/isq.rs(writer);
- 完整示例:Rust 示例 uqff 与 multimodal uqff。
【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考