Управление сложностью диалогов

ОБЛАСТЬ ПРИМЕНЕНИЯ: ПАКЕТ SDK версии 4

Компонентные диалоги позволяют создавать независимые диалоги для обработки определенных сценариев, разбивая большие наборы диалогов на более управляемые фрагменты. Каждый из этих компонентов имеет отдельный набор диалогов, что позволяет избежать конфликтов имен с внешними наборами диалогов. Компонентные диалоги можно использовать многократно для:

  • добавления в другой ComponentDialog или DialogSet в боте;
  • экспорта как части пакета;
  • использования в других ботах.

Примечание.

Пакеты SDK для JavaScript, C# и Python для Bot Framework по-прежнему будут поддерживаться, однако пакет SDK java отменяется с окончательной долгосрочной поддержкой, заканчивающейся в ноябре 2023 года. В этом репозитории будут выполняться только критически важные исправления безопасности и ошибок.

Существующие боты, созданные с помощью пакета SDK для Java, будут продолжать функционировать.

Для создания нового бота рекомендуется использовать Power Virtual Agent и ознакомиться с выбором подходящего решения чат-бота.

Дополнительные сведения см. в статье "Будущее создания бота".

Необходимые компоненты

Сведения о примере

В примере запроса с несколькими поворотами мы используем каскадное диалоговое окно, несколько запросов и диалоговое окно компонента для создания взаимодействия, которое задает пользователю ряд вопросов. Код диалога циклически перебирает следующие действия:

Шаги Тип запроса
Запрос к пользователю о режиме транспортировки Запрос выбора
Запрос имени пользователя Запрос текста
Запрос к пользователю, готов ли он указать свой возраст Запрос подтверждения
Если они ответили да, попросите их возраст Запрос числа с проверкой, при которой принимается возраст только в диапазоне от 0 до 150.
Спросите, является ли собранная информация "ок" Повторный запрос подтверждения

Наконец, если они ответили да, отобразите собранные сведения; в противном случае сообщите пользователю, что их сведения не будут храниться.

Реализация диалогового окна компонента

В примере запроса с несколькими поворотами мы используем каскадное диалоговое окно, несколько запросов и диалоговое окно компонента для создания взаимодействия, которое задает пользователю ряд вопросов.

Компонентный диалог включает один или несколько диалогов. Компонентный диалог содержит внутренний набор диалогов, в котором все добавляемые к диалоги и запросы имеют собственные идентификаторы, доступные только для компонентного диалога.

Чтобы использовать диалоги, установите пакет NuGet Microsoft.Bot.Builder.Dialogs.

Dialogs\UserProfileDialog.cs

Класс UserProfileDialog является производным от класса ComponentDialog.

public class UserProfileDialog : ComponentDialog

В конструкторе метод AddDialog добавляет диалоги и запросы в компонентный диалог. Первый элемент, добавляемый с помощью этого метода, задается как начальное диалоговое окно. Вы можете изменить начальное диалоговое окно, явно задав InitialDialogId свойство. При запуске компонентного диалога будет запущен начальный диалог.

public UserProfileDialog(UserState userState)
    : base(nameof(UserProfileDialog))
{
    _userProfileAccessor = userState.CreateProperty<UserProfile>("UserProfile");

    // This array defines how the Waterfall will execute.
    var waterfallSteps = new WaterfallStep[]
    {
        TransportStepAsync,
        NameStepAsync,
        NameConfirmStepAsync,
        AgeStepAsync,
        PictureStepAsync,
        ConfirmStepAsync,
        SummaryStepAsync,
    };

    // Add named dialogs to the DialogSet. These names are saved in the dialog state.
    AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
    AddDialog(new TextPrompt(nameof(TextPrompt)));
    AddDialog(new NumberPrompt<int>(nameof(NumberPrompt<int>), AgePromptValidatorAsync));
    AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
    AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
    AddDialog(new AttachmentPrompt(nameof(AttachmentPrompt), PicturePromptValidatorAsync));

    // The initial child Dialog to run.
    InitialDialogId = nameof(WaterfallDialog);
}

Следующий код представляет первый шаг каскадного диалога.

private static async Task<DialogTurnResult> NameStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    stepContext.Values["transport"] = ((FoundChoice)stepContext.Result).Value;

    return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("Please enter your name.") }, cancellationToken);
}

См. подробнее о реализации последовательного потока диалога.

Во время выполнения компонентный диалог поддерживает собственный стек диалогов. При запуске компонентного диалога происходит следующее:

  • Создается экземпляр, который добавляется во внешний стек диалогов.
  • Создается внутренний стек диалогов, который добавляется в свое состояние.
  • Запускается начальный диалог, который добавляется во внутренний стек диалогов.

Родительский контекст отображает компонент как активное диалоговое окно. Однако для контекста внутри компонента он выглядит так, как начальное диалоговое окно является активным диалогом.

Вызов диалогового окна из бота

В внешнем наборе диалоговых окон, в который вы добавили диалоговое окно компонента, в диалоговом окне компонента есть идентификатор, с помощью которого вы создали его. Во внешнем наборе компонентный диалог выглядят как один диалог, похожий на обычные запросы.

Чтобы использовать диалоговое окно компонента, добавьте экземпляр в набор диалоговых окон бота.

Bots\DialogBot.cs

В нашем примере это выполняется с помощью метода RunAsync, вызываемого из метода OnMessageActivityAsync бота.

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

Протестируйте бота

  1. Если это еще не сделано, установите эмулятор Bot Framework.
  2. Выполните этот пример на локальном компьютере.
  3. Запустите эмулятор, подключитесь к боту и отправьте несколько сообщений, как показано ниже.

Sample transcript from the multi-turn prompt dialog.

Дополнительные сведения

Как работает отмена для компонентных диалогов

Если вы вызовете метод отмены всех диалогов из контекста компонентного диалога, этот метод отменит все диалоги во внутреннем стеке и завершит работу, передав управление следующему диалогу во внешнем стеке.

При вызове всех диалоговых окон из внешнего контекста компонент отменяется вместе с остальными диалогами внешнего контекста.

Следующие шаги

Узнайте, как управлять сложными диалогами с ветвлениями и циклами.