Qwen 昇腾 NPU 微调实战:基于 mindformers 的 7B/14B 全流程指南

原创2026-09-30 17:45:561,336 阅读
文章标签:人工智能大模型微调LoRA模型量化本地部署模型推理服务

Qwen 昇腾 NPU 微调实战:基于 mindformers 的 7B/14B 全流程指南

本文是 Qwen(通义千问)系列大模型在昇腾(Ascend)910A/B NPU 上完成微调的实操指南。文中基于当前仓库 recipes/finetune/ascend/README.md 的官方流程,结合仓库内 ascend-support 辅助脚本,完整覆盖「环境准备 → 模型下载与权重转换 → 训练数据预处理 → 分布式训练 → 权重合并 → 推理验证」的端到端闭环。读完本文,你将能够在昇腾 NPU 集群上独立复现 Qwen-7B / Qwen-14B 的微调训练,并对 mindformers 训练管线中的关键参数与底层机制有清晰认识。

适用范围与前提

本方案面向以下场景与约束:

  • 硬件:昇腾 910A / 910B 系列 NPU(即 Ascend 910A/B),通过 /dev/davinci* 设备节点接入容器。
  • 模型:当前官方验证支持 Qwen 7B 与 Qwen 14B 的微调和推理;本文以 Qwen-7B-Chat 为例展开。
  • 软件栈:基于阿里云 PAI 提供的 llm-inference 预构建镜像(内含 mindformers 框架),因此训练管线整体运行在 MindSpore 生态上,而非 PyTorch + CUDA。
  • 训练范式:mindformers 的多卡并行微调(8 NPU),以 chat 模型为对象进行指令微调。

说明:更详细、更新版本的 mindformers 昇腾用法可参考 mindformers 官方文档中 research/qwen 目录的说明;本文以本仓库固定版本的实际命令为准。

整体流程概览

整个微调链路可以划分为七个环节,与官方文档步骤一一对应:

  1. 启动带昇腾驱动的 Docker 镜像(打通 NPU 设备与驱动映射);
  2. 下载官方模型(ModelScope)并转换为 mindformers 的 ckpt 权重格式;
  3. 准备训练数据:原始 JSON → 对话格式 JSON → Mindrecord 二进制格式;
  4. 生成 RANK_TABLE_FILE,声明 8 卡 NPU 的拓扑关系;
  5. 以 run_qwen.py 启动 8 卡分布式微调;
  6. 合并多卡训练产出的分片权重;
  7. 用微调后的权重进行推理验证。

下面按步骤逐一展开,并补充源码级参数说明。

第一步:启动 Docker 镜像(打通 NPU 环境)

手动启动方式

昇腾设备无法在容器内热插拔,因此容器启动时必须把 NPU 设备、驱动、监控工具逐一映射进去。官方给出的完整命令如下:

ImageID=pai-image-manage-registry.cn-wulanchabu.cr.aliyuncs.com/pai/llm-inference:qwen_v23.0.rc3
docker run -it -u root --ipc=host \
--device=/dev/davinci0 \
--device=/dev/davinci1 \
--device=/dev/davinci2 \
--device=/dev/davinci3 \
--device=/dev/davinci4 \
--device=/dev/davinci5 \
--device=/dev/davinci6 \
--device=/dev/davinci7 \
--device=/dev/davinci_manager \
--device=/dev/devmm_svm \
--device=/dev/hisi_hdc \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /var/log/npu/:/usr/slog \
-v /etc/hccn.conf:/etc/hccn.conf \
${ImageID} /bin/bash

各挂载项的作用归纳如下:

参数 作用
--device=/dev/davinci0..7 映射 8 个 NPU 计算设备,对应微调所需的 8 卡资源
--device=/dev/davinci_manager 昇腾设备管理接口(Device Manager)
--device=/dev/devmm_svm 设备内存管理(SVM)节点
--device=/dev/hisi_hdc 昇腾 Host-Device 通信通道(HDC)
/usr/local/Ascend/driver 昇腾驱动库,容器内算子执行依赖
/usr/local/Ascend/add-ons/ 驱动附加组件
/usr/local/bin/npu-smi 等 NPU 状态监控工具 npu-smi
/etc/ascend_install.info 昇腾软件安装信息文件
/var/log/npu/ → /usr/slog NPU 运行日志目录映射
/etc/hccn.conf HCCN(华为集合通信库)配置,多卡通信依赖

使用仓库内置脚本快速启动

除了手动拼写上述长命令,本仓库在 ascend-support/docker_qwen.sh 中封装了一个等价脚本(该脚本面向推理场景,镜像为 qwenllm/qwen-mindspore:v23.0.RC3),用法如下:

cd /path/to/Qwen/ascend-support

# 下载模型到本地目录,例如 /path/to/Qwen-7B-Chat
CHECKPOINT_PATH=/path/to/Qwen-7B-Chat

# 启动 docker 容器
bash docker_qwen.sh -c ${CHECKPOINT_PATH}

脚本支持的参数:

  • -i / --image:指定镜像名,默认 qwenllm/qwen-mindspore:v23.0.RC3;
  • -c / --checkpoint:宿主机构模型权重目录,默认挂载到容器内 /data/qwen/models/Qwen-7B-Chat;
  • -n / --name:容器名,默认 qwen-mindspore;
  • -h:打印用法。

从脚本实现可以看出,它同样映射了全部 8 个 davinci 设备与驱动文件,与官方微调镜像的设备映射逻辑一致,可作为快速验证环境连通性的入口。

第二步:下载官方模型并转换权重

通过 ModelScope 下载模型

在容器内进入 mindformers 代码目录后,使用 ModelScope SDK 将 Qwen-7B-Chat 权重与代码下载到本地:

cd mindformers
python3 -c "from modelscope.hub.snapshot_download import snapshot_download; snapshot_download('Qwen/Qwen-7B-Chat', cache_dir='.', revision='master')"

下载完成后,模型目录下会包含权重文件、qwen.tiktoken 分词词表以及模型代码文件。qwen.tiktoken 是 Qwen 基于 tiktoken 的分词器词表,在后续数据预处理与微调启动时都需要显式指定(详见第三步与第五步)。

将 HuggingFace/ModelScope 权重转换为 ckpt

mindformers 的并行训练格式与 Transformers 的权重组织方式不同,必须先用官方转换脚本完成格式迁移:

python research/qwen/convert_weight.py \
    --torch_ckpt_dir Qwen/Qwen-7B-Chat \
    --mindspore_ckpt_path qwen-7b-chat.ckpt

mkdir -vp load_checkpoint/rank_0
mv qwen-7b-chat.ckpt load_checkpoint/rank_0/

要点说明:

  • --torch_ckpt_dir 指向第一步下载的原始模型目录;
  • --mindspore_ckpt_path 指定转换后 ckpt 的输出路径;
  • 转换产物必须放置到 load_checkpoint/rank_0/ 目录下,这是 mindformers 微调启动时加载预训练权重的默认约定路径;
  • 若在 ascend-support/README.md 描述的推理容器中执行,对应命令为 python3 /data/qwen/mindformers/research/qwen/convert_weight.py,转换结果输出在 ${CHECKPOINT_PATH}/qwen-7b-chat.ckpt。

第三步:准备训练数据(JSON → Mindrecord)

mindformers 的 run_qwen.py 训练入口直接消费 Mindrecord 二进制格式,因此原始对话数据需要经过两次转换。

3.1 下载演示数据集

官方提供了一份精简的 Alpaca 指令数据用于跑通流程:

wget -c https://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/alpaca_data_min.json

3.2 转换为对话(conversation)格式

python research/qwen/alpaca_converter.py \
    --data_path alpaca_data_min.json \
    --output_path alpaca-data-conversation_min.json

该脚本把 Alpaca 的 instruction / input / output 三字段结构重排为多轮对话列表,使其符合 Qwen ChatML 对话模板的训练习惯。

3.3 生成 Mindrecord 数据

python research/qwen/qwen_preprocess.py \
    --input_glob alpaca-data-conversation_min.json \
    --model_file Qwen/Qwen-7B-Chat/qwen.tiktoken \
    --seq_length 1024 \
    --output_file alpaca_min.mindrecord

关键参数:

  • --model_file:必须指向模型目录中的 qwen.tiktoken,保证切词与模型训练时一致(Qwen 分词器基于 tiktoken,与 SentencePiece 系分词器有本质区别,微调时对特殊 token 的处理需要格外注意,可参考仓库 tokenization_note.md 的说明);
  • --seq_length 1024:单样本截断/补齐的目标序列长度,实际训练时需根据显存与业务数据长度权衡;
  • --output_file:产出的 Mindrecord 文件路径,将直接传给微调命令的 --train_data。

第四步:生成 RANK_TABLE_FILE(8 卡拓扑)

mindformers 多卡并行依赖 RANK_TABLE_FILE 描述设备拓扑与 rank 映射。使用仓库自带的 hccl_tools.py 一键生成 8 卡配置:

# generate RANK_TABLE_FILE with 8 npu
python mindformers/tools/hccl_tools.py --device_num "[0,8)"
  • --device_num "[0,8)" 表示取物理设备编号 0~7 共 8 张 NPU;
  • 生成物通常为形如 hccl_8p_*.json 的文件,微调启动时需将其路径替换到命令中的 RANK_TABLE_FILE 位置(见下一步)。

第五步:启动 8 卡分布式微调

官方微调命令

export MS_ASCEND_CHECK_OVERFLOW_MODE=INFNAN_MODE
bash research/run_singlenode.sh "python3 research/qwen/run_qwen.py \
--config research/qwen/run_qwen_7b.yaml \
--load_checkpoint /mindformers/research/qwen/load_checkpoint \
--vocab_file Qwen/Qwen-7B-Chat/qwen.tiktoken \
--use_parallel True \
--run_mode finetune \
--auto_trans_ckpt True \
--train_data alpaca_min.mindrecord" \
RANK_TABLE_FILE [0,8] 8

参数逐项解读

参数 含义与取值
MS_ASCEND_CHECK_OVERFLOW_MODE=INFNAN_MODE 昇腾环境变量:开启 InfNaN 溢出检测模式,训练出现梯度溢出时打印告警,便于定位
--config research/qwen/run_qwen_7b.yaml 模型结构、优化器、学习率、训练步数等超参的 YAML 配置文件;微调 14B 时替换为对应的 run_qwen_14b.yaml
--load_checkpoint .../load_checkpoint 预训练权重所在目录,即第二步中放置 rank_0/checkpoint... 的 load_checkpoint 目录
--vocab_file tiktoken 词表路径,须与第三步预处理时使用的一致
--use_parallel True 开启分布式并行训练,配合 RANK_TABLE_FILE 使用
--run_mode finetune 运行模式:训练为 finetune,推理为 predict
--auto_trans_ckpt True 自动完成权重切分:将单份预训练 ckpt 按并行策略自动转换为各 rank 的分片,免去手工拆分
--train_data alpaca_min.mindrecord 第三步产出的 Mindrecord 训练数据
RANK_TABLE_FILE [0,8] 8 run_singlenode.sh 的入参:分别指定拓扑文件、使用的设备区间(0~7)与进程数(8)

关于 run_singlenode.sh:它是 mindformers 提供的单机多卡启动封装,内部会依据 RANK_TABLE_FILE 为每个 rank 设置 RANK_ID、DEVICE_ID 等环境变量,并依次拉起 8 个训练进程。若直接裸跑,等价于为每个 NPU 进程设置好环境后分别执行 run_qwen.py。

环境变量层面的一点提醒

与 PyTorch 微调脚本(仓库根目录 finetune.py 配合 DeepSpeed/FSDP 运行于 CUDA 环境)不同,本步骤属于 MindSpore 生态,参数体系完全不同——例如不设 --use_lora / --q_lora / --deepspeed 这类 PyTorch 侧参数,而是由 YAML 配置驱动训练行为。跨生态迁移时不要混淆两套入口。

第六步:合并模型权重

8 卡并行训练结束后,每个 rank 只保存自己负责的参数分片,需要先重命名再合并为完整权重。

6.1 重命名分片文件

cd output/checkpoint_network
mv rank_0/qwen_rank_0-network.ckpt rank_0/checkpoint_0.ckpt
mv rank_1/qwen_rank_1-network.ckpt rank_1/checkpoint_1.ckpt
mv rank_2/qwen_rank_2-network.ckpt rank_2/checkpoint_2.ckpt
mv rank_3/qwen_rank_3-network.ckpt rank_3/checkpoint_3.ckpt
mv rank_4/qwen_rank_4-network.ckpt rank_4/checkpoint_4.ckpt
mv rank_5/qwen_rank_5-network.ckpt rank_5/checkpoint_5.ckpt
mv rank_6/qwen_rank_6-network.ckpt rank_6/checkpoint_6.ckpt
mv rank_7/qwen_rank_7-network.ckpt rank_7/checkpoint_7.ckpt
cd ../..

注意:上述 mv 命令为官方文档给出的原始操作;实际执行时请确认目录结构一致后再进行,避免覆盖已有文件。

6.2 合并为完整权重

python mindformers/tools/transform_ckpt.py \
    --src_ckpt_strategy output/strategy  \
    --src_ckpt_dir output/checkpoint_network \
    --dst_ckpt_dir output/merged_model
  • --src_ckpt_strategy:训练时保存的并行切分策略文件(output/strategy),记录权重与 rank 的映射关系;
  • --src_ckpt_dir:重命名后的分片目录;
  • --dst_ckpt_dir:合并产物的输出目录(output/merged_model),后续推理直接使用其 rank_0/checkpoint_0.ckpt。

第七步:推理验证微调结果

合并完成后,使用与训练相同的入口、以 predict 模式加载合并权重进行验证:

python research/qwen/run_qwen.py \
    --config research/qwen/run_qwen_7b.yaml \
    --predict_data '比较适合深度学习入门的书籍有' \
    --run_mode predict \
    --load_checkpoint output/merged_model/rank_0/checkpoint_0.ckpt \
    --vocab_file Qwen/Qwen-7B-Chat/qwen.tiktoken \
    --auto_trans_ckpt False \
    --device_id 0

与训练命令的差异点:

  • --run_mode predict:切换为推理模式;
  • --predict_data:直接以字符串形式传入测试 prompt;
  • --load_checkpoint:指向合并后的 rank_0/checkpoint_0.ckpt;
  • --auto_trans_ckpt False:权重已是完整单份,无需再自动切分;
  • --device_id 0:单卡推理,只需指定一张 NPU。

若模型对 prompt 的输出符合微调数据所期望的指令跟随行为(例如回答风格、领域知识明显偏向训练数据),则说明微调链路闭环成功。

附:仓库内的昇腾推理辅助方案

除微调外,本仓库还提供了昇腾环境下的快速推理入口。在 ascend-support/README.md 中给出了与微调共享同一套 mindformers 生态的推理流程:

  1. 下载官方模型到本地后启动容器(bash docker_qwen.sh -c ${CHECKPOINT_PATH});
  2. 在容器内执行 python3 /data/qwen/mindformers/research/qwen/convert_weight.py 完成权重转换(输出 ${CHECKPOINT_PATH}/qwen-7b-chat.ckpt);
  3. 进入 /data/qwen/mindformers/research/qwen,设置 PYTHONPATH 后执行 python3 infer_qwen.py 进行推理。

该方案可作为微调前验证环境连通性、或微调后对比效果的辅助手段。

常见问题与注意事项

  • 设备映射缺失:容器内报 No device 类错误时,优先检查 docker run 是否完整映射了 davinci0~7、davinci_manager、devmm_svm、hisi_hdc 等设备节点;
  • 驱动版本不匹配:容器内昇腾算子无法执行时,核对宿主机 /usr/local/Ascend/driver 与镜像要求是否一致;
  • 权重转换失败:确认 --torch_ckpt_dir 指向的目录包含完整的模型代码与权重文件,且 revision 与模型版本匹配;
  • 数据格式错误:qwen_preprocess.py 报词表相关错误时,确认 --model_file 使用的是模型自带的 qwen.tiktoken;
  • RANK_TABLE_FILE 未替换:第五步命令中的 RANK_TABLE_FILE 需替换为第四步实际生成的文件路径,否则并行启动会失败;
  • 多卡权重不完整:合并前务必确认 output/checkpoint_network/rank_0~7 八个分片全部存在且命名正确。

相关资源

登录后查看全文
Qwen