【问题标题】:How to start a waterfall dialog from ActivityHandler.OnMessageActivityAsync in bot framework v4如何在机器人框架 v4 中从 ActivityHandler.OnMessageActivityAsync 启动瀑布对话框
【发布时间】:2020-01-16 23:48:27
【问题描述】:

我正在尝试编写一个简单的机器人,它会在用户输入内容时启动我的瀑布对话框。用例非常简单,但似乎不起作用,有什么问题?

主机器人是这样设置的,我尝试在 OnMessageActivityAsync 函数中调用我的对话框:

namespace EmptyBot1.Dialogs
{
    public class MainChatbot : ActivityHandler
    {
        private readonly IOptions<Models.Configurations> _mySettings;
        protected readonly IRecognizer _recognizer;
        protected readonly BotState _conversationState;

        public MainChatbot(ConversationState conversationState, IOptions<Models.Configurations> mySettings, ChatbotRecognizer recognizer)
        {
            _mySettings = mySettings ?? throw new ArgumentNullException(nameof(mySettings));
            _recognizer = recognizer;
            _conversationState = conversationState;
        }

        protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            string LuisAppId = _mySettings.Value.LuisAppId;
            string LuisAPIKey = _mySettings.Value.LuisAPIKey;
            string LuisAPIHostName = _mySettings.Value.LuisAPIHostName;
            await turnContext.SendActivityAsync(MessageFactory.Text($"You Said: {turnContext.Activity.Text}"), cancellationToken);


            var luisResult = await _recognizer.RecognizeAsync<Models.ChatbotIntent>(turnContext, cancellationToken);
            Models.ChatbotIntent.Intent TopIntent = luisResult.TopIntent().intent;
            await turnContext.SendActivityAsync(MessageFactory.Text($"Your Intention Is: {TopIntent.ToString()}"), cancellationToken);

            switch (TopIntent)
            {
                case Models.ChatbotIntent.Intent.RunBot:
                    var RunBotOptions = new Models.RunBotOptions();
                    Dialog d = new MyCustomDialog();
                    // Trying to start my dialog here.
                    await d.RunAsync(turnContext, _conversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
                    break;
                default:
                    break;
            }
            return;
        }


    }
}

然后我像这样设置我的对话框,也很简单:

namespace EmptyBot1.Dialogs
{
    public class MyCustomDialog : InteruptsDialog
    {
        public MyCustomDialog()
            : base(nameof(MyCustomDialog))
        {
            AddDialog(new TextPrompt(nameof(TextPrompt)));
            AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
            AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
            {
                AskName,
                AskUseDefault,
                FinalStep
            }));

            // The initial child Dialog to run.
            InitialDialogId = nameof(WaterfallDialog);
        }
     // ...
    }
}

所有东西都注入到startup.cs中

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        // Add functionality to inject IOptions<T>
        services.AddOptions();

        // Add our Config object so it can be injected
        services.Configure<Models.Configurations>(Configuration);

        // Create the Bot Framework Adapter with error handling enabled.
        services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

        // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
        services.AddTransient<IBot, Dialogs.MainChatbot>();

        // Create the Conversation state. (Used by the Dialog system itself.)
        var storage = new MemoryStorage();
        var conversationState = new ConversationState(storage);
        services.AddSingleton(conversationState);



        // Register LUIS recognizer
        services.AddSingleton<ChatbotRecognizer>();

        services.AddSingleton<Dialogs.MyCustomDialog>();
    }

但是当我运行它时出现 500 错误,我做错了什么?

编辑:澄清一下,我的目标是能够直接从ActivityHandler.OnMessageActivityAsync 启动一个硬编码的瀑布对话框。

来自在线的通用解决方案和来自 Microsoft 的示例项目都说将对话框作为类型 T 传递给我的机器人。

但是,我已经确切知道要启动哪个对话框,因此需要将其作为类型传递,我可以直接在机器人内部对其进行硬编码,我该如何启动它?

【问题讨论】:

    标签: c# botframework chatbot azure-language-understanding


    【解决方案1】:

    结果我的代码似乎工作正常,不知道为什么它昨天不工作。我会把它留给未来的人检查答案。您可以完全按照问题中的方式使用它。

    【讨论】:

      【解决方案2】:

      据我所知,当您在启动时添加机器人时,您并没有添加机器人本身。你有

      // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
      services.AddTransient<IBot, Dialogs.MainChatbot>();
      

      尝试:

      // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
      services.AddTransient<IBot, MainChatbot<MyCustomDialog>>();
      

      为了做到这一点,您将不得不更改您的 MainChatBot。在你的课堂声明中,你有:

      public class MainChatbot : ActivityHandler
      

      改成:

      public class MainChatbot<T> : ActivityHandler
          where T : Dialog
      

      那里有你的主要“机器人”,但在它获得 LUIS 意图之前,你不会调用对话框。但在启动对话之前,您不能调用 LUIS 意图。改为使用对话框初始化您的机器人,因此您的机器人基本上知道从哪里“开始”。

      【讨论】:

      • 我为什么不能硬编码盯着 MyCustomDialog?为什么它需要作为类型 T 传递?由于我有 LUIS 意图,我可以准确地知道要启动哪个对话框,我不能只告诉它从哪个开始吗?
      猜你喜欢
      • 2021-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-16
      • 1970-01-01
      • 1970-01-01
      • 2019-11-22
      相关资源
      最近更新 更多