Udostępnij za pośrednictwem


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

DOTYCZY: SDK wersja 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 się rozgałęziają i zapętlają oraz jak przekazywać argumenty między różnymi częściami dialogu.

Uwaga

Zestawy SDK w języku JavaScript, C# i Python platformy Bot Framework będą nadal obsługiwane, jednak zestaw SDK w języku Java jest wycofywany, a jego ostateczne długoterminowe wsparcie zakończy 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 zaleca się użycie Microsoft Copilot Studio oraz zapoznanie się z poradnikiem dotyczącym wyboru 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 dialogów składowych do zarządzania przepływem konwersacji. Każde okno dialogowe składnika zawiera dialog kaskadowy oraz wszelkie komunikaty 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 botów przykładowych, wita użytkownika, używa dialogów do przetwarzania wiadomości od użytkownika oraz zapisuje stan użytkownika i konwersacji przed zakończeniem kolejki.

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, podziękuj użytkownikowi za uczestnictwo i przekaż 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, przepływ konwersacji rozgałęzia się 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 procesu.
    • 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 recenzji może się ponownie uruchomić i wykorzystuje to, aby umożliwić użytkownikowi wybór 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.
    • Dodano done opcję, aby umożliwić użytkownikowi wczesne wyjście z pętli.
  2. Powtórz ten dialog lub zakończ, w zależności od potrzeby.
    • 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 ponownie uruchom dialog, inicjując go zawartością ich 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 dialogowego rozszerza obsługiwacz aktywności i zawiera logikę uruchamiania dialogów. Klasa bota dialogowego i powitalnego rozszerza klasę bota dialogowego, aby powitać użytkownika, gdy dołączają do rozmowy.

Zarządzanie kolejnością dialogu bota powtarza przepływ konwersacji zdefiniowany przez trzy dialogi. 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 trwania, co będzie kontynuowało aktywny dialog.
  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: przechowywanie, stan użytkownika i stan konwersacji.
  • Główne okno dialogowe, 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

Pamięć jest wykorzystywana tylko do celów testowych i nie jest przeznaczona do użytku produkcyjnego. Pamiętaj, aby użyć trwałego typu przechowywania dla bota używanego w produkcji.

Przetestuj bota

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

  2. Uruchom próbkę lokalnie na swoim komputerze.

  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 dialogowym.

Dodatkowe zasoby

Aby zapoznać się z wprowadzeniem do implementacji okna dialogowego, zobacz wprowadzenie do implementacji sekwencyjnego przepływu konwersacji, który używa pojedynczego dialogu kaskadowego i kilku monitów, aby zadać użytkownikowi serię 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 dialogu i wykorzystać go w wielu botach, możesz zdefiniować części dialogu jako oddzielną klasę. Aby uzyskać więcej informacji, zobacz ponowne wykorzystanie okien dialogowych.

Następne kroki