Как запустить диалоговое окно с водопадом из ActivityHandler.OnMessageActivityAsyn c в среде ботов v4 - PullRequest
1 голос
/ 17 января 2020

Я пытаюсь написать простого бота, который запустит мой диалог с водопадом, когда пользователь введет что-то. Вариант использования очень прост, но, похоже, он просто не работает, что не так?

Основной бот настроен как таковой, я пытаюсь вызвать мой диалог в функции OnMessageActivityAsyn c:

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 моему боту.

Однако я уже точно знаю, какой диалог нужно запустить, поэтому его нужно передать как типа, я могу просто жестко закодировать его прямо внутри бота, как мне его запустить?

Ответы [ 2 ]

1 голос
/ 18 января 2020

Оказалось, что мой код работает нормально, не знаю, почему он не работал вчера. Я оставлю это для будущих людей, проверяющих ответы. Вы можете использовать его точно так же, как в вопросе.

0 голосов
/ 17 января 2020

Из того, что я вижу, вы не добавляете самого бота при добавлении бота при запуске. у вас есть

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

try:

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

Для этого вам нужно будет изменить свой MainChatBot. В вашем классе delcaration у вас есть:

public class MainChatbot : ActivityHandler

измените его на:

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

У вас есть ваш главный «бот», но вы не вызываете диалог, пока он не получит намерение Луиса. Но вы не можете вызвать намерение LUIS, пока диалог не будет запущен. Вместо этого инициализируйте своего бота с помощью диалогового окна, чтобы ваш бот знал, с чего «начинать».

...