LUIS / Bot Framework多个对话框,将意图处理移动到另一个对话框

时间:2017-06-16 16:25:57

标签: c# botframework luis

我的目标是使用他们的C#SDK将对话框和LUIS实现到Microsoft Bot Framework应用程序中。 我尝试关注此帖子 https://github.com/Microsoft/BotBuilder/issues/127及其相关帖子(最后引用),但无法让我的代码在实践中运行。这是我的RootDialog类。请注意,我创建了一个处理“GetProduct”意图的方法,当它获得此意图时,它应该使用context.Forward()方法将LuisResult转发到ProductsDialog,但我所看到的只是它直接转到ResumeAfter方法,ProductsDialogCompleted。现在,这可能是我失败的地方,但我找不到显示多个LUIS对话框的示例。

public class RootDialog : LuisDialog<object>
{
    [LuisIntent("GetProduct")]
    private async Task GetProduct(IDialogContext context, LuisResult result)
    {
        await context.PostAsync("Calling ProductsDialog...");
        await context.Forward(Chain.From(() => new ProductsDialog()), ProductsDialogCompleted, context.Activity, CancellationToken.None);
    }

    private async Task ProductsDialogCompleted(IDialogContext context, IAwaitable<object> result)
    {
        var res = await result;
        context.PostAsync("ProductsDialogCompleted" + result);
        context.Wait(this.MessageReceived);
    }
}
public class ProductsDialog : LuisDialog<object>
{
    public async Task StartAsync(IDialogContext context)
    {
        await context.PostAsync("Entered ProductsDialog");

        context.Wait(this.MessageReceived);
    }
    [LuisIntent("None")]
    private async Task None(IDialogContext context, LuisResult result)
    {
        context.Done(true);
    }
}

预期的行为如下

  1. 用户触发GetProduct意图
  2. 机器人创建一个新对话框并转到StartAsync方法,等待另一个用户输入
  3. 用户触发无意图
  4. 对话框关闭,返回true并触发ProductsDialogCompleted。
  5. 好像我没有正确绑定对话框。我该如何解决这个问题?

    编辑:添加MessageController,版本为3.8.1

    [BotAuthentication]
    public class MessagesController : ApiController
    {
        /// <summary>
        /// POST: api/Messages
        /// Receive a message from a user and reply to it
        /// </summary>
        public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
        {
            if (activity.Type == ActivityTypes.Message)
            {
                await Conversation.SendAsync(activity, () => new RootDialog());
            }
            else
            {
                HandleSystemMessage(activity);
            }
            var response = Request.CreateResponse(HttpStatusCode.OK);
            return response;
        }
    
        private Activity HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }
    
            return null;
        }
    }
    

2 个答案:

答案 0 :(得分:3)

尝试从Chain.From(()电话中删除context.Forward。不确定为什么要添加它,但它根本不应该存在。

尝试:

await context.Forward(new ProductsDialog(), ProductsDialogCompleted, context.Activity, CancellationToken.None);

顺便说一下,如果您转发的邮件符合None意图,ProductsDialogCompleted方法会被点击,因为您正在执行context.Done,这基本上会结束ProductsDialog。< / p>

另外,请注意StartAsync基类中存在LuisDialog<T>方法,因此您需要添加override关键字。

答案 1 :(得分:0)

我有同样的问题,但是我使用的是Bot Framework的较新版本,更具体地说是V4。

这是我发现的:

  • BeginDialogAsync的{​​{1}}参数采用对象数组,然后可以在对话框中访问这些对象。
options

在第二个对话框中,我们可以通过上下文访问对象并根据需要执行任何强制转换等。就我而言,这是一个瀑布对话框,因此我使用了// Get skill LUIS model from configuration. localizedServices.LuisServices.TryGetValue("MySkill", out var luisService); if (luisService != null) { // Get the Luis result. var result = innerDc.Context.TurnState.Get<MySkillLuis>(StateProperties.SkillLuisResult); var intent = result?.TopIntent().intent; // Behavior switched on intent. switch (intent) { case MySkillLuis.Intent.MyIntent: { // result is passed on to my dialog through the Options parameter. await innerDc.BeginDialogAsync(_myDialog.Id, result); break; } case MySkillLuis.Intent.None: default: { // intent was identified but not yet implemented await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("UnsupportedMessage")); break; } } }