我目前正在使用带有Luis的Enterprise Bot模板将意图路由到正确的QnAMaker知识库。 QnAMaker知识库端点存储在bot文件中。我有一个启用多提示的请求:https://github.com/microsoft/BotBuilder-Samples/tree/master/experimental/qnamaker-prompting/csharp_dotnetcore
在提供的示例中,QnAMaker知识库端点位于appsettings.json中,我不知道如何将其他知识库端点添加到appsettings并将意图发送到适当的知识库或让多提示对话框从bot文件中提取端点信息。
在示例中,知识库是在启动时设置的
BotBuilder-样品主版\ BotBuilder-样品主版\实验\ qnamaker提示\ csharp_dotnetcore \ Helpers \ QnAService.cs:
private static (QnAMakerOptions options, QnAMakerEndpoint endpoint) InitQnAService(IConfiguration configuration)
{
var options = new QnAMakerOptions
{
Top = 3
};
var hostname = configuration["QnAEndpointHostName"];
if (!hostname.StartsWith("https://"))
{
hostname = string.Concat("https://", hostname);
}
if (!hostname.EndsWith("/qnamaker"))
{
hostname = string.Concat(hostname, "/qnamaker");
}
var endpoint = new QnAMakerEndpoint
{
KnowledgeBaseId = configuration["QnAKnowledgebaseId"],
EndpointKey = configuration["QnAEndpointKey"],
Host = hostname
};
return (options, endpoint);
}
BotBuilder-样品主版\ BotBuilder-样品主版\实验\ qnamaker提示\ csharp_dotnetcore \ Startup.cs:
// Helper code that makes the actual HTTP calls to QnA Maker. It is injectable for local unit testing.
services.AddHttpClient<IQnAService, QnAService>();
这是我对示例代码未做任何修改的设置:
在主对话框中:
else if (intent == Dispatch.Intent.q_RJH_Test_multiprompt)
{
_services.QnAServices.TryGetValue("RJH_Test_multiprompt", out var qnaService);
if (qnaService == null)
{
throw new Exception("The specified QnA Maker Service could not be found in your Bot Services configuration.");
}
else
{
QnABotState newState = null;
var query = dc.Context.Activity.Text;
var qnaResult = await _qnaService.QueryQnAServiceAsync(query, newState);
if (qnaResult != null && qnaResult.Count() > 0)
{
// start QnAPrompt dialog
await dc.BeginDialogAsync(nameof(QnADialog));
}
else
{
await _responder.ReplyWith(dc.Context, MainResponses.ResponseIds.Confused);
}
}
}
如果InitQnAService方法中提供了端点,则对话框将正确启动,并且多提示有效-但我无法弄清楚如何在此设置中使用多个知识库。
答案 0 :(得分:0)
在我半途改变想法之前,请先阅读整个答案。
向您传递IBotServices
的修改版本,而不是QnADialog
取得IQnAService
,该实现的实现是here。
您可以删除不需要的LuisRecognizer
属性,并将QnAMaker
属性设为集合,然后从appsettings
读取所有QnA密钥以创建{{1 }}对象,然后将其插入集合中。然后,您需要在QnAMaker
中包含something来遍历并查询各种KB,然后处理是否未找到答案。
一个粗略的轮廓是:
QnADialog
接口(类似于IBotServices
)List<QnAMakerService> QnAMakerKbs
接口的BotServices
类。IBotServices
类的构造函数中,您应该:
BotServices
对象。QnaMakerService
对象添加到QnAMakerService
属性中。QnAMakerKbs
中替换:
Startup.cs
services.AddHttpClient<IQnAService, QnAService>();
services.AddHttpClient<IBotService, BotService>();
的构造函数中,替换为:
QnABot
IQnAService qnaService
,IBotService botService
调用内的QnADialog
的第一个参数替换为: base
。botService
中,将QnADialog.cs
的使用替换为IQnAService
,并适当地重命名变量。IBotService
方法中的逻辑更新为:ProcessAsync
OP的一项工作是添加用于将状态传递给请求的逻辑,以便保持提示状态。我的代码基于this sample,它不使用提示。在您正在使用的自定义示例中,使用了自定义QnAService,该服务根据this code手动构建了请求,并传递了var query = inputActivity.Text;
var index = 0;
foreach (var qnaKb in _botServices.QnAMakerKbs)
{
// Passing in the state won't be supported
var qnaResult = await qnaKb.GetAnswersAsync(query, (QnABotState)oldState);
var qnaAnswer = qnaResult[0].Answer;
// If no answer was found in the KB then go to the next KB,
// unless it is the last KB in the collection, then we will
// fall through to the default else handling below
if (qnaAnswer == "Default no answer found string" && index < _botServices.QnAMakerKbs.Length - 1)
{
continue;
}
var prompts = qnaResult[0].Context?.Prompts;
if (prompts == null || prompts.Length < 1)
{
outputActivity = MessageFactory.Text(qnaAnswer);
}
else
{
// Set bot state only if prompts are found in QnA result
newState = new QnABotState
{
PreviousQnaId = qnaResult[0].Id,
PreviousUserQuery = query
};
outputActivity = CardHelper.GetHeroCard(qnaAnswer, prompts);
}
index++;
}
来跟踪提示进度。
这应该使您走上正确的道路。
修改
使用我上面提供的知识,您可能只需修改QnAService
类(和QnABotState
接口),即可将QnAMakerEndpoint
属性更改为一个集合并处理{ {1}}。