如何为 no.input 事件的每个意图提供自定义重新提示?

How can I provide a custom re-prompt for each intent on the event of no.input?

我正在为智能音箱创建一个问卷机器人,它会向用户询问几个问题。答案存储在 firebase 中。我正在使用 node.js、actions-on-google.

对话是这样的:

在这次对话中,如果用户没有回应(no.input),我想在fulfillment中处理。

对于 no.input,我使用的代码来自:https://developers.google.com/assistant/conversational/reprompts#dialogflow_2。我有 'No Input Prompt' 和 'action and parameters' 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.");
        }
  }

})

使用此代码,当我模拟无输入时,出现此错误:

Failed to parse Dialogflow response into AppResponse because of invalid platform response: Could not find a RichResponse or SystemIntent in the platform response for agentId: 12ae4038-8f17-4005-9bfa-1691ffcde5e5 and intentId: 218605f2-e718-47e0-97f6-e1925755fa7c

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

  1. 在 JavaScript 中,变量名中不能有破折号。所以 current-context 不是一个有效的变量名。
  2. 您将 current-context 声明为常量。顾名思义,这意味着它无法更改。然后您尝试更改它。
  3. 您没有指明执行环境是什么,但是如果您使用的是 Firebase Cloud Functions 之类的东西,则无法保证 "q1" Intent Handler 时您将使用同一台服务器运行s 并且当 "No Input Prompt" Intent Handler 运行s.

要绕过 (3),您需要在对任何 Intent Handler 的调用之间传递信息。在大多数情况下,您会使用 actions-on-google conv.data storage 或 Dialogflow Context.

来执行此操作

但是,由于您要检测的 上下文,您可以做得更好,只需查看当前处于活动状态的上下文即可。您可以通过调用 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.");
        }
  }

})

根据您评论中的问题更新

Cloud Functions for Firebase 使用 "serverless" 技术,因此没有任何一台服务器始终加载您的代码并准备好执行。相反,当您向 URL 发出应该 运行 函数的请求时,Firebase 会确定它是否需要将代码的新副本启动到 运行 然后 运行是请求。如果当前 运行ning 没有副本(它可能出于某种原因将它们全部关闭)或者请求多于当前实例当前可以处理的请求,它可能会启动一个新副本。即使有副本 运行ning,您的两个单独请求也可能会发送到不同的服务器,并且它们不会共享变量实例。

每个被触发的 Intent 都会导致对 Firebase 函数的另一次调用,因此无法保证您会获得同一台服务器,即使同一台服务器一次 运行ning到下一个。

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

这就是为什么除了使用变量之外,还必须以某种方式保存在 Intent Handler 调用之间您想记住的任何内容。