Ответ на диалоговое окно с подсказкой, не переходящее к следующему шагу водопада - PullRequest
0 голосов
/ 12 октября 2019

Когда я запускаю приложение в первый раз, я выполняю некоторые шаги инициализации, такие как запрос имени и режима связи (в чате или разговоре), я использовал BeginDialogAsync, чтобы запустить соответствующее диалоговое окно с приглашением. Но после ответа на приглашение он возвращается к созданному мною MainDialog.cs, чтобы проверить ввод пользователя с помощью LUIS, вместо того, чтобы перейти к следующему шагу водопада.

CODE

OptionsDialog.cs

    private void InitializeWaterfallDialog()
    {
        var waterfallSteps = new WaterfallStep[]
        {
            InitialStepAsync,
            FinalStepAsync
        };

        AddDialog(new WaterfallDialog($"{nameof(OptionsDialog)}.mainFlow", waterfallSteps));
        AddDialog(new ChoicePrompt($"{nameof(OptionsDialog)}.communicationMode"));

        InitialDialogId = $"{nameof(OptionsDialog)}.mainFlow";
    }

    private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        return await stepContext.PromptAsync($"{nameof(OptionsDialog)}.communicationMode",
            new PromptOptions
            {
                Prompt = MessageFactory.Text("Please select how you want to continue interacting with me."),
                Choices = ChoiceFactory.ToChoices(new List<string> { "Chat", "Speak" }),
            }, cancellationToken);
    }

    private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        var attachments = new List<Attachment>();
        var reply = MessageFactory.Attachment(attachments);
        switch (((FoundChoice)stepContext.Result).Value)
        {
            case "Chat":
                reply.Text = "Type something to start";
                break;
            case "Speak":
                reply.Text = "This option is yet to be configured. Continuing with chat option. Type something to start";
                break;
        }
        await stepContext.Context.SendActivityAsync(reply, cancellationToken);
        return await stepContext.EndDialogAsync(null, cancellationToken);
    }
}

MainDialog.cs

    private void InitializeWaterfallDialog()
    {
        var waterfallSteps = new WaterfallStep[]
        {
            InitialStepAsync,
            FinalStepAsync
        };

        AddDialog(new OptionsDialog($"{nameof(MainDialog)}.options", _botStateService));
        AddDialog(new GreetingDialog($"{nameof(MainDialog)}.greeting", _botStateService));
        AddDialog(new RevenueDialog($"{nameof(MainDialog)}.revenue", _botStateService, _botServices, _financialServices, _currencyService));
        AddDialog(new QuarterlyRevenueDialog($"{nameof(MainDialog)}.quarterlyRevenue", _botStateService, _botServices, _financialServices, _currencyService));
        AddDialog(new ProfitDialog($"{nameof(MainDialog)}.profit", _botStateService, _botServices, _financialServices, _currencyService));
        AddDialog(new QuarterlyProfitDialog($"{nameof(MainDialog)}.quarterlyProfit", _botStateService, _botServices, _financialServices, _currencyService));
        AddDialog(new StockPriceDialog($"{nameof(MainDialog)}.stockPrice", _botStateService, _botServices, _financialServices, _currencyService));
        AddDialog(new PersonNameDialog($"{nameof(MainDialog)}.personName", _botStateService, _botServices));
        AddDialog(new FarewellDialog($"{nameof(MainDialog)}.farewell", _botStateService, _botServices));
        AddDialog(new WaterfallDialog($"{nameof(MainDialog)}.mainFlow", waterfallSteps));

        InitialDialogId = $"{nameof(MainDialog)}.mainFlow";
    }

    private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        try
        {
            UserProfile userProfile = await _botStateService.UserProfileAccessor.GetAsync(stepContext.Context, () => new UserProfile());
            var recognizerResult = await _botServices.Dispatch.RecognizeAsync(stepContext.Context, cancellationToken);
            // Top intent tell us which cognitive service to use.
            var topIntent = recognizerResult?.GetTopScoringIntent();
            if(userProfile.HasRestartedConversation)
            {
                userProfile.HasRestartedConversation = false;
                return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.options", null, cancellationToken);
            }
            else
            {
                switch (topIntent?.intent)
                {
                    case "GreetingIntent":
                        return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.greeting", null, cancellationToken);
                    case "FindRevenueIntent":
                        return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.revenue", null, cancellationToken);
                    case "FindQuarterlyRevenueIntent":
                        return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.quarterlyRevenue", null, cancellationToken);
                    case "FindProfitIntent":
                        return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.profit", null, cancellationToken);
                    case "FindQuarterlyProfitIntent":
                        return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.quarterlyProfit", null, cancellationToken);
                    case "FindStockPriceIntent":
                        return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.stockPrice", null, cancellationToken);
                    case "FindPersonNameIntent":
                        return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.personName", null, cancellationToken);
                    case "FarewellIntent":
                        return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.farewell", null, cancellationToken);
                    case "CommunicationSelectIntent":
                        return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.options", null, cancellationToken);
                    case null:
                        break;
                    default:
                        await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Sorry, I don’t have an answer for that. " +
                            $"(Please try something like 'What is revenue of google?')"), cancellationToken);
                        break;
                }
            }
            await _botStateService.UserProfileAccessor.SetAsync(stepContext.Context, userProfile);
        }
        catch (Exception e)
        {
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Sorry, there was an error sending your message. Please try again."), cancellationToken);
        }
        return await stepContext.NextAsync(null, cancellationToken);
    }

После ответа на приглашение в InitialStepAsync в OptionsDialog он должен перейти к следующему шагу водопада, FinalStepAsync, но он перейдет к MainDialog ипроверка ответа с помощью LUIS.

Код триггера активности в основной программе бота 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 occured during the turn.
        await _botStateService.UserState.SaveChangesAsync(turnContext, false, cancellationToken);
        await _botStateService.ConversationState.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.Run(turnContext, _botStateService.DialogStateAccessor, cancellationToken);
    }

Метод запуска:

    public static async Task Run(this Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor<DialogState> accessor, CancellationToken cancellationToken = default(CancellationToken))
    {
        var dialogSet = new DialogSet(accessor);
        dialogSet.Add(dialog);

        var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);
        var results = await dialogContext.ContinueDialogAsync(cancellationToken);
        if (results.Status == DialogTurnStatus.Empty)
        {
            await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
        }
    }

Проблема здесьзаключается в том, что после ответа на приглашение он собирается использовать BeginDialogAsync вместо ContinueDialogAsync, что происходит только при первом запуске бота. Если я вызову OptionsDialog в любое время, шаги водопада выполняются правильно.

...