首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >防止bot自动启动主对话框

防止bot自动启动主对话框
EN

Stack Overflow用户
提问于 2019-09-24 08:27:39
回答 1查看 207关注 0票数 0

我希望我的机器人处理路易斯和QnAMaker的发言,由用户时,没有活动的对话。

最后,我得到了这段代码及其工作原理,唯一的问题是,它只工作了一圈。当用户第二次键入任何内容时,bot再次启动主对话框。

结束这里是取消所有对话框。谁创造你的答案来自QnAMaker。

如何防止机器人自动启动主对话框?

代码语言:javascript
运行
复制
  public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        await base.OnTurnAsync(turnContext, cancellationToken);

        var recognizerResult = turnContext.TurnState.Get<RecognizerResult>("recognizerResult");
        var topIntent = turnContext.TurnState.Get<string>("topDispatchIntent");
        var dc = await Dialogs.CreateContextAsync(turnContext, cancellationToken);

        var dialogResult = await dc.ContinueDialogAsync();

        if (!dc.Context.Responded)
        {
            switch (dialogResult.Status)
            {
                //dispatch to luis or qna when there is no active dialog
                case DialogTurnStatus.Empty:
                    await DispatchToLUISorQnAMakerAsync(turnContext, topIntent, recognizerResult, cancellationToken);
                    break;

                case DialogTurnStatus.Waiting:
                    break;

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

                default:
                    await dc.CancelAllDialogsAsync();
                    break;
            }
        }


        // Save any state changes that might have occured during the turn.
        await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
    }

    private async Task DispatchToTopIntentAsync(ITurnContext turnContext, string intent, RecognizerResult recognizerResult, CancellationToken cancellationToken)
    {
        switch (intent)
        {
            case "none":
                await turnContext.SendActivityAsync("Sorry i did not get that.");
                break;

            case "q_SabikoKB":
                await DispatchToQnAMakerAsync(turnContext, cancellationToken);
                break;

            case "l_SabikoV2":
                await DispatchToLuisModelAsync(turnContext, recognizerResult.Properties["luisResult"] as LuisResult, cancellationToken);
                break;
        }
    }

    private async Task DispatchToQnAMakerAsync(ITurnContext turnContext, CancellationToken cancellationToken)
    {
        if (!string.IsNullOrEmpty(turnContext.Activity.Text))
        {
            var results = await BotServices.QnaService.GetAnswersAsync(turnContext);
            if (results.Any())
            {
                await turnContext.SendActivityAsync(MessageFactory.Text(results.First().Answer), cancellationToken);
            }
            else
            {
                await turnContext.SendActivityAsync(MessageFactory.Text("Sorry, could not find an answer in the Q and A system."), cancellationToken);
            }
        }
    }

    private async Task DispatchToLuisModelAsync(ITurnContext turnContext, LuisResult luisResult, CancellationToken cancellationToken)
    {
        var result = luisResult.ConnectedServiceResult;
        var topIntent = result.TopScoringIntent.Intent; 

        switch (topIntent)
        {
            case "Greeting":
                //..

            default:
                break;
        }
    }

主对话框

代码语言:javascript
运行
复制
    namespace BotV2.DialogsV2.Main_Menu
{
    public class MainDialog : InterruptDialog
    {
        private const string InitialId = nameof(MainDialog);
        private readonly IStatePropertyAccessor<BasicUserState> _userProfileAccessor;

        public MainDialog(UserState userState, ConversationState conversationState, IConfiguration config)
            : base(nameof(MainDialog),userState)
        {
            _userProfileAccessor = userState.CreateProperty<BasicUserState>("UserProfile");

            InitialDialogId = InitialId;
            WaterfallStep[] waterfallSteps = new WaterfallStep[]
             {
                CheckWelcomeMessageStepAsync,
                FirstStepAsync,
                SecondStepAsync,
             };
            AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
            //AddDialogs..
        }

        private async Task<DialogTurnResult> CheckWelcomeMessageStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var userstate = await _userProfileAccessor.GetAsync(stepContext.Context, () => new BasicUserState(), cancellationToken);

            if (!userstate.DialogCheckers.SentWelcomeMessage)
            {
                return await stepContext.BeginDialogAsync(nameof(WelcomeMessageDialog));
            }

            return await stepContext.NextAsync(cancellationToken: cancellationToken);
        }

        private async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var userstate = await _userProfileAccessor.GetAsync(stepContext.Context, () => new BasicUserState(), cancellationToken);

            //only suggestions, interruption will trigger the dialog to begin them.
            return await stepContext.PromptAsync(
                nameof(TextPrompt),
                new PromptOptions
                {
                    Prompt = new Activity
                    {
                        Type = ActivityTypes.Message,
                        Text = $"So {userstate.FirstName}, What can i do for you?",
                        SuggestedActions = new SuggestedActions()
                        {
                            Actions = new List<CardAction>()
                            {
                                    new CardAction() { Title = "Financial Literacy", Type = ActionTypes.ImBack, Value = "Financial Literacy" },
                                    new CardAction() { Title = "My Compass", Type = ActionTypes.ImBack, Value = "My Compass" },
                            },
                        },
                    },
                });             
        }

        private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            return await stepContext.EndDialogAsync();
        }
    }
}

启动

代码语言:javascript
运行
复制
     services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();

  services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

    services.AddSingleton<IBotServices, BotServices>();

    services.AddSingleton<ConcurrentDictionary<string, ConversationReference>>();

    services.AddTransient<MainDialog>();

    services.AddTransient<WelcomeMessageDialog>();

    services.AddTransient<IBot, DialogBot<MainDialog>>();
EN

Stack Overflow用户

回答已采纳

发布于 2019-10-02 16:26:02

MainDialog自动重新启动是因为在DialogBot.cs -> OnMessageActivityAsync()中,您有:

代码语言:javascript
运行
复制
await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);

这将对来自用户的每一条消息调用MainDialog。

您可以很好地检查用户是否已经完成了MainDialog的一部分:

代码语言:javascript
运行
复制
if (!userstate.DialogCheckers.SentWelcomeMessage)
[...]
if (!userstate.DialogCheckers.AskedDiagnosticQuestion)

但是对话本身仍然会在每一条消息上被调用。

我想你把CancelAllDialogs()误解为他们从不开火。相反,它只是清除您的对话框堆栈,但仍然可以再次调用它们。

您有几种不同的“修复”选项:

MembersAdded.

  1. 您可以有某种userState标志,比如,hasCancelledDialogs,当用户调用意图时设置该标志,该意图旨在取消所有对话框,在MainDialog中检查,如果找到,则在第一步检查EndDialog()
  2. DialogBot.cs中删除Dialog.RunAsync调用,而是根据调度意图和/或
  3. 路由到适当的对话框。

我还注意到,您使用了多种方法来路由对话框。你两个都有:

代码语言:javascript
运行
复制
var dc = await Dialogs.CreateContextAsync(turnContext, cancellationToken);

var dialogResult = await dc.ContinueDialogAsync();

if (!dc.Context.Responded)

[...]

代码语言:javascript
运行
复制
await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);

RunAsync takes care of most of that first code block for you

这也可能会引起一些问题。最有可能的是,您开始使用第一个代码块开发您的机器人,然后我们转向了第二种风格,您尝试集成它,而没有完全了解幕后发生了什么。

您的机器人开始变得非常复杂,并且将变得非常难以解决这类问题。我建议将所有内容转换为Dialog.RunAsync样式,并删除旧样式。重构是一项很大的工作,但它将节省大量的调试和故障排除时间。

尽管如此,我只确定我理解你的问题。同样,你的机器人非常复杂,有很多循环和分支,所以我不完全确定这个答案能解决你的问题。如果没有,请提供一个非常详细的描述,您希望发生什么。

票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58076077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档