Erstellen eines erweiterten Konversationsflusses mithilfe von Verzweigungen und Schleifen

GILT FÜR: SDK v4

Mit der Dialogbibliothek können Sie komplexe Konversationsflüsse erstellen. In diesem Artikel erfahren Sie, wie Sie komplexe Konversationen mit Verzweigungen und Schleifen verwalten und wie Sie Argumente zwischen verschiedenen Teilen des Dialogs übergeben.

Hinweis

Die Bot Framework-JavaScript-, C#- und Python-SDKs werden weiterhin unterstützt, das Java SDK wird jedoch eingestellt und der langfristige Support endet im November 2023. Es werden nur kritische Sicherheits- und Programmfehlerbehebungen innerhalb dieses Repositorys durchgeführt.

Bestehende Bots, die mit dem Java SDK erstellt wurden, werden weiterhin funktionieren.

Wenn Sie einen neuen Bot erstellen möchten, sollten Sie den Einsatz von Power Virtual Agents in Betracht ziehen und sich über die Auswahl der richtigen Chatbot-Lösung informieren.

Weitere Informationen finden Sie unter Die Zukunft des Bot-Buildings.

Voraussetzungen

Informationen zu diesem Beispiel

In diesem Beispiel wird ein Bot zum Registrieren von Benutzern verwendet, bei dem bis zu zwei Unternehmen bewertet werden können, die in einer Liste enthalten sind. Der Bot verwendet drei Komponentendialoge, um den Konversationsfluss zu verwalten. Die Komponentendialoge enthalten jeweils einen Wasserfalldialog sowie sämtliche Aufforderungen, die zur Erfassung von Benutzereingaben erforderlich sind. Diese Dialoge werden in den folgenden Abschnitten ausführlicher beschrieben. Die Dialoge werden mithilfe des Konversationszustands verwaltet, und der Benutzerzustand wird verwendet, um Informationen zum Benutzer sowie zu den Unternehmen zu speichern, die er bewerten möchte.

Der Bot wird vom Aktivitätshandler abgeleitet. Wie viele andere Beispielbots begrüßt er den Benutzer, verwendet Dialoge, um Nachrichten des Benutzers zu verarbeiten, und speichert vor dem Ende des Turns den Benutzer- und den Konversationszustand.

Installieren Sie das NuGet-Paket Microsoft.Bot.Builder.Dialogs, um Dialoge verwenden zu können.

Class diagram for C# sample.

Definieren des Benutzerprofils

Das Benutzerprofil enthält Informationen, die im Rahmen der Dialoge erfasst werden, sowie Name und Alter des Benutzers und die zur Bewertung ausgewählten Unternehmen.

UserProfile.cs

/// <summary>Contains information about a user.</summary>
public class UserProfile
{
    public string Name { get; set; }

    public int Age { get; set; }

    // The list of companies the user wants to review.
    public List<string> CompaniesToReview { get; set; } = new List<string>();

Erstellen der Dialoge

Dieser Bot enthält drei Dialoge:

  • Der Hauptdialog startet den gesamten Prozess und fasst die gesammelten Informationen zusammen.
  • Der Dialog der obersten Ebene dient zur Erfassung der Benutzerinformationen und enthält eine Verzweigungslogik, die auf dem Alter des Benutzers basiert.
  • Im Dialog für die Bewertungsauswahl kann der Benutzer nach und nach Unternehmen auswählen, die er bewerten möchte. Hierfür wird eine Schleifenlogik verwendet.

Der Hauptdialog

Der Hauptdialog umfasst zwei Schritte:

  1. Starten des Dialogs der obersten Ebene
  2. Abrufen und Zusammenfassen des Benutzerprofils, das im Rahmen des Dialogs der obersten Ebene erfasst wurde, Speichern dieser Informationen im Benutzerzustand und Signalisieren des Endes des Hauptdialogs

Dialogs\MainDialog.cs

private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    return await stepContext.BeginDialogAsync(nameof(TopLevelDialog), null, cancellationToken);
}

private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var userInfo = (UserProfile)stepContext.Result;

    string status = "You are signed up to review "
        + (userInfo.CompaniesToReview.Count is 0 ? "no companies" : string.Join(" and ", userInfo.CompaniesToReview))
        + ".";

    await stepContext.Context.SendActivityAsync(status);

    var accessor = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
    await accessor.SetAsync(stepContext.Context, userInfo, cancellationToken);

    return await stepContext.EndDialogAsync(null, cancellationToken);
}

Dialog der obersten Ebene

Der Dialog der obersten Ebene umfasst vier Schritte:

  1. Fragen nach dem Namen des Benutzers
  2. Fragen nach dem Alter des Benutzers
  3. Entweder Starten des Dialogs für die Bewertungsauswahl oder Fortfahren mit dem nächsten Schritt (abhängig vom Alter des Benutzers)
  4. Abschließendes Bedanken beim Benutzer für die Teilnahme und Zurückgeben der erfassten Informationen

Im ersten Schritt wird ein leeres Benutzerprofil als Teil des Dialogzustands erstellt. Der Dialog beginnt mit einem leeren Profil und fügt nach und nach Informationen hinzu. Am Ende des Dialogs werden im letzten Schritt die erfassten Informationen zurückgegeben.

Im dritten Schritt (Beginn der Auswahl) verzweigt sich der Konversationsfluss abhängig vom Alter des Benutzers.

Dialogs\TopLevelDialog.cs

            stepContext.Values[UserInfo] = new UserProfile();

            var promptOptions = new PromptOptions { Prompt = MessageFactory.Text("Please enter your name.") };

            // Ask the user to enter their name.
            return await stepContext.PromptAsync(nameof(TextPrompt), promptOptions, cancellationToken);
        }

        private async Task<DialogTurnResult> AgeStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // Set the user's name to what they entered in response to the name prompt.
            var userProfile = (UserProfile)stepContext.Values[UserInfo];
            userProfile.Name = (string)stepContext.Result;

            var promptOptions = new PromptOptions { Prompt = MessageFactory.Text("Please enter your age.") };

            // Ask the user to enter their age.
            return await stepContext.PromptAsync(nameof(NumberPrompt<int>), promptOptions, cancellationToken);
        }

        private async Task<DialogTurnResult> StartSelectionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // Set the user's age to what they entered in response to the age prompt.
            var userProfile = (UserProfile)stepContext.Values[UserInfo];
            userProfile.Age = (int)stepContext.Result;

            if (userProfile.Age < 25)
            {
                // If they are too young, skip the review selection dialog, and pass an empty list to the next step.
                await stepContext.Context.SendActivityAsync(
                    MessageFactory.Text("You must be 25 or older to participate."),
                    cancellationToken);
                return await stepContext.NextAsync(new List<string>(), cancellationToken);
            }
            else
            {
                // Otherwise, start the review selection dialog.
                return await stepContext.BeginDialogAsync(nameof(ReviewSelectionDialog), null, cancellationToken);
            }
        }

        private async Task<DialogTurnResult> AcknowledgementStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // Set the user's company selection to what they entered in the review-selection dialog.
            var userProfile = (UserProfile)stepContext.Values[UserInfo];
            userProfile.CompaniesToReview = stepContext.Result as List<string> ?? new List<string>();

            // Thank them for participating.
            await stepContext.Context.SendActivityAsync(
                MessageFactory.Text($"Thanks for participating, {((UserProfile)stepContext.Values[UserInfo]).Name}."),
                cancellationToken);

            // Exit the dialog, returning the collected user information.
            return await stepContext.EndDialogAsync(stepContext.Values[UserInfo], cancellationToken);
        }
    }
}

Dialog zum Überprüfen der Auswahl

Der Dialog zum Überprüfen der Auswahl umfasst zwei Schritte:

  1. Auffordern des Benutzers, entweder ein zu bewertendes Unternehmen oder done (zum Beenden des Vorgangs) auszuwählen
    • Falls zu Beginn des Dialogs bereits Informationen vorliegen, stehen diese über die Eigenschaft options des Wasserfallschrittkontexts zur Verfügung. Der Dialog für die Bewertungsauswahl kann sich selbst neu starten, was es dem Benutzer ermöglicht, mehrere zu bewertende Unternehmen auszuwählen.
    • Bereits ausgewählte Unternehmen werden aus den verfügbaren Auswahlmöglichkeiten entfernt.
    • Die Option done wird hinzugefügt, damit der Benutzer die Schleife vorzeitig beenden kann.
  2. Wiederholen dieses Dialogs je nach Bedarf oder Beenden des Vorgangs
    • Wenn der Benutzer ein zu bewertendes Unternehmen ausgewählt hat, soll es der Liste des Benutzers hinzugefügt werden.
    • Wenn der Benutzer zwei Unternehmen oder die Option zum Beenden ausgewählt hat, soll der Dialog beendet und die erfasste Liste zurückgegeben werden.
    • Andernfalls soll der Dialog neu gestartet und mit dem Inhalt der Liste initialisiert werden.

Dialogs\ReviewSelectionDialog.cs

private async Task<DialogTurnResult> SelectionStepAsync(
    WaterfallStepContext stepContext,
    CancellationToken cancellationToken)
{
    // Continue using the same selection list, if any, from the previous iteration of this dialog.
    var list = stepContext.Options as List<string> ?? new List<string>();
    stepContext.Values[CompaniesSelected] = list;

    // Create a prompt message.
    string message;
    if (list.Count is 0)
    {
        message = $"Please choose a company to review, or `{DoneOption}` to finish.";
    }
    else
    {
        message = $"You have selected **{list[0]}**. You can review an additional company, " +
            $"or choose `{DoneOption}` to finish.";
    }

    // Create the list of options to choose from.
    var options = _companyOptions.ToList();
    options.Add(DoneOption);
    if (list.Count > 0)
    {
        options.Remove(list[0]);
    }

    var promptOptions = new PromptOptions
    {
        Prompt = MessageFactory.Text(message),
        RetryPrompt = MessageFactory.Text("Please choose an option from the list."),
        Choices = ChoiceFactory.ToChoices(options),
    };

    // Prompt the user for a choice.
    return await stepContext.PromptAsync(nameof(ChoicePrompt), promptOptions, cancellationToken);
}

private async Task<DialogTurnResult> LoopStepAsync(
    WaterfallStepContext stepContext,
    CancellationToken cancellationToken)
{
    // Retrieve their selection list, the choice they made, and whether they chose to finish.
    var list = stepContext.Values[CompaniesSelected] as List<string>;
    var choice = (FoundChoice)stepContext.Result;
    var done = choice.Value == DoneOption;

    if (!done)
    {
        // If they chose a company, add it to the list.
        list.Add(choice.Value);
    }

    if (done || list.Count >= 2)
    {
        // If they're done, exit and return their list.
        return await stepContext.EndDialogAsync(list, cancellationToken);
    }
    else
    {
        // Otherwise, repeat this dialog, passing in the list from this iteration.
        return await stepContext.ReplaceDialogAsync(nameof(ReviewSelectionDialog), list, cancellationToken);
    }
}

Ausführen der Dialoge

Die Klasse dialog bot erweitert den Aktivitätshandler und enthält die Logik zum Ausführen der Dialoge. Die Klasse dialog and welcome bot erweitert den Dialogbot, sodass dieser den Benutzer zu Beginn der Konversation begrüßt.

Der Turn-Handler des Bots wiederholt den durch die drei Dialoge definierten Konversationsfluss. Wenn eine Nachricht des Benutzers empfangen wird, geschieht Folgendes:

  1. Der Hauptdialog wird ausgeführt.
    • Ist der Dialogstapel leer, wird der Hauptdialog gestartet.
    • Andernfalls sind die Dialogprozesse noch nicht abgeschlossen, und der aktive Dialog wird fortgesetzt.
  2. Der Zustand wird gespeichert, damit alle Aktualisierungen des Benutzer-, Konversations- und Dialogzustands erhalten bleiben.

Bots\DialogBot.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);
}

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    Logger.LogInformation("Running dialog with Message Activity.");

    // Run the Dialog with the new message Activity.
    await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}

Registrieren von Diensten für den Bot

Erstellen und registrieren Sie Dienste nach Bedarf:

  • Grundlegende Dienste für den Bot: Adapter und Botimplementierung
  • Dienste für die Zustandsverwaltung: Speicher, Benutzerzustand und Konversationszustand
  • Der vom Bot verwendete Stammdialog

Startup.cs

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient().AddControllers().AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth;
    });

    // Create the Bot Framework Authentication to be used with the Bot Adapter.
    services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

    // Create the Bot Adapter with error handling enabled.
    services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

    // Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.)
    services.AddSingleton<IStorage, MemoryStorage>();

    // Create the User state. (Used in this bot's Dialog implementation.)
    services.AddSingleton<UserState>();

Hinweis

Arbeitsspeicher wird nur für Testzwecke genutzt und ist nicht für die Verwendung in der Produktion vorgesehen. Verwenden Sie für einen Produktionsbot unbedingt einen permanenten Speicher.

Testen des Bots

  1. Installieren Sie Bot Framework Emulator, sofern noch nicht geschehen.

  2. Führen Sie das Beispiel lokal auf Ihrem Computer aus.

  3. Starten Sie den Emulator, stellen Sie eine Verbindung mit Ihrem Bot her, und senden Sie Nachrichten wie unten dargestellt.

    Example transcript from a conversation with the complex dialog bot.

Zusätzliche Ressourcen

Eine Einführung in die Implementierung eines Dialogs finden Sie unter Implementieren eines sequenziellen Konversationsflusses. In diesem Artikel werden ein einzelner Wasserfalldialog und einige Eingabeaufforderungen verwendet, die dem Benutzer mehrere Fragen stellen.

Die Dialogbibliothek enthält eine einfache Validierung für Eingabeaufforderungen. Sie können auch eine benutzerdefinierte Validierung hinzufügen. Weitere Informationen finden Sie unter Erfassen von Benutzereingaben mit einer Dialogaufforderung.

Zum Vereinfachen Ihres Dialogcodes und Wiederverwenden in mehreren Bots können Sie Teile eines Dialogsatzes als separate Klasse definieren. Weitere Informationen finden Sie unter Wiederverwenden von Dialogen.

Nächste Schritte