Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Dans le flux d’invite, vous pouvez déployer un flux sur un point de terminaison en ligne managé Azure Machine Learning pour une inférence en temps réel.
Lorsque vous consommez le point de terminaison en envoyant une requête, le comportement par défaut est que le point de terminaison en ligne continue d’attendre que l’ensemble de la réponse soit prête, avant de la renvoyer au client. Cela peut entraîner un long délai pour le client et une expérience utilisateur médiocre.
Pour éviter cela, vous pouvez utiliser la diffusion en continu lorsque vous consommez les points de terminaison. Une fois la diffusion en continu activée, vous n’avez pas besoin d’attendre que toute la réponse soit prête. Au lieu de cela, le serveur renvoie la réponse en blocs à mesure qu’ils sont générés. Le client peut ensuite afficher la réponse progressivement, avec moins de temps d’attente et plus d’interactivité.
Cet article décrit l’étendue et le fonctionnement de la diffusion en continu, ainsi que la façon de consommer des points de terminaison de streaming.
Créer un flux avec diffusion en continu
Si vous souhaitez utiliser le mode de diffusion en continu, vous devez créer un flux avec un nœud qui produit un générateur de chaînes comme sortie de flux. Un générateur de chaînes est un objet qui peut renvoyer une chaîne à la fois lors de requêtes. Vous pouvez utiliser les types de nœuds suivants pour créer un générateur de chaînes :
Nœud LLM : ce nœud utilise un modèle de langage volumineux pour générer des réponses en langage naturel en fonction de l’entrée.
{# Sample prompt template for LLM node #} system: You are a helpful assistant. user: {{question}}
Nœud Python : ce nœud vous permet d’écrire du code Python personnalisé qui peut générer des sorties de chaîne. Vous pouvez utiliser ce nœud pour appeler des bibliothèques ou des API externes qui prennent en charge la diffusion en continu. Par exemple, vous pouvez utiliser ce code pour répéter l’entrée mot par mot :
from promptflow import tool # Sample code echo input by yield in Python tool node @tool def my_python_tool(paragraph: str) -> str: yield "Echo: " for word in paragraph.split(): yield word + " "
Important
Seule la sortie du dernier nœud du flux peut prendre en charge la diffusion en continu.
« Dernier nœud » signifie que la sortie du nœud n’est pas consommée par d’autres nœuds.
Dans ce guide, nous allons utiliser l’exemple de flux « Conversation avec Wikipédia ». Ce flux traite la question de l’utilisateur, recherche des articles pertinents sur Wikipédia et répond à la question avec des informations provenant des articles. Il utilise le mode de diffusion en continu pour afficher la progression de la génération de réponses.
Pour savoir comment créer un flux de conversation, consultez comment développer un flux de conversation dans un flux d’invite.
Déployer le flux en tant que point de terminaison en ligne
Pour utiliser le mode de diffusion en continu, vous devez déployer votre flux en tant que point de terminaison en ligne. Cela vous permettra d’envoyer des requêtes et de recevoir des réponses de votre flux en temps réel.
Pour savoir comment déployer votre flux en tant que point de terminaison en ligne, consultez Déployer un flux vers un point de terminaison en ligne pour l’inférence en temps réel avec l’interface CLI.
Remarque
Déployez avec une version de l’environnement d’exécution ultérieure à la version 20230816.v10
.
Vous pouvez vérifier votre version d’exécution et la mettre à jour sur la page des détails de l’exécution.
Comprendre le processus de diffusion en continu
Lorsque vous disposez d’un point de terminaison en ligne, le client et le serveur doivent suivre des principes spécifiques pour la négociation du contenu afin d’utiliser le mode de diffusion en continu :
La négociation de contenu ressemble à une conversation entre le client et le serveur au sujet du format préféré des données qu’ils veulent envoyer et recevoir. Elle garantit une communication et un accord efficaces sur le format des données échangées.
Pour comprendre le processus de diffusion en continu, procédez comme suit :
Tout d’abord, le client construit une requête HTTP avec le type de média souhaité inclus dans l’en-tête
Accept
. Le type de média indique au serveur le type de format de données attendu par le client. C’est comme si le client disait : « Je recherche un format spécifique pour les données que vous allez m’envoyer. Il peut s’agir de JSON, de texte ou d’autre chose. » Par exemple,application/json
indique une préférence pour les données JSON,text/event-stream
indique un souhait de données de diffusion en continu et*/*
signifie que le client accepte n’importe quel format de données.Remarque
Si une requête n’a pas d’en-tête
Accept
ou a un en-têteAccept
vide, cela implique que le client acceptera n’importe quel type de média en réponse. Le serveur le traite comme*/*
.Ensuite, le serveur répond en fonction du type de média spécifié dans l’en-tête
Accept
. Il est important de noter que le client est susceptible de demander plusieurs types de médias dans l’en-têteAccept
et que le serveur doit tenir compte de ses fonctionnalités et de ses priorités de format pour déterminer la réponse appropriée.- Tout d’abord, le serveur vérifie si
text/event-stream
est spécifié explicitement dans l’en-têteAccept
:- Pour un flux avec diffusion en continu, le serveur retourne une réponse avec un
Content-Type
detext/event-stream
, indiquant que les données sont en cours de diffusion. - Pour un flux sans diffusion en continu, le serveur passe à la vérification d’autres types de médias spécifiés dans l’en-tête.
- Pour un flux avec diffusion en continu, le serveur retourne une réponse avec un
- Si
text/event-stream
n’est pas spécifié, le serveur vérifie alors siapplication/json
ou*/*
est spécifié dans l’en-têteAccept
:- Dans ce cas, le serveur retourne une réponse avec un
Content-Type
deapplication/json
, en fournissant les données au format JSON.
- Dans ce cas, le serveur retourne une réponse avec un
- Si l’en-tête
Accept
spécifie d’autres types de médias, tels quetext/html
:- Le serveur retourne une réponse
424
avec un code d’erreur d’exécution du flux d’inviteUserError
et un état HTTP d’exécution406
, indiquant que le serveur ne peut pas répondre à la requête avec le format de données demandé. Pour plus d’informations, consultez erreurs de traitement.
- Le serveur retourne une réponse
- Tout d’abord, le serveur vérifie si
Enfin, le client vérifie l’en-tête de réponse
Content-Type
. S’il est défini surtext/event-stream
, cela indique que les données sont en cours de diffusion.
Examinons de plus près le fonctionnement du processus de diffusion en continu. Les données de réponse en mode de diffusion en continu suivent le format des événements envoyés par le serveur (SSE).
Le processus global fonctionne comme suit :
0. Le client envoie un message au serveur
POST https://<your-endpoint>.inference.ml.azure.com/score
Content-Type: application/json
Authorization: Bearer <key or token of your endpoint>
Accept: text/event-stream
{
"question": "Hello",
"chat_history": []
}
Remarque
L’en-tête Accept
est défini sur text/event-stream
pour demander une réponse de diffusion en continu.
1. Le serveur renvoie la réponse en mode de diffusion en continu
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Connection: close
Transfer-Encoding: chunked
data: {"answer": ""}
data: {"answer": "Hello"}
data: {"answer": "!"}
data: {"answer": " How"}
data: {"answer": " can"}
data: {"answer": " I"}
data: {"answer": " assist"}
data: {"answer": " you"}
data: {"answer": " today"}
data: {"answer": " ?"}
data: {"answer": ""}
Remarque
Le Content-Type
est défini sur text/event-stream; charset=utf-8
, indiquant que la réponse est un flux d’événements.
Le client doit décoder les données de réponse en tant qu’événements envoyés par le serveur et les afficher de manière incrémentielle. Le serveur ferme la connexion HTTP après l’envoi de toutes les données.
Chaque événement de réponse est le delta de l’événement précédent. Il est recommandé au client de suivre les données fusionnées en mémoire et de les renvoyer au serveur en tant qu’historique des conversations dans la requête suivante.
2. Le client envoie un autre message de conversation, avec l’historique complet des conversations, au serveur
POST https://<your-endpoint>.inference.ml.azure.com/score
Content-Type: application/json
Authorization: Bearer <key or token of your endpoint>
Accept: text/event-stream
{
"question": "Glad to know you!",
"chat_history": [
{
"inputs": {
"question": "Hello"
},
"outputs": {
"answer": "Hello! How can I assist you today?"
}
}
]
}
3. Le serveur renvoie la réponse en mode de diffusion en continu
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Connection: close
Transfer-Encoding: chunked
data: {"answer": ""}
data: {"answer": "Nice"}
data: {"answer": " to"}
data: {"answer": " know"}
data: {"answer": " you"}
data: {"answer": " too"}
data: {"answer": "!"}
data: {"answer": " Is"}
data: {"answer": " there"}
data: {"answer": " anything"}
data: {"answer": " I"}
data: {"answer": " can"}
data: {"answer": " help"}
data: {"answer": " you"}
data: {"answer": " with"}
data: {"answer": "?"}
data: {"answer": ""}
La conversation continue ensuite de la même manière.
Gérer les erreurs
Le client doit d’abord vérifier le code de réponse HTTP. Consultez la table de codes d’état HTTP pour connaître les codes d’erreur courants retournés par les points de terminaison en ligne.
Si le code de réponse est « Erreur de modèle 424 », cela signifie que l’erreur est provoquée par le code du modèle. La réponse d’erreur d’un modèle de flux d’invite suit toujours ce format :
{
"error": {
"code": "UserError",
"message": "Media type text/event-stream in Accept header is not acceptable. Supported media type(s) - application/json",
}
}
- Il s’agit toujours d’un dictionnaire JSON avec une seule clé « error » définie.
- La valeur de la clé « error » est un dictionnaire contenant « code » et « message ».
- « code » définit la catégorie d’erreur. Actuellement, il peut s’agir de « UserError » pour les entrées utilisateur incorrectes et de « SystemError » pour les erreurs internes du service.
- « message » contient une description de l’erreur. Il peut être affiché à l’utilisateur final.
Comment utiliser les événements envoyés par le serveur
Consommer à l’aide de Python
Dans cet exemple d’utilisation, nous utilisons la classe SSEClient
. Cette classe n’est pas une classe Python intégrée et doit être installée séparément. Vous pouvez l’installer via pip :
pip install sseclient-py
Un exemple d’utilisation serait :
import requests
from sseclient import SSEClient
from requests.exceptions import HTTPError
try:
response = requests.post(url, json=body, headers=headers, stream=stream)
response.raise_for_status()
content_type = response.headers.get('Content-Type')
if "text/event-stream" in content_type:
client = SSEClient(response)
for event in client.events():
# Handle event, i.e. print to stdout
else:
# Handle json response
except HTTPError:
# Handle exceptions
Consommer à l’aide de JavaScript
Il existe plusieurs bibliothèques pour utiliser les événements envoyés par le serveur dans JavaScript. Voici l’un d’entre eux comme exemple.
Exemple d’application de conversation utilisant Python
Voici un exemple d’application de conversation écrite en Python.
Utilisation avancée – Sortie de flux avec et sans diffusion hybride
Parfois, vous souhaiterez probablement obtenir des résultats avec et sans stream d’une sortie de flux. Par exemple, dans le flux « Conversation avec Wikipédia », vous souhaiterez probablement obtenir non seulement la réponse de LLM, mais aussi la liste des URL recherchées par le flux. Pour ce faire, vous devez modifier le flux pour générer une combinaison de la réponse de LLM avec diffusion et de la liste d’URL sans diffusion.
Dans l’exemple de flux « Conversation avec Wikipédia », la sortie est connectée au nœud LLM augmented_chat
. Pour ajouter la liste d’URL à la sortie, vous devez ajouter un champ de sortie avec le nom url
et la valeur ${get_wiki_url.output}
.
La sortie du flux sera un champ sans diffusion comme base et un champ de diffusion en tant que delta. Voici un exemple de requête et de réponse.
Utilisation avancée – 0. Le client envoie un message au serveur
POST https://<your-endpoint>.inference.ml.azure.com/score
Content-Type: application/json
Authorization: Bearer <key or token of your endpoint>
Accept: text/event-stream
{
"question": "When was ChatGPT launched?",
"chat_history": []
}
Utilisation avancée, 1. Le serveur renvoie la réponse en mode de diffusion en continu
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Connection: close
Transfer-Encoding: chunked
data: {"url": ["https://en.wikipedia.org/w/index.php?search=ChatGPT", "https://en.wikipedia.org/w/index.php?search=GPT-4"]}
data: {"answer": ""}
data: {"answer": "Chat"}
data: {"answer": "G"}
data: {"answer": "PT"}
data: {"answer": " was"}
data: {"answer": " launched"}
data: {"answer": " on"}
data: {"answer": " November"}
data: {"answer": " "}
data: {"answer": "30"}
data: {"answer": ","}
data: {"answer": " "}
data: {"answer": "202"}
data: {"answer": "2"}
data: {"answer": "."}
data: {"answer": " \n\n"}
...
data: {"answer": "PT"}
data: {"answer": ""}
Utilisation avancée, 2. Le client envoie un autre message de conversation, avec l’historique complet des conversations, au serveur
POST https://<your-endpoint>.inference.ml.azure.com/score
Content-Type: application/json
Authorization: Bearer <key or token of your endpoint>
Accept: text/event-stream
{
"question": "When did OpenAI announce GPT-4? How long is it between these two milestones?",
"chat_history": [
{
"inputs": {
"question": "When was ChatGPT launched?"
},
"outputs": {
"url": [
"https://en.wikipedia.org/w/index.php?search=ChatGPT",
"https://en.wikipedia.org/w/index.php?search=GPT-4"
],
"answer": "ChatGPT was launched on November 30, 2022. \n\nSOURCES: https://en.wikipedia.org/w/index.php?search=ChatGPT"
}
}
]
}
Utilisation avancée, 3. Le serveur renvoie la réponse en mode de diffusion en continu
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Connection: close
Transfer-Encoding: chunked
data: {"url": ["https://en.wikipedia.org/w/index.php?search=Generative pre-trained transformer ", "https://en.wikipedia.org/w/index.php?search=Microsoft "]}
data: {"answer": ""}
data: {"answer": "Open"}
data: {"answer": "AI"}
data: {"answer": " released"}
data: {"answer": " G"}
data: {"answer": "PT"}
data: {"answer": "-"}
data: {"answer": "4"}
data: {"answer": " in"}
data: {"answer": " March"}
data: {"answer": " "}
data: {"answer": "202"}
data: {"answer": "3"}
data: {"answer": "."}
data: {"answer": " Chat"}
data: {"answer": "G"}
data: {"answer": "PT"}
data: {"answer": " was"}
data: {"answer": " launched"}
data: {"answer": " on"}
data: {"answer": " November"}
data: {"answer": " "}
data: {"answer": "30"}
data: {"answer": ","}
data: {"answer": " "}
data: {"answer": "202"}
data: {"answer": "2"}
data: {"answer": "."}
data: {"answer": " The"}
data: {"answer": " time"}
data: {"answer": " between"}
data: {"answer": " these"}
data: {"answer": " two"}
data: {"answer": " milestones"}
data: {"answer": " is"}
data: {"answer": " approximately"}
data: {"answer": " "}
data: {"answer": "3"}
data: {"answer": " months"}
data: {"answer": ".\n\n"}
...
data: {"answer": "Chat"}
data: {"answer": "G"}
data: {"answer": "PT"}
data: {"answer": ""}
Étapes suivantes
- En savoir plus sur la manière de résoudre les problèmes liés aux points de terminaison en ligne managés.
- Une fois que vous avez amélioré votre flux et que vous souhaitez déployer la version améliorée avec une stratégie de déploiement sécurisé, vous pouvez vous référer à Déploiement sécurisé pour les points de terminaison en ligne.