使用 Workbench 对 LLM 进行微调
背景
模型微调和训练通常需要适配不同的模型结构、硬件设备以及合适的并行训练方法。Alauda AI Workbench 提供了一套完整的方案,从模型开发到训练任务提交、管理和实验跟踪,帮助模型和算法工程师快速适配并完成整个模型微调与训练流程。
在本方案中,我们提供了一个使用 LLaMA-Factory 对 Qwen3-0.6B 模型进行微调的示例。
Alauda AI Workbench 会在用户命名空间中为开发和调试创建一个 Notebook/VSCode(CodeServer)容器环境。一个命名空间内可以创建多个 Notebook/VSCode 实例,以便为不同用户和开发任务保留各自的环境。Notebook 可以仅申请 CPU 资源用于开发和集群任务提交,并利用集群的 GPU 资源运行任务。Notebook 也可以申请 GPU 资源,从而使训练和微调等任务能够直接在 Notebook 内完成,无论模型是否需要分布式训练。
此外,你可以使用平台内置的 MLFlow 记录每次模型微调训练的各种指标,便于比较多个实验并选择最终模型。
我们使用 Kubernetes 原生资源管理器 VolcanoJob 从 Notebook 中提交集群任务。Volcano 调度器支持队列、优先级以及多种调度策略,有助于更高效地调度集群任务并提升资源利用率。
本方案使用 LLaMA-Factory 启动微调和训练任务。不过,对于更大规模的模型微调和训练场景,如果需要使用 Tensor Parallelism、Context Parallelism 和 Expert Parallelism 等并行方式训练更大的模型,可能需要使用其他工具、构建自定义的微调运行时镜像,并修改任务启动脚本以适配不同的工具和模型。关于 LLaMA-Factory 的更详细用法和参数配置,请参考:https://llamafactory.readthedocs.io/en/latest/index.html
适用范围
- 本方案适用于 Alauda AI 1.3 及更高版本。
- LLM 模型的微调和训练。如果你需要训练其他类型的模型(例如 YOLOv5),则需要使用不同的镜像、启动脚本、数据集等。
- 本方案适用于 x86/64 CPU 和 NVIDIA GPU 场景。
- NPU 场景需要基于本方案构建合适的运行时镜像以保证兼容性。
准备工作
- 首先需要部署 “Alauda AI Workbench” 插件以启用 Workbench 支持(或者部署 Kubeflow Base 插件以使用 Kubeflow Notebook)。
- 安装
MLFlow 插件用于实验跟踪。
LLM 模型微调步骤
创建 Notebook/VSCode 实例
进入 Alauda AI - Workbench(或 Advanced - Kubeflow - Notebook),
然后创建一个新的 Notebook 或使用已有 Notebook。注意,建议 Notebook 仅使用 CPU 资源。
从 Notebook 内提交集群任务时,会在集群中申请 GPU 资源,以提高资源利用率。
详见 创建 Workbench 以了解创建 Notebook/VSCode 实例的详细步骤。
准备模型
从 Huggingface 或其他开源模型分享网站下载 Qwen/Qwen3-0.6B 模型,然后将模型上传到模型仓库。
有关将模型文件上传到模型仓库的详细步骤,请参见 使用 Notebook 上传模型。
准备模型输出位置
在模型仓库中创建一个空模型用于存储输出模型。在配置微调输出位置时,输入该模型的 Git 仓库 URL。
准备数据集
下载并将 示例身份数据集 推送到数据集仓库。该数据集用于微调 LLM,使其能够回答诸如“你是谁?”之类的用户问题。
- 首先,在 “Datasets” - “Dataset Repository” 下创建一个空的数据集仓库。
- 将 zip 文件上传到 notebook,解压后进入数据集目录。使用 git lfs 将数据集推送到数据集仓库的 Git URL。步骤与上传模型类似。
- 推送完成后,刷新数据集页面,你应该会在 “File Management” 选项卡中看到文件已成功上传。
注意: 数据集格式必须能够被微调框架正确识别,才能用于后续微调任务。
以下示例展示了两种常见的 LLM 微调数据集格式:
Huggingface 数据集格式
你可以使用以下代码检查数据集目录格式是否能够被 datasets 正确加载:
import datasets
ds_infos = datasets.get_dataset_infos(<dataset directory>)
ds = datasets.load_dataset(<dataset directory>)
print(ds_infos)
print(ds)
LLaMA-Factory 格式
如果你使用示例中的 LLaMA-Factory 工具完成训练,则数据集格式必须符合 LLaMA-Factory 格式。参考:data_preparation
准备运行时镜像
使用以下 Containerfile 构建训练运行时镜像,或者直接使用预构建镜像:alaudadockerhub/fine_tune_with_llamafactory:v0.1.1。如果你希望使用其他训练框架,例如 YOLOv5,则可能需要自定义该镜像并在其中安装所需依赖。
镜像构建完成后,需要将其上传到 Alauda AI 平台集群的镜像仓库,并在后续任务中进行配置。
注意: 镜像中需要包含 git lfs 命令,以便下载和上传模型与数据集文件。
Containerfile
ARG LLAMA_FACTORY_VERSION="v0.9.4"
# FROM docker-mirrors.alauda.cn/library/python:3.13-trixie
FROM 152-231-registry.alauda.cn:60070/mlops/nvidia/pytorch:24.12-py3
RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list.d/ubuntu.sources && \
sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list.d/ubuntu.sources && \
apt-get update && \
export DEBIAN_FRONTEND=noninteractive && \
apt-get install -yq --no-install-recommends git git-lfs unzip curl ffmpeg default-libmysqlclient-dev build-essential pkg-config && \
apt clean && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -U pip setuptools && \
cd /opt && \
HTTPS_PROXY=http://192.168.144.12:7890 git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git && \
cd LLaMA-Factory && git checkout ${LLAMA_FACTORY_VERSION} && \
sed -i '/torch>=2.4.0/d' pyproject.toml && \
sed -i '/torchvision>=0.19.0/d' pyproject.toml && \
sed -i '/torchaudio>=2.4.0/d' pyproject.toml && \
pip install --no-cache-dir -e ".[metrics,awq,modelscope]" -i https://pypi.tuna.tsinghua.edu.cn/simple
RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple \
"transformers>=4.51.1,<=4.53.3" \
"tokenizers>=0.21.1" \
"sqlalchemy~=2.0.30" \
"pymysql~=1.1.1" \
"loguru~=0.7.2" \
"mysqlclient~=2.2.7" \
"deepspeed~=0.18.8" \
"mlflow>=3.1"
#RUN pip install torch==2.9.1 torchvision==0.24.1 torchaudio==2.9.1 --index-url https://download.pytorch.org/whl/cu126
WORKDIR /opt
创建微调 VolcanoJob 任务
在 Notebook 中创建任务提交所需的 YAML 文件。参考以下示例:
VolcanoJob YAML 文件
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
generateName: vcjob-sft-qwen3-
spec:
minAvailable: 1
schedulerName: volcano
maxRetry: 1
queue: default
volumes:
# 任务运行所在的工作区 PVC(临时 PVC)
- mountPath: "/mnt/workspace"
volumeClaim:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "sc-topolvm"
resources:
requests:
storage: 5Gi
tasks:
- name: "train"
# 并行副本数。对于分布式训练任务,可以指定 replicas > 2
replicas: 1
template:
metadata:
name: train
spec:
restartPolicy: Never
securityContext:
runAsNonRoot: true
runAsUser: 65534
runAsGroup: 65534
fsGroup: 65534
# 挂载 shm 设备,提供多卡通信所需的共享内存空间。
volumes:
- emptyDir:
medium: Memory
# 这里可以调整共享内存的大小
sizeLimit: 2Gi
name: dshm
# 用于存储模型和数据集的 PVC。
# 在分布式训练任务(replicas >= 2)中,请确保使用合适的存储类型缓存大模型:
# 1. 网络存储,例如 NFS 或 Ceph:直接挂载网络存储。注意多个容器可能会同时访问该网络存储,导致高并发流量。此外,读取大模型文件可能比本地读取更慢(取决于网络存储性能)。
# 2. 本地存储,例如 topolvm 或 local-storage:在挂载此 PVC 之前,使用 `kserve local model cache` 预先在每个节点上缓存模型文件。训练任务无法缓存每个本地 PVC。
- name: models-cache
persistentVolumeClaim:
claimName: wy-model-cache
initContainers:
- name: prepare
image: alaudadockerhub/fine_tune_with_llamafactory:v0.1.1
imagePullPolicy: IfNotPresent
env:
# 将 BASE_MODEL_URL 修改为基础模型地址,将 DATASET_URL 修改为数据集地址
- name: BASE_MODEL_URL
value: "https://<your-model-registry-git-address>/mlops-demo-ai-test/amlmodels/qwen3-0.6b"
- name: DATASET_URL
value: "https://<your-model-registry-git-address>/mlops-demo-ai-test/amldatasets/identity-alauda"
- name: GIT_USER
valueFrom:
secretKeyRef:
name: aml-image-builder-secret
key: MODEL_REPO_GIT_USER
- name: GIT_TOKEN
valueFrom:
secretKeyRef:
name: aml-image-builder-secret
key: MODEL_REPO_GIT_TOKEN
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 2
memory: 4Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: models-cache
mountPath: /mnt/models
command:
- /bin/bash
- -c
- |
set -ex
cd /mnt/models
BASE_MODEL_NAME=$(basename ${BASE_MODEL_URL})
# 下载基础模型
gitauth="${GIT_USER}:${GIT_TOKEN}"
BASE_MODEL_URL_NO_HTTPS="${BASE_MODEL_URL//https:\/\/}"
if [ -d ${BASE_MODEL_NAME} ]; then
echo "${BASE_MODEL_NAME} dir already exists, skip downloading"
else
GIT_LFS_SKIP_SMUDGE=1 git -c http.sslVerify=false -c lfs.activitytimeout=36000 clone "https://${gitauth}@${BASE_MODEL_URL_NO_HTTPS}"
(cd ${BASE_MODEL_NAME} && git -c http.sslVerify=false -c lfs.activitytimeout=36000 lfs pull)
fi
# 下载数据集
DATASET_NAME=$(basename ${DATASET_URL})
DATASET_URL_NO_HTTPS="${DATASET_URL//https:\/\/}"
rm -rf ${DATASET_NAME}
rm -rf data
if [ -d ${DATASET_NAME} ]; then
echo "dataset ${DATASET_NAME} already exists skipping download"
else
git -c http.sslVerify=false -c lfs.activitytimeout=36000 clone "https://${gitauth}@${DATASET_URL_NO_HTTPS}"
fi
echo "listing files under /mnt/models ..."
ls /mnt/models
echo "listing model files ..."
ls ${BASE_MODEL_NAME}
echo "listing dataset files ..."
ls ${DATASET_NAME}
containers:
# 运行时环境镜像。你可以参考 src/llm/Containerfile 构建类似镜像。通常应包含 cuda、transformers、pytorch、datasets、evaluate 和 git lfs 等运行时。
- name: train
image: alaudadockerhub/fine_tune_with_llamafactory:v0.1.1
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /dev/shm
name: dshm
- name: models-cache
mountPath: /mnt/models
env:
# 将 BASE_MODEL_URL 修改为基础模型地址,将 DATASET_URL 修改为数据集地址,将 OUTPUT_MODEL_URL 修改为输出模型地址
- name: BASE_MODEL_URL
value: "https://<your-model-registry-git-address>/mlops-demo-ai-test/amlmodels/qwen3-0.6b"
- name: DATASET_URL
value: "https://<your-model-registry-git-address>/mlops-demo-ai-test/amldatasets/identity-alauda"
- name: OUTPUT_MODEL_URL
value: "https://<your-model-registry-git-address>/mlops-demo-ai-test/amlmodels/wy-sft-output"
# huggingface 等库(如 datasets、transformers)的缓存目录
- name: HF_HOME
value: /mnt/workspace/hf_cache
- name: DO_MERGE
value: "true"
- name: GIT_USER
valueFrom:
secretKeyRef:
name: aml-image-builder-secret
key: MODEL_REPO_GIT_USER
- name: GIT_TOKEN
valueFrom:
secretKeyRef:
name: aml-image-builder-secret
key: MODEL_REPO_GIT_TOKEN
# 将 MLFLOW_TRACKING_URI 修改为你的实际 mlflow 服务端点
- name: MLFLOW_TRACKING_URI
value: "http://mlflow-tracking-server.kubeflow:5000"
# 将 MLFLOW_EXPERIMENT_NAME 设置为你的命名空间名或你自己的实验名称
- name: MLFLOW_EXPERIMENT_NAME
value: mlops-demo-ai-test
command:
- bash
- -c
- |
set -ex
echo "job workers list: ${VC_WORKER_HOSTS}"
if [ "${VC_WORKER_HOSTS}" != "" ]; then
export N_RANKS=$(echo "${VC_WORKER_HOSTS}" |awk -F',' '{print NF}')
export RANK=$VC_TASK_INDEX
export MASTER_HOST=$(echo "${VC_WORKER_HOSTS}" |awk -F',' '{print $1}')
export RANK=$RANK
export WORLD_SIZE=$N_RANKS
export NNODES=$N_RANKS
export NODE_RANK=$RANK
export MASTER_ADDR=${MASTER_HOST}
export MASTER_PORT="8888"
else
export N_RANKS=1
export RANK=0
export NNODES=1
export MASTER_HOST=""
fi
cd /mnt/workspace
BASE_MODEL_NAME=$(basename ${BASE_MODEL_URL})
DATASET_NAME=$(basename ${DATASET_URL})
cat >lf-sft.yaml <<EOL
model_name_or_path: /mnt/models/${BASE_MODEL_NAME}
stage: sft
do_train: true
finetuning_type: lora
lora_target: all
lora_rank: 8
lora_alpha: 16
lora_dropout: 0.1
dataset: identity_alauda
dataset_dir: /mnt/models/${DATASET_NAME}
template: qwen
cutoff_len: 1024
max_samples: 1000
overwrite_cache: true
preprocessing_num_workers: 8
output_dir: output_models
logging_steps: 10
save_steps: 500
plot_loss: true
overwrite_output_dir: true
# global batch size: 8
per_device_train_batch_size: 2
gradient_accumulation_steps: 2
learning_rate: 2.0e-4
num_train_epochs: 4.0
bf16: false
fp16: true
ddp_timeout: 180000000
val_size: 0.1
per_device_eval_batch_size: 1
eval_strategy: steps
eval_steps: 500
report_to: mlflow
EOL
# Run training
if [ ${NNODES} -gt 1 ]; then
echo "deepspeed: ds-z3-config.json" >> lf-sft.yaml
FORCE_TORCHRUN=1 llamafactory-cli train lf-sft.yaml
else
unset NNODES
unset NODE_RANK
unset MASTER_ADDR
unset MASTER_PORT
llamafactory-cli train lf-sft.yaml
fi
if [ "${DO_MERGE}" == "true" ]; then
# 合并 LoRA adapter
cat >lf-merge-config.yaml <<EOL
model_name_or_path: /mnt/models/${BASE_MODEL_NAME}
adapter_name_or_path: output_models
template: qwen
finetuning_type: lora
### export
export_dir: output_models_merged
export_size: 4
export_device: cpu
export_legacy_format: false
EOL
llamafactory-cli export lf-merge-config.yaml
else
# 将输出 adapter 移动以便推送
mv output_models output_models_merged
fi
# 将合并后的模型推送到模型仓库
gitauth="${GIT_USER}:${GIT_TOKEN}"
cd /mnt/workspace/output_models_merged
touch README.md
OUTPUT_MODEL_NO_HTTPS="${OUTPUT_MODEL_URL//https:\/\/}"
PUSH_URL="https://${gitauth}@${OUTPUT_MODEL_NO_HTTPS}"
push_branch=$(date +'%Y%m%d-%H%M%S')
git init
git checkout -b sft-${push_branch}
git lfs track *.safetensors
git add .
git -c user.name='AMLSystemUser' -c user.email='aml_admin@cpaas.io' commit -am "fine tune push auto commit"
git -c http.sslVerify=false -c lfs.activitytimeout=36000 push -u ${PUSH_URL} sft-${push_branch}
resources:
# 确保有足够资源运行微调。如果需要 GPU,请申请相应的 GPU/vGPU 资源。
requests:
cpu: "1"
memory: "2Gi"
limits:
cpu: "8"
memory: "16Gi"
nvidia.com/gpu: 1
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
在提交任务之前,请在上述 YAML 文件中修改以下设置。
- 镜像:包含任务执行所需的依赖。
- 环境变量: 任务原始模型、数据集和输出模型的位置:
BASE_MODEL_URL:修改为已准备模型的 Git URL。
DATASET_URL:修改为已准备数据集 identity-alauda 的 Git URL。
OUTPUT_MODEL_URL:在模型仓库中创建一个空模型用于存储输出模型,然后输入该模型的 Git URL。
- 任务所需资源,包括:
- model cache PVC(可选): 用于存储基础模型(在运行预训练任务时,可以省略基础模型下载步骤)和数据集的 PVC。你需要在上述 YAML 文件中手动创建并指定该 PVC。使用这个 “model cache PVC” 可加速在多个模型上的多次微调实验。
- workspace PVC(必需):任务运行的 PVC 和工作目录。检查点和输出模型文件将存储在这里。在上述示例中,我们使用的是临时 PVC,因为输出模型已经上传到模型仓库,任务结束后该 PVC 会被删除。
- Shared Memory:对于多 GPU/分布式训练任务,建议至少分配 4 Gi 的共享内存。
- CPU、memory 和 GPU:任务所需资源(基于集群中部署的 GPU device plugin)。
- 任务执行脚本:
- 上面的示例脚本包括将模型从模型仓库缓存到 PVC、将训练数据集缓存到 PVC,以及在微调后将模型推送到新的模型仓库。你可以根据自己的任务自定义脚本。
- 示例脚本使用
LLaMA-Factory 启动微调任务,可覆盖大多数 LLM 微调训练场景。
- 超参数:在上面的示例中,超参数直接定义在启动脚本中。你也可以使用环境变量读取可重复调整的超参数,这样更便于多次运行和配置。
关于使用 NFS PVC 的说明
当使用 NFS 作为 workspace 或 model cache PVC 时,你应确保执行以下操作,以保证挂载的 NFS 卷具有正确的文件系统权限:
INFO
Workbench 镜像默认不包含 kubectl。你可以使用 Jupyter 界面中的上传按钮,将从本地机器下载的 kubectl 二进制文件上传到 Jupyter 环境。
完成上述设置后,在 Notebook 中打开终端并执行:kubectl create -f vcjob_sft.yaml,即可将 VolcanoJob 提交到集群。
管理任务
在 Notebook 终端中:
- 运行
kubectl get vcjob 查看任务列表,然后运行 kubectl get vcjob <task name> 查看 VolcanoJob 任务状态。
- 运行
kubectl get pod 查看 pod 状态,运行 kubectl logs <pod name> 查看任务日志。注意,分布式任务可能会有多个 pod。
- 如果 pod 未创建,运行
kubectl describe vcjob <task name> 或 kubectl get podgroups 查看 Volcano podgroup。你也可以检查 Volcano 调度器日志,以确定调度问题是否由资源不足、无法挂载 PVC 或其他调度问题导致。
- 任务成功执行后,微调后的模型将自动推送到模型仓库。注意,任务会根据时间自动生成一个用于推送的仓库分支。使用输出模型时,请务必选择正确的版本。
运行 kubectl delete vcjob <task name> 可删除任务。
实验跟踪
在上面的微调示例任务中,我们使用 LLaMA-Factory 启动微调任务,并在任务配置中设置 report_to: mlflow。这会自动将训练指标输出到 mlflow server。任务启动后,你可以在 Alauda AI - Advanced - MLFlow 中找到实验跟踪记录,并比较多个执行结果。例如,你可以比较多个实验的 loss。
使用微调后的模型启动推理服务
微调任务完成后,模型会自动推送到模型仓库。你可以使用微调后的模型来启动推理服务并进行访问。
注意: 在上面的示例任务中,我们使用的是 LoRA 微调方法。在上传模型之前,LoRA adapter 已与原始模型合并。这使得输出模型可以直接发布到推理服务。当前版本不支持使用基础模型和 adapters 启动推理服务。
步骤:
- 进入 Alauda AI - Model Repository,找到微调后的输出模型,进入 Model Info - File Management - Edit Metadata,将 “Task Type” 选择为 “Text Classification”,将 “Framework” 选择为 “Transformers”。
- 点击 Publish Inference API 按钮,然后选择 Custom Publishing。
- 在 Publish Inference Service 页面,选择 vLLM 推理运行时(选择集群 GPU 节点支持的 CUDA 版本对应的 vLLM),填写存储、资源、GPU 等配置,然后点击 Publish。
- 等待推理服务完全启动后,点击右上角的 Experience 按钮,即可开始与模型对话。(注意:包含
chat_template 配置的模型才具备聊天能力。)
在非 Nvidia GPU 上运行
当使用非 Nvidia GPU 环境(例如 NPU、Intel Gaudi、AMD 等)时,你可以按照以下通用步骤在 AML Notebook 中微调模型、启动训练任务并进行管理。
基于 PyTorch CANN workbench 镜像和 MindSpeed-LLM notebooks 的华为 Ascend NPU 具体示例,请参见 使用 Workbench 在 Ascend NPU 上微调和预训练 LLM。
注意: 以下步骤也可适配于 LLM 预训练和传统 ML 场景。这些是将供应商方案转换为可在 Alauda AI 上通过 Notebook 和 VolcanoJob 运行的一般步骤。
准备工作
- 前提条件:集群中已部署供应商 GPU 驱动和 Kubernetes device plugin。Kubernetes 创建的 pod 内可以访问这些设备。
注意:你需要了解供应商 GPU 资源名称以及集群中的设备资源总数,以便后续任务提交。
例如,对于华为 NPU,你可以通过
huawei.com/Ascend910:1 申请一张 NPU 卡。
- 获取供应商提供的当前 GPU 微调方案文档和相关材料。这通常包括:
- 方案文档和步骤。可以在 Kubernetes 中完成,也可以在容器中使用
nerdctl run 完成。
- 用于运行微调的镜像。例如,供应商提供了基于
LLaMA-Factory 的微调方案以及对应的 LLaMA-Factory 镜像(也可能已包含在镜像中)。
- 用于运行微调的模型。通常,供应商设备支持一系列模型。请使用设备支持的模型,或者使用供应商方案中提供的模型。
- 训练数据。使用供应商方案文档中提供的示例数据,或构建与你自己的数据集格式相同的数据集。
- 任务启动命令和参数。例如,
LLaMA-Factory 框架的微调方案使用 llamafactory-cli 命令启动微调任务,并在 YAML 文件中配置包括任务超参数在内的各项参数。
验证原始供应商方案(可选)
为了确保供应商方案能够正确执行并减少后续排障,你可以先完全按照供应商方案运行一次,以验证其工作是否正常。
这一步可以跳过。但如果后续任务执行出现问题,你可以回到这一步,确认问题是否出在原始方案本身。
将供应商方案转换为 Kubernetes Job/Deployment 运行(可选)
如果供应商方案已经以 Kubernetes job/deployment/pod 的形式运行,则可以跳过此步骤。
如果供应商方案使用的是容器执行方式,例如 nerdctl run,你可以先使用一个简单的 Kubernetes job,验证该方案是否能在已部署供应商 device plugin 的 Kubernetes 环境中正常运行。
注意: 这一步可以排除 Volcano job 无法调度供应商 GPU 设备的问题,因此可以单独验证。
参考示例:
apiVersion: batch/v1
kind: Job
metadata:
name: custom-gpu-ft-job
spec:
template:
spec:
containers:
- name: train
image: <Image used by the vendor to fine-tune training solutions>
command: ["Task start command", "Parameter 1", "Parameter 2"]
restartPolicy: Never
# 注意:如果是分布式任务,也可以通过修改 parallelism、completions 来指定分布式训练的并行度。
completions: 1
parallelism: 1
将供应商方案修改为 volcano job 运行
参考以下 YAML 定义
VolcanoJob YAML 文件
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
generateName: vcjob-sft-
spec:
minAvailable: 1
schedulerName: volcano
maxRetry: 1
queue: default
volumes:
# 任务运行所在的工作区 PVC(临时 PVC)
- mountPath: "/mnt/workspace"
volumeClaim:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "sc-topolvm"
resources:
requests:
storage: 5Gi
tasks:
- name: "train"
# 并行副本数。对于分布式训练任务,可以指定 replicas >= 2
replicas: 1
template:
metadata:
name: train
spec:
restartPolicy: Never
# 挂载 shm 设备,提供多卡通信所需的共享内存空间。
volumes:
- emptyDir:
medium: Memory
# 这里可以调整共享内存的大小
sizeLimit: 2Gi
name: dshm
# 用于存储模型和数据集的 PVC。
# 在分布式训练任务(replicas >= 2)中,请确保使用合适的存储类型缓存大模型:
# 1. 网络存储,例如 NFS 或 Ceph:直接挂载网络存储。注意多个容器可能会同时访问该网络存储,导致高并发流量。此外,读取大模型文件可能比本地读取更慢(取决于网络存储性能)。
# 2. 本地存储,例如 topolvm 或 local-storage:在挂载此 PVC 之前,使用 `kserve local model cache` 预先在每个节点上缓存模型文件。训练任务无法缓存每个本地 PVC。
- name: models-cache
persistentVolumeClaim:
claimName: sft-qwen3-volume
containers:
# 运行环境镜像。
- image: <Specify the image used by the vendor's solution or customize the image on site>
imagePullPolicy: IfNotPresent
name: train
volumeMounts:
- mountPath: /dev/shm
name: dshm
- name: models-cache
mountPath: /mnt/models
env:
- name: MLFLOW_TRACKING_URI
value: "http://mlflow-tracking-server.aml-system.svc.cluster.local:5000"
- name: MLFLOW_EXPERIMENT_NAME
value: kubeflow-admin-cpaas-io
command:
- bash
- -c
- |
set -ex
echo "job workers list: ${VC_WORKER_HOSTS}"
# 在下面添加启动任务的命令行
# ...
resources:
# 确保有足够资源运行微调。如果需要 GPU,请申请相应的 GPU/vGPU 资源。
requests:
cpu: "1"
memory: "8Gi"
limits:
cpu: "8"
memory: "16Gi"
nvidia.com/gpualloc: "1"
nvidia.com/gpucores: "50"
nvidia.com/gpumem: "8192"
实验跟踪
某些微调/训练框架会自动将实验进度记录到各种实验跟踪服务中。例如,LLaMA-Factory 和 Transformers 框架可以指定将实验进度记录到 mlflow、wandb 等服务。根据你的部署情况,可以配置以下环境变量:
MLFLOW_TRACKING_URI:mlflow tracking server 的 URL。
MLFLOW_EXPERIMENT_NAME:实验名称,通常使用命名空间名称,用于区分一组任务。
框架还需要指定记录目标。例如,LLaMA-Factory 需要在任务参数配置 YAML 文件中指定 report_to: mlflow。
训练任务开始后,你可以在 Alauda AI - “Advanced” - MLFlow 界面中找到对应任务,并在 “Metrics” 中查看各项已记录指标的曲线,或查看每次执行的参数配置。你也可以比较多个实验。
总结
使用 Alauda AI Notebook 开发环境,你可以通过 YAML 和命令行工具快速将微调和训练任务提交到集群,并管理这些任务的执行状态。这种方式使你能够快速开发和自定义模型微调与训练步骤,从而支持 LLM SFT、偏好对齐、传统模型训练以及多实验对比等操作。