2

我是 dialogflow 和 javascript 的新手,所以我真的不熟悉如何编写实现 dialogflow 的代码,这是我的 if 语句,用于检查用户参数是否与 firebase 中的值匹配,但它不起作用并且触发了回退意图。场景是,如果 answer = firebase value,bot 回复它是正确的,添加分数并询问下一个问题。

function q1correct(agent){  
    const q1snapshot = admin.database().ref('quizanswers/q1').once('value');
    if(q1snapshot.val() == agent.parameters.pikachu){
      agent.add(`That's correct!`);
      score = score + 1;
      return admin.database().ref('quizquestions').once('value').then((snapshot) =>{
        const value = snapshot.child('q2').val();                                                            
        agent.add(`${value}`); 
    }); 
    }
    else{
      agent.add(`Sadly, that is incorrect.`);
      score = score;
      return admin.database().ref('quizquestions').once('value').then((snapshot) =>{
      const value = snapshot.child('q2').val();                                                            
      agent.add(`${value}`);

    });
    }
  }

if 语句不起作用

如此处所示,我没有训练短语,因为如果数据库内的答案发生变化,我让它是动态的,这是不可能的吗?我必须有训练短语吗? 在此处输入图像描述

在此处输入图像描述

4

2 回答 2

1

听起来您在这里有两个不同的问题-一个是您期望 Dialogflow 如何检测 Intent,另一个是您期望 Firebase 如何获取值。

Dialogflow 和检测意图

Dialogflow 的目的是获取用户的短语并通过将它们与许多可能的语句匹配来确定其广泛的意图。这使您可以创建一个 Intent,例如,用户可以在其中说“是”或“确定”或“当然”或其他变体,而您的代码只需要以一种方式处理它们。

有时我们有回复,他们可能会回复一个短语,但该短语中的某些值会有所不同,因此我们可以设置参数。如果这些参数可以来自一组固定的值(或这些值的同义词),我们可以将它们设置为Entities。Dialogflow 定义了一些实体类型,我们可以定义自己的自定义类型。

如果您的问题需要多项选择答案,您甚至可以创建一个会话实体,其中包含下一个问题的可能答案。这样,您将知道他们是否回答了您期望的内容,或者他们是否没有尝试。

如果您期待开放式答案,事情会变得更加困难。由于 Dialogflow 不知道用户何时回复的任何模式,它通常会以 Fallback Intent 结束。这是一个特殊的 Intent,它匹配“所有其他不匹配的内容”,通常用于用户说出完全出乎意料的话的情况——尽管它可以用来收集自由格式的答案。

所有这些都发生您编写的实现 webhook 中的任何 if 语句被评估之前。一旦检测到一个 Intent(或者它恢复选择 Fallback Intent),它就会将此 Intent、检测到的任何参数以及完整的短语发送到您的 webhook。

更新

正如您所注意到的,您根本没有为您的 Intent 设置任何训练短语。如果您没有任何事件(在这种情况下您可能不想要一个),那么 Dialogflow 最终将永远不会匹配此 Intent。

在这种情况下,参数无关紧要。参数是短语中的占位符,这些参数将在用户输入时用短语的该部分填充。

可以创建具有输入上下文的后备意图。只有在没有其他 Intent 匹配且Input Context 部分中列出的所有Context 当前处于活动状态时,这才会触发 Fallback Intent 。这将提供来自用户的整个短语,您可以在您的 Handler 中将此短语用于此 Fallback Intent 的比较。

然而,这可能不是一个好主意。不提供训练短语和实体会使对话更加生硬。听起来您可以为所有可能的 pokemon(例如,@pokemon)创建一个实体,并创建您的训练短语来接受以下内容:

  • 我觉得是皮卡丘
  • 皮卡丘
  • 皮卡丘可能是正确的
  • ...

这样,Dialogflow 可以将所有这些短语与同一个 Intent 匹配,但只需将“Pikachu”作为参数报告给您。

从 Firebase 获取价值

使用 Firebase 数据库,通过引用数据库中的记录来获取值,然后使用once(). (您也可以使用 订阅对记录的更新on(),但在您的情况下这是不必要的。)

创建引用是本地操作,因此它会立即返回。但是,获取值是异步操作的,因此您需要使用仅在网络操作完成时才解析的 Promise。对于足够现代的节点版本(您应该使用它),您可以使用 async/await。

在您的if测试中,您正在根据参考而不是 value 检查来自用户的。要检查该值,您可能需要在异步函数中执行更多类似的操作(未经测试):

const db = admin.database();
const q1snapshot = await db.ref('quizanswers/q1').once('value');
if( q1snapshot.val() === agent.parameters.pikachu ){
  // They got it right. Fetch and ask the next question
  const q2snapshot = await db.ref('quizquestions/q2').once('value');
  agent.add(q2snapshot.val());
} else {
  // They got it wrong. Say so.
  agent.add( "That isn't correct. Please try again." );
}

根据您更新的代码进行更新,并说明您正在使用 Dialogflow 内联编辑器

内联编辑器仍然(显然)使用不支持 async/await 的 Node 6。如果您不使用 async/await,那么您需要使用 Promises(Node 6 确实支持)。

所以你的台词

const q1snapshot = admin.database().ref('quizanswers/q1').once('value');
if(q1snapshot.val() == agent.parameters.pikachu){

最终仍然是不正确的,因为q1snapshot分配了一个 Promise,并且根本不是结果的快照。因此,尝试将val()Promise 与参数进行比较是行不通的。

您最好的选择是升级到现代 Node 引擎。您将编辑您的 package.json 文件以包含“引擎”部分。它可能看起来像这样:

{
  "name": "dialogflowFirebaseFulfillment",
  "description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
  "version": "0.0.1",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "Google Inc.",
  "engines": {
    "node": "8"
  },
  "scripts": {
    ...
  },
  "dependencies": {
    ...
  }
}

该节目将其设置为节点 8。您可能希望考虑使用节点 10,尽管这仍处于 Cloud Functions for Firebase 的 beta 支持中。

如果您在 Dialogflow 中使用内联编辑器,要进行此更改,您需要选择作为编辑器一部分的 (package.json) 选项卡:

显示 package.json 的内联编辑器

于 2020-01-02T12:28:20.697 回答
0

@囚犯

我想到了你说的话,也相应地改变了我的意图,就这样

我的意图

然后我在映射到这个意图的实现中使用这些代码来检查用户参数和实时数据库 const q1snapshot = admin.database().ref('quizanswers/q1').once('value'); if(q1snapshot.val() === agent.parameters.pikachu){ agent.add(这是正确的!${价值}); score = score + 1; return admin.database().ref('quizquestions').once('value').then((snapshot) =>{ const value = snapshot.child('q2').val();
agent.add(
); });

但它仍然没有检查,这就是我在我的电报机器人中得到的

而这是原始 api 响应,{“responseId”:“6371e43d-4d2a-428d-9b40-6c224ec7a21e-b4ef8d5f”,“queryResult”:{“queryText”:“pikachu”,“parameters”:{“pikachu”:“皮卡丘"},

"allRequiredParamsPresent": true,
"outputContexts": [
  {
    "name": "projects/physicstutor-ydlgsm/agent/sessions/75bb149e-9803-1c15-4cfb-6689ad5e3a79/contexts/awaitans2",
    "lifespanCount": 1,
    "parameters": {
      "pikachu": "pikachu",
      "pikachu.original": "pikachu"
    }
  }
],
"intent": {
  "name": "projects/physicstutor-ydlgsm/agent/intents/f0313e22-6794-475b-ac11-279866ee5317",
  "displayName": "qStartcorrect"
},
"intentDetectionConfidence": 0.3,
"diagnosticInfo": {
  "webhook_latency_ms": 128
},
"languageCode": "en"
"webhookStatus": {
"code": 14,
"message": "Webhook call failed. Error: UNAVAILABLE."
},
"alternativeQueryResults": [
{
  "queryText": "pikachu",
  "outputContexts": [
    {
      "name": "projects/physicstutor-ydlgsm/agent/sessions/75bb149e-9803-1c15-4cfb-6689ad5e3a79/contexts/awaitans1",
      "parameters": {
        "quiz.original": [
          "quiz"
        ],
        "quiz": [
          "quiz"
        ]
      }
    }
  ],
  "languageCode": "en"
}
]
}

有人可以启发我吗?

于 2020-01-06T04:52:58.963 回答