当用户键入“退出”,“退出”等时,终止所有对话框并退出MS Bot Framework中的对话

时间:2016-08-24 02:16:08

标签: c# bots botframework

我无法弄清楚如何在MS Bot Framework中做一个非常简单的事情:允许用户突破任何对话,离开当前对话框并通过键入“quit”返回主菜单,“退出“或”重新开始“。

以下是我的主要对话设置方式:

    public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        try
        {
            if (activity.Type == ActivityTypes.Message)
            {
                UserActivityLogger.LogUserBehaviour(activity);

                if (activity.Text.ToLower() == "start over")
                {
                    //Do something here, but I don't have the IDialogContext here!
                }
                BotUtils.SendTyping(activity); //send "typing" indicator upon each message received
                await Conversation.SendAsync(activity, () => new RootDialog());
            }
            else
            {
                HandleSystemMessage(activity);
            }
        }

我知道如何使用context.Done<DialogType>(this);终止对话框,但在此方法中,我无法访问IDialogContext对象,因此无法调用.Done()

当用户键入某个消息时,除了在所有对话框的每个步骤中添加一个检查之外,还有其他方法可以终止整个对话框堆栈吗?

发布赏金:

我需要一种终止所有IDialog的方法,而不使用我在此处发布的令人发指的黑客攻击(删除我需要的所有用户数据,例如用户设置和首选项)。

基本上,当用户键入“退出”或“退出”时,我需要退出当前正在进行的任何IDialog并返回到新状态,就好像用户刚刚发起了对话一样。

我需要能够从MessageController.cs,执行此操作,我仍然无法访问IDialogContext。我似乎唯一有用的数据是Activity对象。如果有人指出其他方法,我会很高兴。

另一种方法是找到一些其他方法来检查机器人的其他位置的“退出”和“退出”关键字,而不是在Post方法中。

但它不应该是在IDialog的每一步都完成的检查,因为代码太多甚至不可能(使用PromptDialog时,我无法访问用户键入的文本)。

我没有探索的两种可能方式:

  • 不是终止所有当前IDialog,而是开始新的对话 与用户(新ConversationId
  • 获取IDialogStack对象并使用它来管理对话框堆栈。

Microsoft文档对此对象保持沉默,因此我不知道如何获取它。我没有在机器人的任何地方使用允许Chain的{​​{1}}对象,但如果您认为可以重写它以使用它,它也可以是解决此问题的方法之一。但是,我还没有找到如何在各种类型的对话框(.Switch()和普通的FormFlow)之间进行分支,这些对话框又调用了自己的子对话框等。

4 个答案:

答案 0 :(得分:25)

问题突破

根据我对您的问题的理解,您想要实现的是重置对话框而不会完全破坏僵尸状态

FACTS(从我从github存储库中读取的内容)

  1. 框架如何保存对话框堆栈如下:
  2.   

    BotDataStore&gt; BotData&gt; DialogStack

    1. BotFramework使用AutoFac作为DI容器
    2. DialogModule 是用于对话框组件的Autofac模块
    3. 怎么做

      从上面知道 FACTS ,我的解决方案将是

      1. 注册依赖项 ,以便我们可以在我们的控制器中使用:
      2. // in Global.asax.cs
        var builder = new ContainerBuilder();
        builder.RegisterModule(new DialogModule());
        builder.RegisterModule(new ReflectionSurrogateModule());
        builder.RegisterModule(new DialogModule_MakeRoot());
        
        var config = GlobalConfiguration.Configuration;
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
        builder.RegisterWebApiFilterProvider(config);
        var container = builder.Build();
        config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        
        1. 获取 Autofac容器 (随意在您的代码中放置任何您感到满意的地方)
        2. private static ILifetimeScope Container
          {
              get
              {
                  var config = GlobalConfiguration.Configuration;
                  var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;
                  return resolver.Container;
              }
          }
          
          1. 范围
          2. 中加载 BotData
          3. 加载 DialogStack
          4. 重置 DialogStack
          5. 将新 BotData 推回 BotDataStore
          6. using (var scope = DialogModule.BeginLifetimeScope(Container, activity))
            {
                var botData = scope.Resolve<IBotData>();
                await botData.LoadAsync(default(CancellationToken));
                var stack = scope.Resolve<IDialogStack>();
                stack.Reset();
                await botData.FlushAsync(default(CancellationToken));
            }
            

            希望它有所帮助。

            更新1(2016年8月27日)

            感谢@ejadib指出,容器已在会话类中公开。

            我们可以删除上面答案中的第2步,最后代码会是

            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
            {
                var botData = scope.Resolve<IBotData>();
                await botData.LoadAsync(default(CancellationToken));
                var stack = scope.Resolve<IDialogStack>();
                stack.Reset();
                await botData.FlushAsync(default(CancellationToken));
            }
            

答案 1 :(得分:8)

这是一个非常难看的黑客行为。它基本上删除了所有用户数据(您可能实际需要),这会导致会话重新启动。

如果有人知道更好的方式,而不删除用户数据,请分享。

    public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        try
        {
            if (activity.Type == ActivityTypes.Message)
            {
                //if the user types certain messages, quit all dialogs and start over
                string msg = activity.Text.ToLower().Trim();
                if (msg == "start over" || msg == "exit" || msg == "quit" || msg == "done" || msg =="start again" || msg == "restart" || msg == "leave" || msg == "reset")
                {
                    //This is where the conversation gets reset!
                    activity.GetStateClient().BotState.DeleteStateForUser(activity.ChannelId, activity.From.Id);
                }

                //and even if we reset everything, show the welcome message again
                BotUtils.SendTyping(activity); //send "typing" indicator upon each message received
                await Conversation.SendAsync(activity, () => new RootDialog());
            }
            else
            {
                HandleSystemMessage(activity);
            }
        }

答案 2 :(得分:2)

我知道这有点旧,但我遇到了同样的问题,而且发布的解决方案不再是最好的方法了。

我不确定自哪个版本可用,但是在3.8.1上你可以注册可以在对话框的任何地方触发的IScorable服务。

有一个示例代码显示它是如何工作的,它有一个“取消”全局命令处理程序:

https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-GlobalMessageHandlers

代码的一部分如下所示:

protected override async Task PostAsync(IActivity item, string state, CancellationToken token)
{
    this.task.Reset();
}

答案 3 :(得分:0)

适用于其他人的其他代码:

private async Task _reset(Activity activity)
    {
        await activity.GetStateClient().BotState
            .DeleteStateForUserWithHttpMessagesAsync(activity.ChannelId, activity.From.Id);

        var client = new ConnectorClient(new Uri(activity.ServiceUrl));
        var clearMsg = activity.CreateReply();
        clearMsg.Text = $"Reseting everything for conversation: {activity.Conversation.Id}";
        await client.Conversations.SendToConversationAsync(clearMsg);
    }

此代码由用户mmulhearn在此发布:https://github.com/Microsoft/BotBuilder/issues/101#issuecomment-316170517