View a markdown version of this page

Stellen Sie große Modelle für Inferenzen bereit mit TorchServe - Amazon SageMaker KI

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Stellen Sie große Modelle für Inferenzen bereit mit TorchServe

Dieses Tutorial zeigt, wie Sie große Modelle bereitstellen und Inferenzen in Amazon SageMaker AI mit TorchServe GPUs bereitstellen. In diesem Beispiel wird das OPT-30b Modell auf einer Instance bereitgestellt. ml.g5 Sie können dies so ändern, dass es mit anderen Modellen und Instance-Typen funktioniert. Ersetzen Sie die italicized placeholder text in den Beispielen durch Ihre eigenen Angaben.

TorchServe ist eine leistungsstarke offene Plattform für umfangreiche verteilte Modellinferenzen. Durch die Unterstützung gängiger Bibliotheken wie PyTorch natives PiPPy und HuggingFace Accelerate bietet sie einheitliche Handler-APIs, die in verteilten großen Modellen und nicht verteilten Modellinferenzszenarien konsistent bleiben. DeepSpeed Weitere Informationen finden Sie in der umfangreichen Dokumentation TorchServe zur Modellinferenz.

Deep-Learning-Container mit TorchServe

Um ein großes Modell ohne TorchServe KI bereitzustellen, können Sie einen der SageMaker SageMaker KI-Deep-Learning-Container (DLCs) verwenden. TorchServe Ist standardmäßig in allen AWS PyTorch DLCs installiert. Beim Laden des Modells TorchServe können spezielle Bibliotheken installiert werden, die auf große Modelle zugeschnitten sind, wie PiPPY, Deepspeed und Accelerate.

In der folgenden Tabelle sind alle SageMaker AI-DLCs mit aufgeführt. TorchServe

DLC-Kategorie Framework Hardware (Hardware) Beispiel-URL

SageMaker AI Framework-Container

PyTorch 2.0.0+

CPU, GPU

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

SageMaker Graviton-Container im KI-Framework

PyTorch 2.0.0+

CPU

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

Stabilität/KI-Inferenzcontainer

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

Behälter für Neuronen

PyTorch 1.13.1

Neuronen

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

Erste Schritte

Bevor Sie Ihr Modell bereitstellen, müssen Sie die Voraussetzungen erfüllen. Sie können auch die Modellparameter konfigurieren und den Handler Code anpassen.

Voraussetzungen

Um mit der Arbeit zu beginnen, müssen Sie die folgenden Voraussetzungen erfüllen:

  1. Stellen Sie sicher, dass Sie Zugriff auf ein Konto haben. AWS Richten Sie Ihre Umgebung so ein, dass sie entweder über einen AWS IAM-Benutzer oder eine IAM-Rolle auf Ihr Konto zugreifen AWS CLI können. Wir empfehlen die Verwendung einer IAM-Rolle. Zu Testzwecken in Ihrem persönlichen Konto können Sie der IAM-Rolle die folgenden Richtlinien für verwaltete Berechtigungen hinzufügen:

    Weitere Informationen zum Zuordnen von IAM-Richtlinien zu einer Rolle finden Sie unter Hinzufügen und Entfernen von IAM-Identitätsberechtigungen im AWS IAM-Benutzerhandbuch.

  2. Konfigurieren Sie die Abhängigkeiten lokal, wie in den folgenden Beispielen gezeigt.

    1. Installieren Sie Version 2 von: 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. Installieren Sie SageMaker AI und den Boto3-Client:

      # 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

Modelleinstellungen und Parameter konfigurieren

TorchServe verwendet torchrun, um die verteilte Umgebung für die parallele Modellverarbeitung einzurichten. TorchServe ist in der Lage, mehrere Worker für ein großes Modell zu unterstützen. TorchServe Verwendet standardmäßig einen Round-Robin-Algorithmus, um GPUs einem Worker auf einem Host zuzuweisen. Bei umfangreichen Modellinferenzen wird die Anzahl der jedem Worker zugewiesenen GPUs automatisch auf der Grundlage der in der model_config.yaml-Datei angegebenen Anzahl der GPUs berechnet. Die Umgebungsvariable CUDA_VISIBLE_DEVICES, die die GPU-Geräte-IDs angibt, die zu einem bestimmten Zeitpunkt sichtbar sind, wird auf der Grundlage dieser Zahl festgelegt.

Nehmen wir zum Beispiel an, es gibt 8 GPUs auf einem Knoten und ein Worker benötigt 4 GPUs auf einem Knoten (nproc_per_node=4). TorchServe Weist in diesem Fall dem ersten Worker (CUDA_VISIBLE_DEVICES="0,1,2,3") vier GPUs zu und dem zweiten Worker () vier GPUs. CUDA_VISIBLE_DEVICES="4,5,6,7”

Zusätzlich zu diesem Standardverhalten TorchServe bietet es Benutzern die Flexibilität, GPUs für einen Worker anzugeben. Wenn Sie beispielsweise die Variable deviceIds: [2,3,4,5] in der YAML-Datei der Modellkonfiguration festlegen und setzen nproc_per_node=2, wird sie dann dem ersten Worker und CUDA_VISIBLE_DEVICES=”2,3” CUDA_VISIBLE_DEVICES="4,5” dem zweiten Worker TorchServe zugewiesen.

Im folgenden model_config.yaml Beispiel konfigurieren wir sowohl Front-End- als auch Back-End-Parameter für das Modell. OPT-30b Die konfigurierten Front-End-Parameter sind parallelType, deviceType, deviceIds und torchrun. Weitere Informationen zu den Frontend-Parametern, die Sie konfigurieren können, finden Sie in der Dokumentation. PyTorch GitHub Die Back-End-Konfiguration basiert auf einer YAML-Map, die eine individuelle Anpassung ermöglicht. Für die Backend-Parameter definieren wir die DeepSpeed Konfiguration und zusätzliche Parameter, die vom benutzerdefinierten Handlercode verwendet werden.

# 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

Handler anpassen

TorchServe bietet Basishandler und Handler-Dienstprogramme für umfangreiche Modellinferenzen, die mit gängigen Bibliotheken erstellt wurden. Das folgende Beispiel zeigt, wie die benutzerdefinierte Handler-Klasse die TransformersSeqClassifierHandler BaseDeepSpeedHandler Handler-Dienstprogramme erweitert und verwendet. https://github.com/pytorch/serve/blob/master/ts/handler_utils/distributed/deepspeed.py Ein vollständiges Codebeispiel finden Sie im custom_handler.py Code in der PyTorch GitHub Dokumentation.

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. """

Vorbereiten Ihrer Modellartefakte

Bevor Sie Ihr Modell auf SageMaker KI bereitstellen, müssen Sie Ihre Modellartefakte verpacken. Für große Modelle empfehlen wir, das Tool PyTorch Torch-Model-Archiver mit dem Argument zu verwenden, wodurch das Komprimieren von Modellartefakten --archive-format no-archive übersprungen wird. Im folgenden Beispiel werden alle Modellartefakte in einem neuen Ordner mit dem Namen opt/ gespeichert.

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

Sobald der opt/ Ordner erstellt wurde, laden Sie das OPT-30b Modell mithilfe des Tools in den Ordner herunter. PyTorch Download_model

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

Laden Sie abschließend die Modellartefakte zu einem Amazon S3 Bucket hoch.

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

Sie sollten jetzt Modellartefakte in Amazon S3 gespeichert haben, die für die Bereitstellung auf einem SageMaker KI-Endpunkt bereit sind.

Stellen Sie das Modell mithilfe des SageMaker Python-SDK bereit

Nachdem Sie Ihre Modellartefakte vorbereitet haben, können Sie Ihr Modell auf einem SageMaker AI Hosting-Endpunkt bereitstellen. In diesem Abschnitt wird beschrieben, wie Sie ein einzelnes großes Modell auf einem Endpunkt bereitstellen und Streaming-Antwortprognosen erstellen. Weitere Informationen zum Streamen von Antworten von Endpunkten finden Sie unter Echtzeit-Endpunkte aufrufen.

Führen Sie die folgenden Schritte aus, um Ihr Modell bereitzustellen:

  1. Erstellen Sie eine SageMaker AI-Sitzung, wie im folgenden Beispiel gezeigt.

    import boto3 import sagemaker from sagemaker.core.resources import Model from sagemaker.core import image_uris from sagemaker.core.helper.session_helper import get_execution_role, Session boto3_session=boto3.session.Session(region_name="us-west-2") smr = boto3.client('sagemaker-runtime-demo') sm = boto3.client('sagemaker') role = get_execution_role() # execution role for the endpoint sess= 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. Erstellen Sie ein unkomprimiertes Modell in SageMaker AI, wie im folgenden Beispiel gezeigt.

    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. Stellen Sie das Modell auf einer Amazon-EC2-Instance bereit, wie im folgenden Beispiel gezeigt.

    model.deploy( initial_instance_count=1, instance_type=instance_type, endpoint_name=endpoint_name, volume_size_in_gb=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. Initialisieren Sie eine Klasse, wie im folgenden Beispiel gezeigt, um die Streaming-Antwort zu verarbeiten.

    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. Testen Sie eine Streaming-Antwortvorhersage, wie im folgenden Beispiel gezeigt.

    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=' ')

Sie haben Ihr Modell jetzt auf einem SageMaker KI-Endpunkt bereitgestellt und sollten in der Lage sein, es für Antworten aufzurufen. Weitere Informationen zu SageMaker KI-Echtzeit-Endpunkten finden Sie unter. Single-model Endpunkte