Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Déployez de grands modèles à des fins d'inférence avec TorchServe
Ce didacticiel explique comment déployer de grands modèles et utiliser l'inférence dans Amazon SageMaker avec TorchServe onGPUs. Cet exemple déploie le modèle OPT-30bml.g5
Vous pouvez le modifier pour l'adapter à d'autres modèles et types d'instance. Remplacez les informations figurant
dans les exemples par vos propres informations.italicized placeholder text
TorchServe est une puissante plateforme ouverte pour l'inférence de modèles distribués à grande échelle. En prenant en charge les bibliothèques populaires telles que PyTorch Native P iPPy et HuggingFace Accelerate, il offre un gestionnaire uniforme APIs qui reste cohérent entre les scénarios d'inférence de grands modèles distribués et de modèles non distribués. DeepSpeed Pour plus d'informations, consultez TorchServela documentation sur l'inférence de grands modèles
Conteneurs de deep learning avec TorchServe
Pour déployer un modèle de grande taille avec TorchServe on SageMaker, vous pouvez utiliser l'un des conteneurs de SageMaker deep learning (DLCs). Par défaut, TorchServe est installé dans tous AWS PyTorchDLCs. Pendant le chargement du modèle, TorchServe vous pouvez installer des bibliothèques spécialisées adaptées aux grands modèles tels que PiPPy, Deepspeed et Accelerate.
Le tableau suivant répertorie tous les SageMaker DLCsavec TorchServe
DLCcatégorie | Framework | Matériel | Exemple 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 |
Neurones |
763104351884.dkr. ecr.us-west-2.amazonaws.com /:1.13.1-neuron-py310-sdk2.12.0-ubuntu20.04 pytorch-inference-neuron |
Premiers pas
Avant de déployer votre modèle, remplissez les conditions préalables. Vous pouvez également configurer les paramètres de votre modèle et personnaliser le code du gestionnaire.
Prérequis
Avant de démarrer, vérifiez que les conditions préalables suivantes sont respectées :
-
Assurez-vous d'avoir accès à un AWS compte. Configurez votre environnement de manière à ce qu' AWS CLI ils puissent accéder à votre compte par le biais d'un AWS IAM utilisateur ou d'un IAM rôle. Nous vous recommandons d'utiliser un IAM rôle. À des fins de test dans votre compte personnel, vous pouvez associer les politiques d'autorisations gérées suivantes au IAM rôle :
Pour plus d'informations sur IAM l'attachement de politiques à un rôle, consultez la section Ajouter et supprimer des autorisations IAM d'identité dans le Guide de AWS IAM l'utilisateur.
-
Configurez vos dépendances localement, comme indiqué dans les exemples suivants.
-
Installez la version 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
-
Installez SageMaker et le 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
-
Configuration des paramètres et des paramètres du modèle
TorchServe permet torchrun
model_config.yaml
fichier. La variable d'environnementCUDA_VISIBLE_DEVICES
, qui spécifie les GPU appareils IDs visibles à un moment donné, est définie en fonction de ce nombre.
Par exemple, supposons qu'il y en ait 8 GPUs sur un nœud et qu'un travailleur en ait besoin de 4 GPUs sur un nœud (nproc_per_node=4
). Dans ce cas, en TorchServe attribue quatre GPUs au premier travailleur (CUDA_VISIBLE_DEVICES="0,1,2,3"
) et quatre GPUs au second travailleur (CUDA_VISIBLE_DEVICES="4,5,6,7”
).
Outre ce comportement par défaut, TorchServe offre aux utilisateurs la flexibilité de spécifier GPUs pour un travailleur. Par exemple, si vous définissez la variable deviceIds: [2,3,4,5]
dans le YAMLfichier de configuration du modèlenproc_per_node=2
, puis que vous TorchServe l'CUDA_VISIBLE_DEVICES=”2,3”
assignez au premier et CUDA_VISIBLE_DEVICES="4,5”
au second programme de travail.
Dans l'model_config.yaml
exemple suivant, nous configurons les paramètres frontaux et principaux pour le modèle OPT-30bparallelType
deviceType
, deviceIds
ettorchrun
. Pour des informations plus détaillées sur les paramètres frontaux que vous pouvez configurer, consultez la PyTorch GitHub documentation
# 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
Personnaliser les gestionnaires
TorchServe propose des gestionnaires de base et descustom_handler.py
code figurant dans la PyTorch GitHub documentation
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. """
Préparation des artefacts de votre modèle
Avant de déployer votre modèle sur SageMaker, vous devez empaqueter les artefacts de votre modèle. Pour les modèles de grande taille, nous vous recommandons d'utiliser l' PyTorch torch-model-archiver--archive-format
no-archive
, qui ignore la compression des artefacts du modèle. L'exemple suivant enregistre tous les artefacts du modèle dans un nouveau dossier nommé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
Une fois le opt/
dossier créé, téléchargez le modèle OPT -30b dans le dossier à l'aide de l'outil PyTorch Download_model
cd opt python path_to/Download_model.py --model_path model --model_name facebook/opt-30b --revision main
Enfin, téléchargez les artefacts du modèle dans un compartiment Amazon S3.
aws s3 cp opt
{your_s3_bucket}
/opt --recursive
Vous devriez désormais disposer d'artefacts de modèle stockés dans Amazon S3 prêts à être déployés sur un SageMaker point de terminaison.
Déployez le modèle à l'aide du SageMaker Python SDK
Après avoir préparé les artefacts de votre modèle, vous pouvez déployer votre modèle sur un point de terminaison SageMaker d'hébergement. Cette section explique comment déployer un seul grand modèle sur un point de terminaison et établir des prévisions de réponse au streaming. Pour plus d'informations sur le streaming des réponses provenant des points de terminaison, consultez la section Invoquer des points de terminaison en temps réel.
Pour déployer votre modèle, procédez comme suit :
-
Créez une SageMaker session, comme indiqué dans l'exemple suivant.
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}')
-
Créez un modèle non compressé dans SageMaker, comme indiqué dans l'exemple suivant.
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)
-
Déployez le modèle sur une EC2 instance Amazon, comme illustré dans l'exemple suivant.
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 )
-
Initialisez une classe pour traiter la réponse de streaming, comme indiqué dans l'exemple suivant.
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
-
Testez une prédiction de réponse au streaming, comme illustré dans l'exemple suivant.
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=' ')
Vous avez maintenant déployé votre modèle sur un SageMaker point de terminaison et vous devriez pouvoir l'invoquer pour obtenir des réponses. Pour plus d'informations sur les points de terminaison SageMaker en temps réel, consultezPoints de terminaison à modèle unique.