数据科学

如何使用 NVIDIA NeMo 技能简化复杂的 LLM 工作流程

改进 LLM 的典型方法涉及多个阶段:合成数据生成 (SDG) 、通过监督式微调 (SFT) 或强化学习 (RL) 进行模型训练以及模型评估。每个阶段都需要使用不同的库,这些库通常很难设置,而且难以一起使用。

例如,您可以使用 NVIDIA TensorRT-LLMvLLM 进行 SDG 训练,使用 NVIDIA NeMoverl 进行训练。在这种情况下,您需要调用许多不同的脚本和容器,将 Hugging Face 检查点转换为 TensorRT-LLM,执行大规模 SDG,将数据和模型转换为 NeMo 格式,并在各种基准测试中运行训练和评估。

为了简化这一复杂的工作流程,NVIDIA 开发了 NeMo 技能库。它提供了无缝连接不同框架的高级抽象,使其能够以统一和可互换的方式使用。NeMo-Skill 还可以轻松地从快速本地原型设计过渡到在 Slurm 集群上编排大规模作业。

本文将向您介绍帮助 NVIDIA 团队赢得 AIMO2 Kaggle 比赛的简化版制作流程。该过程从数学推理能力有限的模型开始。然后,通过一系列 NeMo 技能作业来增强这些技能。

如果您继续关注,则需要使用配备 8 个 NVIDIA A100 (或更新版本) GPU 的 NVIDIA DGX 机箱,或具有类似配置节点的 Slurm 集群。演示中使用的所有命令都使用 NeMo 技能进行了测试

视频 1。了解如何开始使用 NeMo 技能构建强大的训练和推理工作流

在本地或 Slurm 上设置 NeMo 技能

为了编排复杂的作业,NeMo-Skills 使用 Docker 容器。如果在本地运行,或使用支持 NVIDIA/pyxis 的 Slurm 集群,则需要安装 NVIDIA Container Toolkit。在这两种情况下,建议您在本地工作站上设置 NeMo-Skill,并将其配置为通过 SSH 访问 Slurm 集群。它会负责上传您的代码并调度作业。

在本地运行以下命令以完成设置:

pip install git+https://github.com/NVIDIA/NeMo-Skills.git  
ns setup

当系统提示您添加挂载时,请将文件夹定义为/workspace。后续命令中将使用此文件夹。有关更多详细信息,请参阅 NeMo-Skills 配置文档。

在以下各节中,我们将始终使用带有 --cluster=local 参数的命令,如果这些命令在 Slurm 上运行,您需要将其更改为 --cluster=slurm (或您在设置过程中命名的任何配置) 。使用 Slurm 时,所有命令将立即完成,并在集群队列中调度作业。

权重和偏差 (W&B) 将用于方便地记录评估结果和模型输出。您可以通过从命令中删除所有与 W&B 相关的参数来禁用此功能。

建立基准

在努力提升 LLM 技能之前,请先评估原始模型,看看它所处的位置。请注意,本教程适用于 Qwen2.5 14B Instruct,并使用 AIME24 和 AIME25 评估模型的数学推理能力。vLLM 用作推理库。

# download the model
ns run_cmd --expname=download-14b --log_dir=/workspace/Qwen2.5-14B-Instruct --cluster=local \
    huggingface-cli download Qwen/Qwen2.5-14B-Instruct --local-dir /workspace/Qwen2.5-14B-Instruct
# prepare benchmark data
ns prepare_data aime24 aime25
# launch evaluation
ns eval \
    --cluster=local \
    --expname=baseline-eval \
    --run_after=download-14b \
    --model=/workspace/Qwen2.5-14B-Instruct \
    --server_type=vllm \
    --server_gpus=8 \
    --benchmarks=aime24:8,aime25:8 \
    --output_dir=/workspace/evals/baseline
# summarize results, after the evaluation job is done
ns summarize_results --cluster=local /workspace/evals/baseline --wandb_name=baseline-evals

在 aime24/ 25 基准测试中,ns eval 命令将为每个样本运行八代,summarize_results 将报告平均通过率 = 1、通过率 = 8 和大多数 = 8 个指标。

--------------------------------- aime24 --------------------------------
evaluation_mode | num_entries | avg_tokens | symbolic_correct | no_answer
pass@1[8]       | 30          | 829        | 11.67%           | 0.00%
majority@8      | 30          | 829        | 13.33%           | 0.00%
pass@8          | 30          | 829        | 33.33%           | 0.00%


--------------------------------- aime25 --------------------------------
evaluation_mode | num_entries | avg_tokens | symbolic_correct | no_answer
pass@1[8]       | 30          | 834        | 11.67%           | 0.42%
majority@8      | 30          | 834        | 20.00%           | 0.00%
pass@8          | 30          | 834        | 26.67%           | 0.00%

请注意,由于 LLM 代次的随机性质,您可能无法获得完全相同的数字。有关 ns eval 工作流选项的更多信息,请参阅 NeMo 技能评估文档。

将 SDG 与 TensorRT-LLM 或 vLLM 结合使用

为改进既定基准,您可以生成一些合成数学数据。按照 OpenMathReasoning recipe,使用少量 AoPS 论坛讨论,并使用 Qwen2.5 14B Instruct 从中提取问题。然后,使用 QwQ 32B 生成新的“长推理”解决方案。这些问题解决方案对将用于训练。

这种简化的工作流非常基础,并且忽略了多个重要步骤 (例如,提取真值答案和筛选正确性) 。但是,教会 14B 模型如何使用长推理并显著改善基准结果就足够了。

首先,下载数据以及问题提取提示和后处理脚本:

ns run_cmd --expname=prepare-data --log_dir=/workspace/prepare-data --cluster=local \
    'cd /workspace && \
    export DOWNLOAD_PREFIX=https://raw.githubusercontent.com/NVIDIA/NeMo-Skills/refs/heads/main/recipes/openmathreasoning && \
    wget $DOWNLOAD_PREFIX/scripts/prepare_raw_data.py && \
    wget $DOWNLOAD_PREFIX/prompts/extract-problems.yaml && \
    wget $DOWNLOAD_PREFIX/scripts/postprocess_problem_extraction.py && \
    python prepare_raw_data.py && \
    head -n 1000 raw_aops_data.jsonl > data.jsonl'

data.jsonl 中的字段将用于填充 extract-problems.yaml 中的提示词,并将此最终提示词传递给 LLM。如需了解详情,您可以查看数据文件并提示脚本。有关提示格式的更多详细信息,请参阅 NeMo 技能提示文档。

接下来,使用 NeMo-Skills Python API 运行生成工作流

# run_sdg.py
from nemo_skills.pipeline.cli import generate, wrap_arguments

cluster = "local"
num_gpus = 8

postprocess_cmd = (
    f"python /workspace/postprocess_problem_extraction.py "
    f"    /workspace/sdg/problems/output.jsonl "
    f"    /workspace/sdg/extracted-problems.jsonl "
)

generate(
    ctx=wrap_arguments(
        f"++prompt_config=/workspace/extract-problems.yaml "
        f"++prompt_template=qwen-instruct "
    ),
    cluster=cluster,
    input_file="/workspace/data.jsonl",
    output_dir="/workspace/sdg/problems",
    postprocess_cmd=postprocess_cmd,
    expname="problem-extraction",
    run_after=["prepare-data", "download-14b"],
    model="/workspace/Qwen2.5-14B-Instruct",
    server_type="vllm",
    server_gpus=num_gpus,
    # remove these parameters to disable wandb logging
    log_samples=True,
    wandb_group="sdg",
)

您可以检查 sdg/extracted-problems.yaml 以查看输出。应有一个新字段,其中包含提取的问题。使用 QwQ 32B 模型生成这些问题的解决方案。由于此模型会生成包含许多 token 的长推理解决方案,因此请将检查点转换TensorRT-LLM 格式,以获得更快的推理速度。

# download the model
ns run_cmd --expname=download-qwq --log_dir=/workspace/QwQ-32B --cluster=local \
    huggingface-cli download Qwen/QwQ-32B --local-dir /workspace/QwQ-32B
# convert to trtllm format
ns convert \
    --cluster=local \
    --expname=convert-qwq-trtllm \
    --run_after=download-qwq \
    --input_model=/workspace/QwQ-32B \
    --output_model=/workspace/qwq32b-trtllm \
    --convert_from=hf \
    --convert_to=trtllm \
    --num_gpus=8 \
    --model_type=qwen \
    --hf_model_name=Qwen/QwQ-32B \
    --max_seq_len 10000

下一步是生成解决方案。将以下代码添加到 sdg.py 脚本的末尾并重新运行。默认情况下,它将跳过问题提取步骤 (如果已完成) ,因为 NeMo-Skill 可以检测生成是否已经完成。

generate(
    ctx=wrap_arguments(
        f"++prompt_config=generic/math "
        f"++inference.temperature=0.6 "
        f"++inference.tokens_to_generate=8192 "
        f"++prompt_template=qwen-instruct "
    ),
    cluster=cluster,
    input_file="/workspace/sdg/extracted-problems.jsonl",
    output_dir="/workspace/sdg/solutions",
    expname="solution-generation",
    run_after=["problem-extraction", "convert-qwq-trtllm"],
    model="/workspace/qwq32b-trtllm",
    server_type="trtllm",
    server_gpus=num_gpus,
    # remove these parameters to disable wandb logging
    log_samples=True,
    wandb_group="sdg",
)

这项工作可能需要几个小时才能完成。如果您能够在 Slurm 集群的多个节点上运行,则可以通过添加 num_chunks=N 在 N 个独立作业中对其进行并行化。您可以在 NeMo 技能生成文档中详细了解此参数和其他参数。

如果您已启用 W&B 日志记录,则可以检查其中的几代产品。图 1 显示了 W&B 控制面板中 ns 生成工作流的输出。您可以打开一个实验,切换到“Files” (文件) 选项卡,然后单击 samples.json 来找到它。

Screenshot showing the output of ns generate pipeline logged in the Weights & Biases dashboard.
图 1。W&B 控制面板中 ns generate 管道的输出

使用 NeMo 进行模型训练

生成合成数据后,您可以使用它来微调模型。以下各节将展示如何使用 NeMo-AlignerNeMo-RL 来执行此操作。

首先,按照所需格式准备数据:

ns run_cmd --log_dir=/workspace/prepare-sft-data --expname=prepare-sft-data --run_after=solution-generation --cluster=local \
    'python -m nemo_skills.training.prepare_data \
      ++input_files=/workspace/sdg/solutions/output.jsonl \
      ++output_path=/workspace/sft-data.jsonl \
      ++prompt_config=generic/math \
      ++prompt_template=qwen-instruct \
      ++filters.remove_contaminated=false \
      ++add_unlabeled=true \
      ++filters.remove_no_think_tags=true \
      ++filters.trim_solutions=false'

接下来,将模型转换为 NeMo 格式。您可以跳过此步骤进行 NeMo-RL 训练。

ns convert \
    --cluster=local \
    --expname=convert-14b-nemo \
    --run_after=download-14b \
    --input_model=/workspace/Qwen2.5-14B-Instruct \
    --output_model=/workspace/qwen2.5-14b-instruct-nemo \
    --convert_from=hf \
    --convert_to=nemo \
    --num_gpus=8 \
    --model_type=qwen \
    --hf_model_name=Qwen/Qwen2.5-14B-Instruct

对于 NeMo-Aligner 后端,请使用以下训练命令。添加 --disable_wandb 以禁用 W&B 日志记录。

ns train \
    --cluster=local \
    --expname=training \
    --run_after=convert-14b-nemo \
    --run_after=prepare-sft-data \
    --output_dir=/workspace/training \
    --nemo_model=/workspace/qwen2.5-14b-instruct-nemo \
    --num_nodes=1 \
    --num_gpus=8 \
    --training_data=/workspace/sft-data.jsonl \
    ++model.data.train_ds.max_seq_length=8192 \
    ++model.data.train_ds.global_batch_size=32 \
    ++model.tensor_model_parallel_size=4 \
    ++model.context_parallel_size=2 \
    ++model.optim.lr=1e-5 \
    ++trainer.sft.max_epochs=2

对于 NeMo-RL 后端,请使用以下训练命令。添加 --disable_wandb 以禁用 W&B 日志记录。仅运行其中一个训练命令,不能同时运行 (或相应地更改路径和表达式名称) 。

ns nemo_rl sft \
    --cluster=local \
    --expname=training \
    --run_after=download-14b \
    --run_after=prepare-sft-data \
    --output_dir=/workspace/training \
    --hf_model=/workspace/Qwen2.5-14B-Instruct \
    --num_nodes=1 \
    --num_gpus=8 \
    --training_data=/workspace/sft-data.jsonl \
    --cache_dir=/workspace/nemo-rl-cache \
    --final_hf_path=/workspace/training/qwen2.5-14b-improved-hf \
    ++sft.max_num_epochs=4 \
    ++policy.dtensor_cfg.tensor_parallel_size=8 \
    ++policy.max_total_sequence_length=8192 \
    ++policy.train_global_batch_size=32 \
    ++policy.optimizer.kwargs.lr=1e-5 \
    ++policy.dtensor_cfg.sequence_parallel=true \
    ++policy.dtensor_cfg.activation_checkpointing=true

如需了解有关 SFT 配置的更多信息,请参阅 NeMo-Skills 训练文档。如果您已启用 W&B 日志记录,则可以检查此处的训练指标。

Screenshot of training metrics in the Weights & Biases dashboard.
图 2。W&B 控制面板中的训练指标

最终评估

要检查模型改进,请运行另一个评估。将检查点转换回 Hugging Face 格式,以加快评估速度。如果使用 NeMo-RL 后端进行训练,则可以跳过转换步骤。

# converting back to HF format
ns convert \
   --cluster=local \
   --expname=convert-14b-hf \
   --run_after=training \
   --input_model=/workspace/training/model-averaged-nemo \
   --output_model=/workspace/training/qwen2.5-14b-improved-hf \
   --convert_from=nemo \
   --convert_to=hf \
   --num_gpus=8 \
   --model_type=qwen \
   --hf_model_name=Qwen/Qwen2.5-14B-Instruct
# launching evaluation
ns eval \
    --cluster=local \
    --expname=final-eval \
    --run_after=convert-14b-hf \
    --run_after=training \
    --model=/workspace/training/qwen2.5-14b-improved-hf \
    --server_type=vllm \
    --server_gpus=8 \
    --benchmarks=aime24:8,aime25:8 \
    --output_dir=/workspace/evals/after-training \
    ++inference.tokens_to_generate=16384
# summarize results, after the evaluation job is done
ns summarize_results --cluster=local /workspace/evals/after-training --wandb_name=after-training-evals

此评估应显示两个基准都有不错的改进。图 3 显示了 W&B 控制面板中的评估结果。切换到“Runs” (运行) 面板并单击“Columns” (列) 以自定义显示的指标。

--------------------------------- aime24 --------------------------------
evaluation_mode | num_entries | avg_tokens | symbolic_correct | no_answer
pass@1[8]       | 30          | 13362      | 27.92%           | 55.83%
majority@8      | 30          | 13362      | 40.00%           | 16.67%
pass@8          | 30          | 13362      | 50.00%           | 16.67%


--------------------------------- aime25 --------------------------------
evaluation_mode | num_entries | avg_tokens | symbolic_correct | no_answer
pass@1[8]       | 30          | 13445      | 17.92%           | 53.33%
majority@8      | 30          | 13445      | 26.67%           | 10.00%
pass@8          | 30          | 13445      | 36.67%           | 10.00%
Screenshot of evaluation results in the Weights & Biases dashboard.
图 3。W&B 控制面板中的评估结果

使用 NeMo-Skills 改进任何 LLM

借助 NeMo-Skills,您可以连接提高 LLM 能力所需的各个阶段,从而轻松构建复杂的工作流。这使您能够在不同的训练和推理框架之间无缝切换。本教程中使用的所有命令都可以组合成一个脚本来调度整个作业。只需更改一次生产线,您就可以从本地工作站上的快速原型设计过渡到 Slurm 集群上的大规模实验。

作为练习,请尝试添加 NeMo-Skills 文档中提到的额外过滤步骤。您还可以尝试为每个问题生成多个解决方案,并检查这会如何影响最终评估结果。如您所见,只需一个脚本即可运行从数据生成到模型训练再到评估的所有内容,因此您可以轻松地对管道的任何部分进行更改迭代。

NVIDIA 团队成功使用 NeMo-Skills 开发了多个热门模型和数据集。具体来说,它用于:

开始使用 NeMo-Skills,将其用于您自己的项目。

 

标签