Speichern von Benutzer- und KonversationsdatenSave user and conversation data

gilt für: SDK v4APPLIES TO: SDK v4

Ein Bot ist grundsätzlich zustandslos.A bot is inherently stateless. Nachdem Ihr Bot bereitgestellt wurde, kann es sein, dass er für die einzelnen Durchläufe nicht als Teil desselben Prozesses oder auf demselben Computer ausgeführt wird.Once your bot is deployed, it may not run in the same process or on the same machine from one turn to the next. Unter Umständen muss Ihr Bot aber den Kontext einer Konversation nachverfolgen, damit er das Verhalten verwalten und Antworten auf vorherige Fragen speichern kann.However, your bot may need to track the context of a conversation so that it can manage its behavior and remember answers to previous questions. Mit den Zustands- und Speicherfeatures des Bot Framework SDK können Sie Ihrem Bot den Zustand hinzufügen.The state and storage features of the Bot Framework SDK allow you to add state to your bot. Bots verwenden Zustandsverwaltungs- und Speicherobjekte, um den Zustand zu verwalten und zu speichern.Bots use state management and storage objects to manage and persist state. Der Zustands-Manager bietet eine Abstraktionsebene, mit der Sie unabhängig von der Art des zugrunde liegenden Speichers mithilfe von Eigenschaftenaccessoren auf Zustandseigenschaften zugreifen können.The state manager provides an abstraction layer that lets you access state properties using property accessors, independent of the type of underlying storage.

VoraussetzungenPrerequisites

Informationen zu diesem BeispielAbout this sample

Nach dem Empfang der Benutzereingabe überprüft das Beispiel den gespeicherten Konversationszustand, um festzustellen, ob der Benutzer bereits zur Eingabe seines Namens aufgefordert wurde.Upon receiving user input, this sample checks the stored conversation state to see if this user has previously been prompted to provide their name. Wenn dies nicht der Fall ist, wird der Name des Benutzers angefordert, und die Eingabe wird im Benutzerzustand gespeichert.If not, the user's name is requested and that input is stored within user state. Ist dies der Fall, wird der im Benutzerzustand gespeicherte Name zur Konversation mit dem Benutzer verwendet, und die Eingabedaten werden zusammen mit der Empfangszeit und der ID des Eingabekanals an den Benutzer zurückgegeben.If so, the name stored within user state is used to converse with the user and their input data, along with the time received and input channel Id, is returned back to the user. Die Werte für die Uhrzeit und die Kanal-ID werden aus den Benutzerkonversationsdaten abgerufen und dann im Konversationszustand gespeichert.The time and channel Id values are retrieved from the user conversation data and then saved to conversation state. Das folgende Diagramm zeigt die Beziehung zwischen dem Bot, dem Benutzerprofil und den Konversationsdatenklassen.The following diagram shows the relationship between the bot, user profile, and conversation data classes.

Definieren von KlassenDefine classes

Der erste Schritt beim Einrichten der Zustandsverwaltung ist das Definieren der Klassen, die die Informationen enthalten, die im Benutzer- und Konversationszustand verwaltet werden sollen.The first step in setting up state management is to define the classes containing the information to manage in the user and conversation state. In dem in diesem Artikel verwendeten Beispiel werden die folgenden Klassen definiert:The example used in this article, defines the following classes:

  • In UserProfile.cs definieren Sie eine UserProfile Klasse für die Benutzerinformationen, die der Bot sammelt.In UserProfile.cs, you define a UserProfile class for the user information that the bot will collect.
  • In ConversationData.cs definieren Sie eine ConversationData -Klasse, um den Konversationszustand beim Sammeln von Benutzerinformationen zu steuern.In ConversationData.cs, you define a ConversationData class to control our conversation state while gathering user information.

Die folgenden Codebeispiele zeigen die Definitionen für die Klassen UserProfile und ConversationData.The following code examples show the definitions for the UserProfile and ConversationData classes.

UserProfile.csUserProfile.cs

// Defines a state property used to track information about the user.
public class UserProfile
{
    public string Name { get; set; }
}

ConversationData.csConversationData.cs

// Defines a state property used to track conversation data.
public class ConversationData
{
    // The time-stamp of the most recent incoming message.
    public string Timestamp { get; set; }

    // The ID of the user's channel.
    public string ChannelId { get; set; }

    // Track whether we have already asked the user's name
    public bool PromptedUserForName { get; set; } = false;
}

Erstellen von Konversations- und BenutzerzustandsobjektenCreate conversation and user state objects

Als Nächstes registrieren Sie MemoryStorage , das zum Erstellen von - und -Objekten verwendet UserState ConversationState wird.Next, you register MemoryStorage that is used to create UserState and ConversationState objects. Die Benutzer- und Konversationszustandsobjekte werden beim Startup erstellt, und Abhängigkeiten werden in den Botkonstruktor injiziert.The user and conversation state objects are created at Startup and dependency injected into the bot constructor. Weitere Dienste, die für einen Bot registriert werden, sind ein Anmeldeinformationsanbieter, ein Adapter und die Botimplementierung.Other services for a bot that are registered are: a credential provider, an adapter, and the bot implementation.

Startup.csStartup.cs

// Create the storage we'll be using for User and Conversation state.
// (Memory is great for testing purposes - examples of implementing storage with
// Azure Blob Storage or Cosmos DB are below).
var storage = new MemoryStorage();
// Create the User state passing in the storage layer.
var userState = new UserState(storage);
services.AddSingleton(userState);

// Create the Conversation state passing in the storage layer.
var conversationState = new ConversationState(storage);
services.AddSingleton(conversationState);

Bots/StateManagementBot.csBots/StateManagementBot.cs

private BotState _conversationState;
private BotState _userState;

public StateManagementBot(ConversationState conversationState, UserState userState)
{
    _conversationState = conversationState;
    _userState = userState;
}

Hinzufügen von ZustandseigenschaftenaccessorenAdd state property accessors

Nun erstellen Sie Eigenschaftenzugriffsoren mithilfe der CreateProperty -Methode, die ein Handle für das -Objekt BotState bietet.Now you create property accessors using the CreateProperty method that provides a handle to the BotState object. Mit jedem Zustandseigenschaftenaccessor können Sie den Wert der zugeordneten Zustandseigenschaft abrufen oder festlegen.Each state property accessor allows you to get or set the value of the associated state property. Bevor Sie die Zustandseigenschaften verwenden, verwenden Sie jeden Accessor, um die Eigenschaft aus dem Speicher zu laden und aus dem Zustandscache zu erhalten.Before you use the state properties, use each accessor to load the property from storage and get it from the state cache. Rufen Sie die -Methode auf, um den ordnungsgemäß bereichsumfangsierten Schlüssel zu erhalten, der der Zustandseigenschaft GetAsync zugeordnet ist.To get the properly scoped key associated with the state property, you call the GetAsync method.

Bots/StateManagementBot.csBots/StateManagementBot.cs

var conversationStateAccessors =  _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));

Zugreifen auf den Zustand von Ihrem Bot ausAccess state from your bot

Im vorherigen Abschnitt wurden die Schritte erläutert, die während der Initialisierung ausgeführt werden, um dem Bot Zustandseigenschaftenaccessoren hinzuzufügen.The preceding section covers the initialization-time steps to add state property accessors to our bot. Jetzt können Sie diese Accessoren zur Laufzeit verwenden, um Zustandsinformationen zu lesen und zu schreiben.Now, you can use those accessors at run-time to read and write state information. Der folgende Beispielcode verwendet den unten dargestellten Logikflow:The sample code below uses the following logic flow:

  • Wenn userProfile.Name ist und conversationData.PromptedUserForName true ist, rufen Sie den angegebenen Benutzernamen ab und speichern diesen im Benutzerzustand.If userProfile.Name is empty and conversationData.PromptedUserForName is true, you retrieve the user name provided and store this within user state.
  • Wenn userProfile.Name leer ist und conversationData.PromptedUserForName false ist, fragen Sie nach dem Namen des Benutzers.If userProfile.Name is empty and conversationData.PromptedUserForName is false, you ask for the user's name.
  • Wenn userProfile.Name zuvor gespeichert wurde, rufen Sie die Nachrichtenzeit und die Kanal-ID aus der Benutzereingabe ab, geben alle Daten an den Benutzer zurück und speichern die abgerufenen Daten im Konversationszustand.If userProfile.Name was previously stored, you retrieve message time and channel Id from the user input, echo all data back to the user, and store the retrieved data within conversation state.

Bots/StateManagementBot.csBots/StateManagementBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    // Get the state properties from the turn context.

    var conversationStateAccessors =  _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
    var conversationData = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData());

    var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
    var userProfile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile());

    if (string.IsNullOrEmpty(userProfile.Name))
    {
        // First time around this is set to false, so we will prompt user for name.
        if (conversationData.PromptedUserForName)
        {
            // Set the name to what the user provided.
            userProfile.Name = turnContext.Activity.Text?.Trim();

            // Acknowledge that we got their name.
            await turnContext.SendActivityAsync($"Thanks {userProfile.Name}. To see conversation data, type anything.");

            // Reset the flag to allow the bot to go through the cycle again.
            conversationData.PromptedUserForName = false;
        }
        else
        {
            // Prompt the user for their name.
            await turnContext.SendActivityAsync($"What is your name?");

            // Set the flag to true, so we don't prompt in the next turn.
            conversationData.PromptedUserForName = true;
        }
    }
    else
    {
        // Add message details to the conversation data.
        // Convert saved Timestamp to local DateTimeOffset, then to string for display.
        var messageTimeOffset = (DateTimeOffset) turnContext.Activity.Timestamp;
        var localMessageTime = messageTimeOffset.ToLocalTime();
        conversationData.Timestamp = localMessageTime.ToString();
        conversationData.ChannelId = turnContext.Activity.ChannelId.ToString();

        // Display state data.
        await turnContext.SendActivityAsync($"{userProfile.Name} sent: {turnContext.Activity.Text}");
        await turnContext.SendActivityAsync($"Message received at: {conversationData.Timestamp}");
        await turnContext.SendActivityAsync($"Message received from: {conversationData.ChannelId}");
    }
}

Bevor Sie den Turn-Handler beenden, verwenden Sie die SaveChangesAsync()-Methode der Zustandsverwaltungsobjekte, um alle Zustandsänderungen zurück in den Speicher zu schreiben.Before you exit the turn handler, you use the state management objects' SaveChangesAsync() method to write all state changes back to storage.

Bots/StateManagementBot.csBots/StateManagementBot.cs

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
    await base.OnTurnAsync(turnContext, cancellationToken);

    // Save any state changes that might have occurred during the turn.
    await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
}

Testen des BotsTest the bot

Laden Sie die aktuelle Version von Bot Framework Emulator herunter, und installieren Sie sie.Download and install the latest Bot Framework Emulator

  1. Führen Sie das Beispiel lokal auf Ihrem Computer aus.Run the sample locally on your machine. Eine Anleitung finden Sie in der Infodatei für das C#-Beispiel bzw. das JS-Beispiel.If you need instructions, refer to the README file for C# Sample or JS Sample.
  2. Verwenden Sie den Emulator, um den Bot wie unten dargestellt zu testen.Use the Emulator to test the bot as shown below.

Testen des Beispiels „state bot“

Zusätzliche RessourcenAdditional resources

Datenschutz: Wenn Sie persönliche Daten von Benutzern speichern möchten, müssen Sie sicherstellen, dass die Anforderungen der Datenschutz-Grundverordnung erfüllt sind.Privacy: If you intend to store user's personal data, you should ensure compliance with General Data Protection Regulation.

Zustandsverwaltung: Alle Aufrufe der Zustandsverwaltung sind asynchron, und standardmäßig gilt der Konfliktauflösungsmodus „Letzter Schreiber gewinnt“.State management: All of the state management calls are asynchronous, and last-writer-wins by default. In der Praxis sollten Sie das Abrufen, Festlegen und Speichern des Zustands in Ihrem Bot möglichst nah beieinander anordnen.In practice, you should get, set, and save state as close together in your bot as possible.

Kritische Geschäftsdaten: Verwenden Sie den Botzustand zum Speichern von Einstellungen, des Benutzernamens oder der letzten Bestellung, aber nicht zum Speichern von kritischen Geschäftsdaten.Critical business data: Use bot state to store preferences, user name, or the last thing they ordered, but do not use it to store critical business data. Erstellen Sie für kritische Daten eigene Speicherkomponenten, oder schreiben Sie direkt in den Speicher.For critical data, create your own storage components or write directly to storage.

Recognizer-Text: In diesem Beispiel werden die Microsoft/Recognizers-Text-Bibliotheken verwendet, um Benutzereingaben zu analysieren und zu überprüfen.Recognizer-Text: The sample uses the Microsoft/Recognizers-Text libraries to parse and validate user input. Weitere Informationen finden Sie auf der Seite mit der Übersicht.For more information, see the overview page.

Nächste SchritteNext steps

Nachdem Sie nun wissen, wie Sie den Zustand konfigurieren, um Bot-Daten im Speicher zu lesen und zu schreiben, können Sie sich über Folgendes informieren: Stellen einer Reihe von Fragen an Benutzer, Überprüfen der Antworten und Speichern der Eingaben.Now that you know how to configure state to help you read and write bot data to storage, let's learn how ask the user a series of questions, validate their answers, and save their input.