【免费下载链接】DeepSeek-V4-Flash-nvfp4-DSpark
📦DeepSeek-V4-Flash-nvfp4-DSpark是 NVIDIA 基于 Model Optimizer 量化(NVFP4)的 DeepSeek-V4-Flash MoE 模型,并内嵌了 DeepSeek 官方的 DSpark 投机解码头。想把它跑在自己的多张 GPU 上?本文带你用 convert.py 把 HF 权重转换成多卡推理格式,并讲透 MXFP4→NVFP4 无损 Cast 的原理。
为什么要做权重转换?
模型目录下的 46 个model-00001-of-00046.safetensors分片,是 Hugging Face 格式——它们面向"单进程全量加载",和推理框架(如 vLLM)搭配即可使用。而本项目自带的极简多卡推理引擎(generate.py + model.py)则期望每张卡只加载属于自己的那一片,文件名形如:
model0-mp4.safetensors model1-mp4.safetensors model2-mp4.safetensors model3-mp4.safetensorsconvert.py就是中间的"桥梁",它一次性做三件事:
| 步骤 | 做了什么 | 说明 |
|---|---|---|
| 🏷️ 命名转换 | HF 权重名 → 推理引擎权重名 | 只改键名,数值不动 |
| ✂️ 张量并行切分 | 按--model-parallel把权重切成 MP 份 | 专家按编号分、dense 权重按维度切 |
| 🔁 专家 Cast(可选) | MXFP4 → NVFP4 无损转换 | 让目标模型与 DSpark 草稿头共用一套量化配置 |
💡 关键认知:这不是重新量化,也不是微调。转换前后模型的计算结果一致,改变的只是"权重的组织与打包方式"。
HF 目录(46 个分片 + tokenizer) │ convert.py:改名 → 切分 → cast ▼ model{rank}-mp{mp}.safetensors × MP │ torchrun 多卡加载 ▼ generate.py 交互式对话 / 批量推理转换规则拆解:命名映射、专家切分与 dense 层切分
打开 convert.py,三条核心规则一目了然。
1️⃣ 命名映射:HF 名字 → 推理引擎名字
脚本里的mapping字典(inference/convert.py)把 HF 命名翻译成推理引擎的内部命名,例如q_proj → wq、kv_a_proj_with_mqa → wkv_a、gate_proj/up_proj/down_proj → w1/w3/w2、lm_head → head。另外还有几处直接替换:self_attn → attn、mlp → ffn、weight_scale_inv → scale(inference/convert.py)。
只改键名,数值完全不动——所以这一步没有任何精度变化。
2️⃣ 张量并行切分:MP 张卡,每人一份
- 专家权重(MoE FFN):模型共有256个路由专家(见 inference/config.json 的
n_routed_experts)。--model-parallel 4时,第 i 张卡只保留编号落在[64i, 64i+64)区间的专家(inference/convert.py)。专家之间彼此独立,"编号连续分配"即可保证均匀。 - Dense 投影层:
wq、wq_b、wkv_b、w1、w3沿行方向切分,wo、w2沿列方向切分(mapping表中的dim=0 / dim=1,inference/convert.py)——这是标准的张量并行布局:列切后各卡算出的部分和,在列切侧做 all-reduce 合并。 - 公共权重:
attn_sink、weights_proj、共享专家等不在mapping中指定维度,不切分,每张卡保留完整副本。
3️⃣ Tokenizer 随附拷贝
转换结束后,tokenizer.json与tokenizer_config.json会被自动拷贝到输出目录(inference/convert.py),这样输出目录就是一个"自包含"的推理目录,generate.py加载模型和 tokenizer 时只用指向它一处。
原理篇:MXFP4 → NVFP4 无损 Cast 到底"无损"在哪?
这是convert.py里最精彩的部分(cast_e2m1fn_to_e4m3fn,inference/convert.py)。先交代背景:
- MXFP4:4-bit 浮点值(e2m1)+32 元素一组的 scale,scale 用 e8m0(只有指数的 8-bit 格式,即 2 的整数次幂)。DSpark 草稿头里的 256 个专家在官方发布时就是这个格式。
- NVFP4:同样是 e2m1 的 4-bit 值,但16 元素一组,组 scale 用 e4m3 浮点。本 checkpoint 主干(43 层 MoE 专家)就是这个格式,见 hf_quant_config.json。
由于两者"值域"一致(4-bit 值能表示的数完全相同),只换 scale 的打包方式即可逐位无损地转换。实现分四步:
- 解包 + 查表:MXFP4 权重以 int8 存储、一字节打包 2 个 4-bit 值。脚本把它们拆成高低两个 nibble,查一张 16 项查找表
FP4_TABLE(inference/convert.py),还原出 e2m1 的全部取值:±0.5, ±1, ±1.5, ±2, ±3, ±4, ±6与 0。 - 重排分块:把权重组重排成
128 × 128的小块(bOut × 128 × bIn × 128),并把每 32 个值共享的 MXFP4 scale 广播到对应的 4-bit 值上,实现 128 元素块内逐值对齐。 - 归一化偏移:对每个 128 元素块,取块内 scale 的最大值右移 6 个偏移比特,算出块内每个 scale 相对最大值的比例。因为 MXFP4 的 scale 是 2 的整数次幂,这个比例永远是 2 的整数次幂,乘回 4-bit 值上时没有任何舍入。
- 写回 e4m3:偏移后的值量化为 e4m3。为什么乘数上限取
2^6?因为 e2m1 最大绝对值是 6.0,而6.0 × 2^6 = 384 < 448(e4m3 的表示上限),2^7就会溢出(inference/convert.py)。新的块 scale 再以 e8m0 存出。
整条链路只有"精确嵌入(e2m1 ⊆ e4m3 的表示范围)+2 的幂缩放"两类操作,每个数值转换前后严格相等——这就是"无损"的含义。🎯
📌 两种专家格式怎么选?
- 默认(不加参数):专家权重保持 int8 打包的 e2m1 原样(直接按
float4_e2m1fn_x2视图读取,inference/convert.py),原生 MXFP4 语义,零改动。--expert-dtype fp8:走上面的无损 cast,专家变成 e4m3 + e8m0 的块量化格式。数值完全相同,只是存储格式统一成了 NVFP4 风格。inference/README.md 提示:使用该选项时,需同步删掉 config.json 里的"expert_dtype": "fp4"。
实操:一键转换与多卡推理完整命令
第一步:转换 HF 权重(CPU 即可,无需 GPU)
export EXPERTS=256 # 模型的路由专家数,本模型固定 256 export MP=4 # 模型并行卡数,须能整除 256 export CONFIG=config.json python convert.py \ --hf-ckpt-path ${HF_CKPT_PATH} \ --save-path ${SAVE_PATH} \ --n-experts ${EXPERTS} \ --model-parallel ${MP}运行结束后,${SAVE_PATH}里会生成model0-mp4.safetensors…model3-mp4.safetensors以及拷贝过来的 tokenizer 文件。
第二步:多卡交互式对话
torchrun --nproc-per-node ${MP} generate.py \ --ckpt-path ${SAVE_PATH} \ --config ${CONFIG} \ --interactive启动后输入/exit退出对话。
第三步:批量推理 / 多机部署
从文件批量推理:
torchrun --nproc-per-node ${MP} generate.py \ --ckpt-path ${SAVE_PATH} --config ${CONFIG} --input-file ${FILE}多机推理(NCCL 跨机通信,见 inference/generate.py):
torchrun --nnodes ${NODES} \ --nproc-per-node $((MP / NODES)) \ --node-rank ${RANK} \ --master-addr ${ADDR} \ generate.py --ckpt-path ${SAVE_PATH} --config ${CONFIG} --input-file ${FILE}完整命令与参数说明见 inference/README.md。
常见问题速查 ⚠️
| 现象 | 原因与对策 |
|---|---|
| 加载分片报"文件不是合法 safetensors" | 46 个分片可能还停留在 Git LFS 指针状态(文件仅几百字节),请确认大文件已完整拉取 |
Number of experts must be divisible by model parallelism | --model-parallel必须整除--n-experts(如 4、8、16、32、64、128、256) |
启动时缺model{rank}-mp{mp}.safetensors | 推理的卡数必须与转换时的--model-parallel一致,generate.py按model{rank}-mp{WORLD_SIZE}.safetensors精确取名(inference/generate.py) |
| 精度与官方不一致 | 先检查EXPERTS是否为 256,以及是否误改了 config.json 中的维度参数 |
🔁 小提示:转换是幂等的——同一输入重复运行
convert.py会得到相同结果(权重数值不变,只是重新切分与打包)。产物文件可以直接用 safetensors 工具打开抽查张量名与形状。
写在最后
回顾整条链路:convert.py把 HF 的 46 个分片,按"改名 → 切分 → cast"三步,变成 MP 张卡各自专属的切片文件;其中专家权重按编号均匀分配,dense 层按标准张量并行布局切分,MXFP4 专家则借"精确嵌入 + 2 的幂缩放"实现逐位无损的 NVFP4 转换。转换完成后,torchrun拉起 generate.py,对话即刻开始。
仓库结构速览:
- 权重转换与推理:inference/(convert.py 转换脚本、model.py 模型定义、kernel.py 自定义 GEMM/注意力 kernel、config.json 模型配置)
- 对话编码格式:encoding/(encoding_dsv4.py 官方编码参考实现)
- 量化配置:hf_quant_config.json
掌握这套流程后,你不仅能让本模型跑在多卡上,同样思路也适用于其他"MoE + 分组量化"模型的权重切分与格式迁移。🚀
【免费下载链接】DeepSeek-V4-Flash-nvfp4-DSpark
相关推荐
OHIF 3.11 ToolbarService 迁移指南:从 ViewportActionCornersService 到统一工具栏体系
OHIF 3.11 ToolbarService 迁移指南:从 ViewportActionCornersService 到统一工具栏体系 导读 本文是 OHI
人工智能大模型基础模型模型量化DeepSeek用免费开源天气API做应用:Open-Meteo 实用指南
用免费开源天气API做应用:Open Meteo 实用指南 Open Meteo是一款免费的开源天气API,为天气预报应用、智能家居等场景提供无需API密钥的气
大模型模型量化DeepSeekSDR++:把整片频谱装进桌面的跨平台软件定义无线电接收利器
SDR++:把整片频谱装进桌面的跨平台软件定义无线电接收利器 SDR++ 是一款跨平台的软件定义无线电软件,让你在电脑上实时接收并解码各类无线电信号。它最核心的
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考