Invocation de modèles pour une inférence en temps réel - Amazon SageMaker AI

Invocation de modèles pour une inférence en temps réel

Après avoir utilisé Amazon SageMaker AI pour déployer un modèle sur un point de terminaison, vous pouvez interagir avec le modèle en lui envoyant des demandes d’inférence. Pour envoyer une demande d’inférence à un modèle, vous invoquez le point de terminaison qui l’héberge. Vous pouvez invoquer vos points de terminaison à l’aide d’Amazon SageMaker Studio, des kits SDK AWS ou de la AWS CLI.

Invocation de votre modèle à l’aide d’Amazon SageMaker Studio

Après avoir déployé votre modèle sur un point de terminaison, vous pouvez consulter le point de terminaison avec Amazon SageMaker Studio et tester votre point de terminaison en envoyant des demandes d’inférence uniques.

Note

SageMaker AI prend uniquement en charge les tests de points de terminaison dans Studio pour les points de terminaison en temps réel.

Pour envoyer une demande d’inférence de test à votre point de terminaison
  1. Lancez Amazon SageMaker Studio.

  2. Dans le panneau de navigation de gauche, sélectionnez Déploiements.

  3. Dans le menu déroulant, sélectionnez Endpoints (Points de terminaison).

  4. Recherchez votre point de terminaison par son nom, puis choisissez-le dans le tableau. Les noms de point de terminaison répertoriés dans le panneau Points de terminaison sont définis lorsque vous déployez un modèle. L’espace de travail Studio ouvre la page Point de terminaison dans un nouvel onglet.

  5. Sélectionnez l’onglet Tester l’inférence.

  6. Dans Options de test, sélectionnez l’une des options suivantes :

    1. Sélectionnez Tester l’exemple de demande pour envoyer immédiatement une demande à votre point de terminaison. Utilisez l’éditeur JSON pour fournir des exemples de données au format JSON, puis choisissez Envoyer la demande pour envoyer la demande à votre point de terminaison. Après l’envoi de votre demande, Studio affiche le résultat de l’inférence dans une carte à droite de l’éditeur JSON.

    2. Sélectionnez Utiliser un exemple de code du kit SDK Python pour afficher le code permettant d’envoyer une demande au point de terminaison. Copiez ensuite l’exemple de code depuis la section Exemple de demande d’inférence et exécutez le code depuis votre environnement de test.

Le haut de la carte affiche le type de demande qui a été envoyée au point de terminaison (seul JSON est accepté). La carte affiche les champs suivants :

  • Statut : affiche l’un des types de statut suivants :

    • Success : la demande a réussi.

    • Failed : la demande a échoué. Une réponse apparaît sous Motif de l’échec.

    • Pending : une icône circulaire et en rotation apparaît pendant que la demande d’inférence est en attente.

  • Longueur d’exécution : durée de l’invocation (heure de fin moins l’heure de début) en millisecondes.

  • Durée de la demande : nombre de minutes qui se sont écoulées depuis l’envoi de la demande.

  • Durée du résultat : nombre de minutes qui se sont écoulées depuis le renvoi du résultat.

Invocation de votre modèle à l’aide du kit AWS SDK pour Python (Boto3)

Si vous souhaitez invoquer un point de terminaison modèle dans le code de votre application, vous pouvez utiliser l’un des kits SDK AWS, notamment le kit AWS SDK pour Python (Boto3). Pour invoquer votre point de terminaison à l’aide de ce kit SDK, vous devez utiliser l’une des méthodes Python suivantes :

  • invoke_endpoint : envoie une demande d’inférence à un point de terminaison du modèle et renvoie la réponse générée par le modèle.

    Cette méthode renvoie les données utiles d’inférence sous la forme d’une réponse une fois que le modèle a fini de la générer. Pour plus d’informations, consultez invoke_endpoint dans la Référence des API du kit AWS SDK pour Python (Boto).

  • invoke_endpoint_with_response_stream : envoie une demande d’inférence à un point de terminaison du modèle et diffuse la réponse de manière incrémentielle pendant que le modèle la génère.

    Avec cette méthode, votre application reçoit des parties de la réponse dès qu’elles sont disponibles. Pour plus d’informations, consultez invoke_endpoint dans la Référence des API du kit AWS SDK pour Python (Boto).

    Utilisez cette méthode uniquement pour invoquer des modèles qui prennent en charge le streaming d’inférence.

Avant de pouvoir utiliser ces méthodes dans votre code d’application, vous devez initialiser un client de l’environnement d’exécution SageMaker AI et spécifier le nom de votre point de terminaison. L’exemple suivant configure le client et le point de terminaison pour les autres exemples suivants :

import boto3 sagemaker_runtime = boto3.client( "sagemaker-runtime", region_name='aws_region') endpoint_name='endpoint-name'

Invocation pour obtenir une réponse d’inférence

L’exemple suivant utilise la méthode invoke_endpoint pour invoquer un point de terminaison avec le kit AWS SDK pour Python (Boto3) :

# Gets inference from the model hosted at the specified endpoint: response = sagemaker_runtime.invoke_endpoint( EndpointName=endpoint_name, Body=bytes('{"features": ["This is great!"]}', 'utf-8') ) # Decodes and prints the response body: print(response['Body'].read().decode('utf-8'))

Cet exemple fournit des données d’entrée dans le champ Body pour que SageMaker AI les transmette au modèle. Ces données doivent être dans le même format que celui utilisé pour l’entraînement. L’exemple assigne la réponse à la variable response.

La variable response permet d’accéder au statut HTTP, au nom du modèle déployé et à d’autres champs. L’extrait de code suivant imprime le code de statut HTTP :

print(response["HTTPStatusCode"])

Invoquer pour diffuser une réponse d’inférence

Si vous avez déployé un modèle qui prend en charge le streaming d’inférence, vous pouvez invoquer le modèle pour recevoir ses données utiles d’inférence sous forme de flux de parties. Le modèle fournit ces pièces progressivement au fur et à mesure qu’il les génère. Lorsqu’une application reçoit un flux d’inférence, elle n’a pas besoin d’attendre que le modèle génère la totalité des données utiles de réponse. Au lieu de cela, l’application reçoit immédiatement des parties de la réponse dès qu’elles sont disponibles.

En consommant un flux d’inférence dans votre application, vous pouvez créer des interactions dans lesquelles vos utilisateurs perçoivent l’inférence comme étant rapide, car ils obtiennent immédiatement la première partie. Vous pouvez mettre en œuvre le streaming pour prendre en charge des expériences interactives rapides, telles que les chatbots, les assistants virtuels et les générateurs de musique. Par exemple, vous pouvez créer un chatbot qui affiche progressivement le texte généré par un grand modèle de langage (LLM).

Pour obtenir un flux d’inférence, vous pouvez utiliser la méthode invoke_endpoint_with_response_stream. Dans le corps de la réponse, le kit SDK fournit un objet EventStream, qui donne l’inférence sous la forme d’une série d’objets PayloadPart.

Exemple Flux d’inférence

L’exemple suivant est un flux d’objets PayloadPart :

{'PayloadPart': {'Bytes': b'{"outputs": [" a"]}\n'}} {'PayloadPart': {'Bytes': b'{"outputs": [" challenging"]}\n'}} {'PayloadPart': {'Bytes': b'{"outputs": [" problem"]}\n'}} . . .

Dans chaque partie des données utiles, le champ Bytes fournit une partie de la réponse d’inférence du modèle. Cette partie peut être n’importe quel type de contenu généré par un modèle, tel que du texte, des images ou des données audio. Dans cet exemple, les parties sont des objets JSON contenant du texte généré à partir d’un LLM.

En général, la partie de la charge utile contient un fragment discret de données du modèle. Dans cet exemple, les fragments discrets sont des objets JSON entiers. Parfois, la réponse de streaming divise les fragments sur plusieurs parties de la charge utile, ou elle combine plusieurs fragments en une seule partie de charge utile. L’exemple suivant montre un fragment de données au format JSON divisé en deux parties de données utiles :

{'PayloadPart': {'Bytes': b'{"outputs": '}} {'PayloadPart': {'Bytes': b'[" problem"]}\n'}}

Lorsque vous écrivez du code d’application qui traite un flux d’inférence, incluez une logique qui gère ces divisions et combinaisons de données occasionnelles. Une stratégie consisterait à écrire du code qui concatène le contenu d’Bytes pendant que votre application reçoit les parties des données utiles. En concaténant les données JSON d’exemple ici, vous combineriez les données dans un corps JSON délimité par de nouvelles lignes. Ensuite, votre code pourrait traiter le flux en analysant l’ensemble de l’objet JSON sur chaque ligne.

L’exemple suivant montre le JSON délimité par de nouvelles lignes que vous créeriez lorsque vous concaténez le contenu de l’exemple d’Bytes :

{"outputs": [" a"]} {"outputs": [" challenging"]} {"outputs": [" problem"]} . . .
Exemple Code pour traiter un flux d’inférence

L’exemple de classe Python suivant, SmrInferenceStream, montre comment traiter un flux d’inférence qui envoie des données texte au format JSON :

import io import json # Example class that processes an inference stream: class SmrInferenceStream: def __init__(self, sagemaker_runtime, endpoint_name): self.sagemaker_runtime = sagemaker_runtime self.endpoint_name = endpoint_name # A buffered I/O stream to combine the payload parts: self.buff = io.BytesIO() self.read_pos = 0 def stream_inference(self, request_body): # Gets a streaming inference response # from the specified model endpoint: response = self.sagemaker_runtime\ .invoke_endpoint_with_response_stream( EndpointName=self.endpoint_name, Body=json.dumps(request_body), ContentType="application/json" ) # Gets the EventStream object returned by the SDK: event_stream = response['Body'] for event in event_stream: # Passes the contents of each payload part # to be concatenated: self._write(event['PayloadPart']['Bytes']) # Iterates over lines to parse whole JSON objects: for line in self._readlines(): resp = json.loads(line) part = resp.get("outputs")[0] # Returns parts incrementally: yield part # Writes to the buffer to concatenate the contents of the parts: def _write(self, content): self.buff.seek(0, io.SEEK_END) self.buff.write(content) # The JSON objects in buffer end with '\n'. # This method reads lines to yield a series of JSON objects: def _readlines(self): self.buff.seek(self.read_pos) for line in self.buff.readlines(): self.read_pos += len(line) yield line[:-1]

Cet exemple traite le flux d’inférence en procédant comme suit :

  • Initialise un client de l’environnement d’exécution SageMaker AI et définit le nom d’un point de terminaison de modèle. Avant de pouvoir obtenir un flux d’inférence, le modèle que le point de terminaison héberge doit prendre en charge le streaming d’inférence.

  • Dans l’exemple de méthode stream_inference, il reçoit le corps d’une demande et le transmet à la méthode invoke_endpoint_with_response_stream du kit SDK.

  • Il itère sur chaque événement de l’objet EventStream renvoyé par le kit SDK.

  • À partir de chaque événement, il obtient le contenu de l’objet Bytes dans l’objet PayloadPart.

  • Dans l’exemple de méthode _write, il écrit dans un tampon pour concaténer le contenu des objets Bytes. Le contenu combiné forme un corps JSON délimité par de nouvelles lignes.

  • Il utilise l’exemple de méthode _readlines pour obtenir une série itérable d’objets JSON.

  • Dans chaque objet JSON, il obtient une partie de l’inférence.

  • Avec l’expression yield, il renvoie les pièces de manière incrémentielle.

L’exemple suivant crée et utilise un objet SmrInferenceStream :

request_body = {"inputs": ["Large model inference is"], "parameters": {"max_new_tokens": 100, "enable_sampling": "true"}} smr_inference_stream = SmrInferenceStream( sagemaker_runtime, endpoint_name) stream = smr_inference_stream.stream_inference(request_body) for part in stream: print(part, end='')

Cet exemple transmet un corps de demande à la méthode stream_inference. Il itère la réponse pour imprimer chaque élément renvoyé par le flux d’inférence.

L’exemple suppose que le modèle au point de terminaison spécifié est un LLM qui génère du texte. Le résultat de cet exemple est un corps de texte généré qui s’imprime de manière incrémentielle :

a challenging problem in machine learning. The goal is to . . .

Invocation de votre modèle à l’aide du kit AWS CLI

Vous pouvez invoquer votre point de terminaison de modèle en exécutant des commandes avec la AWS Command Line Interface (AWS CLI). L’AWS CLI prend en charge les demandes d’inférence standard avec la commande invoke-endpoint et prend en charge les demandes d’inférence asynchrones avec la commande invoke-endpoint-async.

Note

L’AWS CLI ne prend pas en charge les demandes d’inférence en streaming.

L’exemple suivant utilise la commande invoke-endpoint pour envoyer une demande d’inférence à un point de terminaison du modèle :

aws sagemaker-runtime invoke-endpoint \ --endpoint-name endpoint_name \ --body fileb://$file_name \ output_file.txt

Pour le paramètre --endpoint-name, indiquez le nom de point de terminaison que vous avez spécifié lors de sa création. Pour le paramètre --body, fournissez des données d’entrée que SageMaker AI transmettra au modèle. Les données doivent être dans le même format que celui utilisé pour l’entraînement. Cet exemple montre comment envoyer des données binaires à votre point de terminaison.

Pour plus d’informations sur l’utilisation de file:// plutôt que fileb:// lors de la transmission du contenu d’un fichier à un paramètre de l’AWS CLI, consultez Bonnes pratiques pour les paramètres de fichier local.

Pour plus d’informations et pour voir les paramètres supplémentaires que vous pouvez transmettre, consultez invoke-endpoint dans la Référence des commandes de l’AWS CLI.

Si la commande invoke-endpoint réussit, elle renvoie une réponse telle que la suivante :

{ "ContentType": "<content_type>; charset=utf-8", "InvokedProductionVariant": "<Variant>" }

Si la commande échoue, vérifiez si le format des données utiles d’entrée est correct.

Affichez la sortie de l’invocation en vérifiant le fichier de sortie du fichier (output_file.txt dans cet exemple).

more output_file.txt