Verwalten des Zustands
GILT FÜR: SDK v4
Der Zustand in einem Bot basiert auf den gleichen Paradigmen wie bei modernen Webanwendungen, und über das Bot Framework SDK werden einige Abstraktionen bereitgestellt, um die Verwaltung des Zustands zu vereinfachen.
Wie bei Web-Apps auch, ist ein Bot grundsätzlich zustandslos. Jedes einzelne Segment der Konversation kann auch von einer anderen Instanz Ihres Bots verarbeitet werden. Für einige Bots ist diese Einfachheit bevorzugt– der Bot kann entweder ohne zusätzliche Informationen funktionieren, oder die erforderlichen Informationen werden innerhalb der eingehenden Nachricht garantiert. Für andere ist der Zustand (z. B. wo die Unterhaltung nicht mehr über den Benutzer empfangen wurde) für den Bot erforderlich, um eine nützliche Unterhaltung zu haben.
Warum benötige ich den Zustand?
Wenn der Zustand verwaltet wird, kann Ihr Bot aussagekräftigere Konversationen durchführen, indem bestimmte Punkte zu einem Benutzer oder einer Konversation gespeichert werden. Wenn mit einem Benutzer beispielsweise schon einmal eine Konversation erfolgt ist, können Sie die bereits erhaltenen Informationen zum Benutzer speichern, damit Sie nicht noch einmal danach fragen müssen. Bei der Zustandsspeicherung werden Daten auch länger als nur für den aktuellen Durchlauf (Turn) gespeichert, damit Informationen auch im Verlauf einer Konversation mit mehreren Durchläufen erhalten bleiben.
Wie es sich auf Bots bezieht, gibt es einige Ebenen, um den Zustand zu verwenden: die Speicherschicht, die Statusverwaltung (im Botstatus im folgenden Diagramm enthalten) und Statuseigenschaftszugriffer. Das Diagramm zeigt Teile der Interaktionssequenz zwischen diesen Ebenen. Die durchgezogenen Pfeile stellen einen Methodenaufruf dar, und die gestrichelten Pfeile stellen die Antwort dar (mit oder ohne Rückgabewert).
Der im Diagramm dargestellte Fluss wird in den folgenden Abschnitten mit Details zu jeder dieser Ebenen erläutert.
Speicherebene
Ab dem Back-End, wo die Statusinformationen tatsächlich gespeichert werden, ist die Speicherschicht. Dies kann als physischer Speicher gedacht werden, z. B. In-Memory, Azure oder ein Drittanbieterserver.
Das Bot Framework SDK enthält einige Implementierungen für die Speicherebene:
- Bei Arbeitsspeicher wird zu Testzwecken In-Memory-Speicher implementiert. In-Memory-Datenspeicher ist nur für lokale Tests bestimmt, da er flüchtig und temporär ist. Die Daten werden jedes Mal gelöscht, wenn der Bot neu gestartet wird.
- Bei Azure Blob Storage wird eine Verbindung mit einer Azure Blob Storage-Objektdatenbank hergestellt.
- Bei partitioniertem Azure Cosmos DB-Speicher wird eine Verbindung mit einer partitionierten Cosmos DB-NoSQL-Datenbank hergestellt.
Wichtig
Die Klasse Cosmos DB-Speicher wurde als veraltet gekennzeichnet. Container, die ursprünglich mit CosmosDbStorage erstellt wurden, hatten keinen Partitionsschlüsselsatz und erhielten den Standardpartitionsschlüssel "/_partitionKey".
Container, die mit Cosmos DB-Speicher erstellt wurden, können mit Cosmos DB-Partitionierungsspeicher verwendet werden. Weitere Informationen finden Sie unter Partitionierung in Azure Cosmos DB.
Beachten Sie auch, dass der Cosmos DB-Speicher im Gegensatz zum älteren Cosmos DB-Speicher nicht automatisch eine Datenbank in Ihrem Cosmos DB-Konto erstellt. Sie müssen eine neue Datenbank manuell erstellen, aber einen Container manuell erstellen, da CosmosDbPartitionedStorage den Container für Sie erstellt.
Eine Anleitung zum Herstellen einer Verbindung für andere Speicheroptionen finden Sie unter Direktes Schreiben in den Speicher.
Zustandsverwaltung
Mit der Zustandsverwaltung wird das Lesen und Schreiben des Zustands Ihres Bots auf die zugrunde liegende Speicherebene automatisiert. Der Zustand wird in Form von Zustandseigenschaften gespeichert. Hierbei handelt es sich im Wesentlichen um Schlüssel-Wert-Paare, die von Ihrem Bot über das Zustandsverwaltungsobjekt gelesen und geschrieben werden können, ohne sich um die zugrunde liegenden Implementierungen kümmern zu müssen. Mit diesen Zustandseigenschaften wird definiert, wie diese Informationen gespeichert werden. Wenn Sie beispielsweise eine Eigenschaft abrufen, die Sie als spezifische Klasse oder Objekt definiert haben, wissen Sie, wie diese Daten strukturiert werden.
Diese Zustandseigenschaften werden in bereichsbezogenen „Buckets“ zusammengefasst, wobei es sich lediglich um Sammlungen für die Organisation dieser Eigenschaften handelt. Das SDK enthält drei dieser Buckets:
- Benutzerzustand
- Konversationszustand
- Zustand der privaten Konversation
Alle diese Buckets sind Unterklassen der Bot State-Klasse, von der Ableitungen erstellt werden können, um andere Arten von Buckets mit anderen Bereichen zu definieren.
Diese vordefinierten Buckets beziehen sich jeweils auf eine bestimmte Sichtbarkeit:
- Der Benutzerzustand ist für jeden Durchlauf verfügbar, den der Bot unabhängig von der Konversation mit dem Benutzer über den Kanal durchführt.
- Unterhaltungsstatus ist jederzeit in einer bestimmten Unterhaltung verfügbar, unabhängig von Benutzern, z. B. in Gruppenunterhaltungen
- Der Zustand der privaten Konversation bezieht sich auf die jeweilige Konversation und den jeweiligen Benutzer.
Tipp
Sowohl der Benutzerzustand als auch der Konversationszustand bezieht sich jeweils auf den Kanal. Wenn eine Person unterschiedliche Kanäle nutzt, um auf Ihren Bot zuzugreifen, wird sie jeweils als ein anderer Benutzer angezeigt (einer für jeden Kanal), der jeweils einen eigenen Benutzerzustand aufweist.
Die Schlüssel, die für diese einzelnen vordefinierten Buckets verwendet werden, gelten spezifisch für den Benutzer oder die Konversation (oder beides). Wenn Sie den Wert Ihrer Statuseigenschaft festlegen, wird der Schlüssel für Sie intern definiert, wobei Informationen im Turnkontext enthalten sind, um sicherzustellen, dass jeder Benutzer oder jede Unterhaltung im richtigen Bucket und in der richtigen Eigenschaft platziert wird. Die Schlüssel werden wie folgt definiert:
- Vom Benutzerzustand wird ein Schlüssel erstellt, indem die Kanal-ID und die Von-ID (Channel ID/From ID) verwendet werden. Beispiel: {Activity.ChannelId}/users/{Activity.From.Id}#YourPropertyName.
- Mit dem Konversationszustand wird ein Schlüssel erstellt, indem die Kanal-ID und die Konversations-ID (Channel ID/Conversation ID) verwendet werden. Beispiel: {Activity.ChannelId}/conversations/{Activity.Conversation.Id}#YourPropertyName.
- Mit dem Zustand der privaten Konversation wird ein Schlüssel erstellt, indem die Kanal-ID, die Von-ID und die Konversations-ID verwendet werden. Beispiel: {Activity.ChannelId}/conversations/{Activity.Conversation.Id}/users/{Activity.From.Id}#YourPropertyName.
Verwenden der einzelnen Zustandsarten
Der Konversationszustand ist gut für die Nachverfolgung des Konversationskontexts, z.B.:
- Ob der Bot dem Benutzer eine Frage gestellt hat und welche Frage dies war
- Was das aktuelle Thema der Konversation ist oder das vorherige Thema war
Der Benutzerzustand ist gut für Nachverfolgungsinformationen zum Benutzer, z.B.:
- Nicht kritische Benutzerinformationen, z.B. Name und Präferenzen, eine Alarmeinstellung oder eine Alarmpräferenz
- Informationen zur letzten Konversation des Benutzers mit dem Bot
- Ein Bot für die Produktunterstützung kann beispielsweise verfolgen, nach welchen Produkten der Benutzer gefragt hat.
Der private Konversationszustand ist gut für Kanäle, die Gruppenkonversationen unterstützen, bei denen Sie aber sowohl benutzer- als auch konversationsspezifische Informationen nachverfolgen möchten. Beispielsweise bei einem Clicker-Bot für ein Klassenzimmer:
- Der Bot kann Antworten der Kursteilnehmer auf eine bestimmte Frage aggregieren und anzeigen.
- Der Bot kann die Leistung jedes Kursteilnehmers aggregieren und am Ende der Stunde für jeden Kursteilnehmer jeweils „privat“ bereitstellen.
Weitere Informationen zur Verwendung dieser vordefinierten Buckets finden Sie im Gewusst-wie-Artikel zum Zustand.
Herstellen einer Verbindung mit mehreren Datenbanken
Wenn Ihr Bot eine Verbindung mit mehreren Datenbanken herstellen muss, können Sie eine Speicherebene für jede Datenbank erstellen. Sie können mehrere Datenbanken verwenden, wenn Ihr Bot Informationen sammelt, die unterschiedliche Sicherheits-, Übereinstimmungs- oder Datenspeicherortanforderungen aufweisen.
Erstellen Sie für jede Speicherebene die Objekte für die Zustandsverwaltung, die Sie zum Unterstützen Ihrer Zustandseigenschaften benötigen.
Zustandseigenschaftenaccessoren
Zustandseigenschaftenaccessoren werden verwendet, um das eigentliche Lesen bzw. Schreiben für eine Ihrer Zustandseigenschaften durchzuführen und get-, set- und delete-Methoden für den Zugriff auf Ihre Zustandseigenschaften aus einem Durchlauf bereitzustellen. Für die Erstellung eines Accessors müssen Sie den Eigenschaftennamen angeben (normalerweise beim Initialisieren Ihres Bots). Anschließend können Sie diesen Accessor verwenden, um diese Eigenschaft für den Zustand Ihres Bots abzurufen und zu ändern.
Mit den Accessoren kann das SDK den Zustand aus dem zugrunde liegenden Speicher abrufen und den Zustandscache für Sie aktualisieren. Der Zustandscache ist ein lokaler Cache, der von Ihrem Bot verwaltet und in dem das Zustandsobjekt für Sie gespeichert wird. Auf diese Weise werden Lese- und Schreibvorgänge ermöglicht, ohne dass auf den zugrunde liegenden Speicher zugegriffen werden muss. Wenn er nicht bereits im Cache vorhanden ist, wird durch das Aufrufen der get-Methode des Accessors der Zustand abgerufen und im Cache abgelegt. Nach dem Abruf kann die Zustandseigenschaft genau wie jede andere lokale Variable geändert werden.
Mit der delete-Methode des Accessors wird die Eigenschaft aus dem Cache entfernt und aus dem zugrunde liegenden Speicher gelöscht.
Wichtig
Für den ersten Aufruf der get-Methode eines Accessors müssen Sie eine Factorymethode für die Erstellung des Objekts bereitstellen, falls es in Ihrem Zustand noch nicht enthalten ist. Wenn keine Fabrikmethode angegeben wird, erhalten Sie eine Ausnahme. Ausführliche Informationen zur Nutzung einer Factorymethode finden Sie im Gewusst wie-Artikel zum Zustand.
Damit die Änderungen beibehalten werden, die Sie an der vom Accessor erhaltenen Zustandseigenschaft vornehmen, muss die Eigenschaft im Zustandscache aktualisiert werden. Hierfür können Sie die set-Methode des Accessors aufrufen. Mit dieser Methode wird der Wert Ihrer Eigenschaft im Cache festgelegt, damit er verfügbar ist, wenn zu einem späteren Zeitpunkt des Durchlaufs das Lesen oder Aktualisieren erforderlich ist. Sie müssen dann den Zustand speichern, um diese Daten dauerhaft im zugrunde liegenden Speicher abzulegen (damit sie auch nach dem aktuellen Durchlauf verfügbar sind).
Funktionsweise der Zustandseigenschaftenaccessor-Methoden
Die Accessormethoden stellen den Hauptansatz für die Interaktion Ihres Bots mit dem Zustand dar. Hier sind die einzelnen Funktionsweisen und zugrunde liegenden Ebenen beschrieben:
- Die get-Methode des Accessors:
- Der Accessor fordert die Eigenschaft vom Zustandscache an.
- Wenn die Eigenschaft im Cache enthalten ist, wird sie zurückgegeben. Andernfalls wird sie aus dem Zustandsverwaltungsobjekt abgerufen. (Wenn es noch nicht im Zustand ist, verwenden Sie die in den Accessoren bereitgestellte Fabrikmethode aufrufen .)
- Die set-Methode des Accessors:
- Aktualisiert den Zustandscache mit dem neuen Eigenschaftswert.
- Die save changes-Methode des Objekts für die Zustandsverwaltung:
- Überprüfen Sie die Änderungen an der Eigenschaft im Zustandscache.
- Schreiben Sie diese Eigenschaft in den Speicher.
Status in Dialogfeldern
Die Dialogfelderbibliothek verwendet einen Dialogstatuseigenschaftszugriffor, der im Unterhaltungszustand des Bots definiert ist, um den Platz eines Dialogfelds in der Unterhaltung beizubehalten. Die Dialogfeldzustandseigenschaft ermöglicht es jedem Dialogfeld auch, vorübergehende Informationen zwischen den Drehungen zu speichern.
Adaptive Dialogfelder verfügen über eine komplexere Speicherbereichsstruktur, wodurch der Zugriff auf Konfigurations- und Erkennungsergebnisse unter anderem erleichtert wird. Der Dialogfelder verwendet die Benutzer- und Unterhaltungsstatusverwaltungsobjekte, um diese Speicherbereiche bereitzustellen.
Informationen zur Dialogfelderbibliothek finden Sie im Artikel zur Dialogfelderbibliothek .
- Informationen zu Komponenten- und Wasserfalldialogfeldern finden Sie für Informationen, die für diese Arten von Dialogfeldern spezifisch sind.
- Sehen Sie sich die Einführung in adaptive Dialogfelder und das Verwalten des Zustands in adaptiven Dialogfeldern an, um Informationen speziell für adaptive Dialogfelder zu finden.
Speichern des Zustands
Wenn Sie die set-Methode des Accessors aufrufen, um den aktualisierten Zustand aufzuzeichnen, wurde diese Zustandseigenschaft noch nicht in Ihrem permanenten Speicher abgelegt, sondern nur im Zustandscache Ihres Bots. Um die im Zustandscache befindlichen Änderungen im permanenten Speicher abzulegen, müssen Sie die save changes-Methode des Zustandsverwaltungsobjekts aufrufen. Sie ist unter der oben erwähnten Implementierung der Botzustandsklasse verfügbar (z.B. Benutzerzustand oder Konversationszustand).
Beim Aufrufen der Methode "Speichern von Änderungen" für ein Statusverwaltungsobjekt (z. B. die oben erwähnten Buckets) werden alle Eigenschaften im Statuscache gespeichert, die Sie an diesem Punkt für diesen Bucket eingerichtet haben, aber nicht für alle anderen Buckets, die Sie möglicherweise im Status Ihres Bots haben.
Tipp
Anhand des Botzustands wird das Verhalten „letzter Schreibvorgang gewinnt“ implementiert, bei dem der letzte Schreibvorgang den vorherigen Schreibzustand außer Kraft setzt. Dieses Verhalten ist ggf. für viele Anwendungen geeignet, aber es sind einige Aspekte zu beachten. Dies gilt vor allem für Szenarien mit horizontaler Skalierung, bei denen bestimmte Parallelitäts- oder Latenzebenen zu berücksichtigen sind.
Falls Sie über benutzerdefinierte Middleware verfügen, über die der Zustand nach Abschluss Ihres Turn-Handlers aktualisiert wird, helfen Ihnen ggf. die Informationen unter Verarbeiten des Zustands in Middleware weiter.