Skip to content

使用 LLaMA-Factory 进行训练

本页适用于已经熟悉 LLaMA-Factory,希望把本地或开发机中的 LLaMA-Factory 训练命令迁移到 AIStudio 训练任务的用户。重点是确认镜像、共享存储路径、单机或多机启动方式,以及 AIStudio 注入的 DDP 环境变量如何映射到 torchrun

本页不重复训练任务创建流程。创建训练任务、选择资源来源、挂载存储、配置 TensorBoard 和提交任务的通用步骤,见选择任务类型与资源来源

准备 LLaMA-Factory 镜像、模型和数据

先确认训练任务使用的镜像已经包含 LLaMA-Factory、训练脚本和固定依赖。长期训练不建议在任务启动后临时安装大量依赖;网络、源站或版本问题会在 GPU 已经分配后才暴露。

可以选择以下方式准备镜像:

如果还没有确定使用官方镜像还是自建镜像,先阅读选择 LLaMA-Factory 镜像准备方式

提交训练任务前,确认以下内容已经准备好:

  • 镜像中可以执行 python src/train.py 或等价的 LLaMA-Factory 入口。
  • 模型路径位于任务会挂载的共享存储中。
  • --dataset 使用的数据集名称已经在 LLaMA-Factory 配置中可用。
  • --template 与模型类型匹配,例如 Llama 3 模型使用 llama3
  • --output_dir、TensorBoard 日志和 checkpoint 都写入共享存储。

后续示例默认使用 --report_to tensorboard。LLaMA-Factory 支持 TensorBoard 记录,但 TensorBoard 不一定随外部镜像预装。如果使用在开发机中构建 LLaMA-Factory 训练镜像中的镜像,TensorBoard 已经安装;如果导入官方镜像或其它自带镜像,先在镜像或 Worker 中确认:

language-shell
python -m pip show tensorboard
python -c "import tensorboard; print(tensorboard.__version__)"

演示任务可以在启动命令前临时安装 TensorBoard:

language-shell
python -m pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
python -m pip install tensorboard

正式训练建议把 TensorBoard 和其它固定依赖构建进镜像,避免任务拿到 GPU 后才因为依赖安装、网络或版本问题失败。

后续脚本用于展示 LLaMA-Factory 命令迁移到 AIStudio 后的启动方式。使用时先修改脚本顶部的 STORAGE_ROOTMODEL_NAME_OR_PATHDATASETOUTPUT_DIR,并确保 HF_HOME 指向共享存储。

判断使用单机多卡还是多机多卡

先根据训练规模选择启动方式,再回到创建页选择对应的 分布式框架

  • 单机多卡Worker 数量 为 1,在 分布式框架 中选择 单机。脚本使用 torchrun --standalone,不读取 MASTER_ADDRWORLD_SIZERANK
  • 多机多卡Worker 数量 大于 1,在 分布式框架 中选择 PyTorch DDP。平台会为各 Worker 注入 DDP 环境变量,脚本读取这些变量后传给 torchrun

多机训练通常需要稳定的训练网。需要跨 Worker 高速通信时,优先选择支持 IB/RoCE 的规格,并按任务创建页提示开启 RDMA 配置。RDMA 的适用条件见RDMA 网络

编写单机多卡启动命令

单机多卡任务只运行 1 个 Worker,不依赖 AIStudio 注入的 DDP 环境变量。脚本自动读取当前 Worker 上的 GPU 数量,并使用 torchrun --standalone 启动 LLaMA-Factory。

将以下脚本按需修改后填写到 启动命令。脚本顶部的路径和训练参数是主要替换点,后半段用于展示可靠启动、日志保存和失败状态返回方式。

language-bash
#!/usr/bin/env bash
set -euo pipefail

echo "=== [Phase] Initializing LLaMA-Factory training ==="

################## 按您的训练任务修改 ##################
# 示例个人路径,请替换为您自己的共享存储挂载路径
STORAGE_ROOT="${STORAGE_ROOT:-/mnt/zhaoyinghao}"

export HF_ENDPOINT="${HF_ENDPOINT:-https://hf-mirror.com}"
export HF_HOME="${HF_HOME:-${STORAGE_ROOT}/huggingface}"

TEMPLATE="${TEMPLATE:-llama3}"
MODEL_NAME_OR_PATH="${MODEL_NAME_OR_PATH:-${STORAGE_ROOT}/Meta-Llama-3-8B-Instruct/}"
DATASET="${DATASET:-alpaca_en_demo}"
OUTPUT_DIR="${OUTPUT_DIR:-${STORAGE_ROOT}/saves/llama3-8b/lora/}"
KEEP_ALIVE_ON_FAIL="${KEEP_ALIVE_ON_FAIL:-0}"

################## 启动前检查 ##################
test -d /app
test -d "${MODEL_NAME_OR_PATH}"
mkdir -p "${OUTPUT_DIR}"

GPUS_PER_NODE="$(nvidia-smi --query-gpu=index --format=csv,noheader | wc -l | tr -d ' ')"
if [[ "${GPUS_PER_NODE}" -lt 1 ]]; then
    echo "No GPU detected on this Worker."
    exit 1
fi

DISTRIBUTED_ARGS=(
    --standalone
    --nnodes "1"
    --nproc_per_node "${GPUS_PER_NODE}"
)

cd /app

echo "=== [Phase] Starting torchrun: gpus_per_node=${GPUS_PER_NODE} ==="

RET=0

torchrun "${DISTRIBUTED_ARGS[@]}" \
    src/train.py \
    --stage sft \
    --model_name_or_path "${MODEL_NAME_OR_PATH}" \
    --do_train \
    --dataset "${DATASET}" \
    --template "${TEMPLATE}" \
    --finetuning_type lora \
    --output_dir "${OUTPUT_DIR}" \
    --overwrite_cache \
    --per_device_train_batch_size 1 \
    --gradient_accumulation_steps 8 \
    --lr_scheduler_type cosine \
    --logging_steps 100 \
    --save_steps 500 \
    --learning_rate 1e-4 \
    --num_train_epochs 20.0 \
    --plot_loss \
    --report_to tensorboard \
    --bf16 > >(tee -i "${OUTPUT_DIR}/node-0.log") 2>&1 || RET=$?

sleep 2

if [[ "${RET}" -ne 0 ]]; then
    echo "Training failed with exit code ${RET}."
    if [[ "${KEEP_ALIVE_ON_FAIL}" == "1" ]]; then
        echo "Keeping container alive for debugging. GPU resources remain occupied during this time."
        sleep 10000
    fi
else
    echo "=== [Phase] Training finished successfully ==="
fi

exit "${RET}"

脚本使用 Process Substitution 保存日志,平台看到的退出结果仍来自 torchrun。如果需要失败后保留现场,将环境变量 KEEP_ALIVE_ON_FAIL 设置为 1;调试结束后关闭该设置,避免任务失败后继续占用 GPU。

读取 AIStudio 注入的 DDP 环境变量

只有在 Worker 数量 大于 1,并且 分布式框架 选择 PyTorch DDP 时,AIStudio 才会为多 Worker DDP 启动注入以下变量:

  • MASTER_ADDR:主 Worker 地址,对应 torchrun --master_addr
  • MASTER_PORT:主 Worker 端口,对应 torchrun --master_port
  • WORLD_SIZE:Worker 数量,对应 torchrun --nnodes
  • RANK:当前 Worker 编号,对应 torchrun --node_rank

警告

AIStudio 注入的 WORLD_SIZE 表示 Worker 数量。PyTorch 训练进程中的 WORLD_SIZE 表示总进程数,通常等于 Worker 数量 x 每个 Worker 的 GPU 数量。在启动脚本中建议把平台变量保存为 NNODEStorchrun 会为训练进程设置 PyTorch 自己的 WORLD_SIZE

编写多机多卡启动命令

多机多卡任务会在每个 Worker 上执行同一份 启动命令。脚本必须读取平台注入的 MASTER_ADDRWORLD_SIZERANK,并把它们传给 torchrun。如果这些变量缺失,脚本应立即失败,避免在多机任务中误启动成单机训练。

将以下脚本按需修改后填写到 启动命令。脚本顶部的路径和训练参数是主要替换点;MASTER_ADDRWORLD_SIZERANK 由多 Worker PyTorch DDP 任务注入。

language-bash
#!/usr/bin/env bash
set -euo pipefail

echo "=== [Phase] Initializing LLaMA-Factory DDP training ==="

################## 按您的训练任务修改 ##################
# 示例个人路径,请替换为您自己的共享存储挂载路径
STORAGE_ROOT="${STORAGE_ROOT:-/mnt/zhaoyinghao}"

export HF_ENDPOINT="${HF_ENDPOINT:-https://hf-mirror.com}"
export HF_HOME="${HF_HOME:-${STORAGE_ROOT}/huggingface}"

TEMPLATE="${TEMPLATE:-llama3}"
MODEL_NAME_OR_PATH="${MODEL_NAME_OR_PATH:-${STORAGE_ROOT}/Meta-Llama-3-8B-Instruct/}"
DATASET="${DATASET:-alpaca_en_demo}"
OUTPUT_DIR="${OUTPUT_DIR:-${STORAGE_ROOT}/saves/llama3-8b/lora/}"
KEEP_ALIVE_ON_FAIL="${KEEP_ALIVE_ON_FAIL:-0}"

################## 启动前检查 ##################
test -d /app
test -d "${MODEL_NAME_OR_PATH}"
mkdir -p "${OUTPUT_DIR}"

GPUS_PER_NODE="$(nvidia-smi --query-gpu=index --format=csv,noheader | wc -l | tr -d ' ')"
if [[ "${GPUS_PER_NODE}" -lt 1 ]]; then
    echo "No GPU detected on this Worker."
    exit 1
fi

NNODES="${WORLD_SIZE:?AIStudio WORLD_SIZE is required for multi-Worker DDP jobs}"
NODE_RANK="${RANK:?AIStudio RANK is required for multi-Worker DDP jobs}"
MASTER_ADDR="${MASTER_ADDR:?AIStudio MASTER_ADDR is required for multi-Worker DDP jobs}"
MASTER_PORT="${MASTER_PORT:-29500}"
TOTAL_PROCS=$((GPUS_PER_NODE * NNODES))

DISTRIBUTED_ARGS=(
    --nproc_per_node "${GPUS_PER_NODE}"
    --nnodes "${NNODES}"
    --node_rank "${NODE_RANK}"
    --master_addr "${MASTER_ADDR}"
    --master_port "${MASTER_PORT}"
)

cd /app

echo "=== [Phase] Starting torchrun: nnodes=${NNODES} node_rank=${NODE_RANK} gpus_per_node=${GPUS_PER_NODE} total_procs=${TOTAL_PROCS} master=${MASTER_ADDR}:${MASTER_PORT} ==="

RET=0

torchrun "${DISTRIBUTED_ARGS[@]}" \
    src/train.py \
    --stage sft \
    --model_name_or_path "${MODEL_NAME_OR_PATH}" \
    --do_train \
    --dataset "${DATASET}" \
    --template "${TEMPLATE}" \
    --finetuning_type lora \
    --output_dir "${OUTPUT_DIR}" \
    --overwrite_cache \
    --per_device_train_batch_size 1 \
    --gradient_accumulation_steps 8 \
    --lr_scheduler_type cosine \
    --logging_steps 100 \
    --save_steps 500 \
    --learning_rate 1e-4 \
    --num_train_epochs 20.0 \
    --plot_loss \
    --report_to tensorboard \
    --bf16 > >(tee -i "${OUTPUT_DIR}/node-${NODE_RANK}.log") 2>&1 || RET=$?

sleep 2

if [[ "${RET}" -ne 0 ]]; then
    echo "Training failed with exit code ${RET}."
    if [[ "${KEEP_ALIVE_ON_FAIL}" == "1" ]]; then
        echo "Keeping container alive for debugging. GPU resources remain occupied during this time."
        sleep 10000
    fi
else
    echo "=== [Phase] Training finished successfully ==="
fi

exit "${RET}"

如果是 2 个 Worker、每个 Worker 8 张 GPU 的任务,脚本会读取到 NNODES=2、每个 Worker 的 GPUS_PER_NODE=8,并让 torchrun 启动总计 16 个训练进程。更多 PyTorch DDP 启动规则见编写 PyTorch DDP torchrun 启动脚本

确认 LLaMA-Factory 参数和输出路径

提交前先确认 LLaMA-Factory 参数与平台路径一致:

  • --model_name_or_path 指向共享存储中的模型目录。
  • --dataset 是 LLaMA-Factory 配置中已经注册的数据集名称。
  • --template 与模型类型匹配。
  • --output_dir 指向共享存储,任务结束后仍可读取。
  • --report_to tensorboard 需要镜像中已经安装 TensorBoard。
  • 日志文件写入 ${OUTPUT_DIR}/node-${NODE_RANK}.log 或等价的共享存储路径。

提交任务后,先在任务日志中查找脚本打印的 Starting torchrun 阶段标记,确认 nnodesnode_rankgpus_per_nodemaster 符合创建页配置。TensorBoard 日志和训练输出的查看方式见TensorBoard获取训练结果

排查 LLaMA-Factory 常见失败

  • 启动后找不到 /appsrc/train.py:确认镜像是否为 LLaMA-Factory 镜像,或把脚本中的 cd /app 改为训练代码实际目录。
  • 模型加载失败:检查 MODEL_NAME_OR_PATH 是否已经挂载到当前 Worker,路径是否位于共享存储中。
  • 数据集加载失败:检查 DATASET 是否已在 LLaMA-Factory 数据集配置中注册,数据文件是否随镜像或共享存储一起提供。
  • 第一个 batch 前失败:检查 template、tokenizer、数据字段、最大长度和 LoRA 配置是否与模型和数据集匹配。
  • 多机 DDP 初始化超时:确认创建页选择 PyTorch DDPWorker 数量 大于 1,并且各 Worker 日志中的 node_rank 不同。
  • TensorBoard 没有曲线:确认镜像包含 TensorBoard,--report_to tensorboard 已开启,TensorBoard 配置路径与 OUTPUT_DIR 下的实际日志目录一致。如果导入官方镜像或其它自带镜像,先用 python -m pip show tensorboard 确认 TensorBoard 是否已安装。
  • 任务显示成功但没有结果:检查 OUTPUT_DIR 是否为共享存储路径,并确认启动命令没有在训练失败后隐藏 torchrun 的退出结果。详见编写可靠启动命令

进入 Worker 调试

任务仍在运行时,可在任务详情页登录 Worker 的 Web Terminal,查看文件、进程、GPU 状态和日志。需要统一下发检查命令时,可使用 atlctl 命令行调试工具

如果需要失败后保留现场,将 KEEP_ALIVE_ON_FAIL=1 配置到环境变量或脚本中。该设置会在失败后继续占用 GPU,完成调试后应关闭。