【问题标题】:dialogflow fullfilment and firebase response time对话流履行和 Firebase 响应时间
【发布时间】:2018-08-23 20:52:07
【问题描述】:

我正在尝试使用DialogFlow 构建一个简单的聊天机器人。

我的目标是提供来自用户问题的信息,例如:在克罗地亚哪里可以在水面上放绳?我有两个参数(croatiawaterline)和一个松弛线位置列表。

所以我需要一个数据库来从参数中检索信息。 DialogFlow 允许使用Firebase 实现。我建立了一个包含地点(名称、国家、松弛类型)的数据库并启用webhook 呼叫我的意图。

我使用内联编辑器和 index.js

const parameters = request.body.queryResult.parameters;
var country = parameters.country.toString();

function show(snap) {
   console.log('snap');
   agent.add(JSON.stringify(snap.val(),null,2));
}

function slkplc(agent) {
     var testRef;
     firebase.database().ref('slackplace').once('value',show);
}

// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('slack place', slkplc);
agent.handleRequest(intentMap);

但在 DialogFlow 或 Google Assistant 上尝试时,我没有得到预期的结果。函数 show 被异步调用但为时已晚,响应对 DialogFlow 不可用:

我看到了解决这个问题的三种方法:

  1. 对数据库使用阻塞调用:另一个数据库?
  2. 使用 DialogFlow 处理异步消息???
  3. 向用户回复发生错误。

我选择了第三个,但总是出错。

在尝试了几件事来等待来自数据库响应的数据后,我唯一设法冻结响应,因此达到了 DialogFlow - 5s - 和 Firebase - 60s - 的超时。

解决方法

另一种方法是将数据库获取和请求/响应与 DialogFlow 分开。数据库的数据是在dialogflowFirebaseFulfillment之外收集的

var data;
var inidata = firebase.database().ref().on('value',function(snap) {
     console.log('snap');
     data = snap.val();
 });

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
 const agent = new WebhookClient({ request, response });
 ...
 function slkplc(agent) {
     agent.add(JSON.stringify(data,null,2));
 }

  // Run the proper function handler based on the matched Dialogflow intent name
  let intentMap = new Map();
  intentMap.set('slack place', slkplc);
  agent.handleRequest(intentMap);
}

现在我可以用数据做我想做的事了,我可以在克罗地亚找到可以练习吃水线的地方。但是总有一些奇怪的东西,数据库的数据是重复的……

【问题讨论】:

    标签: node.js firebase dialogflow-es


    【解决方案1】:

    “正确”的解决方案是您建议的选项 2:由于您正在进行异步调用,因此在使用 dialogflow-fulfillment 库时需要正确处理此问题。

    基本上,如果您的处理程序进行异步调用,它也需要是异步的。要向 handleRequest() 方法表明您的处理程序是异步的,您需要返回一个 Promise 对象。

    如果您不向 Firebase 的 once() 方法传递一个回调函数,它就会返回一个 Promise。您可以利用这一点,返回该 Promise,还可以处理您希望它作为 .then() 子句的一部分执行的操作。它可能看起来像这样:

    function slkplc(agent) {
      var testRef;
      return firebase.database().ref('slackplace').once('value')
        .then( snap => {
          var val = snap.val();
          return agent.add( JSON.stringify( val, null, 2 ) );
        });
    }
    

    重要的部分不仅在于您使用了 Promise,还在于您返回了该 Promise。

    【讨论】:

    • 行为是相同的,在数据​​恢复之前发送响应,我设法使其工作的唯一方法是获取请求之外的数据。
    • 在 Promise 中处理它并返回 Promise 应该可以工作。您能否展示代码,说明它仍然无法正常工作,即使您返回了 Promise?
    • 我又试了一次,现在可以了。感谢您指出returning Promise,这是我错过的重点。
    • 太棒了!很高兴你让它工作。我已经澄清了我的答案,以确保它强调返回承诺。如果答案对您有帮助,欢迎接受和/或支持它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-19
    • 2018-07-30
    • 1970-01-01
    相关资源
    最近更新 更多