使用 Workbench 对 LLM 进行微调

背景

模型微调和训练通常需要适配不同的模型结构、硬件设备以及合适的并行训练方式。Alauda AI Workbench 提供了从模型开发到训练任务提交、管理和实验追踪的全流程方案,帮助模型和算法工程师快速适配并完成整个模型微调和训练过程。

本方案中,我们提供了使用 LLaMA-FactoryQwen3-0.6B 模型进行微调的示例。

Alauda AI Workbench 会在用户命名空间内创建 Notebook/VSCode(CodeServer)容器环境,用于开发和调试。一个命名空间内可以创建多个 Notebook/VSCode 实例,以便为不同用户和开发任务保留环境。Notebook 可以仅申请 CPU 资源用于开发和集群任务提交,集群任务运行时使用集群的 GPU 资源。Notebook 也可以申请 GPU 资源,支持在 Notebook 内直接完成训练和微调等任务,无论模型是否需要分布式训练。

此外,您还可以使用平台内置的 MLFlow 记录每次模型微调训练的各类指标,方便对多个实验进行对比和最终模型选择。

我们使用 Kubernetes 原生资源管理器 VolcanoJob 从 Notebook 提交集群任务。Volcano 调度器支持队列、优先级和多种调度策略,方便更高效地调度集群任务,提高资源利用率。

本方案使用 LLaMA-Factory 启动微调和训练任务。但对于需要使用张量并行、上下文并行、专家并行等并行方式训练更大模型的规模化微调训练场景,可能需要使用其他工具,构建自定义微调运行时镜像,并修改任务启动脚本以适配不同工具和模型。更多 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 仅使用 CPU 资源, 从 Notebook 内提交集群任务时,集群会申请 GPU 资源以提升资源利用率。

详细创建 Notebook/VSCode 实例步骤请参见 Creating a Workbench

准备模型

从 Huggingface 或其他开源模型分享网站下载模型 Qwen/Qwen3-0.6B,然后上传模型到模型仓库。

详细上传模型文件到模型仓库步骤请参见 Upload Models Using Notebook

准备模型输出位置

在模型仓库创建一个空模型用于存储输出模型。配置微调输出位置时,填写该模型的 Git 仓库 URL。

准备数据集

下载并推送 示例身份数据集 到数据集仓库。该数据集用于微调 LLM 回答诸如“你是谁?”等用户问题。

  1. 首先在 “Datasets” - “Dataset Repository” 下创建一个空数据集仓库。
  2. 将 zip 文件上传到 Notebook,解压后进入数据集目录,使用 git lfs 将数据集推送到数据集仓库的 Git URL。步骤与上传模型类似。
  3. 推送完成后刷新数据集页面,在 “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 python:3.13-trixie

RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list.d/debian.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 && \
git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git && \
cd LLaMA-Factory && git checkout ${LLAMA_FACTORY_VERSION} && \
pip install --no-cache-dir -e ".[torch,metrics,deepspeed,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,<5" \
"tokenizers>=0.21.1" \
"sqlalchemy~=2.0.30" \
"pymysql~=1.1.1" \
"loguru~=0.7.2" \
"mysqlclient~=2.2.7" \
"mlflow>=3.1"
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。
            # 分布式训练任务(副本数 >= 2)需确保使用合适的存储类型缓存大模型:
            # 1. 网络存储,如 NFS 或 Ceph:直接挂载网络存储。注意多个容器可能同时访问该网络存储,导致高并发流量,且读取大模型文件可能比本地慢(视网络存储性能)。
            # 2. 本地存储,如 topolvm 或 local-storage:使用 `kserve local model cache` 在每个节点预缓存模型文件后再挂载该 PVC。训练任务无法缓存每个本地 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

                # 运行训练
                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 适配器
                  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
                  # 移动输出适配器以便推送
                  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 文件中,提交任务前请修改以下配置:

  1. 镜像:包含任务执行所需依赖。
  2. 环境变量:任务的原始模型、数据集和输出模型位置:
  • BASE_MODEL_URL:修改为准备好的模型 Git URL。
  • DATASET_URL:修改为准备好的数据集 identity-alauda 的 Git URL。
  • OUTPUT_MODEL_URL:在模型仓库创建空模型用于存储输出模型,填写该模型的 Git URL。
  1. 任务所需资源,包括:
  • 模型缓存 PVC(可选):用于存储基础模型(运行预训练作业时可省略基础模型下载步骤)和数据集。需手动创建并在上述 YAML 文件中指定 PVC。使用该“模型缓存 PVC”可加速多个模型的多次微调实验。
  • 工作空间 PVC(必需):任务运行的 PVC 和工作目录,检查点和输出模型文件存储于此。示例中使用临时 PVC,任务完成后会删除,因为输出模型已上传到模型仓库。
  • 共享内存:多 GPU/分布式训练任务建议分配至少 4 Gi 共享内存。
  • 任务所需的 CPU、内存和 GPU 资源(基于集群中部署的 GPU 设备插件)。
  1. 任务执行脚本
  2. 示例脚本包含从模型仓库缓存模型到 PVC、缓存训练数据集到 PVC,以及微调完成后推送模型到新模型仓库。可根据自身任务定制脚本。
  3. 示例脚本使用 LLaMA-Factory 启动微调任务,能覆盖大多数 LLM 微调训练场景。
  4. 超参数:示例中超参数直接定义在启动脚本中,也可通过环境变量读取,方便多次运行和配置。

关于使用 NFS PVC 的说明

使用 NFS 作为工作空间或模型缓存 PVC 时,应确保执行以下操作,保证挂载的 NFS 卷具有正确的文件系统权限:

  • 所有可使用 NFS PVC 的 K8s 节点必须安装 nfs-utils,例如执行 yum install -y nfs-utils

  • 创建 NFS 存储类时,添加 mountPermissions: "0757" 配置,例如:

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: ai-nfs
      labels:
        project.cpaas.io/name: null
        project.cpaas.io/ALL_ALL: "true"
      annotations:
        cpaas.io/display-name: ""
        cpaas.io/access-mode: ReadWriteOnce,ReadWriteMany
        cpaas.io/features: ""
    provisioner: nfs.csi.k8s.io
    parameters:
      mountPermissions: "0757"
      server: 192.168.17.28
      share: /nfs_data/int/ai
    reclaimPolicy: Delete
    volumeBindingMode: Immediate
    mountOptions:
      - hard
      - nfsvers=4.1
    driverName: ""
INFO

Workbench 镜像默认不包含 kubectl,可通过 Jupyter 界面上传按钮,将本地下载的 kubectl 二进制文件上传到 Jupyter 环境。

完成上述配置后,在 Notebook 中打开终端,执行:kubectl create -f vcjob_sft.yaml 提交 VolcanoJob 到集群。

管理任务

在 Notebook 终端:

  1. 运行 kubectl get vcjob 查看任务列表,再运行 kubectl get vcjob <任务名> 查看 VolcanoJob 任务状态。
  2. 运行 kubectl get pod 查看 Pod 状态,使用 kubectl logs <pod 名称> 查看任务日志。分布式任务可能存在多个 Pod。
  3. 若 Pod 未创建,运行 kubectl describe vcjob <任务名>kubectl get podgroups 查看 Volcano podgroup。也可查看 Volcano 调度器日志,判断调度问题是否因资源不足、PVC 挂载失败或其他调度问题。
  4. 任务成功执行后,微调模型会自动推送至模型仓库。任务会基于时间自动生成推送分支,使用输出模型时请确保选择正确版本。

运行 kubectl delete vcjob <任务名> 删除任务。

实验追踪

上述微调示例任务中,我们使用 LLaMA-Factory 启动微调任务,并在任务配置中设置 report_to: mlflow,自动将训练指标输出到 mlflow 服务器。任务启动后,可在 Alauda AI - Advanced - MLFlow 中查看实验追踪记录,方便对比多次执行,例如比较多个实验的 loss 曲线。

使用微调模型启动推理服务

微调任务完成后,模型会自动推送到模型仓库。您可以使用微调后的模型启动推理服务并访问。

注意: 示例任务中使用 LoRA 微调方法,上传模型前已将 LoRA 适配器与原模型合并,输出模型可直接发布推理服务。当前版本不支持使用基础模型和适配器启动推理服务。

步骤:

  1. 进入 Alauda AI - Model Repository,找到微调输出模型,进入 Model Info - File Management - Edit Metadata,选择“任务类型”为“Text Classification”,“框架”为“Transformers”。
  2. 点击 Publish Inference API 按钮,选择 Custom Publishing
  3. 在发布推理服务页面,选择 vLLM 推理运行时(选择集群 GPU 节点支持的 CUDA 版本的 vLLM),填写存储、资源、GPU 等设置,点击 Publish
  4. 等待推理服务完全启动后,点击右上角的 Experience 按钮开始与模型对话。(注:包含 chat_template 配置的模型才具备聊天能力。)

在非 Nvidia GPU 上运行

使用非 Nvidia GPU 环境(如 NPU、Intel Gaudi、AMD 等)时,可参考以下通用步骤,在 AML Notebook 中完成模型微调、启动训练任务及管理。

注意: 以下步骤同样适用于 LLM 预训练和传统 ML 场景,是将厂商方案转换为在 Alauda AI 上使用 Notebook 和 VolcanoJob 运行的通用步骤。

准备工作

  1. 前提条件:集群已部署厂商 GPU 驱动和 Kubernetes 设备插件,Pod 内可访问设备。 需了解厂商 GPU 资源名称及集群设备总数,便于后续任务提交。 例如华为 NPU,可申请 NPU 卡资源:huawei.com/Ascend910:1
  2. 获取厂商提供的当前 GPU 微调方案文档和材料,通常包括:
  3. 方案文档和步骤,可在 Kubernetes 或容器中使用 nerdctl run 执行。
  4. 运行微调的镜像,如厂商提供基于 LLaMA-Factory 的微调方案及对应镜像(可能包含在镜像中)。
  5. 运行微调的模型,通常厂商设备支持一系列模型,使用设备支持的模型或厂商方案提供的模型。
  6. 训练数据,使用厂商方案文档提供的示例数据,或构建格式相同的数据集。
  7. 任务启动命令和参数,如 LLaMA-Factory 框架微调方案使用 llamafactory-cli 命令启动微调任务,并在 YAML 文件中配置任务超参数等。

验证原厂商方案(可选)

为确保厂商方案正确执行,减少后续排查,可先完整运行厂商方案验证其可用性。

此步骤可跳过,但若后续任务执行出现问题,可回到此步骤确认原方案是否存在问题。

将厂商方案转换为 Kubernetes Job/Deployment(可选)

若厂商方案已作为 Kubernetes job/deployment/pod 运行,可跳过此步骤。

若厂商方案使用容器执行方式(如 nerdctl run),可先使用简单 Kubernetes job 验证方案在部署了厂商设备插件的 Kubernetes 环境中能正常运行。

注意: 此步骤可排除 volcano job 无法调度厂商 GPU 设备的问题,可单独验证。

参考示例:

apiVersion: batch/v1
kind: Job
metadata:
  name: custom-gpu-ft-job
spec:
  template:
    spec:
      containers:
      - name: train
        image: <厂商用于微调训练方案的镜像>
        command: ["任务启动命令", "参数1", "参数2"]
      restartPolicy: Never
  # 注:分布式任务可通过修改 completions、parallelism 指定并行度。
  completions: 1
  parallelism: 1

修改厂商方案以 VolcanoJob 方式运行

参考以下 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。
            # 分布式训练任务(副本数 >= 2)需确保使用合适的存储类型缓存大模型:
            # 1. 网络存储,如 NFS 或 Ceph:直接挂载网络存储。注意多个容器可能同时访问该网络存储,导致高并发流量,且读取大模型文件可能比本地慢(视网络存储性能)。
            # 2. 本地存储,如 topolvm 或 local-storage:使用 `kserve local model cache` 在每个节点预缓存模型文件后再挂载该 PVC。训练任务无法缓存每个本地 PVC。
            - name: models-cache
              persistentVolumeClaim:
                claimName: sft-qwen3-volume
          containers:
            # 运行环境镜像。
            - image: <指定厂商方案使用的镜像或现场定制镜像>
              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-FactoryTransformers 框架可指定将实验进度记录到 mlflow、wandb 等服务。根据部署情况,可配置以下环境变量:

  • MLFLOW_TRACKING_URI:mlflow 追踪服务器 URL。
  • MLFLOW_EXPERIMENT_NAME:实验名称,通常使用命名空间名,用于区分一组任务。

框架还需指定记录目标,例如 LLaMA-Factory 需在任务参数配置 YAML 文件中指定 report_to: mlflow

训练任务开始后,可在 Alauda AI - “Advanced” - MLFlow 界面找到对应任务,查看各指标曲线或每次执行的参数配置,也可对比多个实验。

总结

通过 Alauda AI Notebook 开发环境,您可以快速使用 YAML 和命令行工具向集群提交微调和训练任务,并管理这些任务的执行状态。该方式支持快速开发和定制模型微调与训练流程,实现 LLM SFT、偏好对齐、传统模型训练及多实验对比等操作。