

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.

# Code d’inférence personnalisé avec les services d’hébergement
<a name="your-algorithms-inference-code"></a>

Cette section explique comment Amazon SageMaker AI interagit avec un conteneur Docker qui exécute votre propre code d'inférence pour les services d'hébergement. Utilisez ces informations pour écrire du code d’inférence et créer une image Docker. 

**Topics**
+ [Comment SageMaker l'IA gère votre image d'inférence](#your-algorithms-inference-code-run-image)
+ [Comment SageMaker l'IA charge les artefacts de votre modèle](#your-algorithms-inference-code-load-artifacts)
+ [Comment votre conteneur doit-il répondre aux requêtes d’inférence ?](#your-algorithms-inference-code-container-response)
+ [Comment votre conteneur doit-il répondre aux requêtes de surveillance de l’état (Ping) ?](#your-algorithms-inference-algo-ping-requests)
+ [Container Contract pour soutenir les capacités de streaming bidirectionnel](#your-algorithms-inference-algo-bidi)
+ [Utilisation d’un registre Docker privé pour les conteneurs d’inférence en temps réel](your-algorithms-containers-inference-private.md)

## Comment SageMaker l'IA gère votre image d'inférence
<a name="your-algorithms-inference-code-run-image"></a>

Pour configurer un conteneur et utiliser celui-ci en tant qu’exécutable, utilisez une instruction `ENTRYPOINT` dans un Dockerfile. Notez ce qui suit : 
+ Pour l'inférence du modèle, l' SageMaker IA exécute le conteneur comme suit :

  ```
  docker run image serve
  ```

  SageMaker L'IA remplace les `CMD` instructions par défaut dans un conteneur en spécifiant l'`serve`argument après le nom de l'image. L’argument `serve` remplace les arguments fournis avec la commande `CMD` dans le Dockerfile.

   
+ SageMaker L'IA s'attend à ce que tous les conteneurs fonctionnent avec des utilisateurs root. Créez votre conteneur de manière à ce qu’il n’utilise que des utilisateurs root. Lorsque SageMaker l'IA gère votre conteneur, les utilisateurs qui n'ont pas d'accès au niveau root peuvent provoquer des problèmes d'autorisations.

   
+ Nous vous recommandons d’utiliser le formulaire `exec` de l’instruction `ENTRYPOINT` :

  ```
  ENTRYPOINT ["executable", "param1", "param2"]
  ```

  Par exemple :

  ```
  ENTRYPOINT ["python", "k_means_inference.py"]
  ```

  Le formulaire `exec` de l’instruction `ENTRYPOINT` lance l’exécutable directement, et non en tant qu’enfant de `/bin/sh`. Cela lui permet de recevoir des signaux tels que `SIGTERM` et `SIGKILL` provenant des opérations de l' SageMaker API, ce qui est une exigence. 

   

  Par exemple, lorsque vous utilisez l'[https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateEndpoint.html](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateEndpoint.html)API pour créer un point de terminaison, l' SageMaker IA fournit le nombre d'instances de calcul ML requises par la configuration du point de terminaison, que vous spécifiez dans la demande. SageMaker AI exécute le conteneur Docker sur ces instances. 

   

  Si vous réduisez le nombre d'instances soutenant le point de terminaison (en appelant l'[https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateEndpointWeightsAndCapacities.html](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateEndpointWeightsAndCapacities.html)API), SageMaker AI exécute une commande pour arrêter le conteneur Docker sur les instances en cours de résiliation. La commande envoie le signal `SIGTERM`, puis envoie le signal `SIGKILL` 30 secondes plus tard.

   

  Si vous mettez à jour le point de terminaison (en appelant l'[https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateEndpoint.html](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateEndpoint.html)API), SageMaker AI lance un autre ensemble d'instances de calcul ML et exécute les conteneurs Docker qui contiennent votre code d'inférence. Ensuite, il exécute une commande pour arrêter les conteneurs Docker précédents. Pour arrêter un conteneur Docker, la commande envoie le signal `SIGTERM`, puis le signal `SIGKILL` 30 secondes plus tard. 

   
+ SageMaker AI utilise la définition de conteneur que vous avez fournie dans votre [https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateModel.html](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateModel.html)demande pour définir les variables d'environnement et le nom d'hôte DNS du conteneur comme suit :

   
  + Il définit les variables d'environnement à l'aide de la `ContainerDefinition.Environment` string-to-string carte.
  + Il définit le nom d’hôte DNS à l’aide de `ContainerDefinition.ContainerHostname`.

     
+ Si vous prévoyez d’utiliser des dispositifs GPU pour les inférences de modèle (en spécifiant les instances de calcul ML basées sur des GPU dans votre demande `CreateEndpointConfig`), assurez-vous que vos conteneurs sont compatibles avec `nvidia-docker`. Ne regroupez pas des pilotes NVIDIA avec l’image. Pour plus d’informations sur `nvidia-docker`, consultez [NVIDIA/nvidia-docker](https://github.com/NVIDIA/nvidia-docker). 

   
+ Vous ne pouvez pas utiliser l'`tini`initialiseur comme point d'entrée dans les conteneurs SageMaker AI car les arguments `train` et `serve` le confondent.

  

## Comment SageMaker l'IA charge les artefacts de votre modèle
<a name="your-algorithms-inference-code-load-artifacts"></a>

Dans votre demande d'[https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateModel.html](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateModel.html)API, vous pouvez utiliser le `S3DataSource` paramètre `ModelDataUrl` or pour identifier l'emplacement S3 où les artefacts du modèle sont stockés. SageMaker L'IA copie les artefacts de votre modèle de l'emplacement S3 vers le `/opt/ml/model` répertoire pour les utiliser par votre code d'inférence. Votre conteneur dispose d’un accès en lecture seule à `/opt/ml/model`. N’écrivez pas dans ce répertoire.

L’élément `ModelDataUrl` doit pointer vers un fichier tar.gz. Sinon, SageMaker AI ne téléchargera pas le fichier. 

Si vous avez entraîné votre modèle à l' SageMaker IA, les artefacts du modèle sont enregistrés dans un seul fichier tar compressé dans Amazon S3. Si vous avez entraîné votre modèle en dehors de l' SageMaker IA, vous devez créer ce fichier tar compressé unique et l'enregistrer dans un emplacement S3. SageMaker AI décompresse ce fichier tar dans le opt/ml/model répertoire/avant le démarrage de votre conteneur.

Pour le déploiement de modèles de grande taille, nous vous recommandons de suivre [Déploiement de modèles non compressés](large-model-inference-uncompressed.md).

## Comment votre conteneur doit-il répondre aux requêtes d’inférence ?
<a name="your-algorithms-inference-code-container-response"></a>

Pour obtenir des inférences, l'application cliente envoie une requête POST au point de terminaison SageMaker AI. SageMaker L'IA transmet la demande au conteneur et renvoie le résultat de l'inférence du conteneur au client.

Pour plus d'informations sur les demandes d'inférence que votre conteneur recevra, consultez les actions suivantes dans le manuel *Amazon SageMaker AI API Reference :*
+ [ InvokeEndpoint](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_runtime_InvokeEndpoint.html)
+ [ InvokeEndpointAsync](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_runtime_InvokeEndpointAsync.html)
+ [ InvokeEndpointWithResponseStream](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_runtime_InvokeEndpointWithResponseStream.html)
+ [ InvokeEndpointWithResponseStream](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_runtime_InvokeEndpointWithBidirectionalStream.html)

**Exigences relatives aux conteneurs d’inférence**

Pour répondre aux demandes d’inférence, votre conteneur doit répondre aux exigences suivantes :
+ SageMaker L'IA supprime tous les `POST` en-têtes sauf ceux pris en charge par`InvokeEndpoint`. SageMaker L'IA peut ajouter des en-têtes supplémentaires. Les conteneurs d’inférence doivent être en mesure d’ignorer sans risque ces en-têtes supplémentaires.
+ Pour recevoir des demandes d’inférence, le conteneur doit avoir un serveur web à l’écoute sur le port 8080 et doit accepter les demandes `POST` envoyées aux points de terminaison `/invocations` et `/ping`. 
+ Les conteneurs de modèles d’un client doivent accepter les requêtes de connexion au socket dans un délai de 250 millisecondes.
+ Les conteneurs de modèles d’un client doivent répondre aux requêtes dans un délai de 60 secondes. Le traitement du modèle lui-même peut durer 60 secondes au maximum, avant de répondre aux `/invocations`. Si le traitement de votre modèle dure entre 50 et 60 secondes, définissez le délai d’expiration du socket du kit SDK sur 70 secondes.
+ Le modèle de conteneur d'un client qui prend en charge le streaming bidirectionnel doit :
  + supporte WebSockets les connexions sur le port 8080 à/invocations-bidirectional-stream par défaut.
  + ont un serveur Web qui écoute sur le port 8080 et doivent accepter les requêtes POST adressées aux points de terminaison /ping.
  + Outre les contrôles de santé du conteneur via HTTP, le conteneur doit répondre avec Pong Frame per ([RFC6455](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.3)), pour le WebSocket Ping Frame envoyé.

**Example fonctions d’invocation**  
Les exemples suivants montrent comment le code de votre conteneur peut traiter les demandes d’inférence. Ces exemples traitent les demandes que les applications clientes envoient à l'aide de l' InvokeEndpoint action.  
FastAPI est un framework Web permettant de créer avec APIs Python.  

```
from fastapi import FastAPI, status, Request, Response
. . .
app = FastAPI()
. . .
@app.post('/invocations')
async def invocations(request: Request):
    # model() is a hypothetical function that gets the inference output:
    model_resp = await model(Request)

    response = Response(
        content=model_resp,
        status_code=status.HTTP_200_OK,
        media_type="text/plain",
    )
    return response
. . .
```
Dans cet exemple, la `invocations` fonction gère la demande d'inférence que l' SageMaker IA envoie au `/invocations` point de terminaison.
Flask est un framework pour le développement d’applications web avec Python.  

```
import flask
. . .
app = flask.Flask(__name__)
. . .
@app.route('/invocations', methods=["POST"])
def invoke(request):
    # model() is a hypothetical function that gets the inference output:
    resp_body = model(request)
    return flask.Response(resp_body, mimetype='text/plain')
```
Dans cet exemple, la `invoke` fonction gère la demande d'inférence que l' SageMaker IA envoie au `/invocations` point de terminaison.

**Example fonctions d’invocation pour le streaming des demandes**  
Les exemples suivants montrent comment le code figurant dans votre conteneur d’inférence peut traiter les demandes d’inférence en streaming. Ces exemples traitent les demandes que les applications clientes envoient à l'aide de l' InvokeEndpointWithResponseStream action.  
Lorsqu’un conteneur traite une demande d’inférence en streaming, il renvoie l’inférence du modèle sous la forme d’une série de parties au fur et à mesure que le modèle les génère. Les applications clientes commencent à recevoir des réponses dès qu’elles sont disponibles. Elles n’ont pas besoin d’attendre que le modèle génère la réponse complète. 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.  
FastAPI est un framework Web permettant de créer avec APIs Python.  

```
from starlette.responses import StreamingResponse
from fastapi import FastAPI, status, Request
. . .
app = FastAPI()
. . .
@app.post('/invocations')
async def invocations(request: Request):
    # Streams inference response using HTTP chunked encoding
    async def generate():
        # model() is a hypothetical function that gets the inference output:
        yield await model(Request)
        yield "\n"

    response = StreamingResponse(
        content=generate(),
        status_code=status.HTTP_200_OK,
        media_type="text/plain",
    )
    return response
. . .
```
Dans cet exemple, la `invocations` fonction gère la demande d'inférence que l' SageMaker IA envoie au `/invocations` point de terminaison. Pour diffuser en continu la réponse, l’exemple utilise la classe `StreamingResponse` du framework Starlette.
Flask est un framework pour le développement d'applications web avec Python.  

```
import flask
. . .
app = flask.Flask(__name__)
. . .
@app.route('/invocations', methods=["POST"])
def invocations(request):
    # Streams inference response using HTTP chunked encoding

    def generate():
        # model() is a hypothetical function that gets the inference output:
        yield model(request)
        yield "\n"
    return flask.Response(
        flask.stream_with_context(generate()), mimetype='text/plain')
. . .
```
Dans cet exemple, la `invocations` fonction gère la demande d'inférence que l' SageMaker IA envoie au `/invocations` point de terminaison. Pour diffuser en continu la réponse, l’exemple utilise la fonction `flask.stream_with_context` du framework Flask.

**Example Exemples de fonctions d'invocation pour le streaming bidirectionnel**  
Les exemples suivants montrent comment le code de votre conteneur peut traiter les demandes et réponses d'inférence en continu. Ces exemples traitent les demandes de streaming envoyées par les applications clientes à l'aide de l' InvokeEndpointWithBidirectionalStreamaction.  
Un conteneur doté d'une fonctionnalité de streaming bidirectionnel gère les demandes d'inférence de streaming dans lesquelles des parties sont générées de manière incrémentielle chez le client et diffusées vers le conteneur. Il renvoie l'inférence du modèle au client sous la forme d'une série de pièces au fur et à mesure que le modèle les génère. Les applications clientes commencent à recevoir des réponses dès qu’elles sont disponibles. Ils n'ont pas besoin d'attendre que la demande soit entièrement générée par le client ou que le modèle génère la réponse complète. Vous pouvez implémenter le streaming bidirectionnel pour favoriser des expériences interactives rapides, telles que des chatbots, des assistants vocaux intelligents interactifs et des traductions en temps réel pour une expérience plus en temps réel.  
FastAPI est un framework Web permettant de créer avec APIs Python.  

```
import sys
import asyncio
import json
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import JSONResponse
import uvicorn

app = FastAPI()
...
@app.websocket("/invocations-bidirectional-stream")
async def websocket_invoke(websocket: WebSocket):
    """
    WebSocket endpoint with RFC 6455 ping/pong and fragmentation support
    
    Handles:
    - Text messages (JSON) - including fragmented frames
    - Binary messages - including fragmented frames
    - Ping frames (automatically responds with pong)
    - Pong frames (logs receipt)
    - Fragmented frames per RFC 6455 Section 5.4
    """
    await manager.connect(websocket)
    
    # Fragment reassembly buffers per RFC 6455 Section 5.4
    text_fragments = []
    binary_fragments = []
    
    while True:
        # Use receive() to handle all WebSocket frame types
        message = await websocket.receive()
        print(f"Received message: {message}")
        if message["type"] == "websocket.receive":
            if "text" in message:
                # Handle text frames (including fragments)
                text_data = message["text"]
                more_body = message.get("more_body", False)
                
                if more_body:
                    # This is a fragment, accumulate it
                    text_fragments.append(text_data)
                    print(f"Received text fragment: {len(text_data)} chars (more coming)")
                else:
                    # This is the final frame or a complete message
                    if text_fragments:
                        # Reassemble fragmented message
                        text_fragments.append(text_data)
                        complete_text = "".join(text_fragments)
                        text_fragments.clear()
                        print(f"Reassembled fragmented text message: {len(complete_text)} chars total")
                        await handle_text_message(websocket, complete_text)
                    else:
                        # Complete message in single frame
                        await handle_text_message(websocket, text_data)
                
            elif "bytes" in message:
                # Handle binary frames (including fragments)
                binary_data = message["bytes"]
                more_body = message.get("more_body", False)
                
                if more_body:
                    # This is a fragment, accumulate it
                    binary_fragments.append(binary_data)
                    print(f"Received binary fragment: {len(binary_data)} bytes (more coming)")
                else:
                    # This is the final frame or a complete message
                    if binary_fragments:
                        # Reassemble fragmented message
                        binary_fragments.append(binary_data)
                        complete_binary = b"".join(binary_fragments)
                        binary_fragments.clear()
                        print(f"Reassembled fragmented binary message: {len(complete_binary)} bytes total")
                        await handle_binary_message(websocket, complete_binary)
                    else:
                        # Complete message in single frame
                        await handle_binary_message(websocket, binary_data)
                
        elif message["type"] == "websocket.ping":
            # Handle ping frames - RFC 6455 Section 5.5.2
            ping_data = message.get("bytes", b"")
            print(f"Received PING frame with payload: {ping_data}")
            # FastAPI automatically sends pong response
            
        elif message["type"] == "websocket.pong":
            # Handle pong frames
            pong_data = message.get("bytes", b"")
            print(f"Received PONG frame with payload: {pong_data}")
            
        elif message["type"] == "websocket.close":
            # Handle close frames - RFC 6455 Section 5.5.1
            close_code = message.get("code", 1000)
            close_reason = message.get("reason", "")
            print(f"Received CLOSE frame - Code: {close_code}, Reason: '{close_reason}'")
            
            # Send close frame response if not already closing
            try:
                await websocket.close(code=close_code, reason=close_reason)
                print(f"Sent CLOSE frame response - Code: {close_code}")
            except Exception as e:
                print(f"Error sending close frame: {e}")
            break
            
        elif message["type"] == "websocket.disconnect":
            print("Client initiated disconnect")
            break

        else:
            print(f"Received unknown message type: {message['type']}")
            break

                        
async def handle_binary_message(websocket: WebSocket, binary_data: bytes):
    """Handle incoming binary messages (complete or reassembled from fragments)"""
    print(f"Processing complete binary message: {len(binary_data)} bytes")
    
    try:
        # Echo back the binary data
        await websocket.send_bytes(binary_data)
    except Exception as e:
        print(f"Error handling binary message: {e}")

async def handle_text_message(websocket: WebSocket, data: str):
    """Handle incoming text messages"""
    try:
        # Send response back to the same client
        await manager.send_personal_message(data, websocket)
    except Exception as e:
        print(f"Error handling text message: {e}")

def main():
    if len(sys.argv) > 1 and sys.argv[1] == "serve":
        print("Starting server on port 8080...")
        uvicorn.run(app, host="0.0.0.0", port=8080)
    else:
        print("Usage: python app.py serve")
        sys.exit(1)

if __name__ == "__main__":
    main()
```
Dans cet exemple, la `websocket_invoke` fonction gère la demande d'inférence que l' SageMaker IA envoie au `/invocations-bidirectional-stream` point de terminaison. Il montre comment gérer les demandes de flux et les réponses de flux renvoyées au client.

## Comment votre conteneur doit-il répondre aux requêtes de surveillance de l’état (Ping) ?
<a name="your-algorithms-inference-algo-ping-requests"></a>

SageMaker L'IA lance de nouveaux conteneurs d'inférence dans les situations suivantes :
+ Réponse aux appels d’API `CreateEndpoint`, `UpdateEndpoint` et `UpdateEndpointWeightsAndCapacities`
+ Application de correctifs de sécurité
+ Remplacement des instances défectueuses

Peu après le démarrage du conteneur, l' SageMaker IA commence à envoyer des requêtes GET périodiques au `/ping` point de terminaison.

L’exigence la plus simple concernant le conteneur consiste à répondre avec un code d’état HTTP 200 et un corps vide. Cela indique à l' SageMaker IA que le conteneur est prêt à accepter les demandes d'inférence au `/invocations` point de terminaison.

Si le conteneur ne commence pas à transmettre les surveillances de l’état, en répondant systématiquement avec 200, pendant les huit minutes suivant le démarrage, le lancement d’une nouvelle instance échoue. Cela provoque l’échec de `CreateEndpoint`, laissant le point de terminaison dans un état d’échec. La mise à jour demandée par `UpdateEndpoint` n’est pas terminée, les correctifs de sécurité ne sont pas appliqués et les instances défectueuses ne sont pas remplacées.

Bien que l’exigence minimale pour le conteneur soit de renvoyer un statique 200, un développeur de conteneur peut utiliser cette fonctionnalité pour effectuer des vérifications plus approfondies. Le délai d’attente des demandes `/ping` est de 2 secondes.

De plus, un conteneur capable de gérer des demandes de streaming bidirectionnelles doit répondre avec un Pong Frame (par WebSocket protocole [RFC6455](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.3)) à un Ping Frame. Si aucun Pong Frame n'est reçu pendant 5 pings consécutifs, la connexion au conteneur sera fermée par la plateforme SageMaker AI. SageMaker La plateforme d'IA répondra également aux Ping Frames à partir d'un conteneur modèle avec des Pong Frames.

## Container Contract pour soutenir les capacités de streaming bidirectionnel
<a name="your-algorithms-inference-algo-bidi"></a>

Si vous souhaitez héberger votre conteneur modèle en tant que point de terminaison SageMaker AI prenant en charge les fonctionnalités de streaming bidirectionnel, le conteneur modèle doit prendre en charge le contrat ci-dessous :

**1. Étiquette Docker bidirectionnelle**

Le modèle de conteneur doit porter une étiquette Docker indiquant à la plate-forme SageMaker AI que la fonctionnalité de streaming bidirectionnel est prise en charge sur ce conteneur.

```
com.amazonaws.sagemaker.capabilities.bidirectional-streaming=true
```

**2. Support WebSocket Connection pour les invocations**

Le modèle de conteneur d'un client qui prend en charge le streaming bidirectionnel doit prendre en charge WebSockets les connexions sur le port 8080 `/invocations-bidirectional-stream` par défaut. 

Ce chemin peut être remplacé en transmettant l'en-tête X-Amzn-SageMaker-Model -Invocation-Path lors de l'appel de l'API. InvokeEndpointWithBidirectionalStream De plus, les utilisateurs peuvent spécifier une chaîne de requête à ajouter à ce chemin en transmettant l'en-tête X-Amzn-SageMaker-Model -Query-String lors de l'appel de l'API. InvokeEndpointWithBidirectionalStream 

**3. Gestion du flux de demandes**

<Blob>Les charges utiles d'entrée de l' InvokeEndpointWithBidirectionalStream API sont diffusées sous la forme d'une série de PayloadParts, qui n'est qu'un wrapper d'un bloc binaire (« Bytes » :) : ******

```
{
   "PayloadPart": { 
      "Bytes": <Blob>,
      "DataType": <String: UTF8 | BINARY>,
      "CompletionState": <String: PARTIAL | COMPLETE>
      "P": <String>
   }
}
```

**3.1. Cadres de données**

SageMaker L'IA transmet l'entrée PayloadParts au conteneur de modèles sous forme de trames de WebSocket données ([RFC6455-Section-5.6](https://datatracker.ietf.org/doc/html/rfc6455#section-5.6))

1. SageMaker L'IA n'inspecte pas le bloc binaire.

1. À la réception d'une entrée PayloadPart
   + SageMaker L'IA crée exactement un bloc de WebSocket données à partir de celui-ci`PayloadPart.Bytes`, puis le transmet au conteneur du modèle.
   + Si `PayloadPart.DataType = UTF8` l' SageMaker IA crée un bloc de données texte
   + Si `PayloadPart.DataType` ce n'est pas le cas ou `PayloadPart.DataType = BINARY` si SageMaker l'IA crée une trame de données binaire

1. Pour une séquence de PayloadParts with`PayloadPart.CompletionState = PARTIAL`, terminée par un PayloadPart with`PayloadPart.CompletionState = COMPLETE`, l' SageMaker IA les traduit en message WebSocket fragmenté [RFC6455-Section-5.4](https://datatracker.ietf.org/doc/html/rfc6455#section-5.4) : Fragmentation :
   + Le PayloadPart with initial `PayloadPart.CompletionState = PARTIAL` sera traduit en un bloc de WebSocket données, avec FIN bit clear.
   + Le PayloadParts with suivant `PayloadPart.CompletionState = PARTIAL` sera traduit en cadres de WebSocket continuation avec FIN bit clear.
   + La version finale PayloadPart `PayloadPart.CompletionState = COMPLETE` sera traduite en cadre de WebSocket continuation avec le bit FIN défini.

1. SageMaker L'IA n'encode ni ne décode le fragment binaire à partir de l'entrée PayloadPart, les octets sont transmis au conteneur du modèle tel quel.

1. SageMaker L'IA ne combine pas plusieurs entrées PayloadParts en une seule BinaryDataFrame.

1. SageMaker L'IA ne divise pas une PayloadPart entrée en plusieurs BinaryDataFrames.

**Exemple : flux de messages fragmenté**

```
Client sends:
PayloadPart 1: {Bytes: "Hello ", DataType: "UTF8", CompletionState: "PARTIAL"}
PayloadPart 2: {Bytes: "World", DataType: "UTF8", CompletionState: "COMPLETE"}

Container receives:
Frame 1: Text Data Frame with "Hello " (FIN=0)
Frame 2: Continuation Frame with "World" (FIN=1)
```

**3,2. Cadres de commande**

Outre les trames de données, l' SageMaker IA envoie également des trames de contrôle au conteneur de modèles ([RFC6455-Section-5.5](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5)) :

1. Cadre fermé : SageMaker AI peut envoyer un cadre fermé ([RFC6455-Section-5.5.1](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.1)) au conteneur du modèle si la connexion est fermée pour une raison quelconque.

1. Ping Frame : SageMaker AI envoie un Ping Frame ([RFC6455-Section-5.5.2](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2)) une fois toutes les 60 secondes, le conteneur modèle doit répondre avec Pong Frame. Si aucun Pong Frame ([RFC6455-Section-5.5.3](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.3)) n'est reçu pendant 5 pings consécutifs, la connexion sera fermée par AI. SageMaker 

1. Pong Frame : SageMaker L'IA répondra aux Ping Frames provenant d'un conteneur modèle avec des cadres Pong.

**4. Gestion du flux de réponses**

Les sorties sont diffusées sous la forme d'une série de PayloadParts, ModelStreamErrors ou InternalStreamFailures.

```
{   
   "PayloadPart": { 
      "Bytes": <Blob>,
      "DataType": <String: UTF8 | BINARY>,
      "CompletionState": <String: PARTIAL | COMPLETE>,
   },
   "ModelStreamError": {
      "ErrorCode": <String>,
      "Message": <String>
   },
   "InternalStreamFailure": {
      "Message": <String>
   }
}
```

**4,1. Cadres de données**

SageMaker L'IA convertit les trames de données reçues du conteneur du modèle en sortie PayloadParts :

1. À la réception d'un bloc de données WebSocket texte du conteneur du modèle, l' SageMaker IA extrait les octets bruts du bloc de données texte et les intègre dans une réponse PayloadPart, tandis qu'il est défini`PayloadPart.DataType = UTF8`.

1. À la réception d'une trame de données WebSocket binaires provenant du conteneur de modèles, l' SageMaker IA enveloppe directement les octets de la trame de données dans une réponse PayloadPart, en attendant qu'elle soit définie`PayloadPart.DataType = BINARY`.

1. Pour un message fragmenté tel que défini dans [RFC6455-Section-5.4](https://datatracker.ietf.org/doc/html/rfc6455#section-5.4) : Fragmentation :
   + La trame de données initiale avec FIN bit clear sera traduite en PayloadPart with`PayloadPart.CompletionState = PARTIAL`.
   + Les trames de continuation suivantes avec FIN bit clear seront traduites en PayloadParts with`PayloadPart.CompletionState = PARTIAL`.
   + La trame de continuation finale avec le jeu de bits FIN sera traduite en PayloadPart with`PayloadPart.CompletionState = COMPLETE`.

1. SageMaker L'IA ne code ni ne décode les octets reçus des conteneurs modèles, les octets sont transmis tels quels au conteneur modèle.

1. SageMaker L'IA ne combine pas plusieurs trames de données reçues du conteneur modèle en une seule réponse PayloadPart.

1. SageMaker L'IA ne divise pas une trame de données reçue du conteneur modèle en réponses PayloadParts multiples.

**Exemple : flux de réponse en streaming**

```
Container sends:
Frame 1: Text Data Frame with "Generating" (FIN=0)
Frame 2: Continuation Frame with " response..." (FIN=1)

Client receives:
PayloadPart 1: {Bytes: "Generating", DataType: "UTF8", CompletionState: "PARTIAL"}
PayloadPart 2: {Bytes: " response...", DataType: "UTF8", CompletionState: "COMPLETE"}
```

**4.2. Cadres de commande**

SageMaker L'IA répond aux trames de contrôle suivantes à partir du conteneur modèle :

1. À la réception d'un cadre fermé ([RFC6455-Section-5.5.1](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.1)) provenant du conteneur modèle, l' SageMaker IA encapsule le code d'état ([RFC6455-Section-7.4](https://datatracker.ietf.org/doc/html/rfc6455#section-7.4)) et les messages d'échec ModelStreamError, puis les transmet à l'utilisateur final.

1. À la réception d'un Ping Frame ([RFC6455-Section-5.5.2](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2)) du conteneur modèle, SageMaker AI répondra avec Pong Frame.

1. Pong Frame ([RFC6455-Section-5.5.3](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.3)) : Si aucun Pong Frame n'est reçu pendant 5 pings consécutifs, la connexion sera fermée par l'IA. SageMaker 