首先要明白的是多轮对话和后续提示处于预览状态。这通常意味着人们应该预料到错误和缺失的功能。在这种情况下,这意味着 SDK 不仅缺少该功能,API 参考中甚至没有它。您可以在生成答案参考打电话给generateAnswer
端点包括一个context
属性在其主体中,但该对象的类型未记录。它链接到Context
在响应中返回的对象类型,而不是您应该放入请求中的对象类型。
既然你的问题提到了CardHelper.GetHeroCard
,我想你已经熟悉了QnA Maker 提示示例。如果您不熟悉该示例,那么当涉及 QnA Maker 中的多轮对话时,它是最终的事实来源。该示例包含您问题的完整答案,因此我不确定您为什么不使用它。但是,您还应该看到您需要做什么您应该遵循的文档:
返回非初始答案和后续提示的 JSON 请求
填补context
对象包含先前的上下文。
在以下 JSON 请求中,当前问题是使用 Windows Hello 登录上一个问题是帐户和登录.
{
"question": "Use Windows Hello to sign in",
"top": 10,
"userId": "Default",
"isTest": false,
"qnaId": 17,
"context": {
"previousQnAId": 15,
"previousUserQuery": "accounts and signing in"
}
}
QnA Maker 本身不会保存任何状态,因此它取决于您的机器人为其提供上一轮的上下文。你的机器人没有这样做,这就是它不起作用的原因。以下是示例代码的简化版本,可帮助您了解需要执行的操作:
async testQnAMaker(turnContext) {
var qna = new QnAMaker({
knowledgeBaseId: '<GUID>',
endpointKey: '<GUID>',
host: 'https://<APPNAME>.azurewebsites.net/qnamaker'
});
var context = await this.qnaState.get(turnContext) || {
PreviousQnaId: 0,
PreviousUserQuery: null
};
// We're passing a context property into the QnAMakerOptions
// even though it's not part of the interface yet
var results = await qna.getAnswers(turnContext, { context });
var firstResult = results[0];
if (firstResult) {
var answer = firstResult.answer;
var resultContext = firstResult.context;
var prompts = resultContext && resultContext.prompts;
if (prompts && prompts.length) {
await this.qnaState.set(turnContext, {
PreviousQnaId: firstResult.id,
PreviousUserQuery: turnContext.activity.text
});
answer = ChoiceFactory.forChannel(
turnContext,
prompts.map(prompt => prompt.displayText),
answer);
}
await turnContext.sendActivity(answer);
} else {
await turnContext.sendActivity("I can't answer that");
}
}
由于您使用的功能目前处于预览状态,因此您需要发挥自己的聪明才智来弄清楚如何使用它。我只是使用状态属性访问器来保存每轮上一个问题的上下文,但您可能希望将其构建到对话框中并将每个用户查询保存在对话框状态中。关键是,如果您希望后续提示起作用,则必须保存 QnA Maker 状态。
EDIT:事实证明,如果您将上下文放入操作本身,则有一种方法可以在没有机器人状态的情况下使用后续提示,但这只有在用户单击按钮而不是输入内容时才有效:显示 QnAMaker 后续提示的文本