Gerenciar a complexidade da caixa de diálogo

aplica-se a: SDK v4

Com os diálogos de componente, é possível criar diálogos independentes para lidar com cenários específicos, como dividir um conjunto de diálogos grande em partes mais gerenciáveis. Cada uma dessas partes tem seu próprio conjunto de diálogos e evita qualquer conflito de nome com o conjunto de diálogos que as contém. As caixas de diálogo de componente são reutilizáveis, pois podem ser:

  • Adicionadas a outro ComponentDialog ou DialogSet em seu bot.
  • Exportadas como parte de um pacote.
  • Usadas em outros bots.

Pré-requisitos

Sobre o exemplo

No exemplo de prompt de vários turnos, usamos um diálogo em cascata, alguns prompts e um diálogo de componente para criar uma interação simples que faz uma série de perguntas ao usuário. O código usa um diálogo para percorrer estas etapas:

Etapas Tipo de prompt
Perguntar ao usuário qual é seu modo de transporte Prompt de escolha
Perguntar o nome do usuário Prompt de texto
Perguntar se o usuário deseja fornecer a idade Prompt de confirmação
Se a resposta for Sim, perguntar a idade dele Prompt de número com validação para aceitar somente idades entre 0 e 150.
Perguntar se as informações coletadas estão “OK” Reutilizar prompt de confirmação

Finalmente, se ele responder sim, exibir as informações coletadas; caso contrário, dizer ao usuário que as informações dele não serão mantidas.

Implementar o diálogo de componente

No exemplo de prompt de vários turnos, usamos um diálogo em cascata, alguns prompts e um diálogo de componente para criar uma interação simples que faz uma série de perguntas ao usuário.

Um diálogo de componente encapsula um ou mais diálogos. O diálogo de componente tem um conjunto de diálogos interno e os diálogos e prompts que você adiciona a esse conjunto têm IDs próprias, visíveis somente no diálogo de componente.

Para usar as caixas de diálogo, instale o pacote do NuGet, Microsoft.Bot.Builder.Dialogs.

Dialogs\UserProfileDialog.cs

Aqui, a classe UserProfileDialog é derivada da classe ComponentDialog.

public class UserProfileDialog : ComponentDialog

No construtor, o método AddDialog adiciona diálogos e prompts ao diálogo de componente. O primeiro item que você adicionar com esse método será definido como o diálogo inicial, mas é possível alterar isso definindo explicitamente a propriedade InitialDialogId. Ao iniciar um diálogo de componente, ele iniciará seu diálogo inicial.

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

Esta é a implementação da primeira etapa do diálogo em cascata.

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

Para obter mais informações sobre como implementar diálogos em cascata, confira como implementar fluxo da conversa sequencial.

Em tempo de execução, o diálogo de componente mantém sua própria pilha de diálogo. Quando o diálogo de componente é iniciado:

  • Uma instância é criada e adicionada à pilha de diálogo externa.
  • Ele cria uma pilha de diálogo interna que adiciona ao próprio estado.
  • Ele começa seu diálogo inicial e adiciona-o à pilha de diálogo interna.

Do contexto pai, ele terá a aparência do componente que for o diálogo ativo. De dentro do componente, ele terá a aparência do diálogo inicial que for o diálogo ativo.

Implemente o restante do diálogo e adicione-o ao bot.

No conjunto de diálogo externo, aquele ao qual você adiciona o diálogo de componente, o diálogo de componente tem a ID que você criou com ele. No conjunto externo, o componente tem a aparência de um único diálogo, muito semelhante aos prompts.

Para usar um diálogo de componente, adicione uma instância dele ao conjunto de diálogo do bot, que é o conjunto de diálogo externo.

Bots\DialogBot.cs

No exemplo, isso é feito usando o método RunAsync chamado do método OnMessageActivityAsync do bot.

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

Para testar o bot

  1. Se ainda não tiver feito isso, instale o Bot Framework Emulator.
  2. Execute o exemplo localmente em seu computador.
  3. Inicie o Emulador, conecte-se ao seu bot e envie mensagens conforme mostrado abaixo.

Execução de exemplo do diálogo de prompt de vários turnos

Informações adicionais

Como funciona o cancelamento nos diálogos de componente

Se você chamar cancel all dialogs pelo contexto do diálogo de componente, esse diálogo cancelará todos os diálogo de sua pilha interna e, em seguida, encerrará, devolvendo o controle ao próximo diálogo na pilha externa.

Se você chamar cancel all dialogs pelo contexto externo, o componente será cancelado, bem como os demais diálogos no contexto externo.

Lembre-se disso ao gerenciar diálogos de componente aninhado em seu bot.

Próximas etapas

Saiba como criar conversas complexas que se ramificam e entram em loop.