Udostępnij za pośrednictwem


Tworzenie zaawansowanego przepływu konwersacji przy użyciu gałęzi i pętli

DOTYCZY: ZESTAW SDK w wersji 4

Złożone przepływy konwersacji można tworzyć przy użyciu biblioteki okien dialogowych. W tym artykule opisano sposób zarządzania złożonymi konwersacjami, które gałęzią i pętlą oraz jak przekazywać argumenty między różnymi częściami okna dialogowego.

Uwaga

Zestawy SDK języka JavaScript, C# i Python platformy Bot Framework będą nadal obsługiwane, jednak zestaw SDK języka Java jest wycofywany z ostatecznym długoterminowym wsparciem kończącym się w listopadzie 2023 r.

Istniejące boty utworzone za pomocą zestawu JAVA SDK będą nadal działać.

W przypadku tworzenia nowych botów rozważ użycie programu Microsoft Copilot Studio i przeczytaj o wyborze odpowiedniego rozwiązania copilot.

Aby uzyskać więcej informacji, zobacz Przyszłość tworzenia botów.

Wymagania wstępne

Informacje o tym przykładzie

Ten przykład reprezentuje bota, który może zarejestrować użytkowników w celu przejrzenia maksymalnie dwóch firm z listy. Bot używa trzech okien dialogowych składników do zarządzania przepływem konwersacji. Każde okno dialogowe składnika zawiera okno dialogowe kaskadowe i wszelkie monity potrzebne do zebrania danych wejściowych użytkownika. Te okna dialogowe zostały szczegółowo opisane w poniższych sekcjach. Używa stanu konwersacji do zarządzania oknami dialogowymi i używa stanu użytkownika do zapisywania informacji o użytkowniku i firmach, które chcą przejrzeć.

Bot pochodzi z programu obsługi działań. Podobnie jak wiele przykładowych botów, wita użytkownika, używa okien dialogowych do obsługi komunikatów od użytkownika oraz zapisuje stan użytkownika i konwersacji przed zakończeniem kolei.

Aby użyć okien dialogowych, zainstaluj pakiet NuGet Microsoft.Bot.Builder.Dialogs .

Diagram klas dla przykładu języka C#.

Definiowanie profilu użytkownika

Profil użytkownika będzie zawierać informacje zebrane przez okna dialogowe, nazwę użytkownika, wiek i firmy wybrane do przejrzenia.

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

Tworzenie okien dialogowych

Ten bot zawiera trzy okna dialogowe:

  • Główne okno dialogowe uruchamia ogólny proces, a następnie podsumowuje zebrane informacje.
  • Okno dialogowe najwyższego poziomu zbiera informacje o użytkowniku i zawiera logikę rozgałęziania na podstawie wieku użytkownika.
  • Okno dialogowe wyboru przeglądu umożliwia użytkownikowi iteracyjne wybieranie firm do przejrzenia. Używa logiki pętli, aby to zrobić.

Główne okno dialogowe

Główne okno dialogowe zawiera dwa kroki:

  1. Uruchom okno dialogowe najwyższego poziomu.
  2. Pobierz i podsumuj profil użytkownika zebrany przez okno dialogowe najwyższego poziomu, zapisz te informacje w stanie użytkownika, a następnie zasygnalizuj koniec głównego okna dialogowego.

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

Okno dialogowe najwyższego poziomu

Okno dialogowe najwyższego poziomu ma cztery kroki:

  1. Poproś o nazwę użytkownika.
  2. Poproś o wiek użytkownika.
  3. Uruchom okno dialogowe wyboru przeglądu lub przejdź do następnego kroku w zależności od wieku użytkownika.
  4. Na koniec dziękujemy użytkownikowi za uczestnictwo i zwróć zebrane informacje.

Pierwszy krok powoduje utworzenie pustego profilu użytkownika w ramach stanu okna dialogowego. Okno dialogowe rozpoczyna się od pustego profilu i dodaje informacje do profilu w miarę postępu. Po zakończeniu ostatni krok zwraca zebrane informacje.

W trzecim kroku (rozpocznij wybór) gałęzie przepływu konwersacji na podstawie wieku użytkownika.

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

Okno dialogowe wyboru przeglądu

Okno dialogowe wyboru przeglądu ma dwa kroki:

  1. Poproś użytkownika o wybranie firmy do przejrzenia lub done zakończenia.
    • Jeśli okno dialogowe zostało uruchomione z wszelkimi początkowymi informacjami, informacje są dostępne za pośrednictwem właściwości options kontekstu kroku kaskadowego. Okno dialogowe wyboru przeglądu może ponownie uruchomić się i używa go do umożliwienia użytkownikowi wyboru więcej niż jednej firmy do przejrzenia.
    • Jeśli użytkownik wybrał już firmę do przejrzenia, ta firma zostanie usunięta z dostępnych opcji.
    • Zostanie done dodany wybór, aby umożliwić użytkownikowi wczesne wyjście z pętli.
  2. Powtórz to okno dialogowe lub zamknij odpowiednio.
    • Jeśli użytkownik wybrał firmę do przejrzenia, dodaj ją do swojej listy.
    • Jeśli użytkownik wybrał dwie firmy lub zdecydował się zakończyć działanie, zakończ okno dialogowe i zwróć zebraną listę.
    • W przeciwnym razie uruchom ponownie okno dialogowe, inicjując go przy użyciu zawartości listy.

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

Uruchamianie okien dialogowych

Klasa bota okna dialogowego rozszerza procedurę obsługi działań i zawiera logikę uruchamiania okien dialogowych. Okno dialogowe i klasa bota powitalnego rozszerza bota okna dialogowego, aby również powitać użytkownika podczas dołączania do konwersacji.

Procedura obsługi kolei bota powtarza przepływ konwersacji zdefiniowany przez trzy okna dialogowe. Po odebraniu komunikatu od użytkownika:

  1. Uruchamia główne okno dialogowe.
    • Jeśli stos okna dialogowego jest pusty, spowoduje to uruchomienie głównego okna dialogowego.
    • W przeciwnym razie okna dialogowe są nadal w trakcie procesu, a to będzie kontynuowane aktywne okno dialogowe.
  2. Zapisuje stan, dzięki czemu wszystkie aktualizacje stanu użytkownika, konwersacji i okna dialogowego są utrwalane.

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

Rejestrowanie usług bota

Utwórz i zarejestruj usługi zgodnie z potrzebami:

  • Podstawowe usługi bota: adapter i implementacja bota.
  • Usługi zarządzania stanem: magazyn, stan użytkownika i stan konwersacji.
  • Okno dialogowe katalogu głównego, którego będzie używać bot.

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

Uwaga

Magazyn pamięci jest używany tylko do celów testowych i nie jest przeznaczony do użytku produkcyjnego. Pamiętaj, aby użyć trwałego typu magazynu dla bota produkcyjnego.

Testowanie bota

  1. Jeśli jeszcze tego nie zrobiono, zainstaluj program Bot Framework Emulator.

  2. Uruchom przykład lokalnie na maszynie.

  3. Uruchom emulator, połącz się z botem i wyślij komunikaty, jak pokazano poniżej.

    Przykładowa transkrypcja z konwersacji ze złożonym botem okna dialogowego.

Dodatkowe zasoby

Aby zapoznać się z wprowadzeniem do implementowania okna dialogowego, zobacz implementowanie sekwencyjnego przepływu konwersacji, który używa pojedynczego okna dialogowego kaskadowego i kilka monitów o zadawanie użytkownikowi serii pytań.

Biblioteka dialogów zawiera podstawową walidację monitów. Możesz również dodać walidację niestandardową. Aby uzyskać więcej informacji, zobacz zbieranie danych wejściowych użytkownika przy użyciu wiersza polecenia okna dialogowego.

Aby uprościć kod okna dialogowego i ponownie użyć go wielu botów, możesz zdefiniować fragmenty zestawu okien dialogowych jako oddzielną klasę. Aby uzyskać więcej informacji, zobacz ponowne używanie okien dialogowych.

Następne kroki