对话式人工智能/自然语言处理

使用 NVIDIA NeMo Megatron 部署 1.3B GPT-3 型号

 

Large language models ( LLMs)是一些能够理解书面语言的最先进的深度学习算法。许多现代 LLM 是使用谷歌 2017 年在 Attention Is All You Need 研究论文中引入的 transformer 网络构建的。

NVIDIA NeMo Megatron 是一个端到端 GPU 加速框架,用于训练和部署高达万亿参数的基于 transformer 的 LLM 。 2022 年 9 月, NVIDIA 宣布 NeMo Megatron is now available in Open Beta ,允许您使用自己的数据训练和部署 LLM 。通过此次发布,几个经过预训练的检查点已上传到 HuggingFace ,使任何人都可以使用 GPU 在本地部署 LLM 。

本文介绍了使用 NeMo Megatron下载、优化和部署 13 亿参数 GPT-3 模型的过程。它包括 NVIDIA Triton Inference Server ,一个强大的开源推理服务软件,可以部署多种模型,并以可扩展的方式为 CPU 和 GPU 上的推理请求提供服务。

系统要求

虽然训练 LLM 需要大量的计算能力,但对于大多数用例来说,可以以小得多的规模部署经过训练的模型进行推理。

HuggingFace 的模型可以部署在具有以下规格的本地机器上:

  • 运行现代 Linux 操作系统(用 Ubuntu 20.04 测试)。
  • NVIDIA Ampere 架构 GPU 或更新版本,具有至少 8 GB GPU 内存。
  • 至少 16 GB 的系统内存。
  • Docker 19.03 版或更新版本,带有 NVIDIA Container Runtime
  • Python 3.7 或更新版本,带有 PIP 。
  • 用于下载模型的可靠 Internet 连接。
  • 允许防火墙,如果服务于来自远程机器的推理请求。

准备

NeMo Megatron is now in Open Beta ,可供完成免费注册表格的任何人使用。需要注册才能访问训练和推理容器,以及用于转换和部署训练模型的助手脚本。

几个经过训练的 NeMo Megatron 模型在 HuggingFace 上公开托管,包括 1.3B 、 5B 和 20B GPT-3 模型。这些模型已转换为. NeMo 格式,该格式已优化用于推理。

转换后的模型不能重新训练或微调,但它们可以部署经过充分训练的模型进行推理。与转换前检查点相比,这些模型的尺寸要小得多,并且受 FasterTransformer (FT) 格式的支持。更快的 transformer 是 Triton 推理服务器中的后端,用于跨 GPU 和节点运行 LLM 。

为了这篇文章的目的,我们使用了 1.3B 模型,它具有最快的推理速度,并且可以舒适地适应大多数现代 GPU 的内存。

要转换模型,请运行以下步骤。

将 1.3B 型号下载到您的系统。在所需目录中运行以下命令,以保存 NVIDIA Triton 的转换模型:

wget https://huggingface.co/nvidia/nemo-megatron-gpt-1.3B/resolve/main/nemo_gpt1.3B_fp16.nemo

记下模型复制到的文件夹,因为它在本文的其余部分中一直使用。

验证下载文件的 MD5sum :

$ md5sum nemo_gpt1.3B_fp16.nemo
38f7afe7af0551c9c5838dcea4224f8a  nemo_gpt1.3B_fp16.nemo

使用网络浏览器登录 NGC. NVIDIA .com 上的 NGC 。通过选择帐户名进入 Setup 菜单。选择 Get API Key ,然后选择 Generate API Key 以创建令牌。记下钥匙,因为它只显示一次。

在终端中,将令牌添加到 Docker :

$ docker login nvcr.io
Username: $oauthtoken
Password: <insert token here>

用生成的令牌替换<insert token here>。用户名必须完全为$oauthtoken,因为这表示正在使用个人访问令牌。

提取 NeMo Megatron 的最新训练和推理图像:

$ docker pull nvcr.io/ea-bignlp/bignlp-training:22.08.01-py3
$ docker pull nvcr.io/ea-bignlp/bignlp-inference:22.08-py3

在出版时,最新的图像标签是用于训练的22.08.01-py3和用于推断的22.08-py3。我们建议检查 NGC 上的较新标签,并在可用的情况下删除这些标签。

验证图像是否已成功提取,因为 ID 可能会随不同的标签而变化:

$ docker images | grep "ea-bignlp/bignlp"
nvcr.io/ea-bignlp/bignlp-training                       22.08.01-py3                         d591b7488a47   11 days ago     17.3GB
nvcr.io/ea-bignlp/bignlp-inference                      22.08-py3                            77a6681df8d6   2 weeks ago     12.2GB

模型转换

为了优化模型的吞吐量和延迟,可以将其转换为 FT 格式,其中包含对 transformer 架构中编码器和解码器层的性能修改。

与非 FT 对等方相比, FT 可以以 3 倍或更多的延迟来服务推理请求。 NeMo Megatron 训练容器包括 FT 框架以及将. NeMo 文件转换为 FT 格式的脚本。

Triton 推理服务器希望模型存储在模型存储库中。模型存储库包含检查点和模型特定信息, Triton Inference Server 在部署时读取这些信息来调整模型。与 FT 框架一样, NeMo Megatron 训练容器包含用于将 FT 模型转换为 Triton 的模型存储库的脚本。

将模型转换为 FT 格式并为转换后的模型创建模型存储库可以在 Docker 容器中一次性完成。要创建基于 FT 的模型存储库,请运行以下命令。可能需要更改的项目在 bold.

docker run --rm \
    --gpus all \
    --shm-size=16GB \
    -v /path/to/checkpoints:/checkpoints \
    -v /path/to/checkpoints/output:/model_repository \
    nvcr.io/ea-bignlp/bignlp-training:22.08.01-py3 \
    bash -c 'export PYTHONPATH=/opt/bignlp/FasterTransformer:${PYTHONPATH} && \
    cd /opt/bignlp && \
    python3 FasterTransformer/examples/pytorch/gpt/utils/nemo_ckpt_convert.py \
        --in-file /checkpoints/nemo_gpt1.3B_fp16.nemo \
        --infer-gpu-num 1 \
        --saved-dir /model_repository/gpt3_1.3b \
        --weight-data-type fp16 \
        --load-checkpoints-to-cpu 0 && \
    python3 /opt/bignlp/bignlp-scripts/bignlp/collections/export_scripts/prepare_triton_model_config.py \
        --model-train-name gpt3_1.3b \
        --template-path /opt/bignlp/fastertransformer_backend/all_models/gpt/fastertransformer/config.pbtxt \
        --ft-checkpoint /model_repository/gpt3_1.3b/1-gpu \
        --config-path /model_repository/gpt3_1.3b/config.pbtxt \
        --max-batch-size 256 \
        --pipeline-model-parallel-size 1 \
        --tensor-model-parallel-size 1 \
        --data-type bf16'

这些步骤启动 Docker 容器以运行转换。以下列表列出了一些重要参数及其功能:

  • -v /path/to/checkpoints:/checkpoints:指定保存检查点的本地目录。这是前面在检查点下载步骤中提到的目录。命令中的最后一个:/ checkins 目录应该保持不变。
  • -v /path/to/checkpoint/output:/model_repository:指定要将转换后的检查点保存到的本地目录。在稍后的部署步骤中使用该位置时,请记下该位置。命令中的最后一个:/ model _ repository 目录应该保持不变。
  • nvcr.io/ea-bignlp/bignlp-training:22.08.01-py3:如果 NGC 上存在更新的图像,请用新版本替换突出显示的标签。
  • --in-file /checkpoints/nemo_gpt1.3B_fp16.nemo:要转换的下载检查点的名称。如果您使用的是其他版本,请在此处替换名称。
  • --infer-gpu-num 1:这是用于部署模型的 GPU 的编号。如果使用多个 GPU ,请将此数量增加到所需数量。本文的其余部分假设这里使用了值 1 。
  • --model-train-name gpt3_1.3b:已部署模型的名称。如果您使用不同的型号名称,请记下新名称,因为 NVIDIA Triton 请求需要指定名称。
  • --tensor-model-parallel-size 1:如果您使用不同的 GPU 计数进行推断,则必须更新此数字。该值应与前面的--infer-gpu-num的值匹配。

运行命令后,通过查看指定的输出目录来验证模型是否已转换。输出应类似于以下内容(为简洁起见,截短):

$ ls -R output/
output/:
gpt3_1.3b

output/gpt3_1.3b:
1-gpu  config.pbtxt

output/gpt3_1.3b/1-gpu:
config.ini
merges.txt
model.final_layernorm.bias.bin
model.final_layernorm.weight.bin
...

模型部署

现在模型已经转换为模型存储库,可以使用 Triton InferenceServer 进行部署。使用内置 NVIDIA Triton 的 NeMo Megatron 推理容器执行此操作。

默认情况下, NVIDIA Triton 为 HTTP 、 gRPC 和度量请求使用三个端口。

docker run --rm \
    --name triton-inference-server \
    -d \
    --gpus all \
    -p 8000-8002:8000-8002 \
    -v /path/to/checkpoints/output:/model_repository \
    nvcr.io/ea-bignlp/bignlp-inference:22.08-py3 \
    bash -c 'export CUDA_VISIBLE_DEVICES=0 && \
    tritonserver --model-repository /model_repository'
  • -d:这告诉 Docker 在后台运行容器。服务器保持在线并可用于请求,直到容器被终止。
  • -p 8000-8002:8000-8002: NVIDIA Triton 使用端口 8000 进行通信,用于 HTTP 请求, 8001 用于 gRPC 请求, 8002 用于度量信息。这些端口从容器映射到主机,允许主机直接处理请求并将其路由到容器。
  • -v /path/to/checkpoints/output:/model_repository:指定转换后的检查点在计算机上保存到的位置。这应该与前面转换步骤中的模型存储库位置相匹配。
  • nvcr.io/ea-bignlp/bignlp-inference:22.08-py3:如果 NGC 上存在更新版本,请用新版本替换突出显示的标签。
  • export CUDA_VISIBLE_DEVICES=0:指定要使用的设备。如果模型之前被转换为使用多个 GPU ,则这应该是一个逗号分隔的 GPU 列表,直到所需的数字。例如,如果您使用四个 GPU ,则应该是CUDA_VISIBLE_DEVICES=0,1,2,3

要验证容器是否已成功启动,请运行 docker ps ,它应显示类似于以下内容的输出:

CONTAINER ID   IMAGE                                          COMMAND                  CREATED              STATUS              PORTS                                                           NAMES
f25cf23b75b7   nvcr.io/ea-bignlp/bignlp-inference:22.08-py3   "/opt/nvidia/nvidia_…"   About a minute ago   Up About a minute   0.0.0.0:8000-8002->8000-8002/tcp, :::8000-8002->8000-8002/tcp   triton-inference-server

检查日志以查看模型是否已部署并准备好接受请求(为简洁起见,输出被截断)。

$ docker logs triton-inference-server
I0928 14:29:34.011299 1 server.cc:629] 
+-----------+---------+--------+
| Model     | Version | Status |
+-----------+---------+--------+
| gpt3_1.3b | 1       | READY  |
+-----------+---------+--------+

I0928 14:29:34.131430 1 metrics.cc:650] Collecting metrics for GPU 0: NVIDIA A100-SXM4-80GB
I0928 14:29:34.132280 1 tritonserver.cc:2176] 
+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Option                           | Value                                                                                                                                                                                        |
+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| server_id                        | triton                                                                                                                                                                                       |
| server_version                   | 2.24.0                                                                                                                                                                                       |
| server_extensions                | classification sequence model_repository model_repository(unload_dependents) schedule_policy model_configuration system_shared_memory cuda_shared_memory binary_tensor_data statistics trace |
| model_repository_path[0]         | /model_repository                                                                                                                                                                            |
| model_control_mode               | MODE_NONE                                                                                                                                                                                    |
| strict_model_config              | 0                                                                                                                                                                                            |
| rate_limit                       | OFF                                                                                                                                                                                          |
| pinned_memory_pool_byte_size     | 268435456                                                                                                                                                                                    |
| cuda_memory_pool_byte_size{0}    | 67108864                                                                                                                                                                                     |
| response_cache_byte_size         | 0                                                                                                                                                                                            |
| min_supported_compute_capability | 6.0                                                                                                                                                                                          |
| strict_readiness                 | 1                                                                                                                                                                                            |
| exit_timeout                     | 30                                                                                                                                                                                           |
+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

I0928 14:29:34.133520 1 grpc_server.cc:4608] Started GRPCInferenceService at 0.0.0.0:8001
I0928 14:29:34.133751 1 http_server.cc:3312] Started HTTPService at 0.0.0.0:8000
I0928 14:29:34.174655 1 http_server.cc:178] Started Metrics Service at 0.0.0.0:8002

如果输出与此处显示的类似,则模型已准备好接收推理请求。

发送推理请求

当本地 Triton 推理服务器运行时,您可以开始向服务器发送推理请求。 NVIDIA Triton 的客户端 API 支持多种语言,包括 Python 、 Java 和 C ++。为了本文的目的,我们提供了一个示例 Python 应用程序。

from argparse import ArgumentParser
import numpy as np
import tritonclient.http as httpclient
from tritonclient.utils import np_to_triton_dtype
from transformers import GPT2Tokenizer

def fill_input(name, data):
    infer_input = httpclient.InferInput(name, data.shape, np_to_triton_dtype(data.dtype))
    infer_input.set_data_from_numpy(data)
    return infer_input

def build_request(query, host, output):
    with httpclient.InferenceServerClient(host) as client:
        request_data = []
        request = np.array([query]).astype(np.uint32)
        request_len = np.array([[len(query)]]).astype(np.uint32)
        request_output_len = np.array([[output]]).astype(np.uint32)
        top_k = np.array([[1]]).astype(np.uint32)
        top_p = np.array([[0.0]]).astype(np.float32)
        temperature = np.array([[1.0]]).astype(np.float32)

        request_data.append(fill_input('input_ids', request))
        request_data.append(fill_input('input_lengths', request_len))
        request_data.append(fill_input('request_output_len', request_output_len))
        request_data.append(fill_input('runtime_top_k', top_k))
        request_data.append(fill_input('runtime_top_p', top_p))
        request_data.append(fill_input('temperature', temperature))
        result = client.infer('gpt3_1.3b', request_data)
        output = result.as_numpy('output_ids').squeeze()
        return output

def main():
    parser = ArgumentParser('Simple Triton Inference Requestor')
    parser.add_argument('query', type=str, help='Enter a text query to send to '
                        'the Triton Inference Server in quotes.')
    parser.add_argument('--output-length', type=int, help='Specify the desired '
                        'length for output.', default=30)
    parser.add_argument('--server', type=str, help='Specify the host:port that '
                        'Triton is listening on. Defaults to localhost:8000',
                        default='localhost:8000')
    args = parser.parse_args()

    tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
    query = tokenizer(args.query).input_ids
    request = build_request(query, args.server, args.output_length)
    print(tokenizer.decode(request))

if __name__ == '__main__':
    main()

在高级别上,脚本执行以下操作:

  1. 接受用户的输入请求,例如“你好!今天好吗?”
  2. 使用来自 HuggingFace 的预训练 GPT-2 标记器标记输入。
  3. 使用几个必需的和可选的参数构建推理请求,例如请求、温度、输出长度等。
  4. 向 NVIDIA Triton 发送请求。
  5. 使用前面的标记器解码响应。

要运行代码,需要几个 Python 依赖项。可以通过运行以下命令来安装这些软件包:

$ pip3 install numpy tritonclient[http] transformers

安装依赖项后,将代码保存到本地文件并将其命名为 infer.py 。接下来,按如下方式运行应用程序:

$ python3 infer.py "1 2 3 4 5 6"

这将向本地推理服务器发送提示“ 1 2 3 4 5 6 ”,并应输出以下内容以完成序列,直到默认响应令牌限制为 30 :

“1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36"

服务器现在可以使用这个基本公式来响应任何 HTTP 请求,并且可以支持本地和远程的多个并发请求。

总结

大型语言模型正在推动越来越多的应用程序。随着几个 NeMo Megatron 模型的公开发布,现在可以在本地部署经过训练的模型。

本文概述了如何使用简单的 Python 脚本部署公共 NeMo Megatron 模型。您可以通过下载 larger models hosted on HuggingFace 来测试更健壮的模型和用例。

有关使用 NeMo Megatron 的更多信息,请参阅 NeMo Megatron 文档和 NVIDIA/nemo GitHub repo 。

 

Tags