微软Bot框架,路易斯和瀑布
本文关键字:路易斯 Bot 框架 微软 | 更新日期: 2023-09-27 18:18:03
我正在尝试建立一个机器人。起初我使用的是Node.js,但显然c#对我的客户端更好,所以我已经开始在c#中创建Bot。我还创建了一个LUIS应用程序。
现在,这个机器人背后的想法是,它会问你一系列问题,然后结合你的结果,最后根据你的答案选择一个解决方案。我的问题是,我不知道如何设置机器人来做到这一点。在node中,它谈到了瀑布,但我在c#版本中看不到任何类似的东西。此外,我不确定是否应该在路易斯,我应该集中我的注意力。
作为一个例子,假设我想让用户选择一个对象,然后根据该对象问3个问题,如:
- 它小吗?
- 它轻吗?
- 你喜欢什么颜色?
最后说:"你想要一个黑色,小,轻的相机。"我好像没法让它工作。我知道你们中的一些人会说使用FormFlow,但问题是动态的,对象也是动态的,这就是我使用LUIS的原因。
有人知道我在哪里可以找到一篇关于如何使用LUIS创建类似的流的好文章吗?
如果FormFlow限制太大,你应该考虑使用对话框。它们允许更开放的对话。
我会这样做:
1)要求用户选择一个类别。
如果可能的话,使用按钮为用户提供一个可供选择的类别列表。这意味着您不必向LUIS询问用户选择的类别。
否则,允许用户键入一个类别并将其传递给LUIS。来自LUIS的响应将包含一个Entity。实体将保存类别的名称。
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题的答案上使用一个开关,来决定第二题的问题。像这样继续对话。
[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语句来决定接下来要问什么问题。
点击这里查看对话框
这里有另一种选择,如果你想手动处理这个,你可以设置不同的上下文。你的每个问题都有等待方法,有点像瀑布方法。
假设你有一个带有choocategory意图的LuisDialog。在这种方法中,您将确定类别,并根据一些自定义逻辑提出新问题。
这可以通过:PromptDialog/ResumeAfter或手动上下文来完成。PostAsync/上下文。等待(它基本上定义了侦听下一条消息的方法)。
我不知道你的自定义逻辑是如何的,但是你应该能够动态地决定哪个是下一个方法,将侦听即将到来的消息
[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 "answerswer 1":
// do something
break;
case "answerswer 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)
{
//...
}