• 文档 >
  • 使用 torchtune 的端到端工作流程
快捷方式

使用 torchtune 的端到端工作流程

在本教程中,我们将逐步介绍如何使用 torchtune 微调、评估、可选量化,然后使用您最喜欢的 LLM 运行生成。我们还将介绍如何与 torchtune 无缝地使用社区中的一些流行工具和库。

本教程将涵盖的内容
  • torchtune 中除了微调之外还提供不同类型的食谱

  • 连接所有这些食谱的端到端示例

  • 您可以与 torchtune 一起使用的不同工具和库

先决条件

概述

微调 LLM 通常只是更大工作流程中的一步。您可能拥有的示例工作流程可能如下所示

  • HF Hub 下载流行模型

  • 使用相关的微调技术微调模型。使用的确切技术将取决于模型、训练数据的数量和性质、硬件设置以及模型将用于的最终任务等因素

  • 在一些基准上评估模型以验证模型质量

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

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

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

在本教程中,我们将介绍如何使用 torchtune 完成上述所有操作,利用与生态系统中流行工具和库的集成。

在本教程中,我们将使用 Llama2 7B 模型。您可以在 此处 找到 torchtune 支持的完整模型集。


下载 Llama2 7B

在本教程中,我们将使用 Llama2 7B 模式的 Hugging Face 模型权重。有关检查点格式以及 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 内存中使用 LoRA 微调 Llama2 7B 模型。有关如何使用 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 检查点和正确的检查点文件。我们只需要更新模型和分词器的检查点目录。让我们使用 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 的评估工具运行评估

我们已经微调了一个模型。但是,这个模型到底表现如何呢?让我们运行一些评估!

torchtune 与 EleutherAI 的评估工具 集成在一起。可以通过 eleuther_eval 食谱获得一个示例。在本教程中,我们将通过修改其关联配置 eleuther_evaluation.yaml 直接使用此食谱。

注意

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

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

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

确实,这座桥很酷!看来我们的 LLM 对湾区略知一二!


使用量化加速生成

我们依赖于 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 中直接对量化模型进行生成,如 此自述文件 中所述。这样,你可以将自己的结果与之前链接的表中的结果进行比较。


在其他库中使用 torchtune 检查点

如上所述,处理检查点转换的优势之一是你可以直接使用标准格式。这有助于与其他库的互操作性,因为 torchtune 不会再添加另一种格式。

让我们看一个使用流行代码库运行 LLM 的高性能推理的示例 - gpt-fast。本节假设你在机器上克隆了该存储库。

gpt-fast 对检查点和键到文件映射的可用性做出了一些假设,即一个文件映射参数名称到包含它们的​​文件。让我们通过创建此映射文件来满足这些假设。假设我们将使用 <new_dir>/Llama-2-7B-hf 作为该目录。 gpt-fast 假设包含检查点的目录具有与 HF 存储库 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://hugging-face.cn/<hf-repo-id>/tree/main/.

注意

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

有关 huggingface-cli upload 功能的更多详细信息,请查看 Hugging Face 文档


希望本教程能让你了解如何将 torchtune 用于自己的工作流程。祝你调优愉快!

文档

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

查看文档

教程

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

查看教程

资源

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

查看资源