Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Implementazione di modelli di grandi dimensioni per l’inferenza con TorchServe
Questo tutorial dimostra come implementare modelli di grandi dimensioni e fornire inferenza in Amazon SageMaker AI con TorchServe su GPU. Questo esempio distribuisce il modello OPT-30bml.g5. È possibile modificarlo per utilizzarlo con altri modelli e tipi di istanze. Negli esempi, sostituire con le tue informazioni.italicized placeholder text
TorchServe è una potente piattaforma aperta per l'inferenza di modelli distribuiti di grandi dimensioni. Supportando librerie popolari come PyTorch, PipPy native, DeepSpeed e HuggingFace Accelerate, offre API di gestione uniformi che rimangono coerenti tra scenari di inferenza distribuiti di modelli di grandi dimensioni e modelli non distribuiti. Per ulteriori informazioni, consulta la documentazione TorchServe’s large model inference
Container di deep learning con TorchServe
Per implementare un modello di grandi dimensioni con TorchServe su SageMaker AI, puoi utilizzare uno dei relativi container di deep learning (DLC). Per impostazione predefinita, TorchServe è installato in tutti i DLC PyTorch AWS. Durante il caricamento del modello, TorchServe è in grado di installare librerie specializzate su misura per modelli di grandi dimensioni come PiPPy, Deepspeed e Accelerate.
La tabella seguente elenca tutti i DLC SageMaker AI con TorchServe
| Categoria DLC | Framework | Hardware | URL di esempio |
|---|---|---|---|
|
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 |
Nozioni di base
Prima di distribuire il modello, completa i prerequisiti. È inoltre possibile configurare i parametri del modello e personalizzare il codice del gestore.
Prerequisiti
Per iniziare, assicurati di rispettare le seguenti condizioni fondamentali:
-
Assicurati di avere accesso a un account AWS. Configura il tuo ambiente in modo tale che AWS CLI possa accedere al tuo account tramite un ruolo IAM o un utente IAM AWS. Consigliamo di utilizzare un ruolo IAM. Ai fini del test nel tuo account personale, puoi collegare le seguenti policy di autorizzazione gestita al ruolo IAM:
Per ulteriori informazioni sul collegamento di policy IAM a un ruolo, consulta Adding and removing IAM identity permissions nella AWSGuida per l'utente IAM.
-
Configurazione locale delle dipendenze, come indicato negli esempi seguenti:
-
Installa la versione 2 del 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 -
Installa SageMaker AI e il client 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
-
Configurazione delle impostazioni e dei parametri del modello
TorchServe utilizza torchrunmodel_config.yaml. La variabile di ambiente CUDA_VISIBLE_DEVICES, che specifica gli ID dei dispositivi GPU visibili in un determinato momento, viene impostata in base a questo numero.
Ad esempio, supponiamo che ci siano otto GPU su un nodo e che un worker abbia bisogno di quattro GPU su un nodo (nproc_per_node=4). In questo caso, TorchServe assegna quattro GPU al primo worker (CUDA_VISIBLE_DEVICES="0,1,2,3") e quattro GPU al secondo worker (CUDA_VISIBLE_DEVICES="4,5,6,7”).
Oltre a questo comportamento predefinito, TorchServe offre agli utenti la flessibilità di specificare le GPU per un worker. Ad esempio, se imposti la variabile deviceIds: [2,3,4,5] nel file YAML di configurazione del modellonproc_per_node=2, TorchServe assegna CUDA_VISIBLE_DEVICES=”2,3” al primo worker e CUDA_VISIBLE_DEVICES="4,5” al secondo worker.
Nell'esempio model_config.yaml seguente, configuriamo i parametri front-end e back-end per il modello OPT-30bparallelType, deviceType, deviceIds e torchrun. Per informazioni più dettagliate sui parametri del front-end che puoi configurare, consulta la documentazione di PyTorch su 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
Personalizzazione di gestori
TorchServe offre gestori di basecustom_handler.py nella documentazione di PyTorch su 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. """
Preparazione degli artefatti di un modello
Prima di implementare il modello su SageMaker AI, è necessario creare pacchetti degli artefatti del modello. Per i modelli di grandi dimensioni, ti consigliamo di utilizzare lo strumento torch-model-archiver--archive-format
no-archive con l’argomento, che salta la compressione degli artefatti del modello. L'esempio seguente salva tutti gli artefatti del modello in una nuova cartella denominata 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 volta creata la cartella opt/, scarica il modello opt-30b nella cartella utilizzando lo strumento PyTorch Download_model
cd opt python path_to/Download_model.py --model_path model --model_name facebook/opt-30b --revision main
Infine, puoi caricare gli artefatti del modello su un bucket Amazon S3.
aws s3 cp opt{your_s3_bucket}/opt --recursive
Ora in Amazon S3 dovrebbero essere archiviati artefatti del modello pronti per l’implementazione su un endpoint di SageMaker AI.
Implementazione del modello utilizzando SageMaker Python SDK
Dopo aver preparato gli artefatti del modello, è possibile implementarlo su un endpoint di hosting SageMaker AI. In questa sezione viene spiegato come distribuire un unico modello di grandi dimensioni su un endpoint ed effettuare previsioni di risposta in streaming. Per ulteriori informazioni sullo streaming delle risposte dagli endpoint, consulta Invoke real-time endpoints.
Per distribuire il modello, completa le seguenti fasi:
-
Creare una sessione SageMaker AI, come mostrato nell’esempio seguente.
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}') -
Creare un modello non compresso in SageMaker AI, come mostrato nell’esempio seguente.
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) -
Implementare un modello su un’istanza di Amazon EC2, come illustrato nell’esempio seguente.
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 ) -
Inizializzare una classe per l'elaborazione di una risposta in streaming, come illustrato nell'esempio seguente.
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 -
Testare una previsione di risposta in streaming, come mostrato nell'esempio seguente.
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=' ')
Ora hai implementato il tuo modello su un endpoint di SageMaker AI e dovresti essere in grado di invocarlo per le risposte. Per ulteriori informazioni sugli endpoint di SageMaker AI in tempo reale, consulta Endpoint per modelli singoli.