Botframework v4: строка «Нет» в verifyPrompt распознается как отмененная в luis.ai - PullRequest
0 голосов
/ 22 февраля 2019

Здравствуйте, когда я запрашиваю пользователя с запросом подтверждения или запросом да или нет.Луис обнаруживает «нет» как намерение отменить, которое отменяет весь мой диалог.А затем я удалил «нет» из намерения отмены, но теперь «Луис не обнаружил, что намерение приветствия было принято« нет ». Нет даже слова« нет »из намерения приветствия. По мере возможности я не хочу отключать Луиспотому что пользователь может отменить в любое время. Как я могу это исправить? спасибо!

Вот код.

       public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken)
    {
        var dc = await _dialogs.CreateContextAsync(turnContext, cancellationToken);
        var activity = turnContext.Activity;

        var userstate = await _basicAccessors.BasicUserStateAccessor.GetAsync(turnContext, () => new BasicUserState(), cancellationToken);
        var state = await _basicAccessors.BasicStateAccessor.GetAsync(turnContext, () => new BasicState(), cancellationToken);

        if (turnContext.Activity.Type == ActivityTypes.Message)
        {
            turnContext.TurnState.Add("BasicAccessors", _basicAccessors);
            string text = string.IsNullOrEmpty(turnContext.Activity.Text) ? string.Empty : turnContext.Activity.Text.ToLower();

            var luisResults = await _services.LuisServices[LuisConfiguration].RecognizeAsync(dc.Context, cancellationToken);

            var topScoringIntent = luisResults?.GetTopScoringIntent();
            var topIntent = topScoringIntent.Value.intent;

            string userName = string.Empty;
            if (activity.From.Name != null)
            {
                userName = activity.From.Name;
            }
            userstate.Name = userName;

            await _basicAccessors.BasicUserStateAccessor.SetAsync(turnContext, userstate);
            await _basicAccessors.BasicStateAccessor.SetAsync(turnContext, state);

            var interrupted = await IsTurnInterruptedAsync(dc, topIntent);
            if (interrupted)
            {
                // Bypass the dialog.
                // Save state before the next turn.
                await _basicAccessors.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
                await _basicAccessors.UserState.SaveChangesAsync(turnContext, false, cancellationToken);
                return;
            }

            // Continue the current dialog
            var dialogResult = await dc.ContinueDialogAsync();

            // if no one has responded,
            if (!dc.Context.Responded)
            {
                // examine results from active dialog
                switch (dialogResult.Status)
                {
                    case DialogTurnStatus.Empty:
                        switch (topIntent)
                        {
                            case GreetingIntent:
                                await dc.BeginDialogAsync(MainDialogId);
                                break;

                            case "loan calculator":
                            case "loan calc":
                                await dc.BeginDialogAsync(MainDialogId);
                                break;

                            case NoneIntent:
                            default:

                                await dc.Context.SendActivityAsync("I didn't understand what you just said to me.");
                                break;
                        }

                        break;

                    case DialogTurnStatus.Waiting:
                        // The active dialog is waiting for a response from the user, so do nothing.
                        break;

                    case DialogTurnStatus.Complete:
                        await dc.EndDialogAsync();
                        break;

                    default:
                        await dc.CancelAllDialogsAsync();
                        break;
                }
            }
        }
        else if (activity.Type == ActivityTypes.ConversationUpdate)
        {
            if (activity.MembersAdded != null)
            {
                // Iterate over all new members added to the conversation.
                foreach (var member in activity.MembersAdded)
                {
                    // Greet anyone that was not the target (recipient) of this message.
                    // To learn more about Adaptive Cards, see https://aka.ms/msbot-adaptivecards for more details.
                    if (member.Id != activity.Recipient.Id)
                    {
                        await SendWelcomeMessageAsync(turnContext, cancellationToken);
                    }
                }
            }
        }

        await _basicAccessors.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        await _basicAccessors.UserState.SaveChangesAsync(turnContext, false, cancellationToken);
    }

 private async Task<bool> IsTurnInterruptedAsync(DialogContext dc, string topIntent)
    {
        // See if there are any conversation interrupts we need to handle.
        if (topIntent.Equals(CancelIntent))
        {
            if (dc.ActiveDialog != null)
            {
                await dc.CancelAllDialogsAsync();
                await dc.Context.SendActivityAsync("Ok. I've canceled our last activity.");
            }
            else
            {
                await dc.Context.SendActivityAsync("I don't have anything to cancel.");
            }

            return true;        // Handled the interrupt.
        }

        if (topIntent.Equals(HelpIntent))
        {
            await dc.Context.SendActivityAsync("Let me try to provide some help.");
            await dc.Context.SendActivityAsync("I understand greetings, being asked for help, or being asked to cancel what I am doing.");
            if (dc.ActiveDialog != null)
            {
                await dc.RepromptDialogAsync();
            }

            return true;        // Handled the interrupt.
        }

1 Ответ

0 голосов
/ 23 февраля 2019

Это похоже на дилемму дизайна.Я рекомендую изменить приоритеты вашего бота так, чтобы LUIS вызывался only , если ваш диалог не был должным образом отреагирован.Это может быть достигнуто путем перемещения IsTurnInterruptedAsync из OnTurnAsync в метод проверки.Метод validator может быть передан в качестве аргумента в конструктор вашей подсказки:

_dialogs.Add(new ConfirmPrompt(CONFIRMPROMPT, ValidateAsync));

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

var topScoringIntent = luisResults?.GetTopScoringIntent();
var topIntent = topScoringIntent.Value.intent;

// Include this:
turnContext.TurnState.Add("topIntent", topIntent);

Ваш метод ValidateAsync может выглядеть следующим образом:

private async Task<bool> ValidateAsync(PromptValidatorContext<bool> promptContext, CancellationToken cancellationToken)
{
    if (promptContext.Recognized.Succeeded)
    {
        return true;
    }

    await IsTurnInterruptedAsync(promptContext.Context);

    return false;
}

Поскольку IsTurnInterruptedAsync теперь может быть в другом классе, он будетнеобходимо получить доступ к верхнему намерению через ваше состояние хода.Если _dialogs находится вне области видимости, вы можете добавить это к состоянию своего хода или просто сделать его публичным / статическим свойством.

private async Task<bool> IsTurnInterruptedAsync(ITurnContext turnContext)
{
    var dc = await _dialogs.CreateContextAsync(turnContext);
    var topIntent = turnContext.TurnState.Get<string>("topIntent");

    // See if there are any conversation interrupts we need to handle.
    if (topIntent.Equals(CancelIntent))
    {
        // . . .

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

Возможно, вы захотите разрешить прерывания, даже если высказывание допустимо для диалога.Конечно, для текстового приглашения все допустимо, но вы все равно не можете позволить пользователю вводить «Что мне делать?»как их зовут.Если вы хотите сначала отправить высказывание в LUIS для определенных типов диалогов и сначала отправить высказывание в диалоговое окно для других типов диалогов, вы можете проверить тип диалога, находящегося в верхней части стека, следующим образом:

var activeDialog = _dialogs.Find(dc.ActiveDialog.Id);
if (activeDialog is ConfirmPrompt || activeDialog is ChoicePrompt)
...