多模态模型预训练可提升跨模态理解与泛化能力,优化下游任务表现,适用于图像描述、视觉问答等跨模态任务。本方案以LLaVa多模态数据集和Qwen2-VL-7B-Instruct模型为例,介绍从数据准备、多模态模型预训练到服务部署的完整流程。
背景信息
本方案使用开源数据处理工具(Data-Juicer)进行数据预处理,使用开源的训练工具(Pai-Megatron-Patch)进行多模态模型训练:
Data-Juicer内容介绍:是一个面向大模型的文本及多模态数据处理开源工具。它提供了丰富的数据处理算子、高效并行化的数据处理流水线,支持数据预处理、可视化、数据评估等各项能力。还为不同背景的用户提供了开箱即用的组件和丰富的数据配方。此外,Data-Juicer与MLLM和分布式计算生态系统无缝集成,以实现高效且可扩展的数据处理。PAI已引用Data-Juicer并将其能力集成到PAI的数据处理产品中。
Pai-Megatron-Patch内容介绍:基于阿里云智算服务PAI-灵骏平台的大模型最佳实践解决方案配套工具。旨在帮助大模型开发者快速上手灵骏产品,完成大语言模型的高效分布式训练,有监督指令微调,及模型离线推理验证等全流程开发链路。该项目提供了业界主流开源大模型基于Megatron-LM的训练流程,方便您快速上手大模型训练。
前提条件
在开始执行操作前,请确认您已经完成以下准备工作:
已购买灵骏智算资源并创建资源配额。以Qwen2-VL-7B-Instruct模型为例,请使用机型
8卡*GU7X
(ml.gu7xf.c96m1600.8-gu108或ml.gu7xf.8xlarge-gu108)或8卡*GU7E
(ml.gu7ef.c96m1600.8-gu100或ml.gu7ef.8xlarge-gu100)。已创建数据集,类型选择阿里云文件存储(通用型NAS),用于存储训练所需的文件和结果文件。默认挂载路径配置为
/mnt/data/nas
。已创建DSW实例(本方案在DSW环境中完成数据准备和单机预训练操作),其中关键参数配置如下:
资源配额:选择已创建的灵骏智算资源的资源配额。
资源规格:配置以下资源规格。
CPU(核数):90。
内存(GiB):1024。
共享内存(GiB):1024。
GPU(卡数):至少为8。
镜像:在镜像地址页签,配置镜像为
dsw-registry.cn-wulanchabu.cr.aliyuncs.com/pai/pai-megatron-patch:25.01
。数据集挂载:单击自定义数据集,选择已创建的数据集,并使用默认挂载路径。
使用限制
数据处理无地域和机型限制,模型训练仅支持华北6(乌兰察布)地域。
步骤一:准备数据
本方案基于开源LLaVa数据集,使用Data-Juicer预处理数据,并通过Pai-Megatron-Patch将数据转换为支持预训练的Megatron-Energon格式(一种适用于分布式训练的高效数据存储格式)。
LLaVa数据集介绍:该数据集包含文本和图像数据,用于训练跨模态模型。
Data-Juicer数据处理流程介绍:使用YAML格式的数据配方来协调和简化整个数据处理流程。以LLaVA数据的处理配方(llava-pretrain-refine.yaml)为例进行说明,数据配方主要由以下两部分内容组成:
全局参数:
参数
描述
参数
描述
project_name
项目名称。
dataset_path
数据路径,支持文件或文件夹。
export_path
处理后的数据保存路径。
np
处理的多进程数,也支持算子单独配置多进程数(独立算子通用参数:num_proc)。
text_keys
要处理的文本字段名称。例如:
text,instruction,output,......
多模态相关全局参数
image_key
存储图像路径的字段名称。该字段对应列表类型的数据,存储多个图像的路径。
image_special_token
图像的特殊标记字符,从文本中识别该字符来判断是否有图像数据。
eoc_special_token
结束字符标记。默认为
<|__dj__eoc|>
。处理算子列表:数据配方必须包含算子注册名称及其对应的参数,Data-Juicer将按照配方中算子列表顺序处理数据。Data-Juicer中所有的算子列表请参考Operators_ZH.md;yaml文件支持的配置请参考config_all.yaml。
此外,Data-Juicer支持分布式Ray框架,启动Ray集群后,只需在全局参数中配置:
executor_type: ray
即可。PAI-DLC已支持Ray框架,您可在DLC创建Ray分布式作业,详情请参见创建训练任务。
在DSW开发环境的Notebook中完成以下操作,具体步骤如下:
1.进入PAI-DSW开发环境
登录PAI控制台,在页面上方选择目标地域,并在右侧选择目标工作空间,然后单击进入DSW。
单击目标实例操作列下的打开,然后在Notebook页签,单击Notebook>Python 3(ipykernel)。
2.安装环境
在Notebook中执行以下代码,安装运行代码所需依赖。
! pip uninstall -y cmake && apt-get update -y && apt-get install cmake -y && pip install py-data-juicer
3.准备数据集
本方案使用从开源LLaVa数据集中抽取的部分数据进行演示,该数据已转换为Data-Juicer支持的格式。执行以下代码下载数据和处理配方,并更新配置。
下载并解压Demo数据至
./data
目录。!mkdir ./data && wget http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release_pai-designer/lm_data_processor/demo_data/llava_part.zip -O data/llava_part.zip && unzip -d ./data ./data/llava_part.zip
下载数据处理配方llava-pretrain-refine.yaml,后续将使用该数据配方对数据进行处理。
!curl -O https://raw.githubusercontent.com/modelscope/data-juicer/main/configs/data_juicer_recipes/llava-pretrain-refine.yaml
修改llava-pretrain-refine.yaml中的
dataset_path
和export_path
为当前路径。# 带备份的安全替换命令。确保修改生效,若有问题,请手动调整。 !sed -i.bak -E "s|(dataset_path: +').*(' +#)|\1./data/llava_part/dj_llava_100.jsonl\2|;s|(export_path: +').*(')|\1./data_output/dj_llava_refined.jsonl\2|" llava-pretrain-refine.yaml
其中:
dataset_path:要处理的原始文件路径。例如
./data/llava_part/dj_llava_100.jsonl
。export_path:处理后数据文件的保存路径。例如
./data_output/dj_llava_refined.jsonl
。
设置多进程参数为
np:1
。由于DSW开发环境的Python版本为3.12,因dill包与当前的Python 3.12版本有冲突,所以需要执行该命令,将处理的多进程修改为单进程。如果需要使用多进程,建议将Python版本降至<=Python 3.10版本。
!sed -i "s/^\(\s*\)\bnp\b:.*/\1np: 1/" llava-pretrain-refine.yaml
您也可以下载开源全量数据集(LLaVA Data.md),并参考Data-Juicer的转换脚本(llava_to_dj.py),将LLaVa数据集转换为Data-Juicer支持的数据格式。参考命令为python llava_to_dj.py "blip_laion_cc_sbu_558k.json" "blip_laion_cc_sbu_558k_dj_format.jsonl"
,表示将开源meta文件blip_laion_cc_sbu_558k.json
,转换为Data-Juicer格式并保存为blip_laion_cc_sbu_558k_dj_format.jsonl
文件。
4.准备数据处理时依赖的模型
下载数据处理时依赖的相关模型(openai/clip-vit-base-patch32
和Salesforce/blip-itm-base-coco
)。默认使用HuggingFace下载通道可能会失败,这里使用备用链接进行下载。
!mkdir -p ~/.cache/data_juicer/models
!wget http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release_pai-designer/lm_data_processor/pretrained_models/paiflow_merge_ops/en.sp.model -O ~/.cache/data_juicer/models/en.sp.model
!wget http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release_pai-designer/lm_data_processor/pretrained_models/paiflow_merge_ops/en.arpa.bin -O ~/.cache/data_juicer/models/en.arpa.bin
!wget http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release_pai-designer/lm_data_processor/pretrained_models/Salesforce.zip && unzip Salesforce.zip
!wget http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release_pai-designer/lm_data_processor/pretrained_models/openai.zip && unzip openai.zip
5.处理数据
DataJuicer默认支持算子容错,会跳过异常样本的报错,继续运行,防止个别异常样本导致处理中断。这也可能导致其他报错被忽略导致处理异常,建议调试阶段在llava-pretrain-refine.yaml的每个算子配置中添加
skip_op_error: false
参数,关闭算子容错功能。例如以最后两个算子为例:```yaml - image_text_similarity_filter: hf_clip: openai/clip-vit-base-patch32 min_score: 0.20315419 skip_op_error: false - image_text_matching_filter: hf_blip: Salesforce/blip-itm-base-coco min_score: 0.44930778 skip_op_error: false ```
执行以下命令,系统将使用dj-process工具按照数据配方中的算子列表顺序处理数据。处理完成的数据将输出至
./data_output/dj_llava_refined.jsonl
。!pip install -U transformers !dj-process --config ./llava-pretrain-refine.yaml
检查数据处理是否成功执行,并统计输出数据的数量。
!wc -l data_output/dj_llava_refined.jsonl
结果示例如下:
81 data_output/dj_llava_refined.jsonl
6.数据格式转换
执行以下命令,将Data-Juicer格式的数据转换为LLaVa数据集的原格式。有关Data-Juicer和一些开源数据格式间的转换工具,请参考fmt_conversion。
下载数据转换脚本至当前目录。
!curl -O https://raw.githubusercontent.com/modelscope/data-juicer/main/tools/fmt_conversion/multimodal/data_juicer_format_to_target_format/dj_to_llava.py
执行以下命令更新数据转换脚本。将图像对应的输出字段名改为images,字段存储类型改为List,以满足PAI-Megatron-Patch的训练集格式要求。
代码执行成功后,请确认文件已修改成功。若未修改成功,请手动修改,将
new_sample['image'] = image_path
修改为new_sample['images'] = [image_path]
。!sed -i.bak "s/new_sample\['image'\] = image_path/new_sample['images'] = [image_path]/g" dj_to_llava.py
将处理后的数据文件
./data_output/dj_llava_refined.jsonl
转换成LLaVa原格式,并保存到./data/llava_part/refined_llava_format.json
。!python dj_to_llava.py data_output/dj_llava_refined.jsonl data/llava_part/refined_llava_format.json
将开源LLaVa数据集格式转换为Megatron-Energon格式,用于训练。
执行以下代码克隆Pai-Megatron-Patch。
!git clone --recurse-submodules https://github.com/alibaba/Pai-Megatron-Patch.git
安装transformers库。
!pip install -U transformers fsspec
将开源LLaVa数据集格式转换为Megatron-Energon格式,并将结果输出至
.data/llava_part/wds
。由于演示用的数据量较少,为确保训练集和验证集都能分配到数据,将max-samples-per-tar设置为5,train-split设置为6,val-split设置为4。请根据实际数据量进行调整。
!python Pai-Megatron-Patch/toolkits/multimodal_data_preprocessing/convert_custom_dataset_to_wds_chatml.py \ --dataset-root data/llava_part/ \ --json refined_llava_format.json \ --max-samples-per-tar 5 \ --train-split 6 \ --val-split 4
执行以下代码,检查是否输出
.tar
文件和对应的.tar.idx
文件,以及.nv-meta
文件夹,并确认.nv-meta/split.yaml
中已分配训练集和验证集文件。!ls -a data/llava_part/wds/ !cat data/llava_part/wds/.nv-meta/split.yaml
步骤二:准备预训练模型
在DSW Notebook中完成以下操作:
执行以下代码,下载Qwen2-VL-7B-Instruct模型作为基础模型。
!apt-get install git-lfs -y !mkdir -p qwen2-vl-ckpts/Qwen2-VL-7B-Instruct && git clone https://www.modelscope.cn/Qwen/Qwen2-VL-7B-Instruct.git qwen2-vl-ckpts/Qwen2-VL-7B-Instruct
如果下载速度较慢,可使用ModelScope工具进行快速下载:
pip install modelscope && modelscope download --model qwen/Qwen2-VL-7B-Instruct --local_dir qwen2-vl-ckpts/Qwen2-VL-7B-Instruct
将Checkpoint模型格式转换为MCore-Dense,并输出至
./qwen2-vl-ckpts/Qwen2-VL-7B-Instruct-tp2pp2
。!current_dir=$PWD && \ cd ${current_dir}/Pai-Megatron-Patch/toolkits/model_checkpoints_convertor/qwen && \ bash hf2mcore_qwen2_vl_convertor.sh \ 7B \ "${current_dir}/qwen2-vl-ckpts/Qwen2-VL-7B-Instruct" \ "${current_dir}/qwen2-vl-ckpts/Qwen2-VL-7B-Instruct-tp2pp2" \ 2 \ 2 \ false \ bf16
运行hf2mcore_qwen2_vl_convertor.sh脚本需要以下参数:
参数
描述
参数
描述
MODEL_SIZE=$1
模型结构参数量级。
SOURCE_CKPT_PATH=$2
已下载的Qwen2-VL-7B-Instruct模型路径。
TARGET_CKPT_PATH=$3
转换后的模型保存路径。
TP=$4
张量切片数量,与训练保持一致。
PP=$5
流水切片数量,与训练保持一致。
MG2HF=$6
是否为Megatron格式转HuggingFace格式。取值如下:
false:否
true:是
PR=$7
训练精度:fp16或bf16。
步骤三:预训练多模态模型
1.预训练调试
准备好数据和预训练模型后,在DSW的Notebook中执行以下代码进行预训练调试。代码执行成功后,系统将输出预训练模型至./output_mcore_qwen2vl_pretrain
。
!pip install -U transformers && current_dir=$PWD && \
cd ${current_dir}/Pai-Megatron-Patch/examples/qwen2_vl && \
sh run_mcore_qwen.sh \
dsw \
7B \
1 \
32 \
1e-5 \
1e-6 \
2048 \
2048 \
bf16 \
2 \
2 \
1 \
true \
true \
true \
false \
false \
20 \
"${current_dir}/data/llava_part/wds" \
"${current_dir}/data/llava_part/wds" \
"${current_dir}/qwen2-vl-ckpts/Qwen2-VL-7B-Instruct-tp2pp2" \
20 \
5 \
"${current_dir}/output_mcore_qwen2vl_pretrain"
上述代码中的参数值是针对Demo小数据集的调试参数,用于快速验证功能,不保证精度。
2.创建分布式训练任务
在DSW上调试成功后,在分布式训练(DLC)环境中提交多机多卡的分布式训练任务。具体操作步骤如下:
进入新建任务页面。
a. 登录PAI控制台,在页面上方选择目标地域,并在右侧选择目标工作空间,然后单击进入DLC。
b. 在分布式训练(DLC)页面,单击新建任务。
在新建任务页面,配置以下关键参数,其他参数取默认配置即可。
参数
描述
参数
描述
基本信息
任务名称
自定义任务名称。本方案配置为:test_qwen2_vl_dlc。
环境信息
节点镜像
选中镜像地址,并在文本框中输入
dsw-registry.cn-wulanchabu.cr.aliyuncs.com/pai/pai-megatron-patch:25.01
。数据集
单击自定义数据集,并配置以下参数:
自定义数据集:选择已创建的NAS类型的数据集。
挂载路径:配置为
/mnt/data/nas
。
启动命令
配置启动命令,其中run_mcore_qwen.sh脚本输入的启动参数与DSW单机训练一致,只需将ENV=$1配置为dlc。
!pip install -U transformers && current_dir=$PWD && \ cd ${current_dir}/Pai-Megatron-Patch/examples/qwen2_vl && \ sh run_mcore_qwen.sh \ dlc \ 7B \ 1 \ 32 \ 1e-5 \ 1e-6 \ 2048 \ 2048 \ bf16 \ 2 \ 2 \ 1 \ true \ true \ true \ false \ false \ 100000 \ "${current_dir}/data/llava_part/wds" \ "${current_dir}/data/llava_part/wds" \ "${current_dir}/qwen2-vl-ckpts/Qwen2-VL-7B-Instruct-tp2pp2" \ 20000 \ 200 \ "${current_dir}/output_mcore_qwen2vl_pretrain"
资源信息
资源类型
选择灵骏智算。
资源来源
选择资源配额。
资源配额
选择已创建的灵骏智算资源配额。
框架
选择PyTorch。
任务资源
在Worker节点配置以下参数:
节点数量:2,如果需要多机训练,配置节点数量为需要的机器数即可。
GPU(卡数):8
CPU(核数):90,且不能大于96
内存(GiB):1024
单击确定。页面将自动跳转至分布式训练(DLC)页面。当状态变为已成功时,表明训练任务执行成功。
3.模型格式转换
预训练完成后,在DSW开发环境的Notebook中执行以下命令,将预训练生成的MCore-Dense格式的模型转换为HuggingFace格式。
!current_dir=$PWD && \
cd ${current_dir}/Pai-Megatron-Patch/toolkits/model_checkpoints_convertor/qwen && \
bash hf2mcore_qwen2_vl_convertor.sh \
7B \
"${current_dir}/output_mcore_qwen2vl_pretrain/checkpoint/finetune-mcore-qwen2-vl-7B-lr-1e-5-minlr-1e-6-bs-1-gbs-32-seqlen-2048-pr-bf16-tp-2-pp-2-cp-1-ac-false-do-true-sp-true-ti-20-wi-5/iter_0000020" \
"${current_dir}/qwen2-vl-ckpts/Qwen2-VL-7B-Instruct-mc2hf" \
2 \
2 \
true \
bf16 \
"${current_dir}/qwen2-vl-ckpts/Qwen2-VL-7B-Instruct/"
运行hf2mcore_qwen2_vl_convertor.sh脚本的关键参数说明如下:
参数 | 描述 |
参数 | 描述 |
SOURCE_CKPT_PATH=$2 | 预训练生成的MCore-Dense格式的模型路径。例如 |
TARGET_CKPT_PATH=$3 | 转换后的模型保存路径。 |
MG2HF=$6 | 是否为Megatron格式转HuggingFace格式,配置为true。 |
HF_CKPT_PATH=$8 | 预训练基础模型Checkpoint路径。本方案配置为 |
步骤四:部署服务
将转换为HuggingFace格式的预训练结果模型部署为EAS服务。具体操作步骤如下:
登录PAI控制台,在页面上方选择目标地域,并在右侧选择目标工作空间,然后单击进入EAS。
在模型在线服务(EAS)页面,单击部署服务,然后在自定义模型部署区域,单击自定义部署。
在自定义部署页面,配置以下关键参数,然后单击部署。
参数
描述
参数
描述
基本信息
服务名称
自定义服务名称。例如test_qwen2_vl_7b_instruct。
环境信息
部署方式
选择镜像部署。
镜像配置
在镜像地址页签输入镜像地址
eas-registry-vpc.cn-wulanchabu.cr.aliyuncs.com/pai-eas/pai-quickstart:mllm-deploy-swift3.0.1
。模型配置
本方案通过NAS挂载预训练模型,单击通用型NAS,并配置以下参数:
选择文件系统:选择创建数据集时使用的NAS文件系统。
文件系统挂载点:选择NAS文件系统对应的挂载点。
文件系统路径:配置为存放在NAS中的转换后的HuggingFace格式模型的路径。本方案配置为
/qwen2-vl-ckpts/Qwen2-VL-7B-Instruct-mc2hf
,即转换后的模型路径。挂载路径:指定挂载路径,通过该路径读取转换后的模型文件。本方案配置为
/qwen2-vl-7b-instruct
。
运行命令
配置为
swift deploy --model /qwen2-vl-7b-instruct --model_type qwen2_vl --infer_backend pt --stream true --temperature 0 --max_new_tokens 2048 --served_model_name Qwen2-VL-7B-Instruct
。其中--model
需要与模型配置中的挂载路径一致,通过该路径读取模型文件。端口号
配置为8000。
资源部署
资源类型
选择公共资源。
部署资源
选择资源规格,本方案根据模型显存大小配置为ecs.gn8v.6xlarge。
额外系统盘
配置为100 GB。
专有网络
专有网络(VPC)
挂载NAS后,系统会自动配置与NAS一致的专有网络和交换机,选择安全组名称即可。
交换机
安全组名称
步骤五:调用服务
在线调试服务
在模型在线服务(EAS)页面,单击目标服务操作列下的
>在线调试。
在调试页面的在线调试请求参数区域的Body处填写已准备好的请求体,并在请求URL文本编辑框中添加
/v1/chat/completions
,然后单击发送请求。请求接口:
/v1/chat/completions
请求体示例如下:
{ "model": "Qwen2-VL-7B-Instruct", "messages": [ { "role": "user", "content": [ { "type": "image", "image": "<image URL>" }, { "type": "text", "text": "Describe the image" } ] } ] }
请将image配置为图片URL地址。如果图片存储在公网,EAS服务默认不通公网,需要配置公网连接,确保EAS服务能正常访问图片URL地址。
通过API调用服务
模型部署后,支持使用OpenAI API进行推理。
查看调用信息。
在模型在线服务(EAS)页面,单击目标服务的服务方式列下的调用信息,查看服务的访问地址和Token。
您可以选择使用公网地址或VPC内网地址。如果使用VPC内网地址,调用客户端必须与EAS服务位于同一个专有网络内。
在终端中执行代码调用服务。以图片推理为例,Python调用代码示例如下:
部署的服务仅在配置了专有网络(VPC)且VPC能连通公网的情况下才能访问公网。因此,在调用服务进行推理时,请求数据的图片采用Base64编码的格式,而不是图片URL。
import base64 import requests from openai import OpenAI # Modify OpenAI's API key and API base to use eas API server. openai_api_key = "<EAS API KEY>" openai_api_base = "<EAS API Endpoint>/v1" client = OpenAI( api_key=openai_api_key, base_url=openai_api_base, ) models = client.models.list() model = models.data[0].id def encode_base64_content_from_url(content_url: str) -> str: """Encode a content retrieved from a remote url to base64 format.""" with requests.get(content_url) as response: response.raise_for_status() result = base64.b64encode(response.content).decode("utf-8") return result def main(): image_url = "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg" stream = True image_base64 = encode_base64_content_from_url(image_url) chat_completion_from_base64 = client.chat.completions.create( messages=[ { "role": "user", "content": [ { "type": "image", "image": f"data:image/jpeg;base64,{image_base64}", }, { "type": "text", "text": "Describe the image", }, ], } ], model=model, max_completion_tokens=1024, stream=stream, ) if stream: for chunk in chat_completion_from_base64: print(chunk.choices[0].delta.content, end="") else: result = chat_completion_from_base64.choices[0].message.content print(result) if __name__ == "__main__": main()
其中:
openai_api_key:将<EAS API KEY>替换为EAS服务Token。
openai_api_base:将<EAS API Endpoint>替换为服务访问地址。
image_url:配置为支持公网访问的图片URL。
- 本页导读 (1)
- 背景信息
- 前提条件
- 使用限制
- 步骤一:准备数据
- 1.进入PAI-DSW开发环境
- 2.安装环境
- 3.准备数据集
- 4.准备数据处理时依赖的模型
- 5.处理数据
- 6.数据格式转换
- 步骤二:准备预训练模型
- 步骤三:预训练多模态模型
- 1.预训练调试
- 2.创建分布式训练任务
- 3.模型格式转换
- 步骤四:部署服务
- 步骤五:调用服务
- 在线调试服务
- 通过API调用服务