• Русский
  • Дообучение LLM с использованием Workbench

    Общие сведения

    Дообучение и обучение моделей часто требуют адаптации к различным структурам моделей, аппаратным устройствам и подходящим методам параллельного обучения. Alauda AI Workbench предоставляет комплексный подход: от разработки модели до отправки задач на обучение, управления ими и отслеживания экспериментов, помогая инженерам по моделям и алгоритмам быстро адаптироваться и завершить весь процесс дообучения и обучения модели.

    В этом решении мы приводим пример дообучения модели Qwen3-0.6B с использованием LLaMA-Factory.

    Alauda AI Workbench создает контейнерную среду Notebook/VSCode (CodeServer) для разработки и отладки в пользовательском namespace. В пределах одного namespace можно создать несколько экземпляров Notebook/VSCode, чтобы сохранять среды для разных пользователей и задач разработки. Notebook может запрашивать только CPU-ресурсы для разработки и отправки кластерных задач, используя GPU-ресурсы кластера для выполнения задач. Для Notebook также можно запрашивать GPU-ресурсы, что позволяет выполнять такие задачи, как обучение и дообучение, непосредственно в Notebook, независимо от того, требуется ли модели распределенное обучение.

    Кроме того, вы можете использовать встроенный MLFlow платформы для записи различных метрик для каждого сеанса дообучения модели, что упрощает сравнение нескольких экспериментов и выбор итоговой модели.

    Для отправки кластерных задач из Notebook мы используем VolcanoJob, Kubernetes-native менеджер ресурсов. Планировщик Volcano поддерживает очереди, приоритеты и различные политики планирования, что способствует более эффективному распределению кластерных задач и повышает использование ресурсов.

    В этом решении для запуска задач дообучения и обучения используется LLaMA-Factory. Однако для сценариев дообучения и обучения моделей большего масштаба, требующих параллельных методов, таких как Tensor Parallelism, Context Parallelism и Expert Parallelism, может потребоваться использование других инструментов, создание собственных runtime-образов для дообучения и изменение скрипта запуска задачи для адаптации к другим инструментам и моделям. Для получения более подробной информации по использованию LLaMA-Factory и настройке параметров, пожалуйста, см. https://llamafactory.readthedocs.io/en/latest/index.html

    Область применения

    • Это решение применимо к Alauda AI 1.3 и более поздним версиям.
    • Дообучение и обучение LLM-моделей. Если вам нужно обучать другие типы моделей (например, YOLOv5), потребуется использовать другие образы, скрипты запуска, датасеты и т. д.
    • Это решение применимо к сценариям x86/64 CPU и NVIDIA GPU.
    • Для сценариев NPU необходимо на основе этого решения собрать подходящий runtime-образ, совместимый с ними.

    Подготовка

    • Сначала необходимо развернуть плагин "Alauda AI Workbench", чтобы включить поддержку Workbench (или развернуть плагин Kubeflow Base, чтобы использовать Notebook с Kubeflow).
    • Установите плагин MLFlow для отслеживания экспериментов.

    Шаги дообучения LLM-модели

    Создание экземпляра Notebook/VSCode

    Перейдите в Alauda AI - Workbench (или Advanced - Kubeflow - Notebook) затем создайте новый Notebook или используйте существующий. Обратите внимание, что рекомендуется, чтобы Notebook использовал только CPU-ресурсы. Отправка кластерной задачи из Notebook будет запрашивать GPU-ресурсы в кластере, чтобы повысить эффективность использования ресурсов.

    См. Создание Workbench для подробных шагов по созданию экземпляра Notebook/VSCode.

    Подготовка модели

    Скачайте модель Qwen/Qwen3-0.6B с Huggingface или других сайтов открытого обмена моделями. Затем загрузите модель в репозиторий моделей.

    Подробные шаги по загрузке файлов модели в репозиторий моделей см. в разделе Upload Models Using Notebook.

    Подготовка места вывода модели

    Создайте пустую модель в репозитории моделей для хранения выходной модели. При настройке места вывода для дообучения укажите Git repository URL модели.

    Подготовка датасета

    Скачайте и отправьте sample identity dataset в репозиторий датасетов. Этот датасет используется для дообучения LLM, чтобы она могла отвечать на пользовательские вопросы, например: "Who are you?"

    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

    Подготовка runtime-образа

    Используйте следующий Containerfile для сборки runtime-образа для обучения или используйте готовый образ: 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 File
    apiVersion: batch.volcano.sh/v1alpha1
    kind: Job
    metadata:
      generateName: vcjob-sft-qwen3-
    spec:
      minAvailable: 1
      schedulerName: volcano
      maxRetry: 1
      queue: default
      volumes:
        # The workspace PVC where the task runs (temporary PVC)
        - mountPath: "/mnt/workspace"
          volumeClaim:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "sc-topolvm"
            resources:
              requests:
                storage: 5Gi
      tasks:
        - name: "train"
          # The number of parallel replicas. For distributed training tasks, you can specify replicas > 2
          replicas: 1
          template:
            metadata:
              name: train
            spec:
              restartPolicy: Never
              securityContext:
                runAsNonRoot: true
                runAsUser: 65534
                runAsGroup: 65534
                fsGroup: 65534
              # Mount the shm device to provide the shared memory space required for multi-card communication.
              volumes:
                - emptyDir:
                    medium: Memory
                    # Here you can adjust the size of the shared memory used
                    sizeLimit: 2Gi
                  name: dshm
                # PVC for storing models and datasets.
                # In distributed training tasks (with >= 2 replicas), ensure that you use the appropriate storage type for caching large models:
                # 1. Network storage, such as NFS or Ceph: Simply mount the network storage. Note that multiple containers may access this network storage simultaneously, resulting in high concurrent traffic. Furthermore, reading large model files may be slower than reading them locally (depending on the network storage's performance).
                # 2. Local storage, such as topolvm or local-storage: Use `kserve local model cache` to pre-cache the model file on each node before mounting this PVC. Training tasks cannot cache each local PVC.
                - name: models-cache
                  persistentVolumeClaim:
                    claimName: wy-model-cache
              initContainers:
                - name: prepare
                  image: alaudadockerhub/fine_tune_with_llamafactory:v0.1.1
                  imagePullPolicy: IfNotPresent
                  env:
                  # Change BASE_MODEL_URL to the base model address, DATASET_URL to the dataset address
                  - 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})
                    # Download base model
                    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
                    # Download dataset
                    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:
                # Runtime environment image. You can refer to src/llm/Containerfile to build a similar image. This typically includes runtimes such as cuda, transformers, pytorch, datasets, evaluate, and 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:
                    # Modify BASE_MODEL_URL to the base model address, DATASET_URL to the dataset address, and OUTPUT_MODEL_URL to the output model address
                    - 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"
                    # Cache dir used by huggingface libs like datasets, transformers etc.
                    - 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
                    # Change the MLFLOW_TRACKING_URI to your actual mlflow service endpoint
                    - name: MLFLOW_TRACKING_URI
                      value: "http://mlflow-tracking-server.kubeflow:5000"
                    # Set MLFLOW_EXPERIMENT_NAME to your namespace or your own 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
                      # Merge LoRA adapters
                      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
                      # move output adapter for push
                      mv output_models output_models_merged
                    fi
                    # push merged model to model repo
                    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:
                    # Ensure that there are sufficient resources to run fine tuning. If GPU is required, apply for the corresponding GPU/vGPU resources.
                    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. Image: содержит зависимости, необходимые для выполнения задачи.
    2. Переменные окружения: расположения исходной модели, датасета и выходной модели для задачи:
    • BASE_MODEL_URL: измените на Git URL подготовленной модели.
    • DATASET_URL: измените на Git URL подготовленного датасета identity-alauda.
    • OUTPUT_MODEL_URL: создайте пустую модель в репозитории моделей для хранения выходной модели, затем укажите Git URL этой модели.
    1. Требуемые ресурсы для задачи, включая:
    • model cache PVC (optional): PVC для хранения базовой модели (при запуске задач предобучения шаг загрузки базовой модели можно опустить) и датасета. Необходимо вручную создать и указать PVC в YAML-файле выше. Используйте этот "model cache PVC" для ускорения нескольких экспериментов по дообучению на разных моделях.
    • workspace PVC (required): PVC и рабочий каталог, где выполняется задача. Контрольные точки и файлы выходной модели будут сохраняться здесь. В приведенном выше примере используется временный PVC, который будет удален после завершения задачи, поскольку выходная модель уже загружается в репозиторий моделей.
    • Shared Memory: для задач многопроцессорного/распределенного обучения рекомендуется выделять как минимум 4 Gi shared memory.
    • CPU, memory и GPU ресурсы, необходимые для задачи (в зависимости от device plugin для GPU, развернутого в кластере).
    1. Скрипт выполнения задачи:
    2. В приведенном выше примере скрипт включает кэширование модели из репозитория моделей в PVC, кэширование обучающего датасета в PVC и отправку модели в новый репозиторий моделей после дообучения. Вы можете настроить скрипт под свои задачи.
    3. В примере скрипт использует LLaMA-Factory для запуска задачи дообучения, который может обрабатывать большинство сценариев обучения LLM.
    4. Гиперпараметры: в примере выше гиперпараметры заданы непосредственно в скрипте запуска. Также можно использовать переменные окружения для чтения гиперпараметров, которые могут многократно корректироваться, что упрощает многократный запуск и настройку.

    Примечание по использованию PVC на базе NFS

    При использовании NFS в качестве workspace или model cache PVC необходимо убедиться, что выполнены следующие действия, чтобы у смонтированного тома NFS были корректные права доступа к файловой системе:

    • На всех узлах K8s, которые могут использовать NFS PVC, должен быть установлен nfs-utils, например: yum install -y nfs-utils.

    • При создании storage class 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 <task name>, чтобы посмотреть статус задачи VolcanoJob.
    2. Выполните kubectl get pod, чтобы посмотреть статус pod, и kubectl logs <pod name>, чтобы просмотреть логи задачи. Обратите внимание, что для распределенных задач может существовать несколько pod.
    3. Если pod не создан, выполните kubectl describe vcjob <task name> или kubectl get podgroups, чтобы посмотреть Volcano podgroup. Вы также можете проверить лог планировщика Volcano, чтобы определить, связана ли проблема планирования с недостатком ресурсов, невозможностью смонтировать PVC или с другими проблемами планирования.
    4. После успешного выполнения задачи дообученная модель будет автоматически отправлена в репозиторий моделей. Обратите внимание, что задача автоматически создаст ветку репозитория для отправки на основе времени. При использовании выходной модели обязательно выбирайте правильную версию.

    Выполните kubectl delete vcjob <task name>, чтобы удалить задачу.

    Отслеживание экспериментов

    В приведенной выше задаче-примере дообучения мы используем LLaMA-Factory для запуска задачи дообучения и устанавливаем report_to: mlflow в конфигурации задачи. Это автоматически выводит метрики обучения на сервер mlflow. После запуска задачи вы можете найти записи отслеживания экспериментов в Alauda AI - Advanced - MLFlow и сравнивать несколько запусков. Например, можно сравнивать loss нескольких экспериментов.

    Запуск сервиса инференса с использованием дообученной модели

    После завершения задачи дообучения модель автоматически отправляется в репозиторий моделей. Вы можете использовать дообученную модель для запуска сервиса инференса и доступа к нему.

    Примечание: В приведенной выше задаче мы используем метод дообучения LoRA. Перед загрузкой модели LoRA adapter был объединен с исходной моделью. Это позволяет напрямую публиковать выходную модель в сервис инференса. Запуск сервиса инференса с использованием базовой модели и adapter'ов в текущей версии НЕ поддерживается.

    Шаги:

    1. Перейдите в Alauda AI - Model Repository, найдите выходную дообученную модель, затем откройте Model Info - File Management - Edit Metadata, выберите "Task Type": "Text Classification" и "Framework": "Transformers".
    2. Нажмите кнопку Publish Inference API, затем выберите Custom Publishing.
    3. На странице публикации сервиса инференса выберите runtime инференса vLLM (выберите vLLM с версией CUDA, поддерживаемой GPU-узлами кластера), заполните настройки хранилища, ресурсов и GPU, затем нажмите Publish.
    4. Дождитесь полной инициализации сервиса инференса, нажмите кнопку Experience в правом верхнем углу, чтобы начать диалог с моделью. (Примечание: модели, включающие конфигурацию chat_template, поддерживают только chat-возможности.)

    Запуск на GPU, отличных от Nvidia

    При использовании среды GPU, отличной от Nvidia (например, NPU, Intel Gaudi, AMD и т. д.), вы можете следовать общим шагам ниже, чтобы дообучать модели, запускать задачи обучения и управлять ими в AML Notebook.

    Для конкретного примера Huawei Ascend NPU на основе образа workbench PyTorch CANN и ноутбуков MindSpeed-LLM см. Fine-tune and Pretrain LLMs on Ascend NPU Using Workbench.

    Примечание: Следующие шаги также можно адаптировать для предобучения LLM и традиционных ML-сценариев. Это общие шаги по переносу vendor-решения на Alauda AI с использованием Notebook и VolcanoJob.

    Подготовка

    1. Предварительное условие: драйвер GPU от производителя и Kubernetes device plugin развернуты в кластере. Устройства доступны внутри pod, созданного Kubernetes. Примечание: вам необходимо знать имя ресурса vendor GPU и общее количество ресурсов устройства в кластере, чтобы упростить последующую отправку задачи. Например, для Huawei NPU можно запросить карту NPU с помощью: huawei.com/Ascend910:1.
    2. Получите документацию и материалы решения, предоставленные производителем, для дообучения на GPU текущего производителя. Обычно это включает:
    3. Документация и шаги решения. Это можно выполнить в Kubernetes или в контейнере с использованием nerdctl run.
    4. Image для запуска дообучения. Например, производитель предоставляет решение для дообучения с использованием LLaMA-Factory и соответствующий образ LLaMA-Factory (который может входить в состав образа).
    5. Модель для запуска дообучения. Обычно устройства производителя поддерживают набор моделей. Используйте модели, поддерживаемые устройством, или модели, предоставленные в vendor-решении.
    6. Обучающие данные. Используйте пример данных, предоставленный в документации vendor-решения, или подготовьте собственный датасет в том же формате.
    7. Команда запуска задачи и параметры. Например, решение для дообучения на базе фреймворка LLaMA-Factory использует команду llamafactory-cli для запуска задачи дообучения и настройки различных параметров, включая гиперпараметры задачи, в YAML-файле.

    Проверка исходного vendor-решения (необязательно)

    Чтобы убедиться в корректном выполнении vendor-решения и снизить объем последующей отладки, вы можете сначала полностью выполнить его в соответствии с vendor-решением, чтобы убедиться, что оно работает правильно.

    Этот шаг можно пропустить. Однако если позже возникнут проблемы с выполнением задачи, вы можете вернуться к этому шагу, чтобы проверить, не является ли проблема исходным решением.

    Преобразование vendor-решения для запуска как Kubernetes Job/Deployment (необязательно)

    Если vendor-решение уже запускается как Kubernetes job/deployment/pod, этот шаг можно пропустить.

    Если vendor-решение использует контейнерный способ запуска, например nerdctl run, вы можете сначала использовать простой Kubernetes job, чтобы проверить, что решение корректно работает в среде Kubernetes, где развернут device plugin производителя.

    Примечание: Этот шаг позволяет исключить проблемы, связанные с тем, что Volcano jobs не могут запланировать vendor 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
      # Note: If it is a distributed task, you can also specify the parallelism of distributed training by modifying parallelism, completions.
      completions: 1
      parallelism: 1

    Изменение vendor-решения для запуска как volcano job

    См. следующее определение YAML

    VolcanoJob YAML File
    apiVersion: batch.volcano.sh/v1alpha1
    kind: Job
    metadata:
      generateName: vcjob-sft-
    spec:
      minAvailable: 1
      schedulerName: volcano
      maxRetry: 1
      queue: default
      volumes:
        # The workspace PVC where the task runs (temporary PVC)
        - mountPath: "/mnt/workspace"
          volumeClaim:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "sc-topolvm"
            resources:
              requests:
                storage: 5Gi
      tasks:
        - name: "train"
          # The number of parallel replicas. For distributed training tasks, you can specify replicas >= 2
          replicas: 1
          template:
            metadata:
              name: train
            spec:
              restartPolicy: Never
              # Mount the shm device to provide the shared memory space required for multi-card communication.
              volumes:
                - emptyDir:
                    medium: Memory
                    # Here you can adjust the size of the shared memory used
                    sizeLimit: 2Gi
                  name: dshm
                # PVC for storing models and datasets.
                # In distributed training tasks (with >= 2 replicas), ensure that you use the appropriate storage type for caching large models:
                # 1. Network storage, such as NFS or Ceph: Simply mount the network storage. Note that multiple containers may access this network storage simultaneously, resulting in high concurrent traffic. Furthermore, reading large model files may be slower than reading them locally (depending on the network storage's performance).
                # 2. Local storage, such as topolvm or local-storage: Use `kserve local model cache` to pre-cache the model file on each node before mounting this PVC. Training tasks cannot cache each local PVC.
                - name: models-cache
                  persistentVolumeClaim:
                    claimName: sft-qwen3-volume
              containers:
                # Run the environment image.
                - 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}"
                    # add command lines to start the task below
                    # ...
                  resources:
                    # Ensure that there are sufficient resources to run fine tuning. If GPU is required, apply for the corresponding GPU/vGPU resources.
                    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: URL сервера отслеживания mlflow.
    • MLFLOW_EXPERIMENT_NAME: имя эксперимента, обычно используется имя namespace. Это позволяет различать группу задач.

    Фреймворк также задает место записи. Например, для LLaMA-Factory необходимо указать report_to: mlflow в YAML-файле конфигурации параметров задачи.

    После запуска задачи обучения вы можете найти соответствующую задачу в интерфейсе Alauda AI - "Advanced" - MLFlow и просмотреть кривые каждой записанной метрики в "Metrics" или конфигурацию параметров для каждого запуска. Также можно сравнивать несколько экспериментов.

    Итоги

    Используя среду разработки Alauda AI Notebook, вы можете быстро отправлять задачи дообучения и обучения в кластер с помощью YAML и командной строки, а также управлять состоянием выполнения этих задач. Такой подход позволяет быстро разрабатывать и настраивать шаги дообучения и обучения моделей, обеспечивая такие сценарии, как LLM SFT, preference alignment, обучение традиционных моделей и сравнение нескольких экспериментов.