【问题标题】:Botmaker resolve Qnamaker Followup QuestionsBotmaker 解决 Qna Maker 后续问题
【发布时间】:2020-04-03 01:50:35
【问题描述】:

对于我当前的项目,我尝试使用仅限上下文的后续提示。

我现在的问题是,后续提示中的一些问题是一样的。

在 qna ui 中,上下文的分离工作正常,但是当用户从我在应用程序中实现的聊天中回答问题时,qna 返回错误的答案。

代码: 机器人生成器版本:4.5.3 NodeJS:12.10.0

onMessage(){.....

let results = qna.getAnswer(context);
if(results[0].context.prompts.length){ //  Answer with Follow-up
      return context.sendActivity(CardHelper.GetHeroCard(results[0].answer, results[0].context.prompts))
   }else{ // normal answer
      return context.sendActivity(results[0].answer)
   }
}
Sample Questions:

Expected Answer:
I want to learn programming => java => here is our guide
Real Answer:
I want to learn programming => java => that is the java test

Expected Answer:
I want to do a test => java => that is the java test
Real Answer:
I want to do a test => java => that is the java test

如何在代码中实现这些后续提示,又不丢失后续上下文?

【问题讨论】:

  • 对于您的第一个问题,您是说“Java”是多个根本问题的后续问题,并且您想根据上下文对该问题给出不同的答案吗?当用户在问题 1 后说“Java”时,API 会返回问题 2 的 Java 答案,反之亦然?
  • 我在我的问题中添加了一些示例,希望对您有所帮助 :) tltr:后续的“java”总是返回相同的答案
  • 好的,这澄清了第一个问题,但是“此外,我还想根据代码中的数据回答一些后续问题”是什么意思?您是说要在机器人代码中动态生成一些答案吗?您想使用 Dispatch 将 QnA 知识库问题与代码数据问题区分开来,还是希望机器人知道它需要根据从 QnA Maker 收到的答案从代码数据中生成答案?你能举个例子吗?您想在这篇文章中解决这两个问题,还是想为第二个问题再发一篇文章?
  • 我的想法是我在 Userprofile 中保存 QuestionContext 之类的“Java”,并使用这些信息将答案返回给 qna,而无需再次询问用户。但这首先是不相关的,所以它可能会从我的问题中删除这部分。
  • 明确地说,您使用的是 botbuilder-ai 包中的 QnAMaker.getAnswers 方法,对吧?

标签: javascript node.js azure botframework qnamaker


【解决方案1】:

首先要了解的是多轮对话和后续提示处于预览状态。这通常意味着人们应该预料到错误和缺失的功能。在这种情况下,这意味着该功能不仅在 SDK 中缺失,甚至在 API 参考中也缺失。您可以在Generate Answer reference 中看到对generateAnswer 端点的调用在其主体中包含context 属性,但该对象的类型未记录。它链接到在响应中返回的 Context 对象类型,而不是您应该在请求中放入的对象类型。

由于您的问题提到了CardHelper.GetHeroCard,我想您已经熟悉QnA Maker prompting sample。如果您不熟悉该示例,那么它是 QnA Maker 中多轮对话的最终真相来源。该示例包含您问题的全部答案,因此我不确定您为什么不使用它。不过,你也应该在the documentation you should be following看到你需要做什么:

返回非初始答案和后续提示的 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 状态。

编辑: 如果您将上下文放在操作本身中,则有一种方法可以在没有机器人状态的情况下使用后续提示,但这仅在用户单击按钮时才有效输入内容:Display Text for QnAMaker follow-on prompts

【讨论】:

    猜你喜欢
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 2017-11-24
    相关资源
    最近更新 更多