2016-11-14 45 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

相關問題