【问题标题】:LUIS / Bot Framework multiple dialog, move intent handling to another dialogLUIS / Bot Framework 多个对话框,将意图处理移动到另一个对话框
【发布时间】:2017-11-19 12:08:38
【问题描述】:

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

似乎我没有正确绑定对话框。我该如何解决这个问题?

编辑:添加 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;
    }
}

【问题讨论】:

    标签: c# botframework azure-language-understanding


    【解决方案1】:

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

    这是我发现的:

    • BeginDialogAsyncoptions 参数采用一组对象,然后可以在您的对话框中访问这些对象。
    // 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;
                }
        }
    }
    

    从我们的第二个对话框中,我们可以通过上下文访问对象并根据需要执行任何转换等。在我的例子中,它是一个瀑布对话框,所以我使用了stepContext.options

    【讨论】:

      【解决方案2】:

      尝试从context.Forward 调用中删除Chain.From(()。不知道为什么要添加它,但它根本不应该存在。

      尝试:

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

      顺便说一句,如果您转发的消息命中None 意图,则ProductsDialogCompleted 方法将被命中,因为您正在执行context.Done,这基本上结束了ProductsDialog

      另外,请记住StartAsync 方法存在于LuisDialog&lt;T&gt; 基类中,因此您需要添加override 关键字。

      【讨论】:

      • 它不工作。我希望 ProductsDialog 成为活动对话框,以便它可以像 RootDialog 在程序启动时所做的那样捕获传入的消息,因此它应该在返回 RootDialog 之前接受另一条触发无的消息,我不明白如何启用此行为.
      • 在 None 方法中将 context.Done 替换为 context.Wait 。 context.Done 结束产品对话框。
      • 是的,当你告诉我时我这样做了,但它无论如何都不起作用,我试图在 context.Wait 之前也放置一个 context.PostAsync ,但它没有返回消息。
      • 请显示 MessageController。这些只是对话框。你用的是什么版本的机器人生成器?
      • 此外,StartAsync 方法是 LuisDialog 基类的一部分。您应该在其上添加 override 关键字。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-08
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 2019-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多