问题
I got a System.AggregateException
after running my Core Bot C# sample.
In the Startup.cs
I added the class as followes:
services.AddSingleton<ChitChatRecognizer>();
The Recognizer Class looks like:
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);
}
}
}
}
I'm not even using the Class yet but can't even start my program without the error. What should I do?
ErrorCode:
"Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: CoreBot.ChitChatRecognizer Lifetime: Singleton ImplementationType: CoreBot.ChitChatRecognizer': Unable to resolve service for type 'System.Net.Http.IHttpClientFactory' while attempting to activate 'CoreBot.ChitChatRecognizer'.) (Error while validating the service descriptor 'ServiceType: Microsoft.BotBuilderSamples.Dialogs.MainDialog Lifetime: Singleton ImplementationType: Microsoft.BotBuilderSamples.Dialogs.MainDialog': Unable to resolve service for type 'System.Net.Http.IHttpClientFactory' while attempting to activate 'CoreBot.ChitChatRecognizer'.) (Error while validating the service descriptor 'ServiceType: Microsoft.Bot.Builder.IBot Lifetime: Transient ImplementationType: Microsoft.BotBuilderSamples.Bots.DialogAndWelcomeBot`1[Microsoft.BotBuilderSamples.Dialogs.MainDialog]': Unable to resolve service for type 'System.Net.Http.IHttpClientFactory' while attempting to activate 'CoreBot.ChitChatRecognizer'.)"
回答1:
Your setup is odd...you're making your ChitChatRecognizer
, which is a bot (it derives from ActivityHandler
), and then later DI into either a dialog or another bot, I imagine? Also it seems you want to treat QnAMaker (the recognizer for QnA) as a singleton, but you initialize it in OnMessageActivityAsync
--meaning it won't initialize unless your bot receives a message activity, so if you're trying to initialize something else the requires a QnAMaker
, it won't exist on startup.
Anyways, to answer the question of how do you insert QnAMaker
into corebot, if you wanted to add QnAMaker
as a singleton, you can add it as singleton in startup, then call it from your bot code when you need to make a call to QnAMaker.
Add QnAMaker to Corebot Sample
In 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 constructor
DI QnAMaker
into the Bot
public DialogAndWelcomeBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger, MyQnaMaker myQnAMaker)
: base(conversationState, userState, dialog, logger, myQnAMaker)
DialogBot.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);
}
}
Add more to your classes as needed, this is just the bare minimum. Above in DialogBot.cs
, you can see that I have the trigger to call QnAMaker
be if the user types in "yo"
as a message, for testing purposes.
Running Corebot
Alternatives
Alternatively you could just new
up a new QnAMaker
within the bot's message handler (like DialogBot.OnMessageActivityAsync()
), similar to how is done in sample 11.qnamaker, and do away with the singleton.
来源:https://stackoverflow.com/questions/61343711/how-to-construct-a-qna-maker-instance-class-in-c-sharp-corebot