Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In Prompt Flow können Sie Flows an einen von Azure Machine Learning verwalteten Online-Endpunkt für Echtzeit-Inferenz bereitstellen.
Wenn der Endpunkt durch Senden einer Anfrage konsumiert wird, wartet der Online-Endpunkt standardmäßig so lange, bis die gesamte Antwort fertig ist, und sendet sie dann an den Client zurück. Dies kann zu einer langen Verzögerung für den Kunden und einer schlechten Benutzererfahrung führen.
Um dies zu vermeiden, können Sie Streaming verwenden, wenn Sie die Endpunkte nutzen. Sobald das Streaming aktiviert ist, müssen Sie nicht mehr warten, bis die gesamte Antwort fertig ist. Stattdessen sendet der Server die Antwort in Stücken zurück, sobald sie generiert wurden. Der Client kann dann die Antwort schrittweise anzeigen, mit weniger Wartezeit und mehr Interaktivität.
Dieser Artikel beschreibt den Umfang des Streaming, die Funktionsweise des Streaming und die Nutzung von Streaming-Endpunkten.
Erstellen Sie einen streamingfähigen Flow
Wenn Sie den Streaming-Modus verwenden möchten, müssen Sie einen Flow erstellen, der einen Knoten hat, der einen String-Generator als Ausgabe des Flows erzeugt. Ein String-Generator ist ein Objekt, das auf Anfrage jeweils einen String zurückgeben kann. Sie können die folgenden Knotentypen verwenden, um einen String-Generator zu erstellen:
LLM-Knoten: Dieser Knoten verwendet ein umfangreiches Sprachmodell, um auf der Grundlage der Eingaben natürlichsprachliche Antworten zu generieren.
{# Sample prompt template for LLM node #} system: You are a helpful assistant. user: {{question}}
Python-Knoten: Dieser Knoten ermöglicht es Ihnen, benutzerdefinierten Python-Code zu schreiben, der Zeichenketten ausgeben kann. Sie können diesen Knoten verwenden, um externe APIs oder Bibliotheken aufzurufen, die Streaming unterstützen. Sie können zum Beispiel diesen Code verwenden, um die Eingabe wortweise auszugeben:
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 + " "
Wichtig
Nur die Ausgabe des letzten Knotens des Flows kann Streaming unterstützen.
„Letzter Knoten“ bedeutet, dass die Ausgabe des Knotens nicht von anderen Knoten verbraucht wird.
In diesem Leitfaden wird der Beispielablauf „Chat mit Wikipedia“ als Beispiel verwendet. Dieser Flow verarbeitet die Frage des Benutzers, durchsucht Wikipedia nach relevanten Artikeln und beantwortet die Frage mit Informationen aus den Artikeln. Es verwendet den Streaming-Modus, um den Fortschritt bei der Erstellung der Antwort anzuzeigen.
Informationen zum Erstellen eines Chatflows finden Sie unter Entwickeln eines Chatflows in Prompt Flow.
Stellen Sie den Flow als Online-Endpunkt bereit
Um den Streaming-Modus zu nutzen, müssen Sie Ihren Flow als Online-Endpunkt bereitstellen. So können Sie in Echtzeit Anfragen senden und Antworten von Ihrem Flow erhalten.
Wie Sie Ihren Flow als Online-Endpunkt bereitstellen können, erfahren Sie unter Bereitstellen eines Flows als Online-Endpunkt für Echtzeit-Inferenz mit CLI, um Ihren Flow als Online-Endpunkt bereitzustellen.
Hinweis
Bereitstellung mit einer Laufzeitumgebungsversion höher als Version 20230816.v10
.
Sie können Ihre Laufzeitversion überprüfen und die Laufzeit auf der Laufzeit-Detailseite aktualisieren.
Verstehen des Streaming-Prozesses
Bei einem Online-Endpunkt müssen der Client und der Server bestimmte Prinzipien für die Inhaltsaushandlung befolgen, um den Streaming-Modus zu nutzen:
Die Aushandlung von Inhalten ist wie ein Gespräch zwischen dem Client und dem Server über das bevorzugte Format der Daten, die sie senden und empfangen wollen. Sie gewährleistet eine effektive Kommunikation und eine Einigung über das Format der ausgetauschten Daten.
Um den Streaming-Prozess zu verstehen, sollten Sie die folgenden Schritte beachten:
Zunächst erstellt der Client eine HTTP-Anfrage mit dem gewünschten Medientyp in der
Accept
-Kopfzeile. Der Medientyp teilt dem Server mit, welche Art von Datenformat der Client erwartet. Es ist, als würde der Kunde sagen: „Hey, ich brauche ein bestimmtes Format für die Daten, die Sie mir schicken. Das kann JSON, Text oder etwas anderes sein.“ Zum Beispiel bedeutetapplication/json
, dass JSON-Daten bevorzugt werden,text/event-stream
, dass Streaming-Daten gewünscht werden, und*/*
, dass der Client jedes Datenformat akzeptiert.Hinweis
Wenn eine Anfrage keinen
Accept
-Header oder einen leerenAccept
-Header hat, bedeutet dies, dass der Client jeden Medientyp als Antwort akzeptiert. Der Server behandelt es als*/*
.Anschließend antwortet der Server auf der Grundlage des im
Accept
-Header angegebenen Medientyps. Es ist wichtig zu beachten, dass der Client imAccept
-Header mehrere Medientypen anfordern kann, und der Server muss seine Fähigkeiten und Formatprioritäten berücksichtigen, um die geeignete Antwort zu bestimmen.- Zunächst prüft der Server, ob
text/event-stream
ausdrücklich in der KopfzeileAccept
angegeben ist:- Bei einem Stream-aktivierten DatenFlow gibt der Server eine Antwort mit einem
Content-Type
vontext/event-stream
zurück, was bedeutet, dass die Daten gestreamt werden. - Bei einem nicht Stream-fähigen DatenFlow prüft der Server, ob andere Medientypen im Header angegeben sind.
- Bei einem Stream-aktivierten DatenFlow gibt der Server eine Antwort mit einem
- Wenn
text/event-stream
nicht angegeben ist, prüft der Server, obapplication/json
oder*/*
in der KopfzeileAccept
angegeben ist:- In solchen Fällen gibt der Server eine Antwort mit einem
Content-Type
vonapplication/json
zurück und stellt die Daten im JSON-Format bereit.
- In solchen Fällen gibt der Server eine Antwort mit einem
- Wenn der
Accept
-Header andere Medientypen angibt, wie z. B.text/html
:- Der Server gibt eine
424
-Antwort mit einem Prompt-Flow-LaufzeitfehlercodeUserError
und einem Laufzeit-HTTP-Status406
zurück, der anzeigt, dass der Server die Anforderung nicht mit dem angeforderten Datenformat erfüllen kann. Weitere Informationen finden Sie unter Fehlerbehandlung.
- Der Server gibt eine
- Zunächst prüft der Server, ob
Schließlich prüft der Client den Antwort-Header
Content-Type
. Ist er auftext/event-stream
gesetzt, bedeutet dies, dass die Daten gestreamt werden.
Schauen wir uns genauer an, wie der Streaming-Prozess funktioniert. Die Antwortdaten im Streaming-Modus haben das Format von server-sent events (SSE).
Der gesamte Prozess läuft folgendermaßen ab:
0. Der Client sendet eine Nachricht an den Server
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": []
}
Hinweis
Der Accept
-Header wird auf text/event-stream
gesetzt, um eine Stream-Antwort anzufordern.
1. Der Server sendet die Antwort im Streaming-Modus zurück
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": ""}
Hinweis
Die Content-Type
wird auf text/event-stream; charset=utf-8
gesetzt, was bedeutet, dass die Antwort ein Ereignisstrom ist.
Der Client sollte die Antwortdaten als vom Server gesendete Ereignisse dekodieren und sie inkrementell anzeigen. Der Server schließt die HTTP-Verbindung, nachdem alle Daten gesendet wurden.
Jedes Antwortereignis ist das Delta zum vorherigen Ereignis. Es wird empfohlen, dass der Client die zusammengeführten Daten im Speicher behält und sie bei der nächsten Anfrage als Chatverlauf an den Server zurückschickt.
2. Der Client sendet eine weitere Chat-Nachricht zusammen mit dem gesamten Chat-Verlauf an den Server
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. Der Server sendet die Antwort im Streaming-Modus zurück
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": ""}
Das Gespräch wird dann in ähnlicher Weise fortgesetzt.
Umgang mit Fehlern
Der Client sollte zunächst den HTTP-Antwortcode überprüfen. Siehe HTTP-Statuscode-Tabelle für häufige Fehlercodes, die von Online-Endpunkten zurückgegeben werden.
Wenn der Antwortcode „424 Model Error“ lautet, bedeutet dies, dass der Fehler durch den Code des Modells verursacht wurde. Die Fehlerantwort eines Prompt-Flow-Modells hat immer dieses Format:
{
"error": {
"code": "UserError",
"message": "Media type text/event-stream in Accept header is not acceptable. Supported media type(s) - application/json",
}
}
- Es handelt sich immer um ein JSON-Dictionary mit nur einem definierten Schlüssel „error“.
- Der Wert für „error“ ist ein Wörterbuch, das „code“ und „message“" enthält.
- „code“ definiert die Fehlerkategorie. Derzeit kann es sich um „UserError“ für fehlerhafte Benutzereingaben und „SystemError“ für Fehler innerhalb des Dienstes handeln.
- „message“ ist eine Beschreibung des Fehlers. Sie kann dem Endbenutzer angezeigt werden.
Wie man die vom Server gesendeten Ereignisse konsumiert
Verbrauchen mit Python
In diesem Beispiel verwenden wir die SSEClient
-Klasse. Diese Klasse ist keine integrierte Python-Klasse und muss separat installiert werden. Sie können Sie über „pip“ installieren:
pip install sseclient-py
Ein Beispiel für die Verwendung wäre:
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
Verbrauchen mit JavaScript
Es gibt mehrere Bibliotheken, um vom Server gesendete Ereignisse in JavaScript zu nutzen. Hier finden Sie ein Beispiel für eine dieser Bibliotheken.
Ein Beispiel für eine Chat-Anwendung mit Python
Das folgende Beispiel zeigt eine in Python geschriebene Chat-Anwendung.
Erweiterte Verwendung: Ausgabe von Hybridstreams und nicht streamingfähigen Flows
Es kann vorkommen, dass Sie aus einer Flowausgabe sowohl Stream- als auch Non-Stream-Ergebnisse erhalten möchten. Im Ablauf „Chat mit Wikipedia“ möchten Sie zum Beispiel nicht nur die Antwort von LLM erhalten, sondern auch die Liste der URLs, die der Ablauf durchsucht hat. Dazu müssen Sie den DatenFlow so ändern, dass er eine Kombination aus der Antwort des LLM-Streams und der URL-Liste für Nicht-Streams ausgibt.
Im Beispielflow „Chat mit Wikipedia“ ist die Ausgabe mit dem LLM-Knoten augmented_chat
verbunden. Um die URL-Liste zur Ausgabe hinzuzufügen, müssen Sie ein Ausgabefeld mit dem Namen url
und dem Wert ${get_wiki_url.output}
hinzufügen.
Die Ausgabe des Flows ist ein Nichtstromfeld als Basis und ein Stromfeld als Delta. Hier ist ein Beispiel für eine Anfrage und eine Antwort.
Erweiterte Verwendung – 0. Der Client sendet eine Nachricht an den Server
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": []
}
Vorzeitige Verwendung - 1. Der Server sendet die Antwort im Streaming-Modus zurück
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": ""}
Vorzeitige Verwendung - 2. Der Client sendet eine weitere Chat-Nachricht zusammen mit dem gesamten Chat-Verlauf an den Server
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"
}
}
]
}
Vorzeitige Verwendung - 3. Der Server sendet die Antwort im Streaming-Modus zurück
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": ""}
Nächste Schritte
- Informationen zur Problembehandlung bei verwalteten Onlineendpunkten
- Sobald Sie Ihren Ablauf verbessert haben und die verbesserte Version mit einer sicheren Rollout-Strategie einsetzen möchten, können Sie sich auf Sicheres Rollout für Online-Endpunkte beziehen.