如何在 bot 框架 v4 中从 ActivityHandler.OnMessageActivityAsync 开始瀑布对话
How to start a waterfall dialog from ActivityHandler.OnMessageActivityAsync in bot framework v4
我正在尝试编写一个简单的机器人,它会在用户输入内容时启动我的瀑布对话框。用例非常简单,但似乎不起作用,有什么问题吗?
主机器人是这样设置的,我尝试在 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 传递给我的机器人。
但是,我已经确切地知道要启动哪个对话框,因此需要将其作为类型传递,我可以直接在 bot 中对其进行硬编码,我该如何启动它?
据我所知,您在启动时添加机器人时并没有添加机器人本身。你有
// 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。在您的 class 声明中,您有:
public class MainChatbot : ActivityHandler
改为:
public class MainChatbot<T> : ActivityHandler
where T : Dialog
您的主要 'bot' 在那里,但您不会调用对话框,直到它获得 LUIS 意图。但在对话启动之前,您无法调用 LUIS 意图。改为使用对话框初始化您的机器人,这样您的机器人基本上就知道 'start' 去哪里了。
原来我的代码似乎工作正常,不知道为什么它昨天不工作。我留给未来的人检查答案。您可以完全按照问题中的方式使用它。
我正在尝试编写一个简单的机器人,它会在用户输入内容时启动我的瀑布对话框。用例非常简单,但似乎不起作用,有什么问题吗?
主机器人是这样设置的,我尝试在 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 传递给我的机器人。
但是,我已经确切地知道要启动哪个对话框,因此需要将其作为类型传递,我可以直接在 bot 中对其进行硬编码,我该如何启动它?
据我所知,您在启动时添加机器人时并没有添加机器人本身。你有
// 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。在您的 class 声明中,您有:
public class MainChatbot : ActivityHandler
改为:
public class MainChatbot<T> : ActivityHandler
where T : Dialog
您的主要 'bot' 在那里,但您不会调用对话框,直到它获得 LUIS 意图。但在对话启动之前,您无法调用 LUIS 意图。改为使用对话框初始化您的机器人,这样您的机器人基本上就知道 'start' 去哪里了。
原来我的代码似乎工作正常,不知道为什么它昨天不工作。我留给未来的人检查答案。您可以完全按照问题中的方式使用它。