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.
Adaptez votre propre conteneur d'inférence pour Amazon AI SageMaker
Si vous ne pouvez utiliser aucune des images répertoriées dans Images SageMaker AI Docker prédéfinies Amazon SageMaker AI pour votre cas d'utilisation, vous pouvez créer votre propre conteneur Docker et l'utiliser dans SageMaker AI à des fins de formation et d'inférence. Pour être compatible avec SageMaker l'IA, votre contenant doit présenter les caractéristiques suivantes :
-
Votre conteneur doit avoir une liste de serveurs Web sur le port
8080. -
Votre conteneur doit accepter les demandes
POSTadressées aux points de terminaison/invocationset/pingen temps réel. Les demandes que vous envoyez à ces points de terminaison doivent être renvoyées dans un délai de 60 secondes pour les réponses régulières et de 8 minutes pour les réponses de streaming, et leur taille maximale est de 25 Mo.
Pour plus d'informations et un exemple de création de votre propre conteneur Docker à des fins d'entraînement et d'inférence avec l' SageMaker IA, consultez la section Création de votre propre conteneur d'algorithmes
Le guide suivant explique comment utiliser un JupyterLab espace avec Amazon SageMaker Studio Classic pour adapter un conteneur d'inférence afin qu'il fonctionne avec l'hébergement SageMaker AI. L’exemple utilise un serveur Web NGINX, Gunicorn en tant qu’interface de passerelle de serveur Web Python et Flask en tant que cadre d’application Web. Vous pouvez utiliser différentes applications pour adapter votre conteneur à condition qu’il respecte les conditions énumérées ci-dessus. Pour plus d’informations sur l’utilisation de votre propre code d’inférence, consultez Code d’inférence personnalisé avec les services d’hébergement.
Adaptation de votre conteneur d’inférence
Suivez les étapes ci-dessous pour adapter votre propre conteneur d'inférence afin qu'il fonctionne avec l'hébergement SageMaker AI. L’exemple présenté dans les étapes suivantes utilise un modèle de reconnaissance des entités nommées (NER)Python et les éléments suivants :
-
Un Dockerfile pour créer le conteneur qui contient le modèle NER.
-
Scripts d’inférence destinés au modèle NER.
Si vous adaptez cet exemple à votre cas d’utilisation, vous devez utiliser un Dockerfile les scripts et d’inférence nécessaires au déploiement et au service de votre modèle.
-
Créez de JupyterLab l'espace avec Amazon SageMaker Studio Classic (facultatif).
Vous pouvez utiliser n'importe quel bloc-notes pour exécuter des scripts afin d'adapter votre conteneur d'inférence à l'hébergement SageMaker AI. Cet exemple vous montre comment utiliser un JupyterLab espace dans Amazon SageMaker Studio Classic pour lancer une JupyterLab application fournie avec une image SageMaker AI Distribution. Pour de plus amples informations, veuillez consulter SageMaker JupyterLab.
-
Téléchargez un fichier Docker et des scripts d’inférence.
-
Créez un dossier dans votre répertoire personnel. Si vous utilisez JupyterLab, dans le coin supérieur gauche, cliquez sur l’icône Nouveau dossier et entrez un nom de dossier contenant votre Dockerfile. Dans cet exemple, le dossier est nommé
docker_test_folder. -
Téléchargez un fichier texte Dockerfile dans votre nouveau dossier. Voici un exemple Dockerfile qui crée un conteneur Docker avec un modèle de reconnaissance des entités nommées (NER)
pré-entraîné à partir de spaCy , les applications et les variables d’environnement nécessaires pour exécuter l’exemple : 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/programDans l’exemple de code précédent, la variable d’environnement
PYTHONUNBUFFEREDempêche Python de mettre en mémoire tampon le flux de sortie standard, ce qui permet de livrer plus rapidement les journaux à l’utilisateur. La variable d’environnementPYTHONDONTWRITEBYTECODEempêche Python d’écrire des fichiers.pycde bytecode compilés, qui ne sont pas nécessaires pour ce cas d’utilisation. La variable d’environnementPATHest utilisée pour identifier l’emplacement des programmestrainetservelorsque le conteneur est invoqué. -
Créez un nouveau répertoire dans votre nouveau dossier pour contenir les scripts destinés à servir votre modèle. Cet exemple utilise un répertoire appelé
NER, qui contient les scripts suivants nécessaires pour exécuter cet exemple :-
predictor.py: un script Python contenant la logique permettant de charger et d’effectuer des inférences avec votre modèle. -
nginx.conf: un script pour configurer un serveur Web. -
serve: un script qui démarre un serveur d’inférence. -
wsgi.py: un script d’assistance destiné à servir un modèle.
Important
Si vous copiez vos scripts d’inférence dans un bloc-notes se terminant par
.ipynbet que vous les renommez, votre script peut contenir des caractères de mise en forme qui empêcheront le déploiement de votre point de terminaison. Créez plutôt un fichier texte et renommez-le. -
-
Téléchargez un script pour rendre votre modèle disponible à des fins d’inférence. Voici un exemple de script appelé
predictor.pyqui utilise Flask pour fournir les points de terminaison/pinget/invocations: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')Dans l’exemple de script précédent, le point de terminaison
/pingrenvoie un code d’état indiquant200si le modèle est chargé correctement et404s’il n’est pas chargé correctement. Le point de terminaison/invocationstraite une demande formatée dans JSON, extrait le champ de saisie et utilise le NER modèle pour identifier et stocker les entités dans les entités variables. L’application Flask renvoie la réponse contenant ces entités. Pour plus d’informations sur ces demandes d’intégrité requises, consultez Comment votre conteneur doit-il répondre aux requêtes de surveillance de l’état (Ping) ?. -
Chargez un script pour démarrer un serveur d’inférence. L’exemple de script suivant appelle
serveen utilisant Gunicorn en tant que serveur d’applications et Nginx en tant que serveur 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()L’exemple de script précédent définit une fonction de gestion de signal
sigterm_handler, qui arrête les sous-processus Nginx et Gunicorn lorsqu’elle reçoit un signalSIGTERM. Une fonctionstart_serverdémarre le gestionnaire de signaux, démarre et surveille les sous-processus Nginx et Gunicorn, et capture les flux de journaux. -
Téléchargez un script pour configurer votre serveur Web. L’exemple de script suivant appelé
nginx.confconfigure un serveur Web Nginx en utilisant Gunicorn comme serveur d’applications pour servir votre modèle à des fins d’inférence :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 "{}"; } } }L’exemple de script précédent configure Nginx pour exécution au premier plan, définit l’emplacement pour capturer le
error_loget définitupstreamcomme le socket du serveur Gunicorn. Le serveur configure le bloc serveur pour qu’il écoute sur le port8080, fixe des limites à la taille du corps de demande du client et aux valeurs de délai d’expiration. Le bloc serveur transmet les demandes contenant les chemins/pingou/invocationsvers leserver http://gunicornGunicorn, et renvoie une erreur404pour les autres chemins. -
Téléchargez tous les autres scripts nécessaires pour servir votre modèle. Cet exemple nécessite l’exemple de script suivant appelé
wsgi.pypour aider Gunicorn à trouver votre application :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
Dans le dossier
docker_test_folder, la structure de votre répertoire doit contenir un Dockerfile et le dossier NER. Le dossier NER doit contenir les fichiersnginx.conf,predictor.py,serveetwsgi.pycomme suit :
-
-
Créez votre propre conteneur.
À partir du dossier
docker_test_folder, créez votre conteneur Docker. L’exemple de commande suivant permet de créer le conteneur Docker configuré dans votre Dockerfile :! docker build -t byo-container-test .La commande précédente créera un conteneur appelé
byo-container-testdans le répertoire de travail actuel. Pour plus d’informations sur les paramètres de création Docker, consultez Arguments de création. Note
Si vous obtenez le message d’erreur suivant indiquant que Docker ne peut pas trouver le Dockerfile, assurez-vous que le Dockerfile a été nommé correctement et qu’il est enregistré dans le répertoire.
unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /home/ec2-user/SageMaker/docker_test_folder/Dockerfile: no such file or directoryDocker recherche un fichier appelé spécifiquement Dockerfile, sans extension, dans le répertoire actuel. Si vous avez nommé le fichier différemment, vous pouvez transmettre le nom de fichier manuellement avec l’indicateur -f. Par exemple, si vous avez nommé votre Dockerfile Dockerfile-text.txt, créez votre conteneur Docker en utilisant l’indicateur
-fsuivi de votre fichier comme suit :! docker build -t byo-container-test -f Dockerfile-text.txt . -
Transmission de votre image Docker à Amazon Elastic Container Registry (Amazon ECR)
Transmettez votre image Docker vers un ECR dans une cellule de bloc-notes. L’exemple de code suivant vous montre comment créer votre conteneur localement, vous connecter et le transférer vers 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}Dans l’exemple précédent, il montre comment effectuer les étapes suivantes nécessaires pour transférer l’exemple de conteneur Docker vers un ECR :
-
Définissez le nom de l’algorithme comme
sm-pretrained-spacy. -
Rendez le fichier
servesitué dans le dossier NER exécutable. -
Réglez leRégion AWS.
-
Créez un ECR s’il n’existe pas déjà.
-
Connectez-vous à l’ECR.
-
Créez le conteneur Docker localement.
-
Transmettez l’image Docker à ECR.
-
-
Configuration du client SageMaker AI
Si vous souhaitez utiliser les services d'hébergement SageMaker AI à des fins d'inférence, vous devez créer un modèle, créer une
configuration de point de terminaison et créer un point de terminaison . Pour obtenir des déductions à partir de votre point de terminaison, vous pouvez utiliser le client SageMaker AI boto3 Runtime pour appeler votre point de terminaison. Le code suivant explique comment configurer à la fois le client SageMaker AI et le client SageMaker Runtime à l'aide du client 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()Dans l’exemple de code précédent, le compartiment Amazon S3 n’est pas utilisé, mais il est inséré en tant que commentaire pour montrer comment stocker les artefacts du modèle.
Si vous recevez une erreur d’autorisation après avoir exécuté l’exemple de code précédent, vous devrez peut-être ajouter des autorisations à votre rôle IAM. Pour plus d’informations sur les rôles IAM, consultez Amazon SageMaker Role Manager. Pour plus d’informations sur l’ajout d’autorisations à votre rôle actuel, consultez AWSpolitiques gérées pour Amazon SageMaker AI.
-
Créez votre modèle.
Si vous souhaitez utiliser les services d'hébergement SageMaker AI à des fins d'inférence, vous devez créer un modèle dans SageMaker AI. L'exemple de code suivant vous montre comment créer le spaCy NER modèle dans SageMaker AI :
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'])L’exemple de code précédent montre comment définir une
model_urlà l’aide des3_bucketsi vous deviez utiliser le compartiment Amazon S3 à partir des commentaires de l’étape 5, et définit l’URI ECR pour l’image du conteneur. Les exemples de code précédents définissentml.c5d.18xlargecomme le type d’instance. Vous pouvez également choisir un autre type d’instance. Pour plus d'informations sur les types d'instances disponibles, consultez la section Types d' EC2 instances Amazon. Dans l’exemple de code précédent, la clé
Imagepointe vers l’URI de l’image du conteneur. La définitioncreate_model_responseutilisecreate_model methodpour créer un modèle et renvoyer le nom du modèle, le rôle et une liste contenant les informations sur le conteneur.Voici un exemple de sortie du script précédent :
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 -
-
Configuration et création d’un point de terminaison
Pour utiliser l'hébergement SageMaker AI à des fins d'inférence, vous devez également configurer et créer un point de terminaison. SageMaker L'IA utilisera ce point de terminaison à des fins d'inférence. L’exemple de configuration suivant montre comment générer et configurer un point de terminaison avec le type d’instance et le nom de modèle que vous avez définis précédemment :
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'])Dans l’exemple de configuration précédent,
create_endpoint_config_responseassociemodel_nameà un nom de configuration du point de terminaison uniqueendpoint_config_namecréé avec un horodatage.Voici un exemple de sortie du script précédent :
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-SSPour plus d'informations sur les erreurs de point de terminaison, consultez Pourquoi mon point de terminaison Amazon SageMaker AI passe en état d'échec lorsque je crée ou mets à jour un point de terminaison ?
-
Créez un point de terminaison et attendez qu’il soit en service.
L’exemple de code suivant crée le point de terminaison en utilisant la configuration de l’exemple de configuration précédent et déploie le modèle :
%%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)Dans l’exemple de code précédent, la méthode
create_endpointcrée le point de terminaison avec le nom de point de terminaison généré dans l’exemple de code précédent, et imprime l’Amazon Resource Name (ARN) du point de terminaison. La méthodedescribe_endpointrenvoie des informations sur le point de terminaison et son état. Un serveur SageMaker doté d'une intelligence artificielle attend que le terminal soit en service.
-
-
Testez votre point de terminaison.
Une fois que votre point de terminaison est en service, envoyez-lui une demande d’invocation
. L’exemple de code suivant montre comment envoyer une demande de test à votre point de terminaison : 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'] resultDans l’exemple de code précédent, la méthode
json.dumpssérialiserequest_bodydans une chaîne formatée en JSON et l’enregistre dans les données utiles variables. Le client SageMaker AI Runtime utilise ensuite la méthode d'appel du point de terminaisonpour envoyer la charge utile à votre point de terminaison. Le résultat contient la réponse de votre point de terminaison après l’extraction du champ de sortie. L’exemple de code précédent doit renvoyer à la sortie suivante :
[['NER', 'ORG'], ['America', 'GPE'], ['Amazon', 'ORG'], ['Microsoft', 'ORG'], ['Seattle', 'GPE']] -
Suppression de votre point de terminaison
Une fois que vous avez terminé vos invocations, supprimez votre point de terminaison pour économiser les ressources. L’exemple de code suivant vous indique comment supprimer votre point de terminaison :
sm_client.delete_endpoint(EndpointName=endpoint_name) sm_client.delete_endpoint_config(EndpointConfigName=endpoint_config_name) sm_client.delete_model(ModelName=model_name)Pour un bloc-notes complet contenant le code de cet exemple, consultez BYOC-Single-Model
.