2016-11-14 47 views
1

我正在尝试构建一个bot。 起初,我使用的是Node.js但它是因为很明显c#对我的客户端更好,所以我已经开始在c#中创建Bot。我也创建了一个LUIS应用程序。Microsoft Bot框架,LUIS和瀑布

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

举个例子,比方说,我希望用户选择一个对象,然后根据该对象上问3个问题,如:

  1. 难道少吗?
  2. 它是轻?
  3. 你喜欢什么颜色?

并在最后说“你想要一个黑色的,小的,轻的相机。”我似乎无法得到这个工作。我知道你们中的一些人会说使用FormFlow,但问题是动态的,对象也是如此,这就是我使用LUIS的原因。

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

回答

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)在对话框中提问问题

在对话框中,使用PromptDialog问问题1.对问题1的答案使用开关,将d确定要问什么问题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

+0

这就是我需要的 – r3plica

+0

这不是工作:(向前永不会向MessageReceivedAsync – r3plica

+1

这是工作,似乎有是3.2.1中的一个bug – r3plica

1

这是另一种方法,如果你想手动处理这个,你可以设置不同的context.Wait方法为你的每个问题,有一种瀑布方法。

因此,假设您有一个带有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

我给你一个+1,因为这将有助于太 – r3plica

相关问题