Dialogflow es 如何在没有输入的事件中为每个意图提供自定义重新提示?

Dialogflow es 如何在没有输入的事件中为每个意图提供自定义重新提示?,dialogflow-es,actions-on-google,google-home,Dialogflow Es,Actions On Google,Google Home,我正在为智能扬声器创建一个调查问卷机器人,向用户询问几个问题。答案存储在firebase中。我正在使用node.js,谷歌上的操作 它看起来是这样的: const { dialogflow, SignIn, Confirmation } = require('actions-on-google'); const functions = require('firebase-functions'); const app = dialogflow({ debug: true }); const

我正在为智能扬声器创建一个调查问卷机器人,向用户询问几个问题。答案存储在firebase中。我正在使用node.js,谷歌上的操作

它看起来是这样的:

const { dialogflow, SignIn, Confirmation } = require('actions-on-google');
const functions = require('firebase-functions');
const app = dialogflow({
    debug: true
});
const admin = require("firebase-admin");
admin.initializeApp({
    credential: admin.credential.applicationDefault(),
    databaseURL: 'DATABASE URL',
});
const db = admin.firestore();
const db_ref = db.collection('users');

let current_context = '';

app.intent('q1', (conv, {response}) =>{
    const payload = conv.user.profile.payload
    db_ref.doc(`${payload.email}`).collection(today).doc('q1').set({
        answer: response,
        timestamp: time
    });
    current_context='q1';
    conv.ask(question('Whats your answer for q1?'));
})


app.intent('No Input Prompt', (conv) => {
  const repromptCount = parseInt(conv.arguments.get('REPROMPT_COUNT'));
  if(current_context === 'q1'){
        if (repromptCount === 0) {
              conv.ask("What is your answer for Q1?");
        } else if (repromptCount === 1) {
              conv.ask("What is your answer for Q1? You can say option 1,2,3 or 4");
        } else if (conv.arguments.get('IS_FINAL_REPROMPT')) {
              conv.close("Lets talk some other time.");
        }
  }

})
  • 机器人:嗨,用户,你准备好回答问题了吗?[欢迎意向,带有是/否后续意向]{output context=q1}
  • 用户:是的
  • 机器人:你对第一季度的答案是什么?[意图q1]{输入上下文=q1,输出上下文=q2}
  • 用户:这是我的答案
  • 你对第二季度的答案是什么?[意图q2]{输入上下文=q2,输出上下文=q2}
  • 用户:这是我的答案
  • 谢谢你的回答。再见
在本次对话中,如果用户没有响应(no.input),我希望在实现中处理它

对于no.input,我使用以下代码:。我有一个“无输入提示”的意图,带有“操作和参数”无输入。此意图没有后续意图或任何上下文

我的问题是:如何在没有输入的事件中为每个意图提供自定义的重新提示

我正在做这样的事情:

const { dialogflow, SignIn, Confirmation } = require('actions-on-google');
const functions = require('firebase-functions');
const app = dialogflow({
    debug: true
});
const admin = require("firebase-admin");
admin.initializeApp({
    credential: admin.credential.applicationDefault(),
    databaseURL: 'DATABASE URL',
});
const db = admin.firestore();
const db_ref = db.collection('users');

let current_context = '';

app.intent('q1', (conv, {response}) =>{
    const payload = conv.user.profile.payload
    db_ref.doc(`${payload.email}`).collection(today).doc('q1').set({
        answer: response,
        timestamp: time
    });
    current_context='q1';
    conv.ask(question('Whats your answer for q1?'));
})


app.intent('No Input Prompt', (conv) => {
  const repromptCount = parseInt(conv.arguments.get('REPROMPT_COUNT'));
  if(current_context === 'q1'){
        if (repromptCount === 0) {
              conv.ask("What is your answer for Q1?");
        } else if (repromptCount === 1) {
              conv.ask("What is your answer for Q1? You can say option 1,2,3 or 4");
        } else if (conv.arguments.get('IS_FINAL_REPROMPT')) {
              conv.close("Lets talk some other time.");
        }
  }

})
使用此代码,当我模拟没有输入时,我得到以下错误:

无法将Dialogflow响应解析为AppResponse,原因是 平台响应无效:找不到RichResponse或 agentId平台响应中的SystemIntent: 12ae4038-8f17-4005-9bfa-1691ffcde5e5和intentId: 218605f2-e718-47e0-97f6-e1925755fa7c


您发布的代码有三个主要问题

  • 在JavaScript中,变量名不能有破折号。因此,
    当前上下文
    不是有效的变量名
  • 您正在将
    当前上下文
    声明为常量。顾名思义,这意味着它无法改变。然后你试着改变它
  • 您没有指明执行环境是什么,但如果您使用的是Firebase云函数之类的功能,则无法保证在“q1”意图处理程序运行和“no Input Prompt”意图处理程序运行时使用相同的服务器
  • 要绕过(3),您需要在调用之间向任何意图处理程序传递信息。在大多数情况下,您可以使用google上的操作或Dialogflow上下文来执行此操作

    然而,由于您试图检测的是一个上下文,您可以做得更好,只需查看当前活动的上下文即可。通过调用
    conv.contexts.get('name')
    获取上下文,可以查看上下文是否处于活动状态。如果它处于活动状态,您将得到一个结果。如果它不是活动的,它将是未定义的

    因此,您的代码可能看起来像

    app.intent('No Input Prompt', (conv) => {
      const repromptCount = parseInt(conv.arguments.get('REPROMPT_COUNT'));
      if(conv.contexts.get('q1')){
            if (repromptCount === 0) {
                  conv.ask("What is your answer for Q1?");
            } else if (repromptCount === 1) {
                  conv.ask("What is your answer for Q1? You can say option 1,2,3 or 4");
            } else if (conv.arguments.get('IS_FINAL_REPROMPT')) {
                  conv.close("Lets talk some other time.");
            }
      }
    
    })
    
    根据您评论中的问题更新

    Firebase的云功能使用“无服务器”技术,这样就没有一台服务器总是加载代码并随时可以执行。相反,当您向应该运行该函数的URL发出请求时,Firebase会确定是否需要启动新的代码副本来运行,然后运行该请求。如果当前没有正在运行的副本(可能出于任何原因将其全部关闭),或者当前实例无法处理的请求过多,它可能会启动一个新副本。即使有副本在运行,来自您的两个独立请求也可能会转到不同的服务器,并且它们不共享可变实例

    触发的每个意图都将导致对Firebase函数的另一次调用,因此无法保证您将获得相同的服务器,或者即使相同的服务器在一次又一次运行

    当您开始获得多个用户时,不使用全局变量也很重要。如果您使用的是全局变量,那么两个用户同时说的话可能会相互重叠,因此您为一个用户保存的内容可能会用于另一个用户


    这就是为什么除了使用变量外,在调用Intent处理程序之间要记住的任何内容都必须以某种方式保存。

    您有什么问题吗?如果是这样,您能更清楚地说明您遇到了什么问题、是否出现了任何错误,或者发生了什么出乎您意料的事情吗?1)和2)感谢您指出我代码中的问题。我已经做了改变。常量到Var和“-”到“\ux”。3) 你能详细说明一下吗?您所说的“您不能保证在运行'q1'意图处理程序和运行'no Input Prompt'意图处理程序时使用相同的服务器”是什么意思。我用的是Firebase。我已经更新了代码。我明白你所说的“当'q1'意图处理程序运行和'no Input Prompt'意图处理程序运行时,你不能保证使用相同的服务器”是什么意思。有时数据被设置好了,有时则没有。如果答案有帮助,我们总是很感激向上投票和/或接受它。