Press "Enter" to skip to content

在亚马逊SageMaker上部署带有大模型推理DLC的Falcon-40B

上周,科技创新研究所(TII)发布了TII猎鹰LLM,这是一个开源的基础性大型语言模型(LLM)。猎鹰使用Amazon SageMaker训练了1万亿个令牌,具有一流的性能(在撰写本文时在Hugging Face排行榜上排名第一),同时相对轻量化和比其他LLM(如llama-65B)更便宜。在本文中,我们演示了如何使用SageMaker上的大型模型推理深度学习容器部署猎鹰,以应用于语言理解和自动写作辅助等应用程序。

猎鹰已经在SageMaker上降落

TII是阿布扎比高级技术研究理事会旗下的应用研究机构;其科学家、研究人员和工程师团队致力于发现变革性技术和开发科学突破,为未来社会提供保障。今年早些时候,TII着手训练一种最先进的开源LLM,并利用SageMaker的基础设施、工具和专业知识完成了这项工作(有关如何在SageMaker上训练该模型的更多信息,请参阅Technology Innovation Institute trains the state-of-the-art Falcon LLM 40B foundation model on Amazon SageMaker)。这项工作的结果是TII猎鹰LLM。

猎鹰LLM训练了1万亿个令牌,对Eleuther AI语言模型评估装置具有一流的性能,并且目前在Hugging Face排行榜上排名第一。该模型有两种不同的尺寸,即猎鹰-40B和猎鹰-7B,可用于语言理解、对话体验和自动写作辅助等应用程序的最先进性能。本文将帮助您开始在SageMaker上部署猎鹰,以在这些类型的领域中进行高准确性推理。

SageMaker大型模型推理DLCs简化LLM托管

托管猎鹰-40B和猎鹰-7B等LLM可能会具有挑战性。较大的模型通常更准确,因为它们包括数十亿个参数,但是它们的大小也可能导致推理延迟更慢或吞吐量更低。托管LLM可能需要更多的GPU内存和优化的内核来实现可接受的性能。此外,虽然像猎鹰-7B这样的较小模型通常可以适合单个GPU(例如驱动AWS G5实例类型的NVIDIA A10G实例)上,但是像猎鹰-40B这样的较大模型则不能。在这种情况下,必须使用张量并行性等策略将该较大模型分片为多个部分,并利用多个GPU的内存。通常用于较小模型的传统托管解决方案通常不提供此类功能,增加了困难。

SageMaker大型模型推理(LMI)深度学习容器(DLCs)可以提供帮助。LMI DLCs是托管猎鹰-40B等LLM的完整端到端解决方案。在前端,它们包括一个高性能模型服务器(DJL Serving),用于具有令牌流和自动模型复制等功能的大型模型推理。在后端,LMI DLCs还包括几个高性能的模型并行引擎,例如DeepSpeed和FasterTransformer,它们可以跨多个GPU分片和管理模型参数。这些引擎还包括受欢迎的变形器模型的优化内核,可以将推理加速高达三倍。使用LMI DLCs,您只需要创建一个配置文件即可开始在SageMaker上托管LLM。有关SageMaker LMI DLCs的更多信息,请参阅Model parallelism and large model inference和我们的可用图像列表。您还可以查看我们以前有关使用LMI DLCs在SageMaker上托管Bloom-175B的帖子。

解决方案概述

本文将向您展示如何使用DeepSpeed在SageMaker上使用LMI DLCs托管猎鹰-40B。猎鹰-40B需要使用多个A10 GPU,而猎鹰-7B仅需要一个GPU。我们还准备了示例,您可以参考使用DeepSpeed和Accelerate托管猎鹰-40B和猎鹰-7B。您可以在GitHub上找到我们的代码示例。

此示例可在SageMaker笔记本实例或Amazon SageMaker Studio笔记本中运行。要使用LMI和DeepSpeed托管猎鹰-40B,我们需要使用ml.g5.24xlarge实例。这些实例提供4个NVIDIA A10G GPU,每个GPU支持96 GiB的GPU内存。此外,主机还提供96个vCPU和384 GiB的主机内存。 LMI容器将帮助解决与托管LLM相关的大部分重复工作,包括下载模型和分割模型工件,以便其组成参数可以分布在多个GPU上。

SageMaker机器学习(ML)实例的配额在不同的账户之间可能会有所不同。如果您在遵循本文时收到超出g5.24xlarge实例配额的错误提示,您可以通过Service Quotas控制台增加限制。

笔记本演示

首先,我们安装并导入我们示例所需的必要依赖项。我们使用Boto3 SDK和SageMaker SDK。请注意,我们使用Amazon Simple Storage Service(Amazon S3)存储我们需要SageMaker和LMI使用的模型工件,因此我们相应地设置了一个S3前缀变量。请参阅以下代码:

import sagemaker
import jinja2
from sagemaker import image_uris
import boto3
import os
import time
import json
from pathlib import Path
from sagemaker.utils import name_from_base

role = sagemaker.get_execution_role()  # 执行端点的执行角色
sess = sagemaker.session.Session()  # SageMaker会话,用于与不同的AWS API交互
bucket = sess.default_bucket()  # 存放工件的存储桶
model_bucket = sess.default_bucket()  # 存放工件的存储桶
s3_code_prefix_deepspeed = "hf-large-model-djl-/code_falcon40b/deepspeed"  # 存放代码工件的存储桶内文件夹
region = sess._region_name
account_id = sess.account_id()
s3_client = boto3.client("s3")
sm_client = boto3.client("sagemaker")
smr_client = boto3.client("sagemaker-runtime")
jinja_env = jinja2.Environment()

然后我们创建一个本地文件夹,用于存储我们的模型工件:

!mkdir -p code_falcon40b_deepspeed

我们首先在我们创建的本地目录中创建一个serving.properties配置文件。该serving.properties文件指示LMI容器和前端DJL Serving库我们要使用哪个模型并行化和推理优化引擎。您可以在 Configurations and settings 中找到DeepSpeed和Hugging Face Accelerate的配置选项。这里请注意,我们将option.model_id参数设置为定义要拉取哪个Hugging Face模型。SageMaker使使用Hugging Face模型变得简单,这一行就足够了。此外,我们将option.tensor_parallel_degree设置为4,因为我们的ml.g5.24xlarge实例上有四个GPU。该参数定义要创建和分配多少模型分区。请注意,如果我们使用了具有八个GPU的较大实例,例如ml.g5.48xlarge,并仍将值设置为4,则LMI将自动创建模型的两个副本(每个副本分布在四个GPU上)。请参见以下代码:

%%writefile ./code_falcon40b_deepspeed/serving.properties
engine=Python
#要部署falcon-40b-instruct,请将model_id值设置为'tiiuae/falcon-40b-instruct'
option.model_id=tiiuae/falcon-40b
option.tensor_parallel_degree=4
#option.s3url = {{s3url}}

您还可以使用tiiuae/falcon-40b-instruct替换tiiuae/falcon-40b,如果更适合您的需求。

我们还包括一个requirements.txt文件,您可以指定要安装的包:

%%writefile ./code_falcon40b_deepspeed/requirements.txt
einops
torch==2.0.1

我们需要的最后一件事是将用于您的模型的model.py文件:

%%writefile ./code_falcon40b_deepspeed/model.py
from djl_python import Input, Output
import os
import torch
from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer
from typing import Any, Dict, Tuple
import warnings

predictor = None


def get_model(properties):
    model_name = properties["model_id"]
    local_rank = int(os.getenv("LOCAL_RANK", "0"))
    model = AutoModelForCausalLM.from_pretrained(
        model_name,
        low_cpu_mem_usage=True,
        trust_remote_code=True,
        torch_dtype=torch.bfloat16,
        device_map="auto",
    )
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    generator = pipeline(
        task="text-generation", model=model, tokenizer=tokenizer, device_map="auto"
    )
    return generator


def handle(inputs: Input) -> None:
    global predictor
    if not predictor:
        predictor = get_model(inputs.get_properties())
    if inputs.is_empty():
        # Model server makes an empty call to warmup the model on startup
        return None
    data = inputs.get_as_json()
    text = data["text"]
    text_length = data["text_length"]
    outputs = predictor(text, do_sample=True, min_length=text_length, max_length=text_length)
    result = {"outputs": outputs}
    return Output().add_as_json(result)

完了!此时,我们已经创建了所有部署 Falcon-40B with DeepSpeed 所需的工件!我们将目录打包成 *.tar.gz 文件并上传到 Amazon S3。请注意,实际模型未从这个文件中下载或打包。LMI 容器将会直接从 Hugging Face 下载模型。您也可以选择针对 S3 存储桶,如果您想要自己的模型副本,以更高的性能下载到指定位置。LMI 还包括 Amazon S3 高性能下载的优化。请参阅以下代码:

s3_code_artifact_deepspeed= sess.upload_data("model.tar.gz", bucket, s3_code_prefix_deepspeed)
print(f"S3 Code or Model tar for deepspeed uploaded to --- > {s3_code_artifact_deepspeed}")

此时只需要定义我们要使用的容器并创建一个模型对象:

inference_image_uri = (
    f"763104351884.dkr.ecr.{region}.amazonaws.com/djl-inference:0.22.1-deepspeed0.8.3-cu118"
)
model_name_acc = name_from_base(f"falcon40b-model-ds")
create_model_response = sm_client.create_model(
    ModelName=model_name_acc,
    ExecutionRoleArn=role,
    PrimaryContainer={"Image": inference_image_uri, "ModelDataUrl": s3_code_artifact_deepspeed},
)
model_arn = create_model_response["ModelArn"]

然后创建端点配置并创建端点:

endpoint_config_name = f"{model_name}-config"
endpoint_name = f"{model_name}-endpoint"
endpoint_config_response = sm_client.create_endpoint_config(
    EndpointConfigName=endpoint_config_name,
    ProductionVariants=[
        {
            "VariantName": "variant1",
            "ModelName": model_name,
            "InstanceType": "ml.g5.24xlarge",
            "InitialInstanceCount": 1,
            "ModelDataDownloadTimeoutInSeconds": 3600,
            "ContainerStartupHealthCheckTimeoutInSeconds": 3600,
            # "VolumeSizeInGB": 512
        },
    ],
)
endpoint_config_response

create_endpoint_response = sm_client.create_endpoint(
    EndpointName=f"{endpoint_name}", EndpointConfigName=endpoint_config_name
)
print(f"Created Endpoint: {create_endpoint_response['EndpointArn']}")

成功托管的配置项

对于大型模型的托管,确保有足够的时间从 Hugging Face 下载模型是一个重要的考虑因素。在我们的测试中,Falcon-40B 大约需要 90 分钟才能下载到实例上。为允许这一点,需要设置 ContainerStartupHealthCheckTimeoutInSeconds 和 ModelDataDownloadTimeoutInSeconds 。请确保 SageMaker 端点配置的值为 3600。此外,使用专为 LLMS 设计的 LMI 容器和使用 S5cmd 实用程序从 Amazon S3 下载比从原始模型动物园下载更容易,这将把模型下载时间缩短到约 10 分钟。

您可以通过调用 DescribeEndpoint 监视端点的状态,该函数将告诉您何时全部完成。您的端点现在已准备好响应推理请求!因为 LMI 为您处理了模型分区和编排,每个请求将使用我们的 ml.g5.12xlarge 实例上可用的所有 4 个 GPU 进行处理。如果您将 GPU 加速器水平扩展,这将允许我们托管 LLMS 并提高性能。请参阅以下代码:

response_model = smr_client.invoke_endpoint(
    EndpointName=endpoint_name,
    Body=json.dumps({"text": "What is the purpose of life?", "text_length": 150}),
    ContentType="application/json",
)

response_model["Body"].read().decode("utf8")

如果您已经完成,想要删除端点配置、端点和模型对象,可以运行以下命令:

sm_client.delete_endpoint(EndpointName=endpoint_name)
sm_client.delete_endpoint_config(EndpointConfigName=endpoint_config_name)
sm_client.delete_model(ModelName=model_name)

本文所引用的代码可以在 GitHub 上的完整笔记本中找到。

结论

SageMaker Hosting 和 LMI DLC 使您可以轻松地托管像 Falcon-40B 这样的 LLMS。它承担了在多个 GPU 上编排托管模型所需的非差异化重型工作,并提供可配置的选项以适应您的需求。此外,使用 Hugging Face 模型变得非常简单,内置对这些模型的支持。

在本篇文章中,我们展示了如何使用SageMaker和DeepSpeed托管Falcon-40B模型。此外,我们在GitHub上提供了使用Accelerate托管Falcon-40B和更小的Falcon-7B模型的示例。我们鼓励您在SageMaker上使用LMI尝试一下,并亲身体验迄今为止表现最佳的公开可用LLM!

Leave a Reply

Your email address will not be published. Required fields are marked *