Delen via


Geavanceerde gespreksstroom maken met vertakkingen en lussen

VAN TOEPASSING OP: SDK v4

U kunt complexe gespreksstromen maken met behulp van de dialoogvensterbibliotheek. In dit artikel wordt beschreven hoe u complexe gesprekken beheert die vertakking en lus maken en hoe u argumenten doorgeeft tussen verschillende delen van het dialoogvenster.

Notitie

De Sdk's voor Bot Framework JavaScript, C# en Python blijven ondersteund, maar de Java SDK wordt buiten gebruik gesteld met definitieve langetermijnondersteuning die eindigt op november 2023.

Bestaande bots die zijn gebouwd met de Java SDK blijven functioneren.

Voor het bouwen van nieuwe bots kunt u Power Virtual Agents gebruiken en lezen over het kiezen van de juiste chatbotoplossing.

Zie De toekomst van botbouw voor meer informatie.

Vereisten

Over dit voorbeeld

Dit voorbeeld vertegenwoordigt een bot die gebruikers kan registreren om maximaal twee bedrijven uit een lijst te beoordelen. De bot maakt gebruik van drie onderdeeldialoogvensters om de gespreksstroom te beheren. Elk onderdeeldialoogvenster bevat een watervaldialoogvenster en eventuele prompts die nodig zijn om gebruikersinvoer te verzamelen. Deze dialoogvensters worden uitgebreid beschreven in de volgende secties. De gespreksstatus wordt gebruikt om de dialoogvensters te beheren en de gebruikersstatus te gebruiken om informatie over de gebruiker op te slaan en welke bedrijven ze willen controleren.

De bot is afgeleid van de activiteitshandler. Net als veel van de voorbeeldbots verwelkomt het de gebruiker, gebruikt het dialoogvensters om berichten van de gebruiker te verwerken en slaat de gebruikers- en gespreksstatus op voordat de beurt eindigt.

Als u dialoogvensters wilt gebruiken, installeert u het NuGet-pakket Microsoft.Bot.Builder.Dialogs .

Klassediagram voor C#-voorbeeld.

Het gebruikersprofiel definiëren

Het gebruikersprofiel bevat informatie die wordt verzameld door de dialoogvensters, de naam, leeftijd en bedrijven die zijn geselecteerd om te controleren.

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>();

De dialoogvensters maken

Deze bot bevat drie dialoogvensters:

  • Het hoofddialoogvenster start het algehele proces en geeft vervolgens een overzicht van de verzamelde gegevens.
  • Het dialoogvenster op het hoogste niveau verzamelt de gebruikersgegevens en bevat vertakkingslogica, op basis van de leeftijd van de gebruiker.
  • Met het dialoogvenster beoordelingsselectie kan de gebruiker iteratief bedrijven selecteren om te beoordelen. Hiervoor wordt luslogica gebruikt.

Het hoofddialoogvenster

Het hoofddialoogvenster heeft twee stappen:

  1. Het dialoogvenster op het hoogste niveau starten.
  2. Haal het gebruikersprofiel op dat door het dialoogvenster op het hoogste niveau wordt verzameld, sla deze gegevens op in de gebruikersstatus en geef het einde van het hoofddialoogvenster aan.

Dialoogvensters\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);
}

Het dialoogvenster op het hoogste niveau

Het dialoogvenster op het hoogste niveau bestaat uit vier stappen:

  1. Vraag om de naam van de gebruiker.
  2. Vraag om de leeftijd van de gebruiker.
  3. Start het dialoogvenster beoordelingsselectie of ga door naar de volgende stap, op basis van de leeftijd van de gebruiker.
  4. Tot slot bedankt u de gebruiker voor deelname en retourneert u de verzamelde gegevens.

Met de eerste stap maakt u een leeg gebruikersprofiel als onderdeel van de dialoogvensterstatus. Het dialoogvenster begint met een leeg profiel en voegt informatie toe aan het profiel terwijl het vordert. Wanneer deze eindigt, retourneert de laatste stap de verzamelde gegevens.

In de derde stap (selectie starten) vertakt de gespreksstroom, op basis van de leeftijd van de gebruiker.

Dialoogvensters\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);
        }
    }
}

Het dialoogvenster Controleselectie

Het dialoogvenster controleselectie heeft twee stappen:

  1. Vraag de gebruiker om een bedrijf te kiezen dat moet worden beoordeeld of done voltooid.
    • Als het dialoogvenster is gestart met initiële informatie, is de informatie beschikbaar via de eigenschap Opties van de context van de watervalstap. Het dialoogvenster controleselectie kan zichzelf opnieuw starten en dit wordt gebruikt om de gebruiker in staat te stellen meer dan één bedrijf te kiezen om te controleren.
    • Als de gebruiker al een bedrijf heeft geselecteerd dat moet worden beoordeeld, wordt dat bedrijf verwijderd uit de beschikbare opties.
    • Er wordt een done keuze toegevoegd om de gebruiker in staat te stellen de lus vroeg af te sluiten.
  2. Herhaal dit dialoogvenster of sluit dit, indien van toepassing.
    • Als de gebruiker een bedrijf heeft gekozen dat moet worden gecontroleerd, voegt u deze toe aan de lijst.
    • Als de gebruiker twee bedrijven heeft gekozen of heeft gekozen om af te sluiten, beëindigt u het dialoogvenster en retourneert u de verzamelde lijst.
    • Anders start u het dialoogvenster opnieuw en initialiseert u het met de inhoud van de lijst.

Dialoogvensters\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(InitialDialogId, list, cancellationToken);
    }
}

De dialoogvensters uitvoeren

De klasse van de dialoogvensterbot breidt de activiteitshandler uit en bevat de logica voor het uitvoeren van de dialoogvensters. De dialoogvenster- en welkomstbotklasse breidt de dialoogvensterbot uit om ook een gebruiker te verwelkomen wanneer deze deelneemt aan het gesprek.

De draaihandler van de bot herhaalt de gespreksstroom die is gedefinieerd door de drie dialoogvensters. Wanneer er een bericht van de gebruiker wordt ontvangen:

  1. Het hoofddialoogvenster wordt uitgevoerd.
    • Als de dialoogvensterstack leeg is, wordt het hoofddialoogvenster gestart.
    • Anders zijn de dialoogvensters nog steeds halverwege het proces en wordt het actieve dialoogvenster voortgezet.
  2. De status wordt opgeslagen, zodat updates voor de gebruiker, het gesprek en de dialoogvensterstatus behouden blijven.

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);
}

Services registreren voor de bot

Services maken en registreren indien nodig:

  • Basisservices voor de bot: een adapter en de bot-implementatie.
  • Services voor het beheren van de status: opslag, gebruikersstatus en gespreksstatus.
  • Het hoofddialoogvenster dat de bot gaat gebruiken.

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>();

Notitie

Geheugenopslag wordt alleen gebruikt voor testdoeleinden en is niet bedoeld voor productiegebruik. Zorg ervoor dat u een permanent type opslag gebruikt voor een productiebot.

De bot testen

  1. Als u dit nog niet hebt gedaan, installeert u de Bot Framework Emulator.

  2. Voer het voorbeeld lokaal uit op uw computer.

  3. Start de emulator, maak verbinding met uw bot en verzend berichten zoals hieronder wordt weergegeven.

    Voorbeeldtranscriptie van een gesprek met de complexe dialoogvensterbot.

Aanvullende bronnen

Zie Voor een inleiding over het implementeren van een dialoogvenster de sequentiële gespreksstroom, die gebruikmaakt van één watervaldialoogvenster en een paar prompts om de gebruiker een reeks vragen te stellen.

De dialoogvensterbibliotheek bevat basisvalidatie voor prompts. U kunt ook aangepaste validatie toevoegen. Zie Gebruikersinvoer verzamelen met behulp van een dialoogvensterprompt voor meer informatie.

Als u de dialoogvenstercode wilt vereenvoudigen en meerdere bots opnieuw wilt gebruiken, kunt u delen van een dialoogvensterset definiëren als een afzonderlijke klasse. Zie dialoogvensters opnieuw gebruiken voor meer informatie.

Volgende stappen