Adapte su propio contenedor de inferencias para Amazon AI SageMaker - Amazon SageMaker AI

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.

Adapte su propio contenedor de inferencias para Amazon AI SageMaker

Si no puede usar ninguna de las imágenes incluidas en Imágenes de Docker de IA prediseñadas SageMaker Amazon SageMaker AI para su caso de uso, puede crear su propio contenedor de Docker y usarlo dentro de la SageMaker IA para el entrenamiento y la inferencia. Para ser compatible con la SageMaker IA, el contenedor debe tener las siguientes características:

  • El contenedor debe tener un servidor web mostrado en el puerto 8080.

  • El contenedor debe aceptar solicitudes de POST dirigidas a los puntos de conexión de /invocations y en tiempo real /ping. Las solicitudes que envíes a estos puntos de conexión deben devolverse en 60 segundos para las respuestas normales y 8 minutos para las respuestas en streaming, y deben tener un tamaño máximo de 25 MB.

Para obtener más información y un ejemplo de cómo crear tu propio contenedor de Docker para el entrenamiento y la inferencia con SageMaker IA, consulta Cómo crear tu propio contenedor de algoritmos.

En la siguiente guía, se muestra cómo utilizar un JupyterLab espacio con Amazon SageMaker Studio Classic para adaptar un contenedor de inferencias para que funcione con el alojamiento de SageMaker IA. En el ejemplo se utiliza un servidor web NGINX, Gunicorn como interfaz de puerta de enlace de servidor web Python y Flask como marco de aplicación web. Puede utilizar diferentes aplicaciones para adaptar el contenedor siempre que cumpla los requisitos enumerados anteriormente. Para obtener más información sobre el uso de su propio código de inferencia, consulte Código de inferencia personalizado con los servicios de alojamiento.

Adaptación de su contenedor de inferencias

Siga los siguientes pasos para adaptar su propio contenedor de inferencias para que funcione con el alojamiento de SageMaker IA. El ejemplo que se muestra en los pasos siguientes utiliza un modelo de Reconocimiento de entidades nombradas (NER) anteriormente entrenado que utiliza la biblioteca de procesamiento de lenguaje natural (NLP) spaCy para Python y lo siguiente:

  • Un Dockerfile para crear el contenedor que contiene el modelo de NER.

  • Scripts de inferencia para servir al modelo de NER

Si adapta este ejemplo a su caso de uso, debe usar un Dockerfile y los scripts de inferencia necesarios para implementar y servir su modelo.

  1. Crea JupyterLab espacio con Amazon SageMaker Studio Classic (opcional).

    Puede usar cualquier bloc de notas para ejecutar scripts y adaptar su contenedor de inferencias con alojamiento de SageMaker IA. En este ejemplo, se muestra cómo utilizar un JupyterLab espacio de Amazon SageMaker Studio Classic para lanzar una JupyterLab aplicación que incluye una imagen de SageMaker AI Distribution. Para obtener más información, consulte SageMaker JupyterLab.

  2. Cargue un archivo Docker y scripts de inferencia.

    1. Cree una carpeta en el directorio principal. Si está utilizando JupyterLab, en la esquina superior izquierda, elija el icono de Nueva carpeta e introduzca un nombre de carpeta que contenga el Dockerfile. En este ejemplo, la carpeta se llama docker_test_folder.

    2. Cargue un archivo de texto Dockerfile a su nueva carpeta. A continuación se muestra un Dockerfile de ejemplo que crea un contenedor de Docker con un modelo de Reconocimiento de entidades nombradas (NER) previamente entrenado de spaCy, con las aplicaciones y variables de entorno necesarias para ejecutar el ejemplo:

      FROM python:3.8 RUN apt-get -y update && apt-get install -y --no-install-recommends \ wget \ python3 \ nginx \ ca-certificates \ && rm -rf /var/lib/apt/lists/* RUN wget https://bootstrap.pypa.io/get-pip.py && python3 get-pip.py && \ pip install flask gevent gunicorn && \ rm -rf /root/.cache #pre-trained model package installation RUN pip install spacy RUN python -m spacy download en # Set environment variables ENV PYTHONUNBUFFERED=TRUE ENV PYTHONDONTWRITEBYTECODE=TRUE ENV PATH="/opt/program:${PATH}" COPY NER /opt/program WORKDIR /opt/program

      En el ejemplo de código anterior, la variable de entorno PYTHONUNBUFFERED evita que Python almacene en búfer el flujo de salida estándar, lo que permite una entrega más rápida de los registros al usuario. La variable de entorno PYTHONDONTWRITEBYTECODE impide que Python escriba archivos .pyc de código de bytes compilados, lo que no es necesario en este caso de uso. La variable de entorno PATH se utiliza para identificar la ubicación de los programas train y serve cuando se invoca el contenedor.

    3. Cree un nuevo directorio dentro de la nueva carpeta para que contengan los scripts que sirvan su modelo. En este ejemplo se utiliza un directorio llamado NER, que contiene los siguientes scripts necesarios para ejecutar este ejemplo:

      • predictor.py: un script de Python que contiene la lógica para cargar y realizar inferencias con el modelo.

      • nginx.conf: un script para configurar un servidor web.

      • serve: un script que inicia un servidor de inferencias.

      • wsgi.py: un script auxiliar para servir un modelo.

      importante

      Si copia los scripts de inferencia en un cuaderno que termina en .ipynb y les cambia el nombre, es posible que el script contenga caracteres de formato que impidan que se implemente el punto de conexión. En su lugar, cree un archivo de texto y cámbiele el nombre.

    4. Cargue un script para que su modelo esté disponible para inferencia. El siguiente es un script de ejemplo llamado predictor.py que utiliza Flask para proporcionar los puntos de conexión /invocations y /ping:

      from flask import Flask import flask import spacy import os import json import logging #Load in model nlp = spacy.load('en_core_web_sm') #If you plan to use a your own model artifacts, #your model artifacts should be stored in /opt/ml/model/ # The flask app for serving predictions app = Flask(__name__) @app.route('/ping', methods=['GET']) def ping(): # Check if the classifier was loaded correctly health = nlp is not None status = 200 if health else 404 return flask.Response(response= '\n', status=status, mimetype='application/json') @app.route('/invocations', methods=['POST']) def transformation(): #Process input input_json = flask.request.get_json() resp = input_json['input'] #NER doc = nlp(resp) entities = [(X.text, X.label_) for X in doc.ents] # Transform predictions to JSON result = { 'output': entities } resultjson = json.dumps(result) return flask.Response(response=resultjson, status=200, mimetype='application/json')

      El punto de conexión /ping del ejemplo de script anterior devuelve un código de estado de 200 si el modelo se ha cargado correctamente y 404 si se ha cargado de forma incorrecta. El punto de conexión /invocations procesa una solicitud con formato en JSON, extrae el campo de entrada y utiliza el modelo NER para identificar y almacenar las entidades en las entidades variables. La aplicación Flask devuelve la respuesta que contiene estas entidades. Para obtener más información sobre estas solicitudes de estado obligatorias, consulte Cómo debe responder su contenedor a las solicitudes de comprobación de estado (ping).

    5. Cargue un script para iniciar un servidor de inferencias. En el siguiente ejemplo de script, se llama a serve usando Gunicorn como servidor de aplicaciones y Nginx como servidor web:

      #!/usr/bin/env python # This file implements the scoring service shell. You don't necessarily need to modify it for various # algorithms. It starts nginx and gunicorn with the correct configurations and then simply waits until # gunicorn exits. # # The flask server is specified to be the app object in wsgi.py # # We set the following parameters: # # Parameter Environment Variable Default Value # --------- -------------------- ------------- # number of workers MODEL_SERVER_WORKERS the number of CPU cores # timeout MODEL_SERVER_TIMEOUT 60 seconds import multiprocessing import os import signal import subprocess import sys cpu_count = multiprocessing.cpu_count() model_server_timeout = os.environ.get('MODEL_SERVER_TIMEOUT', 60) model_server_workers = int(os.environ.get('MODEL_SERVER_WORKERS', cpu_count)) def sigterm_handler(nginx_pid, gunicorn_pid): try: os.kill(nginx_pid, signal.SIGQUIT) except OSError: pass try: os.kill(gunicorn_pid, signal.SIGTERM) except OSError: pass sys.exit(0) def start_server(): print('Starting the inference server with {} workers.'.format(model_server_workers)) # link the log streams to stdout/err so they will be logged to the container logs subprocess.check_call(['ln', '-sf', '/dev/stdout', '/var/log/nginx/access.log']) subprocess.check_call(['ln', '-sf', '/dev/stderr', '/var/log/nginx/error.log']) nginx = subprocess.Popen(['nginx', '-c', '/opt/program/nginx.conf']) gunicorn = subprocess.Popen(['gunicorn', '--timeout', str(model_server_timeout), '-k', 'sync', '-b', 'unix:/tmp/gunicorn.sock', '-w', str(model_server_workers), 'wsgi:app']) signal.signal(signal.SIGTERM, lambda a, b: sigterm_handler(nginx.pid, gunicorn.pid)) # Exit the inference server upon exit of either subprocess pids = set([nginx.pid, gunicorn.pid]) while True: pid, _ = os.wait() if pid in pids: break sigterm_handler(nginx.pid, gunicorn.pid) print('Inference server exiting') # The main routine to invoke the start function. if __name__ == '__main__': start_server()

      En el ejemplo de script anterior, se define una función de controlador de señales sigterm_handler, que cierra los subprocesos Nginx y Gunicorn al recibir una señal SIGTERM. Una función start_server inicia el controlador de señales, inicia y supervisa los subprocesos Nginx y Gunicorn, y captura los flujos de registro.

    6. Cargue un script para configurar su servidor web. El siguiente ejemplo de script llamado nginx.conf, configura un servidor web Nginx usando Gunicorn como servidor de aplicaciones para servir su modelo para inferencia:

      worker_processes 1; daemon off; # Prevent forking pid /tmp/nginx.pid; error_log /var/log/nginx/error.log; events { # defaults } http { include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log combined; upstream gunicorn { server unix:/tmp/gunicorn.sock; } server { listen 8080 deferred; client_max_body_size 5m; keepalive_timeout 5; proxy_read_timeout 1200s; location ~ ^/(ping|invocations) { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://gunicorn; } location / { return 404 "{}"; } } }

      El ejemplo de script anterior configura Nginx para ejecutarse en primer plano, establece la ubicación para capturar el error_log y define upstream como el sock socket del servidor Gunicorn. El servidor configura el bloque de servidores para que escuche en el puerto 8080, y establece límites en el tamaño del cuerpo de la solicitud del cliente y los valores de tiempo de espera. El bloque de servidores reenvía las solicitudes que contienen las rutas /ping o /invocations a server http://gunicorn de Gunicorn y devuelve un error 404 para las demás rutas.

    7. Cargue cualquier otro script necesario para entregar el modelo. Este ejemplo necesita el siguiente script de ejemplo llamado wsgi.py para ayudar a Gunicorn a encontrar la aplicación:

      import predictor as myapp # This is just a simple wrapper for gunicorn to find your app. # If you want to change the algorithm file, simply change "predictor" above to the # new file. app = myapp.app

    Desde la carpeta docker_test_folder, la estructura de directorios debe contener un Dockerfile y la carpeta NER. La carpeta NER debe contener los archivos nginx.conf, predictor.py, serve y wsgi.py de la siguiente manera:

    The Dockerfile structure has inference scripts under the NER directory next to the Dockerfile.

  3. Cree su propio contenedor.

    Desde la carpeta docker_test_folder, cree el contenedor de Docker. El siguiente comando de ejemplo creará el contenedor de Docker que está configurado en el Dockerfile:

    ! docker build -t byo-container-test .

    El comando anterior creará un contenedor llamado byo-container-test en el directorio de trabajo actual. Para obtener más información sobre los parámetros de compilación de Docker, consulte Build arguments.

    nota

    Si aparece el siguiente mensaje de error que indica que Docker no encuentra el Dockerfile, asegúrese de que el Dockerfile tenga el nombre correcto y se haya guardado en el directorio.

    unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /home/ec2-user/SageMaker/docker_test_folder/Dockerfile: no such file or directory

    Docker busca un archivo llamado específicamente Dockerfile sin ninguna extensión en el directorio actual. Si le ha asignado otro nombre, puede pasar el nombre de archivo manualmente con la marca -f. Por ejemplo, si has asignado un nombre a su Dockerfile como Dockerfile-text.txt, cree el contenedor de Docker con la marca -f seguida del archivo, de la siguiente manera:

    ! docker build -t byo-container-test -f Dockerfile-text.txt .
  4. Envío de la imagen de Docker a un Amazon Elastic Container Registry (Amazon ECR)

    En una celda del cuaderno, envíe la imagen de Docker a un ECR. En el siguiente ejemplo de código, se muestra cómo se crea el contenedor localmente, se inicia sesión y se envía a un ECR:

    %%sh # Name of algo -> ECR algorithm_name=sm-pretrained-spacy #make serve executable chmod +x NER/serve account=$(aws sts get-caller-identity --query Account --output text) # Region, defaults to us-west-2 region=$(aws configure get region) region=${region:-us-east-1} fullname="${account}.dkr.ecr.${region}.amazonaws.com/${algorithm_name}:latest" # If the repository doesn't exist in ECR, create it. aws ecr describe-repositories --repository-names "${algorithm_name}" > /dev/null 2>&1 if [ $? -ne 0 ] then aws ecr create-repository --repository-name "${algorithm_name}" > /dev/nullfi # Get the login command from ECR and execute it directly aws ecr get-login-password --region ${region}|docker login --username AWS --password-stdin ${fullname} # Build the docker image locally with the image name and then push it to ECR # with the full name. docker build -t ${algorithm_name} . docker tag ${algorithm_name} ${fullname} docker push ${fullname}

    En el ejemplo anterior, se muestra cómo realizar los siguientes pasos necesarios para enviar el contenedor de Docker de ejemplo a un ECR:

    1. Defina el nombre del algoritmo como sm-pretrained-spacy.

    2. Haga que el archivo serve de la carpeta NER sea ejecutable.

    3. Configure el Región de AWS.

    4. Cree un ECR si no existe todavía.

    5. Inicie sesión en el ECR.

    6. Compilación del contenedor de Docker de forma local

    7. Inserte la imagen de Docker en ECR.

  5. Configure el cliente de SageMaker IA

    Si desea utilizar los servicios de alojamiento de SageMaker IA para realizar inferencias, debe crear un modelo, crear una configuración de punto final y crear un punto final. Para obtener inferencias de su punto final, puede usar el cliente SageMaker AI boto3 Runtime para invocar su punto final. En el siguiente código se muestra cómo configurar tanto el cliente SageMaker AI como el cliente SageMaker Runtime mediante el cliente SageMaker AI boto3:

    import boto3 from sagemaker import get_execution_role sm_client = boto3.client(service_name='sagemaker') runtime_sm_client = boto3.client(service_name='sagemaker-runtime') account_id = boto3.client('sts').get_caller_identity()['Account'] region = boto3.Session().region_name #used to store model artifacts which SageMaker AI will extract to /opt/ml/model in the container, #in this example case we will not be making use of S3 to store the model artifacts #s3_bucket = '<S3Bucket>' role = get_execution_role()

    En el ejemplo de código anterior, no se usa el bucket de Amazon S3, sino que se inserta como comentario para mostrar la manera de almacenar los artefactos del modelo.

    Si recibe un error de permiso tras la ejecución del ejemplo de código anterior, es posible que tenga que agregar permisos a su rol de IAM. Para más información acerca de los roles de IAM, consulte Gestor de SageMaker funciones de Amazon. Para obtener más información sobre cómo agregar permisos al rol actual, consulte AWS políticas gestionadas para Amazon SageMaker AI.

  6. Cree el modelo

    Si desea utilizar los servicios de alojamiento de SageMaker IA para realizar inferencias, debe crear un modelo en IA. SageMaker El siguiente ejemplo de código muestra cómo crear el spaCy NER modelo dentro de la SageMaker IA:

    from time import gmtime, strftime model_name = 'spacy-nermodel-' + strftime("%Y-%m-%d-%H-%M-%S", gmtime()) # MODEL S3 URL containing model atrifacts as either model.tar.gz or extracted artifacts. # Here we are not #model_url = 's3://{}/spacy/'.format(s3_bucket) container = '{}.dkr.ecr.{}.amazonaws.com/sm-pretrained-spacy:latest'.format(account_id, region) instance_type = 'ml.c5d.18xlarge' print('Model name: ' + model_name) #print('Model data Url: ' + model_url) print('Container image: ' + container) container = { 'Image': container } create_model_response = sm_client.create_model( ModelName = model_name, ExecutionRoleArn = role, Containers = [container]) print("Model Arn: " + create_model_response['ModelArn'])

    En el ejemplo de código anterior, se muestra cómo definir una model_url con el s3_bucket si tuviera que utilizar el bucket de Amazon S3 de los comentarios del paso 5 y define el URI de ECR para la imagen del contenedor. En los ejemplos de código anteriores, se define ml.c5d.18xlarge como el tipo de instancia. También puede elegir un tipo de instancia diferente. Para obtener más información sobre los tipos de instancias disponibles, consulta Tipos de EC2 instancias de Amazon.

    En el ejemplo de código anterior, la clave Image apunta al URI de la imagen del contenedor. La definición de create_model_response utiliza el create_model method para crear un modelo y devolver el nombre del modelo, el rol y una lista que contiene la información del contenedor.

    A continuación, se muestra una salida de ejemplo del script anterior:

    Model name: spacy-nermodel-YYYY-MM-DD-HH-MM-SS Model data Url: s3://spacy-sagemaker-us-east-1-bucket/spacy/ Container image: 123456789012.dkr.ecr.us-east-2.amazonaws.com/sm-pretrained-spacy:latest Model Arn: arn:aws:sagemaker:us-east-2:123456789012:model/spacy-nermodel-YYYY-MM-DD-HH-MM-SS
    1. Configuración y creación de un punto de conexión

      Para utilizar el alojamiento de SageMaker IA con fines de inferencia, también debes configurar y crear un punto final. SageMaker La IA utilizará este punto final para la inferencia. En el siguiente ejemplo de configuración, se muestra cómo generar y configurar un punto de conexión con el tipo de instancia y el nombre de modelo que ha definido anteriormente:

      endpoint_config_name = 'spacy-ner-config' + strftime("%Y-%m-%d-%H-%M-%S", gmtime()) print('Endpoint config name: ' + endpoint_config_name) create_endpoint_config_response = sm_client.create_endpoint_config( EndpointConfigName = endpoint_config_name, ProductionVariants=[{ 'InstanceType': instance_type, 'InitialInstanceCount': 1, 'InitialVariantWeight': 1, 'ModelName': model_name, 'VariantName': 'AllTraffic'}]) print("Endpoint config Arn: " + create_endpoint_config_response['EndpointConfigArn'])

      En el ejemplo de configuración anterior, create_endpoint_config_response asocia el model_name a un nombre de configuración de punto de conexión único endpoint_config_name que se crea con una marca de tiempo.

      A continuación, se muestra una salida de ejemplo del script anterior:

      Endpoint config name: spacy-ner-configYYYY-MM-DD-HH-MM-SS Endpoint config Arn: arn:aws:sagemaker:us-east-2:123456789012:endpoint-config/spacy-ner-config-MM-DD-HH-MM-SS

      Para obtener más información sobre los errores de punto final, consulte ¿Por qué mi punto de enlace de Amazon SageMaker AI pasa a un estado de error cuando creo o actualizo un punto de enlace?

    2. Cree un punto de conexión y espere a que el punto de conexión esté en servicio.

      El siguiente ejemplo de código crea el punto de conexión con la configuración del ejemplo de configuración anterior e implementa el modelo:

      %%time import time endpoint_name = 'spacy-ner-endpoint' + strftime("%Y-%m-%d-%H-%M-%S", gmtime()) print('Endpoint name: ' + endpoint_name) create_endpoint_response = sm_client.create_endpoint( EndpointName=endpoint_name, EndpointConfigName=endpoint_config_name) print('Endpoint Arn: ' + create_endpoint_response['EndpointArn']) resp = sm_client.describe_endpoint(EndpointName=endpoint_name) status = resp['EndpointStatus'] print("Endpoint Status: " + status) print('Waiting for {} endpoint to be in service...'.format(endpoint_name)) waiter = sm_client.get_waiter('endpoint_in_service') waiter.wait(EndpointName=endpoint_name)

      En el ejemplo de código anterior, el método create_endpoint crea el punto de conexión con el nombre del punto de conexión generado en el ejemplo de código anterior e imprime el nombre de recurso de Amazon del punto de conexión. El método describe_endpoint devuelve información sobre el punto de conexión y su estado. Un camarero de SageMaker IA espera a que el punto final esté en servicio.

  7. Pruebe el punto de conexión.

    Una vez que su punto de conexión esté en servicio, envíe una solicitud de invocación a su punto de conexión. En el siguiente ejemplo de código, se muestra cómo enviar una solicitud de prueba a su punto de conexión:

    import json content_type = "application/json" request_body = {"input": "This is a test with NER in America with \ Amazon and Microsoft in Seattle, writing random stuff."} #Serialize data for endpoint #data = json.loads(json.dumps(request_body)) payload = json.dumps(request_body) #Endpoint invocation response = runtime_sm_client.invoke_endpoint( EndpointName=endpoint_name, ContentType=content_type, Body=payload) #Parse results result = json.loads(response['Body'].read().decode())['output'] result

    En el ejemplo de código anterior, el método json.dumps serializa el request_body en una cadena con formato en JSON y la guarda en la carga útil de la variable. A continuación, el cliente SageMaker AI Runtime utiliza el método invocar punto final para enviar la carga útil a su punto final. El resultado contiene la respuesta del punto de conexión tras extraer el campo de salida.

    El ejemplo de código anterior debe devolver la siguiente salida:

    [['NER', 'ORG'], ['America', 'GPE'], ['Amazon', 'ORG'], ['Microsoft', 'ORG'], ['Seattle', 'GPE']]
  8. Eliminación de su punto de conexión

    Una vez que haya completado las invocaciones, elimine el punto de conexión para conservar los recursos. En el siguiente ejemplo de código, se muestra cómo eliminar un punto de conexión:

    sm_client.delete_endpoint(EndpointName=endpoint_name) sm_client.delete_endpoint_config(EndpointConfigName=endpoint_config_name) sm_client.delete_model(ModelName=model_name)

    Para ver un cuaderno completo que contenga el código de este ejemplo, consulte BYOC-Single-Model.