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.
Implemente modelos de gran tamaño para realizar inferencias con TorchServe
En este tutorial se muestra cómo implementar modelos grandes y realizar inferencias en Amazon SageMaker con TorchServe onGPUs. 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 populares PyTorch, como Native P y HuggingFace Accelerate iPPy DeepSpeed, ofrece un controlador uniforme APIs que mantiene la coherencia 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 TorchServede inferencia de modelos de gran tamaño
Contenedores de aprendizaje profundo con TorchServe
Para implementar un modelo grande con TorchServe on SageMaker, puede usar uno de los contenedores de aprendizaje SageMaker profundo (DLCs). De forma predeterminada, TorchServe está instalado en todos AWS PyTorchDLCs. Durante la carga del modelo, TorchServe puede instalar bibliotecas especializadas diseñadas para modelos grandes, como PiPPy, Deepspeed y Accelerate.
En la siguiente tabla se muestran todas las anchas SageMaker DLCs. TorchServe
DLCcategoría | Marcos | Hardware | Ejemplo URL |
---|---|---|---|
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 /:2.0.1-cpu-py310-ubuntu20.04-sagemaker pytorch-inference-graviton |
|
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 |
|
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 |
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 cuenta. AWS Configure su entorno para que AWS CLI puedan acceder a su cuenta a través de un AWS IAM usuario o un IAM rol. Recomendamos usar un IAM rol. Para realizar pruebas en tu cuenta personal, puedes adjuntar al IAM rol las siguientes políticas de permisos administrados:
Para obtener más información sobre cómo asociar IAM políticas a un rol, consulte Añadir y eliminar permisos de IAM identidad en la Guía del AWS IAMusuario.
-
Configure sus dependencias de forma local, como se muestra en los siguientes ejemplos.
-
Instale la versión 2 de 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
-
La instalación SageMaker 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 se utiliza torchrun
model_config.yaml
archivo. La variable de entornoCUDA_VISIBLE_DEVICES
, que especifica los GPU dispositivos IDs que están visibles en un momento dado, se establece en función de este número.
Por ejemplo, supongamos que hay 8 GPUs en un nodo y un trabajador necesita 4 GPUs en un nodo (nproc_per_node=4
). En este caso, TorchServe asigna cuatro GPUs al primer trabajador (CUDA_VISIBLE_DEVICES="0,1,2,3"
) y cuatro GPUs al segundo trabajador (CUDA_VISIBLE_DEVICES="4,5,6,7”
).
Además de este comportamiento predeterminado, TorchServe proporciona a los usuarios la flexibilidad de especificar GPUs un trabajador. Por ejemplo, si se establece la variable deviceIds: [2,3,4,5]
en el YAMLarchivo de configuración del modelonproc_per_node=2
, se TorchServe asigna CUDA_VISIBLE_DEVICES=”2,3”
al primer elemento de trabajo y CUDA_VISIBLE_DEVICES="4,5”
al segundo elemento de trabajo.
En el siguiente model_config.yaml
ejemplo, configuramos los parámetros de front-end y back-end para el modelo -30b. OPTparallelType
, deviceType
, deviceIds
y torchrun
. Para obtener información más detallada sobre los parámetros de interfaz que puede configurar, consulte la documentación. 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 de la PyTorch GitHub documentación
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 SageMaker, debe empaquetar los artefactos del modelo. Para modelos grandes, le recomendamos que utilice la PyTorch torch-model-archiver--archive-format
no-archive
, ya que evita 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
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 debería tener los artefactos del modelo almacenados en Amazon S3 que estén listos para implementarse en un SageMaker punto final.
Implemente el modelo mediante SageMaker Python SDK
Después de preparar los artefactos del modelo, puede implementarlo en un punto final de SageMaker Hosting. 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 SageMaker sesión, 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 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 en SageMaker, 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 EC2 instancia de Amazon, 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=' ')
Ahora ha implementado su modelo en un SageMaker punto final y debería poder invocarlo para obtener respuestas. Para obtener más información sobre los puntos finales SageMaker en tiempo real, consulte. Terminales de modelo único