Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Implementación de modelos grandes para la inferencia con TorchServe
En este tutorial se muestra cómo implementar modelos grandes y realizar inferencias en Amazon SageMaker AI con TorchServe en las GPU. En este ejemplo, se implementa el modelo OPT-30bml.g5. Puede modificarlo para que funcione con otros modelos y tipos de instancias. En el ejemplo, sustituya por su propia información.italicized placeholder text
TorchServe es una potente plataforma abierta para la inferencia de modelos distribuidos de gran tamaño. Al ser compatible con bibliotecas generales como PyTorch, PiPPY nativo, DeepSpeed y HuggingFace Accelerate, ofrece API de controladores uniformes que siguen siendo coherentes en todos los escenarios de inferencia de modelos distribuidos de gran tamaño y no distribuidos. Para obtener más información, consulte la documentación de inferencia de modelos grandes de TorchServe
Contenedores de aprendizaje profundo con TorchServe
Para implementar un modelo grande con TorchServe en SageMaker AI, puede utilizar uno de los contenedores de aprendizaje profundo (DLC) de SageMaker AI. De forma predeterminada, TorchServe está instalado en todos los DLC de AWS PyTorch. Durante la carga de modelos, TorchServe puede instalar bibliotecas especializadas diseñadas para modelos grandes, como PiPPy, Deepspeed y Accelerate.
En la siguiente tabla se enumeran todos los DLC de SageMaker AI con TorchServe
| Categoría DLC | Marcos | Hardware | URL de ejemplo |
|---|---|---|---|
|
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 |
|
|
PyTorch 2.0.0+ |
CPU |
763104351884.dkr.ecr.us-east-1.amazonaws.com/pytorch-inference-graviton:2.0.1-cpu-py310-ubuntu20.04-sagemaker |
|
|
PyTorch 2.0.0+ |
GPU |
763104351884.dkr.ecr.us-east-1.amazonaws.com/stabilityai-pytorch-inference:2.0.1-sgm0.1.0-gpu-py310-cu118-ubuntu20.04-sagemaker |
|
PyTorch 1.13.1 |
Neuronx |
763104351884.dkr.ecr.us-west-2.amazonaws.com/pytorch-inference-neuron:1.13.1-neuron-py310-sdk2.12.0-ubuntu20.04 |
Introducción
Antes de implementar el modelo, complete los requisitos previos. También se pueden configurar los parámetros del modelo y personalizar el código del controlador.
Requisitos previos
Antes de comenzar, compruebe que cumple los siguientes requisitos previos:
-
Asegúrese de tener acceso a una AWS cuenta. Configure su entorno para que AWS CLI pueda acceder a su cuenta a través de un usuario de AWS IAM o un rol de IAM. Recomendamos utilizar un rol de IAM. Para realizar pruebas en su cuenta personal, puede asociar las siguientes políticas de permisos gestionados al rol de IAM:
Para obtener información sobre cómo asociar políticas de IAM a un rol, consulte Incorporación y eliminación de permisos de identidad de IAM en la AWS Guía del usuario de IAM.
-
Configure sus dependencias de forma local, como se muestra en los siguientes ejemplos.
-
Instale la versión 2 de la 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 -
Instale SageMaker AI y el 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
-
Configure los ajustes y los parámetros del modelo
TorchServe usa torchrunmodel_config.yaml. La variable de entorno CUDA_VISIBLE_DEVICES, que especifica los ID de los dispositivos de GPU que están visibles en un momento específico, se establece en función de este número.
Por ejemplo, supongamos que hay 8 GPU en un nodo y un trabajador necesita 4 GPU en un nodo (nproc_per_node=4). En este caso, TorchServe asigna cuatro GPU al primer trabajador (CUDA_VISIBLE_DEVICES="0,1,2,3") y cuatro GPU al segundo trabajador (CUDA_VISIBLE_DEVICES="4,5,6,7”).
Además de este comportamiento predeterminado, TorchServe ofrece a los usuarios la flexibilidad de especificar las GPU para un trabajador. Por ejemplo, si establece la variable deviceIds: [2,3,4,5] en el archivo model config YAMLnproc_per_node=2, TorchServe asigna CUDA_VISIBLE_DEVICES=”2,3” al primer trabajador CUDA_VISIBLE_DEVICES="4,5” al segundo trabajador.
En el siguiente model_config.yaml ejemplo, configuramos tanto los parámetros de front-end como de back-end correspondientes al modelo OPT-30b parallelType, deviceType, deviceIds y torchrun. Para obtener información más detallada sobre los parámetros de front-end que puede configurar, consulte la documentación de PyTorch GitHub
# 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
Personalización de controladores
TorchServe ofrece controladores básicoscustom_handler.py código en la documentación de PyTorch GitHub
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. """
Preparación de los artefactos de su modelo
Antes de implementar el modelo en SageMaker AI, debe empaquetar los artefactos del modelo. Para modelos grandes, le recomendamos que utilice la herramienta torch-model-archiver--archive-format
no-archive, que omite la compresión de los artefactos del modelo. El siguiente ejemplo guarda todos los artefactos del modelo en una nueva carpeta denominada 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
Una vez creada la opt/ carpeta, descargue el modelo OPT-30b a la carpeta mediante la herramienta Download_model
cd opt python path_to/Download_model.py --model_path model --model_name facebook/opt-30b --revision main
Por último, cargue los artefactos del modelo en un bucket de Amazon S3.
aws s3 cp opt{your_s3_bucket}/opt --recursive
Ahora debe tener los artefactos del modelo almacenados en Amazon S3 y listos para implementarse en un punto de conexión de SageMaker AI.
Implemente el modelo mediante el SDK de SageMaker
Tras preparar los artefactos del modelo, puede implementarlo en un punto de conexión de alojamiento de SageMaker AI. En esta sección se describe cómo implementar un único modelo grande en un punto de conexión y realizar predicciones de respuesta en transmisión. Para obtener más información sobre la transmisión de las respuestas desde los puntos de conexión, consulte Invocar puntos de conexión en tiempo real.
Para implementar el modelo, siga los pasos que se describen a continuación:
-
Cree una sesión de SageMaker AI, como se muestra en el siguiente ejemplo.
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}') -
Cree un modelo sin comprimir de SageMaker AI, como se muestra en el siguiente ejemplo.
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) -
Implemente el modelo en una instancia de Amazon EC2, como se muestra en el siguiente ejemplo.
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 ) -
Inicie una clase para procesar la respuesta de transmisión, como se muestra en el siguiente ejemplo.
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 -
Pruebe una predicción de respuesta de transmisión, como se muestra en el siguiente ejemplo.
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=' ')
Ya ha implementado su modelo en un punto de conexión de SageMaker AI y debería poder invocarlo para obtener respuestas. Para obtener más información sobre los puntos de conexión en tiempo real de SageMaker AI, consulte Puntos de conexión de modelo único.