【问题标题】:Microsoft Bot Framework, LUIS and waterfallingMicrosoft Bot 框架、LUIS 和瀑布流
【发布时间】:2016-11-16 08:45:20
【问题描述】:

我正在尝试构建一个机器人。 起初我使用的是 Node.js,但显然 c# 更适合我的客户,所以我开始使用 c# 创建 Bot。我还创建了一个 LUIS 应用程序。

现在,这个 Bot 背后的想法是,它会在最后结合您的结果并根据您的答案挑选解决方案之前询问您一系列问题。我遇到的问题是我不知道如何设置机器人来做到这一点。在节点中,它谈到了瀑布,但我在 c# 版本中看不到类似的东西。 另外,我不确定是否应该在 LUIS 中集中注意力。

例如,假设我希望用户选择一个对象,然后根据该对象提出 3 个问题,例如:

  1. 很小吗?
  2. 轻吗?
  3. 你喜欢什么颜色?

最后说“你想要一台黑色、小巧、轻便的相机。”我似乎无法让它发挥作用。我知道你们中的一些人会说使用 FormFlow,但问题是动态的,对象也是动态的,这就是我使用 LUIS 的原因。

有谁知道我在哪里可以找到一篇关于如何使用 LUIS 创建类似流程的好文章?

【问题讨论】:

    标签: c# botframework azure-language-understanding


    【解决方案1】:

    如果 FormFlow 过于严格,您应该考虑使用对话框。它们允许更开放的对话。

    我会做以下事情:

    1) 要求用户选择一个类别。

    如果可能,请使用按钮为用户提供可供选择的类别列表。这意味着您不必向 LUIS 询问用户选择的类别。

    否则,允许用户键入类别并将其传递给 LUIS。来自 LUIS 的响应将包含一个实体。实体将持有类别的名称。

    2) 转发到该类别的对话框

    根据从 LUIS 返回的实体,转发到负责询问下一个问题的相应对话框

    [LuisIntent("AskQuestionAboutCategory")]
        public async Task AskQuestion(IDialogContext context, LuisResult result)
        {
           //get Entity from LUIS response
            string category = result.Entities.FirstOrDefault(e => e.Type == "Category")?.Entity;
    
            switch (category)
            {
                case "Category 1":
    
                    //forward to Dialog for Category1
    
                    await
                        context.Forward(new Category1Dialog(), ResumeAfter,
                            new Activity {Text = result.Query}, CancellationToken.None);
                    break;
    
                case "Category 2":
    
                    //forward to Dialog for Category2
    
                    await
                        context.Forward(new Category2Dialog(), ResumeAfter,
                            new Activity {Text = result.Query}, CancellationToken.None);
                    break;
    
            }
        }
    
        private async Task ResumeAfter(IDialogContext context, IAwaitable<object> result)
        {
            context.Wait(MessageReceived);
        }
    

    3) 对话框内

    在 Dialog 中,使用 PromptDialog 来询问问题 1。使用问题 1 的答案上的开关来确定询问问题 2 的内容。 像这样继续对话。

    [Serializable]
    public class Category1Dialog : IDialog<object>
    {
        public async Task StartAsync(IDialogContext context)
        {
            context.Wait(MessageReceivedAsync);
        }
    
        public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
        {
    
            var prompt = "what is the answer to question 1 ?";
    
            //ASK QUESTION 1
            PromptDialog.Text(context, ResumeAfterQuestion1, prompt);
        }
    
        private async Task ResumeAfterQuestion1(IDialogContext context, IAwaitable<string> result)
        {
            var input = await result;
    
            switch (input)
            {
                //ASK QUESTION 2, DEPENDING ON WHAT WAS ANSWERED FOR QUESTION 1
                case "Answer A":
                    PromptDialog.Text(context, ResumeAfterQuestion2, "what is the answer to question 2 ?");
                    break;
                case "Answer B":
                    PromptDialog.Text(context, ResumeAfterQuestion2, "what is the answer to question 2 ?");
                    break;
            }
        }
    
    
        private async Task ResumeAfterQuestion2(IDialogContext context, IAwaitable<string> result)
        {
            var input = await result;
    
            switch (input)
            {
                //ASK QUESTION 3
                case "Answer C":
                    PromptDialog.Text(context, ResumeAfterQuestion3, "what is the answer to next question after Answer C ?");
            break;
                case "Answer D":
                    PromptDialog.Text(context, ResumeAfterQuestion3, "what is the answer to next question after Answer D ?");
            break;
        }
        }
    

    您似乎需要使用 switch 语句来确定接下来要问什么问题。

    click here for more info on Dialogs

    【讨论】:

    • 这是我需要的
    • 这不起作用:(转发永远不会到达 MessageReceivedAsync
    • 如何允许用户键入类别并将其传递给 LUIS?是否可以显示完整的代码示例?
    【解决方案2】:

    这是另一种选择,如果您想手动处理此问题,您可以设置不同的上下文。为您的每个问题设置等待方法,采用瀑布方法。

    假设您有一个带有 ChooseCategory 意图的 LuisDialog。在该方法中,您将确定类别并基于一些自定义逻辑,您将提出一个新问题。

    这可以通过以下方式完成:PromptDialog/ResumeAfter 或手动 context.PostAsync/context.Wait(它基本上定义了将侦听下一条消息的方法)。

    我不知道您的自定义逻辑如何,但您应该能够动态决定哪个是下一个侦听即将到来的消息的方法。

    [LuisIntent("Choose category")]
    public async Task ChooseCategory(IDialogContext context, LuisResult result)
    {
        // get category logic..
    
        await context.PostAsync("This is my first question?");
        context.Wait(CaptureFirstQuestionAnswerAsync);
    }
    
    public async Task CaptureFirstQuestionAnswerAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
    {
        IMessageActivity message = await argument;
        switch (message.Text.ToLower())
        {
            case "answer 1":
                // do something
                break;
            case "answer 2":
               // do something different
                break;
            default:
               // do something ...
                break;
        }
    
        await context.PostAsync($"This is my second question?");
    
        context.Wait(CaptureSecondQuestionAnswerAsync);
    }
    
    public async Task CaptureSecondQuestionAnswerAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
    {
      //...
    }
    

    【讨论】:

    • 我给了你一个+1,因为这也会有帮助
    猜你喜欢
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    相关资源
    最近更新 更多