Мой диалог не ждет ответа пользователя в Bot Framework v4 - PullRequest
0 голосов
/ 29 января 2020

У меня есть 2 класса:

  1. RootDialog
  2. QualificationDialog

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

В этом случае я собираюсь обратиться к методу " IntentQualify", в рамках этого метода я вызываю следующий диалог" QualificationDialog", который содержит SuggestionAction кнопки, встроенные в WaterfallDialog , WaterfallSteps содержит 2 метода, которые должны выполняться последовательно:

Первый (ToShowButton): Показывает кнопки.

Второй (ValidateOption): Захватывает выбор пользователя на основе кнопок.

Проблема в том, что в момент показа кнопок он не генерирует ожидание, он не go для метода 2 ( ValidateOption ) это гаснет и разговор заканчивается.

Кто-нибудь, кто прошел через это дело, кто может мне помочь?

ПЕРВЫЙ ДИАЛОГ

public class RootDialog : ComponentDialog
{
        public RootDialog(ILuisService luisService)
        {
            _luisService = luisService;
            AddDialog(new TextPrompt(nameof(TextPrompt)));
        }
        public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default)
        {
            var luisResult = await _luisService._recognizer.RecognizeAsync(dc.Context, cancellationToken);
            await ManageIntentions(dc, luisResult, cancellationToken);
            return await dc.EndDialogAsync(cancellationToken: cancellationToken);
        }
        private async Task ManageIntentions(DialogContext dc, RecognizerResult luisResult, CancellationToken cancellationToken)
        {
            var topIntent = luisResult.GetTopScoringIntent();
            switch (topIntent.intent)
            {                
                case "Qualify":
                    await IntentQualify(dc, luisResult, cancellationToken);
                    break;
                case "None":
                    await IntentNone(dc, luisResult, cancellationToken);
                    break;
                default:
                    break;
            }
        }
        private async Task IntentQualify(DialogContext dc, RecognizerResult luisResult, CancellationToken cancellationToken)
        {
            // Here I call the second dialog (ss) that contains the buttons and 
            // should generate the wait but does not.
            dc.Dialogs.Add(new QualificationDialog());
            await dc.BeginDialogAsync(nameof(QualificationDialog), null, cancellationToken);
        }


}

ВТОРОЙ ДИАЛОГ

public class QualificationDialog: ComponentDialog
    {
        public QualificationDialog()
        {
            var waterfallSteps = new WaterfallStep[]
            {
                ToShowButton,
                ValidateOption
            };
            AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
            AddDialog(new TextPrompt(nameof(TextPrompt)));
        }
        public static async Task<DialogTurnResult> ToShowButton(DialogContext stepContext, CancellationToken cancellationToken)
        {
            return await stepContext.PromptAsync(
                  nameof(TextPrompt),
                  new PromptOptions
                  {
                      Prompt = CreateButtonsQualification()
                  },
                  cancellationToken
            );
        }
        private async Task<DialogTurnResult> ValidateOption(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var options = stepContext.Context.Activity.Text;
            return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
        }
        public static Activity CreateButtonsQualification()
        {
            var reply = MessageFactory.Text("MY TEXT");

            reply.SuggestedActions = new SuggestedActions()
            {
                Actions = new List<CardAction>()
                {
                    new CardAction(){Title = "OPTION 1", Value = "OPTION 1", Type = ActionTypes.ImBack},
                    new CardAction(){Title = "OPTION 2", Value = "OPTION 2", Type = ActionTypes.ImBack},
                    new CardAction(){Title = "OPTION 3", Value = "OPTION 3", Type = ActionTypes.ImBack}
                }
            };
            return reply as Activity;
        }

Класс, реализующий IBot

public class MyBot<T> : ActivityHandler where T: Dialog
    {
        BotState _conversationState;
        BotState _userState;
        Dialog _dialog;

        public MyBot(ConversationState conversationState, UserState userState, T dialog)
        {
            _conversationState = conversationState;
            _userState = userState;
            _dialog = dialog;
        }

        protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            foreach (var member in membersAdded)
            {
                if (member.Id != turnContext.Activity.Recipient.Id)
                {
                    await turnContext.SendActivityAsync(MessageFactory.Text($"Hello world!"), cancellationToken);
                }
            }
        }

        public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
        {
            await base.OnTurnAsync(turnContext, cancellationToken);
            await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
            await _userState.SaveChangesAsync(turnContext, false, cancellationToken);

        }
        protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            await _dialog.RunAsync(
              turnContext,
              _conversationState.CreateProperty<DialogState>(nameof(DialogState)),
              cancellationToken
            );
        }

    }

1 Ответ

1 голос
/ 30 января 2020

В вашем RootDialog вы вызываете EndDialogAsyn c, как только вы начинаете QualificationDialog в методе BeginDialogAsyn c. Поскольку вы заканчиваете родительский диалог, все дочерние диалоги родителя в стеке удаляются. Вы можете переписать метод, как показано ниже, и проверить, работает ли он, и попробовать завершить диалог root изящно в каком-то другом намерении

public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default) { var luisResult = await _luisService._recognizer.RecognizeAsync(dc.Context, cancellationToken); return await ManageIntentions(dc, luisResult, cancellationToken); }.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...