首页 > 解决方案 > 如何在 C# - CoreBot 中构造 QnA Maker 实例类?

问题描述

System.AggregateException在运行我的 Core Bot C# 示例后得到了一个。

Startup.cs我添加的类如下:

     services.AddSingleton<ChitChatRecognizer>();

识别器类看起来像:

    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Bot.Builder;
    using Microsoft.Bot.Builder.AI.QnA;
    using Microsoft.Bot.Schema;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;

    namespace CoreBot
    {
        public class ChitChatRecognizer : ActivityHandler
        {

            private readonly IConfiguration _configuration;
            private readonly ILogger<ChitChatRecognizer> _logger;
            private readonly IHttpClientFactory _httpClientFactory;

            public ChitChatRecognizer(IConfiguration configuration, ILogger<ChitChatRecognizer> logger, IHttpClientFactory httpClientFactory)
            {
                _configuration = configuration;
                _logger = logger;
                _httpClientFactory = httpClientFactory;
            }

            protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
            {
                var httpClient = _httpClientFactory.CreateClient();

                var qnaMaker = new QnAMaker(new QnAMakerEndpoint
                {
                    KnowledgeBaseId = _configuration["QnAKnowledgebaseId"],
                    EndpointKey = _configuration["QnAEndpointKey"],
                    Host = _configuration["QnAEndpointHostName"]
                },
                null,
                httpClient);

                _logger.LogInformation("Calling QnA Maker");

                var options = new QnAMakerOptions { Top = 1 };

                // The actual call to the QnA Maker service.
                var response = await qnaMaker.GetAnswersAsync(turnContext, options);
                if (response != null && response.Length > 0)
                {
                    await turnContext.SendActivityAsync(MessageFactory.Text(response[0].Answer), cancellationToken);
                }
                else
                {
                    await turnContext.SendActivityAsync(MessageFactory.Text("No QnA Maker answers were found."), cancellationToken);
                }
            }
        }
    }

我什至还没有使用该类,但我什至无法在没有错误的情况下启动我的程序。我应该怎么办?

错误代码:

“某些服务无法构建(验证服务描述符时出错'ServiceType:CoreBot.ChitChatRecognizer Lifetime:Singleton ImplementationType:CoreBot.ChitChatRecognizer':无法解析类型'System.Net.Http.IHttpClientFactory'的服务,同时尝试激活“CoreBot.ChitChatRecognizer”。)(验证服务描述符“ServiceType:Microsoft.BotBuilderSamples.Dialogs.MainDialog Lifetime:Singleton ImplementationType:Microsoft.BotBuilderSamples.Dialogs.MainDialog”时出错:无法解析“System.Net”类型的服务。 Http.IHttpClientFactory”,同时尝试激活“CoreBot.ChitChatRecognizer”。)(验证服务描述符“ServiceType:Microsoft.Bot.Builder.IBot Lifetime:Transient ImplementationType:Microsoft.BotBuilderSamples.Bots.DialogAndWelcomeBot`1[Microsoft.BotBuilderSamples.Dialogs.MainDialog]':尝试激活 'CoreBot.ChitChatRecognizer' 时,无法解析类型为 'System.Net.Http.IHttpClientFactory' 的服务。)”

标签: botframeworkchatbotazure-language-understandingqnamaker

解决方案


你的设置很奇怪......你正在制作你的ChitChatRecognizer,它是一个机器人(它派生自ActivityHandler),然后我想后来 DI 进入一个对话框或另一个机器人?此外,您似乎想将 QnAMaker(QnA 的识别器)视为单例,但您将其初始化为 --OnMessageActivityAsync意味着除非您的机器人收到消息活动,否则它不会初始化,因此如果您尝试初始化其他东西需要 a QnAMaker,它不会在启动时存在。


无论如何,要回答如何插入QnAMakercorebot 的问题,如果您想添加QnAMaker为单例,您可以在启动时将其添加为单例,然后在需要调用 QnAMaker 时从您的机器人代码中调用它。

将 QnAMaker 添加到 Corebot 示例

Startup.ConfigureServices

// Register QnAMaker recognizer
services.AddSingleton<MyQnaMaker>();

MyQnAMaker.cs

namespace Microsoft.BotBuilderSamples
{
    public class MyQnaMaker
    {
        public MyQnaMaker(IConfiguration configuration)
        {
            ChitChatRecognizer = new QnAMaker(new QnAMakerEndpoint
            {
                KnowledgeBaseId = configuration["QnAKnowledgebaseId"],
                EndpointKey = configuration["QnAEndpointKey"],
                Host = configuration["QnAEndpointHostName"]
            });
        }

        public QnAMaker ChitChatRecognizer { get; set; }
    }
}

DialogAndWelcomeBot.cs 构造函数

DIQnAMaker进入机器人

        public DialogAndWelcomeBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger, MyQnaMaker myQnAMaker)
            : base(conversationState, userState, dialog, logger, myQnAMaker)

对话机器人.cs

        public DialogBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger, MyQnaMaker qnaMaker)
        {
            ConversationState = conversationState;
            UserState = userState;
            Dialog = dialog;
            Logger = logger;
            MyQnaMaker = qnaMaker;
        }

...

        protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            Logger.LogInformation("Running dialog with Message Activity.");

            if (turnContext.Activity.Text == "yo")
            {
                await CallQnAMaker(turnContext, cancellationToken);
            } else {
                // Run the Dialog with the new message Activity.
                await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);
            }

        }

        private async Task CallQnAMaker(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            var options = new QnAMakerOptions { Top = 1 };

            // The actual call to the QnA Maker service.
            var response = await MyQnaMaker.ChitChatRecognizer.GetAnswersAsync(turnContext, options);
            if (response != null && response.Length > 0)
            {
                await turnContext.SendActivityAsync(MessageFactory.Text(response[0].Answer), cancellationToken);
            }
            else
            {
                await turnContext.SendActivityAsync(MessageFactory.Text("No QnA Maker answers were found."), cancellationToken);
            }
        }

根据需要向您的课程添加更多内容,这只是最低要求。在上面DialogBot.cs,您可以看到,QnAMaker如果用户"yo"作为消息输入,我有调用 be 的触发器,用于测试目的。


运行 Corebot

在此处输入图像描述


备择方案

或者,您可以在机器人的消息处理程序(如)中new创建一个新的,类似于在 sample 中的完成方式,并取消单例。QnAMakerDialogBot.OnMessageActivityAsync()11.qnamaker


推荐阅读