如何检查用户参数以匹配 firebase 中的值?
How do I check user parameters to match a value in firebase?
我是 dialogflow 的新手,javascript 所以我真的不熟悉如何编写代码来实现 dialogflow
这是我的 if 语句,用于检查用户参数是否与 firebase 中的值匹配,但它不起作用并且触发了回退意图。场景是,
如果 answer = firebase 值,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 语句不起作用
如此处所示,我没有训练短语,因为如果数据库中的答案发生变化,我让它是动态的,这是不可能的吗?我必须有训练短语吗?
听起来您在这里遇到了两个不同的问题 - 一个是您期望 Dialogflow 如何检测 Intents,另一个是您期望 Firebase 获取值的方式。
Dialogflow 和检测意图
Dialogflow 的目的是获取用户的短语并通过将它们与许多可能的陈述相匹配来确定他们的广泛意图。这让您可以创建一个 Intent,例如,用户可以说 "yes" 或 "sure" 或 "of course" 或其他变体,您的代码只需要以一种方式处理它们。
有时我们会收到回复,他们可能会回复一个短语,但该短语中的某些值会有所不同,因此我们可以设置参数。如果这些参数可以来自一组固定的值(或这些值的同义词),我们可以将它们设置为 Entities。 Dialogflow 定义了一些实体类型,我们可以定义自己的自定义类型。
如果您的问题需要多项选择答案,您甚至可以创建一个 Session Entity,其中包含下一个问题的可能答案。这样您就可以知道他们的回答是否符合您的预期,或者他们是否没有尝试。
如果您期待开放式答案,事情就会变得更加困难。由于 Dialogflow 不知道任何有关用户何时回复的模式,因此它通常会以 Fallback Intent 结束。这是一个匹配 "everything else that doesn't match" 的特殊 Intent,通常用于用户说出完全出乎意料的情况 - 尽管它可用于收集自由格式的答案。
所有这一切都发生在之前 评估您编写的 fulfillment webhook 中的任何 if 语句。一旦检测到 Intent(或者它恢复为选择 Fallback Intent),它会将此 Intent、检测到的任何参数和完整短语发送到您的 webhook。
更新
正如您所注意到的,您根本没有为您的 Intent 设置任何训练短语。如果您没有任何 Events(在这种情况下您可能不想要),那么 Dialogflow 最终将永远不会匹配此 Intent。
在这种情况下,参数无关紧要。参数是短语中的占位符,这些参数将填充用户输入的短语部分。
您可以 创建一个具有输入上下文的后备意图。如果没有其他 Intent 匹配并且 Input Context 部分中列出的 all 当前处于活动状态,这只会触发 Fallback Intent。这将提供来自用户的整个短语,您可以在处理程序中针对此后备意图的比较中使用此短语。
然而,这可能不是一个好主意。不提供训练短语和实体可以使对话更加生硬。听起来你可以为所有可能的口袋妖怪(比如,@pokemon)创建一个实体,并创建你的训练短语来接受像这样的东西:
- 我觉得是皮卡丘
- 皮卡丘
- 皮卡丘可能是正确的
- ...
这样 Dialogflow 可以将所有这些短语匹配到同一个 Intent,但只向您报告 "Pikachu" 作为参数。
从 Firebase 获取值
使用 Firebase 数据库,通过 引用 数据库中的记录获取值,然后使用 once()
获取该记录。 (您也可以使用 on()
订阅记录的更新,但这在您的情况下是不必要的。)
创建引用是本地操作,因此 returns 立即执行。但是,获取值是异步操作的,因此您需要使用仅在网络操作完成时才会解析的 Promise。对于足够现代的节点版本(您应该使用),您可以使用 async/await.
在您的 if
测试中,您根据 reference 而不是 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,并且根本不是结果的快照。因此,尝试将 Promise 的 val()
与参数进行比较是行不通的。
您最好的选择是升级到现代节点引擎。您可以编辑 package.json 文件以包含 "engines" 部分。它可能看起来像这样:
{
"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": {
...
}
}
这里显示为 Node 8 设置它。您可能希望考虑使用 Node 10,尽管它在 Cloud Functions for Firebase 中仍处于 Beta 支持阶段。
如果您在 Dialogflow 中使用内联编辑器,要进行此更改,您需要 select 作为编辑器一部分的 (package.json) 选项卡:
@囚犯
我想到了你所说的,并相应地改变了我的意图,因此
My intent
然后我在映射到这个意图的实现中使用了这些代码来根据实时数据库检查用户参数
const q1snapshot = admin.database().ref('quizanswers/q1').once('value');
if(q1snapshot.val() === agent.parameters.pikachu){
agent.add(
没错!);
得分=得分+1;
return admin.database().ref('quizquestions').once('value').then((快照) =>{
常量值 = snapshot.child('q2').val();<br>
agent.add(
${值});
});
But it does not check still, this is what i get in my telegram bot
而这是原始的 api 响应,
{"responseId":“6371e43d-4d2a-428d-9b40-6c224ec7a21e-b4ef8d5f”,
"queryResult":{
"queryText": "pikachu",
"parameters":{
"pikachu": "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"
}
]
}
谁能赐教一下?
我是 dialogflow 的新手,javascript 所以我真的不熟悉如何编写代码来实现 dialogflow 这是我的 if 语句,用于检查用户参数是否与 firebase 中的值匹配,但它不起作用并且触发了回退意图。场景是, 如果 answer = firebase 值,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 语句不起作用
如此处所示,我没有训练短语,因为如果数据库中的答案发生变化,我让它是动态的,这是不可能的吗?我必须有训练短语吗?
听起来您在这里遇到了两个不同的问题 - 一个是您期望 Dialogflow 如何检测 Intents,另一个是您期望 Firebase 获取值的方式。
Dialogflow 和检测意图
Dialogflow 的目的是获取用户的短语并通过将它们与许多可能的陈述相匹配来确定他们的广泛意图。这让您可以创建一个 Intent,例如,用户可以说 "yes" 或 "sure" 或 "of course" 或其他变体,您的代码只需要以一种方式处理它们。
有时我们会收到回复,他们可能会回复一个短语,但该短语中的某些值会有所不同,因此我们可以设置参数。如果这些参数可以来自一组固定的值(或这些值的同义词),我们可以将它们设置为 Entities。 Dialogflow 定义了一些实体类型,我们可以定义自己的自定义类型。
如果您的问题需要多项选择答案,您甚至可以创建一个 Session Entity,其中包含下一个问题的可能答案。这样您就可以知道他们的回答是否符合您的预期,或者他们是否没有尝试。
如果您期待开放式答案,事情就会变得更加困难。由于 Dialogflow 不知道任何有关用户何时回复的模式,因此它通常会以 Fallback Intent 结束。这是一个匹配 "everything else that doesn't match" 的特殊 Intent,通常用于用户说出完全出乎意料的情况 - 尽管它可用于收集自由格式的答案。
所有这一切都发生在之前 评估您编写的 fulfillment webhook 中的任何 if 语句。一旦检测到 Intent(或者它恢复为选择 Fallback Intent),它会将此 Intent、检测到的任何参数和完整短语发送到您的 webhook。
更新
正如您所注意到的,您根本没有为您的 Intent 设置任何训练短语。如果您没有任何 Events(在这种情况下您可能不想要),那么 Dialogflow 最终将永远不会匹配此 Intent。
在这种情况下,参数无关紧要。参数是短语中的占位符,这些参数将填充用户输入的短语部分。
您可以 创建一个具有输入上下文的后备意图。如果没有其他 Intent 匹配并且 Input Context 部分中列出的 all 当前处于活动状态,这只会触发 Fallback Intent。这将提供来自用户的整个短语,您可以在处理程序中针对此后备意图的比较中使用此短语。
然而,这可能不是一个好主意。不提供训练短语和实体可以使对话更加生硬。听起来你可以为所有可能的口袋妖怪(比如,@pokemon)创建一个实体,并创建你的训练短语来接受像这样的东西:
- 我觉得是皮卡丘
- 皮卡丘
- 皮卡丘可能是正确的
- ...
这样 Dialogflow 可以将所有这些短语匹配到同一个 Intent,但只向您报告 "Pikachu" 作为参数。
从 Firebase 获取值
使用 Firebase 数据库,通过 引用 数据库中的记录获取值,然后使用 once()
获取该记录。 (您也可以使用 on()
订阅记录的更新,但这在您的情况下是不必要的。)
创建引用是本地操作,因此 returns 立即执行。但是,获取值是异步操作的,因此您需要使用仅在网络操作完成时才会解析的 Promise。对于足够现代的节点版本(您应该使用),您可以使用 async/await.
在您的 if
测试中,您根据 reference 而不是 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,并且根本不是结果的快照。因此,尝试将 Promise 的 val()
与参数进行比较是行不通的。
您最好的选择是升级到现代节点引擎。您可以编辑 package.json 文件以包含 "engines" 部分。它可能看起来像这样:
{
"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": {
...
}
}
这里显示为 Node 8 设置它。您可能希望考虑使用 Node 10,尽管它在 Cloud Functions for Firebase 中仍处于 Beta 支持阶段。
如果您在 Dialogflow 中使用内联编辑器,要进行此更改,您需要 select 作为编辑器一部分的 (package.json) 选项卡:
@囚犯
我想到了你所说的,并相应地改变了我的意图,因此
My intent
然后我在映射到这个意图的实现中使用了这些代码来根据实时数据库检查用户参数
const q1snapshot = admin.database().ref('quizanswers/q1').once('value');
if(q1snapshot.val() === agent.parameters.pikachu){
agent.add(
没错!);
得分=得分+1;
return admin.database().ref('quizquestions').once('value').then((快照) =>{
常量值 = snapshot.child('q2').val();<br>
agent.add(
${值});
});
But it does not check still, this is what i get in my telegram bot
而这是原始的 api 响应, {"responseId":“6371e43d-4d2a-428d-9b40-6c224ec7a21e-b4ef8d5f”, "queryResult":{ "queryText": "pikachu", "parameters":{ "pikachu": "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"
}
]
}
谁能赐教一下?