Implemente modelos grandes para inferência com TorchServe - SageMaker IA da Amazon

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Implemente modelos grandes para inferência com TorchServe

Este tutorial demonstra como implantar modelos grandes e fornecer inferência na Amazon SageMaker AI com TorchServe on. GPUs Este exemplo implanta o modelo OPT-30b em uma instância ml.g5. Você pode modificar isso para funcionar com outros modelos e tipos de instância. Nos exemplos, substitua italicized placeholder text com suas próprias informações.

TorchServe é uma plataforma aberta poderosa para inferência de modelos distribuídos de grande porte. Ao oferecer suporte a bibliotecas populares como PyTorch Pi PPy nativo e HuggingFace Accelerate, ele oferece um manipulador uniforme APIs que permanece consistente em cenários distribuídos de inferência de modelos grandes e modelos não distribuídos. DeepSpeed Para obter mais informações, consulte TorchServea grande documentação de inferência de modelos.

Contêineres de aprendizado profundo com TorchServe

Para implantar um modelo grande sem TorchServe SageMaker IA, você pode usar um dos contêineres de aprendizado profundo de SageMaker IA (DLCs). Por padrão, TorchServe está instalado em todos AWS PyTorch DLCs. Durante o carregamento do modelo, TorchServe pode instalar bibliotecas especializadas personalizadas para modelos grandes, como PiPPy, Deepspeed e Accelerate.

A tabela a seguir lista toda a SageMaker IA DLCs com TorchServe.

Categoria DLC Framework Hardware Exemplo de URL

SageMaker Contêineres de estrutura de

PyTorch 2.0.0+

CPU, GPU

763104351884.dkr.ecr.us-east-1.amazonaws.com/PyTorch-inference:2.0.1-gpu-py310-cu118-ubuntu20.04-sagemaker

SageMaker Contêineres AI Framework Graviton

PyTorch 2.0.0+

CPU

763104351884.dkr. ecr.us-east-1.amazonaws.com /:2.0.1-cpu-py310-ubuntu20.04-sagemaker pytorch-inference-graviton

Contêineres de inferência StabilityAI

PyTorch 2.0.0+

GPU

763104351884.dkr. ecr.us-east-1.amazonaws.com /:2.0.1-sgm0.1.0-gpu-py310-cu118-ubuntu20.04-sagemaker stabilityai-pytorch-inference

Contêineres de neurônios

PyTorch 1.13.1

Neuronx

763104351884.dkr. ecr.us-west-2.amazonaws.com /:1.13.1-neuron-py310-sdk2.12.0-ubuntu20.04 pytorch-inference-neuron

Conceitos básicos

Antes de implantar seu modelo, preencha os pré-requisitos. Você também pode configurar os parâmetros do modelo e personalizar o código do manipulador.

Pré-requisitos

Para começar, verifique se você tem os seguintes pré-requisitos:

  1. Certifique-se de ter acesso a uma AWS conta. Configure seu ambiente para que eles AWS CLI possam acessar sua conta por meio de um usuário AWS do IAM ou de uma função do IAM. Recomendamos usar uma perfil do IAM. Para fins de teste em sua conta pessoal, você pode anexar as seguintes políticas de permissões gerenciadas à perfil do IAM:

    Para obter informações sobre como anexar políticas a identidades do IAM, consulte Adicionar e remover permissões de identidade do IAM no Guia do usuário do IAM AWS .

  2. Configure suas dependências localmente, conforme mostrado nos exemplos a seguir.

    1. Instale a versão 2 do AWS CLI:

      # Install the latest AWS CLI v2 if it is not installed !curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" !unzip awscliv2.zip #Follow the instructions to install v2 on the terminal !cat aws/README.md
    2. Instale a SageMaker IA e o cliente Boto3:

      # If already installed, update your client #%pip install sagemaker pip --upgrade --quiet !pip install -U sagemaker !pip install -U boto !pip install -U botocore !pip install -U boto3

Configurar parâmetros e configurações do modelo

TorchServe usa torchrunpara configurar o ambiente distribuído para processamento paralelo de modelos. TorchServe tem a capacidade de oferecer suporte a vários trabalhadores em um modelo grande. Por padrão, TorchServe usa um algoritmo round-robin para atribuir GPUs a um trabalhador em um host. No caso de inferência de modelo grande, o número GPUs atribuído a cada trabalhador é calculado automaticamente com base no número GPUs especificado no model_config.yaml arquivo. A variável de ambienteCUDA_VISIBLE_DEVICES, que especifica os dispositivos de GPU IDs que estão visíveis em um determinado momento, é definida com base nesse número.

Por exemplo, suponha que haja 8 GPUs em um nó e um trabalhador precise de 4 GPUs em um nó (nproc_per_node=4). Nesse caso, TorchServe atribui quatro GPUs ao primeiro trabalhador (CUDA_VISIBLE_DEVICES="0,1,2,3") e quatro GPUs ao segundo trabalhador (CUDA_VISIBLE_DEVICES="4,5,6,7”).

Além desse comportamento padrão, TorchServe fornece a flexibilidade para os usuários especificarem GPUs para um trabalhador. Por exemplo, se você definir a variável deviceIds: [2,3,4,5] no arquivo YAML de configuração do modelo e definirnproc_per_node=2, TorchServe atribuirá CUDA_VISIBLE_DEVICES=”2,3” ao primeiro trabalhador e CUDA_VISIBLE_DEVICES="4,5” ao segundo trabalhador.

No exemplo model_config.yaml a seguir, configuramos os parâmetros front-end e backend para o modelo OPT-30b. Os parâmetros de front-end configurados são parallelType, deviceType, deviceIds e torchrun. Para obter informações mais detalhadas sobre os parâmetros de front-end que você pode configurar, consulte a PyTorch GitHub documentação. A configuração de backend é baseada em um mapa YAML que permite a personalização em estilo livre. Para os parâmetros de back-end, definimos a DeepSpeed configuração e os parâmetros adicionais usados pelo código do manipulador personalizado.

# TorchServe front-end parameters minWorkers: 1 maxWorkers: 1 maxBatchDelay: 100 responseTimeout: 1200 parallelType: "tp" deviceType: "gpu" # example of user specified GPU deviceIds deviceIds: [0,1,2,3] # sets CUDA_VISIBLE_DEVICES torchrun: nproc-per-node: 4 # TorchServe back-end parameters deepspeed: config: ds-config.json checkpoint: checkpoints.json handler: # parameters for custom handler code model_name: "facebook/opt-30b" model_path: "model/models--facebook--opt-30b/snapshots/ceea0a90ac0f6fae7c2c34bcb40477438c152546" max_length: 50 max_new_tokens: 10 manual_seed: 40

Personalizar manipuladores

TorchServe oferece manipuladores básicos e utilitários de manipulador para inferência de modelos grandes criados com bibliotecas populares. O exemplo a seguir demonstra como a classe do manipulador personalizado TransformersSeqClassifierHandlerestende BaseDeepSpeedHandlere usa os utilitários do manipulador. Para ver um exemplo de código completo, consulte o custom_handler.pycódigo na PyTorch GitHub documentação.

class TransformersSeqClassifierHandler(BaseDeepSpeedHandler, ABC): """ Transformers handler class for sequence, token classification and question answering. """ def __init__(self): super(TransformersSeqClassifierHandler, self).__init__() self.max_length = None self.max_new_tokens = None self.tokenizer = None self.initialized = False def initialize(self, ctx: Context): """In this initialize function, the HF large model is loaded and partitioned using DeepSpeed. Args: ctx (context): It is a JSON Object containing information pertaining to the model artifacts parameters. """ super().initialize(ctx) model_dir = ctx.system_properties.get("model_dir") self.max_length = int(ctx.model_yaml_config["handler"]["max_length"]) self.max_new_tokens = int(ctx.model_yaml_config["handler"]["max_new_tokens"]) model_name = ctx.model_yaml_config["handler"]["model_name"] model_path = ctx.model_yaml_config["handler"]["model_path"] seed = int(ctx.model_yaml_config["handler"]["manual_seed"]) torch.manual_seed(seed) logger.info("Model %s loading tokenizer", ctx.model_name) self.tokenizer = AutoTokenizer.from_pretrained(model_name) self.tokenizer.pad_token = self.tokenizer.eos_token config = AutoConfig.from_pretrained(model_name) with torch.device("meta"): self.model = AutoModelForCausalLM.from_config( config, torch_dtype=torch.float16 ) self.model = self.model.eval() ds_engine = get_ds_engine(self.model, ctx) self.model = ds_engine.module logger.info("Model %s loaded successfully", ctx.model_name) self.initialized = True def preprocess(self, requests): """ Basic text preprocessing, based on the user's choice of application mode. Args: requests (list): A list of dictionaries with a "data" or "body" field, each containing the input text to be processed. Returns: tuple: A tuple with two tensors: the batch of input ids and the batch of attention masks. """ def inference(self, input_batch): """ Predicts the class (or classes) of the received text using the serialized transformers checkpoint. Args: input_batch (tuple): A tuple with two tensors: the batch of input ids and the batch of attention masks, as returned by the preprocess function. Returns: list: A list of strings with the predicted values for each input text in the batch. """ def postprocess(self, inference_output): """Post Process Function converts the predicted response into Torchserve readable format. Args: inference_output (list): It contains the predicted response of the input text. Returns: (list): Returns a list of the Predictions and Explanations. """

Prepare seus artefatos de modelo

Antes de implantar seu modelo na SageMaker IA, você deve empacotar seus artefatos de modelo. Para modelos grandes, recomendamos que você use a PyTorch torch-model-archiverferramenta com o argumento--archive-format no-archive, que ignora a compactação de artefatos do modelo. O exemplo a seguir salva todos os artefatos do modelo em uma nova pasta chamada opt/.

torch-model-archiver --model-name opt --version 1.0 --handler custom_handler.py --extra-files ds-config.json -r requirements.txt --config-file opt/model-config.yaml --archive-format no-archive

Depois que a opt/ pasta for criada, baixe o modelo Opt-30b para a pasta usando a ferramenta Download_model. PyTorch

cd opt python path_to/Download_model.py --model_path model --model_name facebook/opt-30b --revision main

Por fim, faça upload dos artefatos do modelo para um bucket do Amazon S3.

aws s3 cp opt {your_s3_bucket}/opt --recursive

Agora você deve ter artefatos de modelo armazenados no Amazon S3 prontos para serem implantados em SageMaker um endpoint de IA.

Implante o modelo usando o SDK do SageMaker Python

Depois de preparar seus artefatos de modelo, você pode implantar seu modelo em um endpoint de hospedagem de SageMaker IA. Esta seção descreve como implantar um único modelo grande em um endpoint e fazer predições de resposta de streaming. Para obter mais informações sobre streaming de respostas de endpoints, consulte Invocar endpoints em tempo real.

Para implantar seu modelo, conclua as seguintes etapas:

  1. Crie uma sessão de SageMaker IA, conforme mostrado no exemplo a seguir.

    import boto3 import sagemaker from sagemaker import Model, image_uris, serializers, deserializers boto3_session=boto3.session.Session(region_name="us-west-2") smr = boto3.client('sagemaker-runtime-demo') sm = boto3.client('sagemaker') role = sagemaker.get_execution_role() # execution role for the endpoint sess= sagemaker.session.Session(boto3_session, sagemaker_client=sm, sagemaker_runtime_client=smr) # SageMaker AI session for interacting with different AWS APIs region = sess._region_name # region name of the current SageMaker Studio Classic environment account = sess.account_id() # account_id of the current SageMaker Studio Classic environment # Configuration: bucket_name = sess.default_bucket() prefix = "torchserve" output_path = f"s3://{bucket_name}/{prefix}" print(f'account={account}, region={region}, role={role}, output_path={output_path}')
  2. Crie um modelo não compactado na SageMaker IA, conforme mostrado no exemplo a seguir.

    from datetime import datetime instance_type = "ml.g5.24xlarge" endpoint_name = sagemaker.utils.name_from_base("ts-opt-30b") s3_uri = {your_s3_bucket}/opt model = Model( name="torchserve-opt-30b" + datetime.now().strftime("%Y-%m-%d-%H-%M-%S"), # Enable SageMaker uncompressed model artifacts model_data={ "S3DataSource": { "S3Uri": s3_uri, "S3DataType": "S3Prefix", "CompressionType": "None", } }, image_uri=container, role=role, sagemaker_session=sess, env={"TS_INSTALL_PY_DEP_PER_MODEL": "true"}, ) print(model)
  3. Implante o modelo em uma EC2 instância da Amazon, conforme mostrado no exemplo a seguir.

    model.deploy( initial_instance_count=1, instance_type=instance_type, endpoint_name=endpoint_name, volume_size=512, # increase the size to store large model model_data_download_timeout=3600, # increase the timeout to download large model container_startup_health_check_timeout=600, # increase the timeout to load large model )
  4. Inicialize uma classe para processar a resposta de streaming, conforme mostrado no exemplo a seguir.

    import io class Parser: """ A helper class for parsing the byte stream input. The output of the model will be in the following format: ``` b'{"outputs": [" a"]}\n' b'{"outputs": [" challenging"]}\n' b'{"outputs": [" problem"]}\n' ... ``` While usually each PayloadPart event from the event stream will contain a byte array with a full json, this is not guaranteed and some of the json objects may be split across PayloadPart events. For example: ``` {'PayloadPart': {'Bytes': b'{"outputs": '}} {'PayloadPart': {'Bytes': b'[" problem"]}\n'}} ``` This class accounts for this by concatenating bytes written via the 'write' function and then exposing a method which will return lines (ending with a '\n' character) within the buffer via the 'scan_lines' function. It maintains the position of the last read position to ensure that previous bytes are not exposed again. """ def __init__(self): self.buff = io.BytesIO() self.read_pos = 0 def write(self, content): self.buff.seek(0, io.SEEK_END) self.buff.write(content) data = self.buff.getvalue() def scan_lines(self): self.buff.seek(self.read_pos) for line in self.buff.readlines(): if line[-1] != b'\n': self.read_pos += len(line) yield line[:-1] def reset(self): self.read_pos = 0
  5. Teste uma predição de resposta de streaming, conforme mostrado no exemplo a seguir.

    import json body = "Today the weather is really nice and I am planning on".encode('utf-8') resp = smr.invoke_endpoint_with_response_stream(EndpointName=endpoint_name, Body=body, ContentType="application/json") event_stream = resp['Body'] parser = Parser() for event in event_stream: parser.write(event['PayloadPart']['Bytes']) for line in parser.scan_lines(): print(line.decode("utf-8"), end=' ')

Agora você implantou seu modelo em um endpoint de SageMaker IA e deve ser capaz de invocá-lo para obter respostas. Para obter mais informações sobre endpoints de SageMaker IA em tempo real, consulteEndpoints de modelo único.