目录

端到端工作流与torchtune

在本教程中,我们将通过一个端到端的示例,展示如何使用 torchtune 对您喜爱的 LLM 进行微调、评估、可选的量化,然后执行生成。我们还将介绍如何与社区中一些流行的工具和库无缝配合使用 torchtune。

本教程将涵盖以下内容:
  • torchtune 中除微调外可用的其他类型配方

  • 连接所有这些配方的端到端示例

  • 您可以与 torchtune 配合使用的各种工具和库

先决条件

概览

微调大语言模型通常只是更大工作流中的一个步骤。您可能拥有的一个示例工作流如下所示:

  • HF Hub 下载一个流行的模型

  • 使用相关的微调技术对模型进行微调。具体采用的微调技术将取决于多种因素,包括模型本身、训练数据的数量与性质、您的硬件配置以及模型最终要执行的任务。

  • 在部分基准测试上评估模型,以验证模型质量

  • 运行几次生成,以确保模型输出看起来合理

  • 量化模型以实现高效推理

  • [可选] 导出模型以适配特定环境,例如在手机上进行推理

在本教程中,我们将介绍如何利用 torchtune 完成上述所有内容,并借助生态系统中流行工具和库的集成。

我们将在这个教程中使用 Llama2 7B 模型。您可以在 这里 找到 torchtune 支持的完整模型列表。


下载 Llama2 7B

在本教程中,我们将使用 Hugging Face 的 Llama2 7B 模型权重。 有关检查点格式以及 torchtune 如何处理这些内容的更多信息,请查看 此关于 检查点 的教程。

要下载 HF 格式的 Llama2 7B 模型,我们将使用 tune CLI。

tune download \
meta-llama/Llama-2-7b-hf \
--output-dir <checkpoint_dir> \
--hf-token <ACCESS TOKEN>

请注意<checkpoint_dir>,在本教程中我们将多次使用它。


使用LoRA微调模型

对于本教程,我们将使用LoRA对模型进行微调。LoRA是一种参数高效的微调技术,特别适用于您没有太多GPU内存的情况。LoRA冻结基础LLM并添加一小部分可学习参数。这有助于保持与梯度和优化器状态相关的内存较低。使用torchtune,您应该能够在RTX 3090/4090上使用bfloat16,在不到16GB的GPU内存下对Llama2 7B模型进行LoRA微调。有关如何使用LoRA的更多信息,请查看我们的 LoRA教程

我们将使用我们的 单设备LoRA配方 进行微调,并使用来自 默认配置 的标准设置。

这将使用 batch_size=2dtype=bfloat16 来微调我们的模型。在这些设置下,模型的峰值内存使用量约为 16GB,每个 epoch 的总训练时间约为两小时。 我们需要对配置进行一些更改,以确保我们的配方可以访问正确的检查点。

让我们使用 tune CLI 为此用例寻找合适的配置。

tune ls

RECIPE                                   CONFIG
full_finetune_single_device              llama2/7B_full_low_memory
                                         mistral/7B_full_low_memory
full_finetune_distributed                llama2/7B_full
                                         llama2/13B_full
                                         mistral/7B_full
lora_finetune_single_device              llama2/7B_lora_single_device
                                         llama2/7B_qlora_single_device
                                         mistral/7B_lora_single_device
...

在这个教程中,我们将使用 llama2/7B_lora_single_device 配置。

配置已指向 HF Checkpointer 和正确的检查点文件。 我们只需更新模型和分词器的检查点目录即可。让我们在使用 tune CLI 启动训练时,通过覆盖参数来完成此操作!

tune run lora_finetune_single_device \
--config llama2/7B_lora_single_device \
checkpointer.checkpoint_dir=<checkpoint_dir> \
tokenizer.path=<checkpoint_dir>/tokenizer.model \
checkpointer.output_dir=<checkpoint_dir>

训练完成后,您将在日志中看到以下内容。

[_checkpointer.py:473] Model checkpoint of size 9.98 GB saved to <checkpoint_dir>/hf_model_0001_0.pt

[_checkpointer.py:473] Model checkpoint of size 3.50 GB saved to <checkpoint_dir>/hf_model_0002_0.pt

[_checkpointer.py:484] Adapter checkpoint of size 0.01 GB saved to <checkpoint_dir>/adapter_0.pt

最终训练的权重与原始模型合并,并分割到两个检查点文件中,类似于来自 HF Hub 的源检查点(有关更多详细信息,请参阅 LoRA 教程)。实际上,这些检查点之间的键将是相同的。我们还有一个第三检查点文件,其大小要小得多,包含学习到的 LoRA 适配器权重。对于本教程,我们只使用模型检查点,而不使用适配器权重。


使用EleutherAI的Eval Harness运行评估

我们已经对模型进行了微调。但这个模型的实际表现究竟如何呢?让我们运行一些评估!

torchtune 集成了 EleutherAI 的评估工具包。 一个示例可以通过 eleuther_eval 配方获得。在这个教程中,我们将直接使用这个配方,并通过 修改其关联的配置文件 eleuther_evaluation.yaml 来实现。

注意

本教程的这一部分,您应该首先运行 pip install lm_eval==0.4.* 来安装 EleutherAI 评估工具包。

由于我们计划更新所有检查点文件以指向我们的微调检查点, 让我们首先将配置文件复制到本地工作目录,以便进行修改。这比通过命令行界面覆盖所有这些元素要容易得多。

tune cp eleuther_evaluation ./custom_eval_config.yaml \

在这个教程中,我们将使用来自测试套件的 truthfulqa_mc2 任务。 该任务衡量模型在回答问题时保持真实性的倾向,并测量模型在问题后跟随一个或多个正确答案和一个或多个错误答案的情况下进行零样本准确性的能力。让我们首先运行一个未经微调的基础版本。

tune run eleuther_eval --config ./custom_eval_config.yaml
checkpointer.checkpoint_dir=<checkpoint_dir> \
tokenizer.path=<checkpoint_dir>/tokenizer.model

[evaluator.py:324] Running loglikelihood requests
[eleuther_eval.py:195] Eval completed in 121.27 seconds.
[eleuther_eval.py:197] truthfulqa_mc2: {'acc,none': 0.388...

该模型的准确率约为 38.8%。让我们将其与微调后的模型进行比较。

首先,我们将 custom_eval_config.yaml 修改为包含微调后的检查点。

checkpointer:
    _component_: torchtune.training.FullModelHFCheckpointer

    # directory with the checkpoint files
    # this should match the output_dir specified during
    # finetuning
    checkpoint_dir: <checkpoint_dir>

    # checkpoint files for the fine-tuned model. This should
    # match what's shown in the logs above
    checkpoint_files: [
        hf_model_0001_0.pt,
        hf_model_0002_0.pt,
    ]

    output_dir: <checkpoint_dir>
    model_type: LLAMA2

# Make sure to update the tokenizer path to the right
# checkpoint directory as well
tokenizer:
    _component_: torchtune.models.llama2.llama2_tokenizer
    path: <checkpoint_dir>/tokenizer.model

现在,让我们运行该示例。

tune run eleuther_eval --config ./custom_eval_config.yaml

结果应大致如下所示。

[evaluator.py:324] Running loglikelihood requests
[eleuther_eval.py:195] Eval completed in 121.27 seconds.
[eleuther_eval.py:197] truthfulqa_mc2: {'acc,none': 0.489 ...

我们的微调模型在此任务上取得了约 48% 的准确率,比基线高出约 10 个百分点。太棒了!看来我们的微调确实起到了作用。


生成

我们已进行了一些评估,模型表现似乎不错。但它是否真的能为您关注的提示生成有意义的文本?让我们一探究竟!

为此,我们将使用 生成示例 和相关的 配置

让我们先将配置文件复制到本地工作目录,以便进行修改。

tune cp generation ./custom_generation_config.yaml

让我们修改 custom_generation_config.yaml 以包含以下更改。

checkpointer:
    _component_: torchtune.training.FullModelHFCheckpointer

    # directory with the checkpoint files
    # this should match the output_dir specified during
    # finetuning
    checkpoint_dir: <checkpoint_dir>

    # checkpoint files for the fine-tuned model. This should
    # match what's shown in the logs above
    checkpoint_files: [
        hf_model_0001_0.pt,
        hf_model_0002_0.pt,
    ]

    output_dir: <checkpoint_dir>
    model_type: LLAMA2

# Make sure to update the tokenizer path to the right
# checkpoint directory as well
tokenizer:
    _component_: torchtune.models.llama2.llama2_tokenizer
    path: <checkpoint_dir>/tokenizer.model

配置更新后,让我们开始生成!我们将使用默认的采样设置,top_k=300temperature=0.8。这些参数控制概率的计算方式。这些是 Llama2 7B 的标准设置,我们建议在调整这些参数之前先检查模型。

我们将使用与配置中不同的提示词。

tune run generate --config ./custom_generation_config.yaml \
prompt="What are some interesting sites to visit in the Bay Area?"

生成完成后,您将在日志中看到以下内容。

[generate.py:92] Exploratorium in San Francisco has made the cover of Time Magazine,
                 and its awesome. And the bridge is pretty cool...

[generate.py:96] Time for inference: 11.61 sec total, 25.83 tokens/sec
[generate.py:99] Memory used: 15.72 GB

确实,这座桥非常酷!看来我们的语言模型对湾区略知一二!


使用量化加速生成

我们依赖 torchao 进行 训练后量化。 在安装 torchao 后,我们可以运行以下命令来量化微调后的模型:

# we also support `int8_weight_only()` and `int8_dynamic_activation_int8_weight()`, see
# https://github.com/pytorch/ao/tree/main/torchao/quantization#other-available-quantization-techniques
# for a full list of techniques that we support
from torchao.quantization.quant_api import quantize_, int4_weight_only
quantize_(model, int4_weight_only())

量化后,我们依赖 torch.compile 来实现性能提升。详情请参阅 此示例用法

torchao 还提供了 此表格,列出了 llama2llama3 的性能和准确率结果。

对于Llama模型,您可以直接在量化模型上使用他们的generate.py脚本通过torchao进行生成,如此readme中所述。这样您就可以将您的结果与之前链接的表格中的结果进行比较。


使用torchtune检查点与其他库

正如上文所述,处理检查点转换的一个好处是您可以直接使用标准格式。由于 torchtune 并未引入新的格式,这有助于与其他库实现互操作性。

让我们来看一个使用流行的代码库进行高性能推理的例子—— gpt-fast。本节假设您已经在机器上克隆了该仓库。

gpt-fast 假设了检查点的一些情况以及键到文件映射的可用性,即一个将参数名称映射到包含它们的文件的文件。让我们通过创建这个映射文件来满足这些假设。让我们假设我们将使用 <new_dir>/Llama-2-7B-hf 作为目录。 gpt-fast 假设检查点所在的目录具有与 HF repo-id 相同的格式。

import json
import torch

# create the output dictionary
output_dict = {"weight_map": {}}

# Load the checkpoints
sd_1 = torch.load('<checkpoint_dir>/hf_model_0001_0.pt', mmap=True, map_location='cpu')
sd_2 = torch.load('<checkpoint_dir>/hf_model_0002_0.pt', mmap=True, map_location='cpu')

# create the weight map
for key in sd_1.keys():
    output_dict['weight_map'][key] =  "hf_model_0001_0.pt"
for key in sd_2.keys():
    output_dict['weight_map'][key] =  "hf_model_0002_0.pt"

with open('<new_dir>/Llama-2-7B-hf/pytorch_model.bin.index.json', 'w') as f:
    json.dump(output_dict, f)

既然我们已经创建了 weight_map,现在就来复制我们的检查点。

cp  <checkpoint_dir>/hf_model_0001_0.pt  <new_dir>/Llama-2-7B-hf/
cp  <checkpoint_dir>/hf_model_0002_0.pt  <new_dir>/Llama-2-7B-hf/
cp  <checkpoint_dir>/tokenizer.model     <new_dir>/Llama-2-7B-hf/

一旦目录结构搭建完成,让我们转换检查点并运行推理!

cd gpt-fast/

# convert the checkpoints into a format readable by gpt-fast
python scripts/convert_hf_checkpoint.py \
--checkpoint_dir <new_dir>/Llama-2-7B-hf/ \
--model 7B

# run inference using the converted model
python generate.py \
--compile \
--checkpoint_path <new_dir>/Llama-2-7B-hf/model.pth \
--device cuda

输出结果应如下所示:

Hello, my name is Justin. I am a middle school math teacher
at WS Middle School ...

Time for inference 5: 1.94 sec total, 103.28 tokens/sec
Bandwidth achieved: 1391.84 GB/sec

就是这样!尝试您自己的提示词吧!

将您的模型上传到 Hugging Face Hub

你的新模型运行良好,你想与世界分享它。最简单的方法是利用 huggingface-cli 命令,它可以与 torchtune 无缝配合。只需将 CLI 指向你的微调模型目录,如下所示:

huggingface-cli upload <hf-repo-id> <checkpoint-dir>

该命令应输出指向您在 Hub 上仓库的链接。如果该仓库尚不存在,系统将自动创建:

https://huggingface.co/<hf-repo-id>/tree/main/.

注意

上传之前,请确保您已通过运行 huggingface-cli login 与 Hugging Face 进行了身份验证。

有关huggingface-cli upload功能的更多详情,请查看


希望本教程能为您提供一些关于如何在您的工作流中使用 torchtune 的见解。祝您调优愉快!

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

获取面向初学者和高级开发人员的深入教程

查看教程

资源

查找开发资源并解答您的问题

查看资源