DeepSeek-V4 微调实战:基于 Megatron-SWIFT 的 LoRA/全参数训练、MTP 与 FP8 全流程指南
【免费下载链接】swiftUse PEFT or Full-parameter to CPT/SFT/DPO/GRPO 600+ LLMs (Qwen3.6, DeepSeek-V4, GLM-5.1, InternLM3, Llama4, ...) and 300+ MLLMs (Qwen3-VL, Qwen3-Omni, InternVL3.5, Ovis2.5, GLM4.5v, Gemma4, Llava, Phi4, ...) (AAAI 2025).项目地址: https://gitcode.com/GitHub_Trending/swift1/swift
MS-SWIFT 的 Megatron-SWIFT 模块已实现对 DeepSeek-V4(DeepSeek-V4-Flash / DeepSeek-V4-Pro 系列)的完整训练支持,涵盖 LoRA 微调、全参数微调与 RL 训练,并深度集成了 MTP(Multi-Token Prediction)、FP8 训练/导出、MoE 专家并行、Pipeline 并行、Packing/CP 等特性。本文以仓库内 DeepSeek-V4 训练支持文档 为主线,结合swift/megatron与swift/model的源码实现,完整演示环境安装、精度对齐验证、LoRA/全参数训练、FP8 训练与导出、以及 transformers/vLLM 双后端推理的端到端流程,帮助你在 Megatron 引擎上稳定跑通 DeepSeek-V4 的训练与部署。
一、支持范围与前置环境
1.1 支持的能力边界
目前 Megatron-SWIFT 支持 DeepSeek-V4 的**微调(SFT)与 RL(强化学习)**训练,关键特性包括:
- MTP(Multi-Token Prediction):通过
--mtp_num_layers启用,默认每层 1 个预测头; - FP8 训练与导出:支持 blockwise 等 FP8 recipe,可将训练后权重直接保存为 FP8;
- MoE 专家并行(EP)、Pipeline 并行(PP)、Sequence Packing与Context Parallel(CP);
- LoRA 增量权重保存与 Merge-LoRA:训练完成后同时产出 LoRA 增量与合并后的完整权重。
明确的限制:FP4 blockwise 训练暂时不支持,加载 FP4 权重时会被自动转换成 FP8/BF16;Tensor Parallel(TP)暂时不支持,需等待 Megatron-Core 侧支持。
1.2 版本要求与安装
训练 DeepSeek-V4 需要以下三个组件的特定版本配合:
- Megatron-LM:使用
dev分支(仓库在指定 commit 下完成过验证); - mcore-bridge:
main分支; - ms-swift:
main分支(即本仓库当前主线代码)。
pip install git+https://github.com/NVIDIA/Megatron-LM.git@dev pip install git+https://github.com/modelscope/mcore-bridge.git pip install git+https://github.com/modelscope/ms-swift.git # Megatron-LM 在以下 commit hash 下进行测试 # pip install git+https://github.com/NVIDIA/Megatron-LM.git@fd1121b8ff7e3a4f83a28d35aed172d7bc0260e1Packing/CP 等新特性依赖 mcore-bridge 与 ms-swift 的 main 分支代码,请务必保持三者版本同步更新后再开始训练。
二、精度对齐验证:训练前必做的 Transformers/Megatron 一致性检查
DeepSeek-V4 的 MoE 权重默认以 FP8/FP4 混合精度存放(源码见 swift/model/models/deepseek.py 中deepseek_v4模型族的注册与DeepseekV4ForCausalLM架构映射)。因此在正式训练前,需要先确认 Transformers 与 Megatron 两个引擎的 forward 输出完全对齐。
2.1 修改 Megatron-LM 源码(FP32 对齐测试用)
为了支持 FP32 精度对齐测试,需要注释掉 Megatron-LM 中megatron/core/transformer/experimental_attention_variant/dsa.py第 41-43 行的相关逻辑(该段代码会破坏纯 FP32 下的对齐)。修改完成后,即可用下面的 mini 模型脚本做对齐验证。
2.2 构建 4 层 mini 模型
创建一个 mini 版本的模型(4 层),核心思路是:用SafetensorLazyLoader惰性加载原始权重,跳过layers.4之后的所有层,并用Fp8Dequantizer把 FP8 权重转成 BF16 后重新保存:
import os import torch from modelscope.hub.file_download import model_file_download from safetensors.torch import safe_open from swift import safe_snapshot_download from mcore_bridge.utils import Fp8Dequantizer, SafetensorLazyLoader, StreamingSafetensorSaver model_id = 'deepseek-ai/DeepSeek-V4-Flash-Base' # 部分模型前几层是 dense、其余为 MoE,请按实际情况设置取值 model_dir = safe_snapshot_download(model_id, download_model=False) loader = SafetensorLazyLoader(model_dir) state_dict = loader.get_state_dict() saver = StreamingSafetensorSaver(save_dir=model_dir) fp8_dequantizer = Fp8Dequantizer() # Used to convert fp8 weights to bf16 def _open_file(self, filename: str): if filename not in self._file_handles: file_path = os.path.join(self.hf_model_dir, filename) tmp_dir = os.path.join(self.hf_model_dir, 'tmp') if not os.path.exists(file_path): file_path = os.path.join(tmp_dir, filename) if not os.path.exists(file_path): file_path = model_file_download( model_id=model_id, file_path=filename, local_dir=tmp_dir, ) self._file_handles[filename] = safe_open(file_path, framework='pt') return self._file_handles[filename] SafetensorLazyLoader._open_file = _open_file # monkey patch (lazy downloading) new_state_dict = {} for k, v in state_dict.items(): if k.startswith('layers.'): idx = int(k[len('layers.'):].split('.', 1)[0]) if idx >= 4: continue if k.endswith('.scale'): continue elif k.endswith('.weight'): weight_scale_inv = k.replace('.weight', '.scale') if weight_scale_inv in state_dict: v = fp8_dequantizer.convert(v.load(), state_dict[weight_scale_inv].load()).to(torch.bfloat16) new_state_dict[k] = v if isinstance(v, torch.Tensor) else v.load() for k, v in new_state_dict.items(): saver.add_tensor(k, v) saver.finalize()脚本要点:
SafetensorLazyLoader配合 monkey-patch 后的_open_file实现懒下载:仅在访问到某个分片时才从远端拉取,避免对齐测试下载全部约百 GB 权重;- 所有
.scale张量被跳过,.weight则按weight + scale反量化到 BF16; - 截断到前 4 层,权重文件体积大幅缩小。
2.3 修改 config.json
构建完 mini 权重后,还需要修改config.json三项内容:
| 配置项 | 修改值 | 说明 |
|---|---|---|
num_hidden_layers | 4 | 与截断后的层数保持一致 |
compress_ratios | [0, 0, 4, 128, 0] | 压缩率配置按 mini 模型调整 |
quantization_config | 删除 | 权重已反量化为 BF16,不再需要量化配置 |
2.4 运行对齐测试
创建test.py,设置SWIFT_TEST_CONVERT_PRECISION=1环境变量后,通过megatron_export_main将模型转为 Megatron-Core 格式并做精度对比:
import os os.environ['SWIFT_TEST_CONVERT_PRECISION'] = '1' from swift.megatron import MegatronExportArguments, megatron_export_main from swift import safe_snapshot_download model_id = 'deepseek-ai/DeepSeek-V4-Flash-Base' model_dir = safe_snapshot_download(model_id, download_model=False) if __name__ == '__main__': megatron_export_main( MegatronExportArguments( model=model_dir, to_mcore=True, attention_backend='flash', tensor_model_parallel_size=1, pipeline_model_parallel_layout='Et*3|t*1mL', pipeline_model_parallel_size=2, expert_model_parallel_size=2, mtp_num_layers=1, test_convert_precision=True, ))使用以下命令运行(4 卡):
CUDA_VISIBLE_DEVICES=0,1,2,3 torchrun --nproc_per_node=4 test.py对齐参数说明(对应 swift/megatron/arguments/megatron_args.py 中的参数定义):
pipeline_model_parallel_layout='Et*3|t*1mL':E表示 Expert 层、t表示 Transformer 层、m表示 MTP 层、L表示该段末尾带 Loss。|分隔不同的 PP stage。Et*3|t*1mL即 2 个 stage、共 4 个 Transformer 层加 1 个 MTP 层,与 2×2 的 PP×EP 并行度对应;mtp_num_layers=1:启用 1 层 MTP 预测头,对齐配置要求 MTP 层数与并行布局匹配;test_convert_precision=True:开启转换精度对比开关。
更多并行布局与自定义模型细节可参考仓库文档 自定义 Megatron 模型。
2.5 对齐结果判定
当终端输出与下图一致的精度对齐结果(Transformers 与 Megatron forward 输出逐层一致)时,说明环境与权重转换均无问题,可以进入训练阶段:
三、LoRA 微调:BF16 精度完整脚本与参数精讲
3.1 完整训练脚本
下面是 8 卡 BF16 精度 LoRA 微调脚本,训练完成后会同时保存LoRA 增量权重和Merge-LoRA 后的 BF16 完整权重:
PYTORCH_CUDA_ALLOC_CONF='expandable_segments:True' \ NPROC_PER_NODE=8 \ CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ megatron sft \ --model deepseek-ai/DeepSeek-V4-Flash \ --save_safetensors true \ --dataset 'AI-ModelScope/alpaca-gpt4-data-zh#1000' \ 'AI-ModelScope/alpaca-gpt4-data-en#1000' \ 'swift/self-cognition#1000' \ --model_author swift \ --model_name swift-robot \ --merge_lora true \ --load_from_cache_file true \ --add_non_thinking_prefix true \ --loss_scale ignore_empty_think \ --split_dataset_ratio 0.01 \ --tuner_type lora \ --lora_rank 16 \ --lora_alpha 32 \ --tensor_model_parallel_size 1 \ --expert_model_parallel_size 8 \ --micro_batch_size 4 \ --global_batch_size 32 \ --padding_free false \ --group_by_length true \ --recompute_granularity full \ --recompute_method uniform \ --recompute_num_layers 1 \ --moe_permute_fusion true \ --moe_grouped_gemm true \ --moe_shared_expert_overlap true \ --moe_aux_loss_coeff 1e-3 \ --num_train_epochs 1 \ --finetune true \ --cross_entropy_loss_fusion true \ --lr 1e-4 \ --lr_warmup_fraction 0.05 \ --min_lr 1e-5 \ --output_dir megatron_output/DeepSeek-V4-Flash \ --eval_steps 200 \ --save_steps 200 \ --max_length 4096 \ --dataloader_num_workers 8 \ --dataset_num_proc 8 \ --no_save_optim true \ --no_save_rng true \ --sequence_parallel true \ --mtp_num_layers 1 \ --attention_backend flash3.2 核心参数逐项解读
对照 swift/megatron/arguments/megatron_args.py 与 swift/arguments/base_args/template_args.py 的源码实现,将脚本中的关键参数分类说明如下:
模型与数据集
--model deepseek-ai/DeepSeek-V4-Flash:模型 id。仓库 swift/model/models/deepseek.py 中注册了deepseek_v4模型族,包括DeepSeek-V4-Flash、DeepSeek-V4-Flash-Base、DeepSeek-V4-Pro、DeepSeek-V4-Pro-Base及带日期后缀的Flash-0731、Pro-0813版本;--dataset '...zh#1000' '...en#1000' 'swift/self-cognition#1000':#1000表示每个数据集取前 1000 条,可同时混入多个数据集;--split_dataset_ratio 0.01:划分 1% 数据作为验证集;--model_author swift --model_name swift-robot:用于 self-cognition(自我认知)数据集对话模板替换;--load_from_cache_file true:复用数据集缓存,加速重复实验。
思考模式与损失策略(DeepSeek-V4 混合思考模型特有)
--add_non_thinking_prefix true:训练时在非思考(non-thinking)回复前添加提示前缀。该参数默认值为True,定义于 swift/arguments/base_args/template_args.py;--loss_scale ignore_empty_think:DeepSeek-V4 这类混合思考模型在模板层面会自动为loss_scale追加ignore_empty_think策略(源码见 template_args.py),用于跳过"空思考"样本的思考部分损失,避免模型被训练成只在思考标签里灌废话。
LoRA 配置
--tuner_type lora --lora_rank 16 --lora_alpha 32:LoRA rank 16、alpha 32(经典 1:2 比例);--merge_lora true:训练结束自动执行 Merge-LoRA,产出 BF16 全量权重(输出目录带-merged后缀)。
并行策略(DeepSeek-V4 为 MoE 模型,EP 是关键)
--tensor_model_parallel_size 1:当前版本 TP 暂不支持(见前文限制);--expert_model_parallel_size 8:专家并行度 8,DeepSeek-V4 的 MoE 专家分布在 8 个 rank 上;--sequence_parallel true:开启序列并行;--mtp_num_layers 1:启用 1 层 MTP。保存权重时,swift/megatron/init.py 会把该值写回num_nextn_predict_layers/mtp_num_hidden_layers配置字段。
显存与计算优化
--recompute_granularity full --recompute_method uniform --recompute_num_layers 1:全量重计算 + 均匀分布 + 每 PP stage 重算 1 层,以时间换显存。三个参数分别对应源码中的recompute_granularity(selective/full/none,默认selective)、recompute_method(uniform/block)与recompute_num_layers;--moe_permute_fusion true:融合 MoE token permutation 通信;--moe_grouped_gemm true:MoE 分组 GEMM(源码默认即为True);--moe_shared_expert_overlap true:共享专家与路由专家计算重叠;--moe_aux_loss_coeff 1e-3:MoE 辅助负载均衡损失系数,默认0.,训练时建议设为 1e-3 量级防止专家坍缩;--cross_entropy_loss_fusion true:融合 CrossEntropy 计算(源码默认True);--padding_free false:关闭 padding-free。注意源码中group_by_length与padding_free互斥(megatron_args.py),本脚本用group_by_length做长度分桶,因此必须显式关闭 padding-free;--attention_backend flash:FlashAttention 后端。
训练调度
--micro_batch_size 4 --global_batch_size 32:micro-batch 4,global batch 32,即梯度累积 8 步;--lr 1e-4 --lr_warmup_fraction 0.05 --min_lr 1e-5:LoRA 学习率 1e-4,5% warmup,最小 LR 1e-5;--max_length 4096:序列长度上限;--eval_steps 200 --save_steps 200:每 200 步评估与保存;--no_save_optim true --no_save_rng true:不保存优化器与 RNG 状态,显著减小 checkpoint 体积;--dataloader_num_workers 8 --dataset_num_proc 8:数据加载与预处理并行进程数;--save_safetensors true:以 safetensors 格式保存权重。
3.3 资源占用与训练曲线参考
8 卡 A 系列(BF16 + 上述重计算/并行配置)下的显存占用实测如下:
训练日志与损失曲线如下,可作为训练是否正常的判据:
四、进阶训练配置:PP 并行、全参数训练、Packing/CP 与 FP8
4.1 设置 Pipeline 并行(PP)
开启 PP 并行时,除了--pipeline_model_parallel_size外,必须额外设置--pipeline_model_parallel_layout。例如 2 路 PP:
--pipeline_model_parallel_size 2 \ --pipeline_model_parallel_layout 'Et*22|t*21mL' \布局字符串中E为 Expert 层、t为 Transformer 层、m为 MTP 层、L标记末尾 Loss 所在 stage。megatron_args.py中的_init_vpp_size会解析该布局,校验 stage 数能被pipeline_model_parallel_size整除,并据此推导虚拟 PP 大小(megatron_args.py)。
4.2 全参数微调(64 卡示例)
全参数训练同样受支持,核心调整是降低学习率并提高并行度。64 卡(8 卡 × 8 节点)示例:
--lr 1e-5 \ --min_lr 1e-6 \ --tensor_model_parallel_size 1 \ --expert_model_parallel_size 8 \ --pipeline_model_parallel_size 8 \ --pipeline_model_parallel_layout Et*5|t*5|t*6|t*6|t*6|t*5|t*5|t*5mL \该布局将约 42 层(含 MTP)分配到 8 个 PP stage,EP=8 与 PP=8 组合,共占用 8×8=64 卡。
4.3 Packing / Context Parallel(CP)支持
Packing/CP 能力随 mcore-bridge / ms-swift main 分支提供(Packing 参考 ms-swift 的 sequence packing 相关 PR、CP 参考 mcore-bridge 的 context parallel 相关 PR,二者均已合入 main 分支)。使用 CP 时需额外设置:
--sequence_packing_scheduler dp_balanced \ --cp_partition_mode contiguous \对应源码参数:sequence_packing_scheduler(可选dp_balanced/default_dynamic_cp)、cp_partition_mode(可选zigzag(默认) /contiguous),定义于 megatron_args.py。
4.4 FP8 训练与导出
设置以下参数即可开启 FP8 训练,训练结束后可直接把权重保存为 FP8:
--fp8_recipe blockwise \ --fp8_format e4m3 \ --fp8_param_gather true \参数与源码对应关系(megatron_args.py):
--fp8_recipe:FP8 量化方案,可选tensorwise/delayed/mxfp8/blockwise,默认delayed;DeepSeek-V4 权重本身为 blockwise 量化,训练/导出推荐blockwise;--fp8_format:FP8 格式,可选e4m3/hybrid;--fp8_param_gather true:FP8 权重按参数维度收集,是保存/导出 FP8 权重的前提。
FP8 使用建议:
- 推荐使用全参数训练,这样导出时权重即为完整 FP8 权重;
- 若要用LoRA + FP8,则只能保存 LoRA 增量权重(设置
--merge_lora false),并在之后用BF16 权重执行 Merge-LoRA。原因是 FP8 精度有限,LoRA delta 在 FP8 下会被舍入为 0,无法直接合并。完整可运行示例见仓库脚本 examples/megatron/fp8/lora.sh; - 保存权重时,swift/megatron/init.py 会删除原
quantization_config,并在fp8_recipe == 'blockwise'且开启fp8_param时写入 transformers 的FineGrainedFP8Config,同时为deepseek_v4模型额外写回expert_dtype字段('fp8'或None),保证导出后的 HF 权重可被下游框架正确加载。
五、训练后推理:transformers 与 vLLM
5.1 transformers 后端推理
训练完成后,使用swift infer即可对-merged全量权重做对话推理:
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ swift infer \ --model megatron_output/DeepSeek-V4-Flash/vx-xxx/checkpoint-xxx-merged \ --infer_backend transformers \ --enable_thinking false \ --max_new_tokens 2048--infer_backend transformers:使用 transformers 推理引擎;--enable_thinking false:关闭思考模式(DeepSeek-V4 的思考/非思考双模式通过模板开关控制);--max_new_tokens 2048:最大生成长度。
推理示例输出如下:
5.2 导出 FP8 权重供 vLLM 使用
vLLM 推理需要 FP4/FP8 精度的权重。下面先演示量化导出流程(注意:该量化过程会丢失 LoRA 增量信息,这里仅作为流程示例;实际生产建议使用 FP8 全参数训练并直接导出 FP8 权重):
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ NPROC_PER_NODE=8 \ megatron export \ --model megatron_output/DeepSeek-V4-Flash/vx-xxx/checkpoint-xxx-merged \ --output_dir megatron_output/DeepSeek-V4-Flash/vx-xxx/checkpoint-xxx-merged-FP8 \ --to_hf true \ --fp8_recipe blockwise \ --fp8_format e4m3 \ --fp8_param_gather true \ --mtp_num_layers 1 \ --expert_model_parallel_size 8--to_hf true表示把 Megatron-Core 权重转回 Hugging Face 格式(swift/arguments/export_args.py)。导出时需保持--mtp_num_layers、--expert_model_parallel_size与训练时一致,否则权重张量无法对应回 HF 布局。
5.3 vLLM 启动命令与避坑要点
导出 FP8 权重后,使用 vLLM 的 DeepSeek-V4 专用配置启动服务:
vllm serve megatron_output/DeepSeek-V4-Flash/vx-xxx/checkpoint-xxx-merged-FP8 \ --trust-remote-code \ --kv-cache-dtype fp8 \ --block-size 256 \ --enable-expert-parallel \ --tensor-parallel-size 8 \ --max-model-len 8192 \ --tokenizer-mode deepseek_v4 \ --tool-call-parser deepseek_v4 \ --enable-auto-tool-choice \ --reasoning-parser deepseek_v4vLLM 侧的关键点:
- 参数
--tokenizer-mode deepseek_v4、--tool-call-parser deepseek_v4、--reasoning-parser deepseek_v4均为 DeepSeek-V4 专用配置(工具调用解析与推理解析器); --kv-cache-dtype fp8配合 FP8 权重使用,--enable-expert-parallel开启专家并行;- 必须复制原始的
config.json并修改expert_dtype字段(与训练后导出的 config.json 保持一致),因为 transformers 的config.save_pretrained保存的文件与原始文件不同,vLLM 无法兼容直接保存出的文件(该逻辑对应 swift/megatron/init.py 对expert_dtype的写入); - 若启动时遇到 tilelang 相关问题,可到 ms-swift 仓库的 issue 区检索 tilelang 关键字排查(mcore-bridge 侧已包含 DeepSeek-V4 FP8 相关修复)。
六、模板对齐保障:仓库中的 DeepSeek-V4 专项测试
仓库为 DeepSeek-V4-Flash 提供了字节级模板对齐测试 tests/test_align/test_template/test_deepseek_v4_flash.py。该测试只加载处理器(tokenizer)而不加载权重(避免下载约 163 GB 分片),通过比对官方编码器(encoding/encoding_dsv4.py)的输出文件,逐字节验证 SWIFT 侧模板行为一致,包括:
enable_thinking=True/False与官方thinking_mode='thinking'/'chat'的对应;preserve_thinking=False与官方drop_thinking=True(默认)的对应;REASONING_EFFORT环境变量与官方reasoning_effort的对应;<think>R</think>C内容块与官方reasoning_content=R, content=C的对应;tool_call/tool_response与官方 assistanttool_calls/toolrole 的对应。
该测试同时确认 DeepSeek-V4-Flash 是纯文本模型(config 无 vision/audio 子配置、无多模态 tower),因此不存在多模态对齐路径。这为训练时的思考前缀、损失策略与工具调用模板提供了实现级保障。
七、总结
围绕 DeepSeek-V4,Megatron-SWIFT 提供了一条从精度对齐 → LoRA/全参数训练 → FP8 导出 → 双引擎推理的完整链路:训练前用 4 层 mini 模型 +test_convert_precision完成 Transformers/Megatron forward 对齐;训练中通过expert_model_parallel_size、pipeline_model_parallel_layout、mtp_num_layers、sequence_packing_scheduler/cp_partition_mode以及fp8_*参数组合实现 MoE 模型的高效并行与低显存训练;训练后则通过megatron export --to_hf产出兼容 vLLM 的 FP8 权重,配合deepseek_v4专用 tokenizer/tool-call/reasoning parser 完成部署。实际使用中请牢记三条边界:TP 暂不支持、FP4 训练暂不支持(自动降级 FP8/BF16)、LoRA+FP8 时不可直接 Merge-LoRA。
【免费下载链接】swiftUse PEFT or Full-parameter to CPT/SFT/DPO/GRPO 600+ LLMs (Qwen3.6, DeepSeek-V4, GLM-5.1, InternLM3, Llama4, ...) and 300+ MLLMs (Qwen3-VL, Qwen3-Omni, InternVL3.5, Ovis2.5, GLM4.5v, Gemma4, Llava, Phi4, ...) (AAAI 2025).项目地址: https://gitcode.com/GitHub_Trending/swift1/swift
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考