开发语音应用程序时无法将数据流中的变量映射到用户识别的响应

Cannot map variable from data stream to users identified response while developing voice app

我目前正在开发一个带有 Google 操作的语音应用程序,用户可以在其中请求有关通过 Axios 文件流提供的列表中项目的信息,如下所示 LINK.数据如下所示:

[
  {
    "Name": "Beam",
    "Level": "2",
    "Zone": "A",
    "Location": "Beam is located on Level 2 in zone A",
    "Responsible": "Contractor"
  },
  {
    "Name": "Column",
    "Level": "3",
    "Zone": "A",
    "Location": "Column is located on Level 3 in zone A",
    "Responsible": "Kiewit"
  },
  {
    "Name": "Window",
    "Level": "2",
    "Zone": "B",
    "Location": "Window is located on Level 2 in zone B",
    "Responsible": "Tech"
  }
]

这里显示了BEam、Column、Window三个项目,所以objective是用户询问其中一个项目,语音应用会提供其他信息例如级别、区域、位置或对用户负责。

为了完成这个,我正在使用 Google Actions 的 Web 界面,并在 Google Actions 中使用内联云函数作为 webhook,如下所示:

const { conversation } = require('@assistant/conversation');
const functions = require('firebase-functions');
require('firebase-functions/lib/logger/compat'); // console.log compact
const axios = require('axios');

const app = conversation({debug: true});

app.handle('getItem', async conv => {
  const data = await getItem();
  const itemParam = conv.intent.params.Item.resolved;
//   console.log(itemParam);
//   conv.add(`This test to see if we are accessing the webhook for ${itemParam}`);
  
  data.map(item  => {
      if (item.Name === itemParam);
        conv.add(`These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`);
//              conv.add(`This test to see if we are accessing the webhook for ${item.Name}`);
  });
  
});

async function getItem() {
    const res = await axios.get('https://sheetdb.io/api/v1/n3ol4hwmfsmqd');
  console.log(res.data);
  return res.data; // To use in your Action's response
}

exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

当我检查控制台日志时,我可以看到我正在检索 LINK 中提供的单个事件中的数据。此外,通过在应用程序中定义要根据类型类别识别的类型,项目名称的识别在应用程序中起作用。并且此信息存储在 ItemParam 中。

然而,我现在面临的主要问题是 link 将两者结合在一起。我试图使用映射函数来匹配数据流中的 itemParam 和 Item.Name。但是,这根本不起作用。我试图做的功能是:

data.map(item  => {
          if (item.Name === itemParam);
            conv.add(`These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`);

我想在这里做的是当函数检测到用户 ItemParam 与流中的项目匹配时,使用来自该流项目的信息并向包含 ItemParam 的对话添加一个短语,并且关于同一项目的其他信息。

另外,这个函数现在的样子,也会报这个错误:

cf-GPfYHj4HKDWGvHKWArq34w-name
Error: Error adding simple response: **Two simple responses already defined** 
at addSimple (/workspace/node_modules/@assistant/conversation/dist/conversation/prompt/prompt.js:34:15) 

at Prompt.add (/workspace/node_modules/@assistant/conversation/dist/conversation/prompt/prompt.js:108:17) 

at ConversationV3.add (/workspace/node_modules/@assistant/conversation/dist/conversation/conv.js:102:21) 
at data.map.item (/workspace/index.js:16:13) 
at Array.map (<anonymous>) at app.handle (/workspace/index.js:14:8) at process._tickCallback (internal/process/next_tick.js:68:7)

老实说,我对 Javascript 不是很熟悉,我可能会犯一些愚蠢的错误,但我真的想不通。

任何帮助将不胜感激。谢谢

您看到的错误是:

Error: Error adding simple response: Two simple responses already defined

您的操作响应只能包含 two simple responses。例如,每个响应都呈现为 phone 上的单独文本气泡。

因此 item.Name === itemParam 似乎多次为真,您最终创建了太多回复。

为什么会这样?它来自你的条件是如何写的:

  data.map(item  => {
      if (item.Name === itemParam);
        conv.add(`These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`);
  });

您已正确识别出 ; 分号字符表示语句的结尾。但是,这不适用于 if 语句。因为它的编写方式,你有这个条件,然后在你真正 运行 conv.add 之前得出结论。这意味着 conv.add 会逃避您的检查,并且每个项目都会 运行s。如果您要记录 conv 响应,您会看到一堆文本。

要修复它,请记住条件需要 包装 周围的代码。这是用大括号 { & }.

完成的
  data.map(item  => {
      if (item.Name === itemParam) {
        conv.add(`These are the datails for ${itemParam}. It is located in zone ${item.Zone}, at level ${item.Level}`);
      }
  });

您甚至可以在 map 方法中看到这一点,其中映射逻辑用花括号将 if-statement 括起来。这表明一个完全包含在另一个中。

谢谢,尼克,我根据您的反馈修复了我的功能,现在我对地图功能有了更好的了解。我在此过程中发现的另一个问题是大写和小写对于匹配 map 函数很重要,所以我还必须将类型修改为小写并将 .toLowerCase() 方法添加到变量。

现在我的代码使用两个变量 Item 和 Item_ID 因此如果用户询问通用项目,可以通过将项目的 ID 添加到查询问题来获得详细信息。

现在我的代码如下所示:

// From here, there are all the required libraries to be loaded
const { conversation } = require('@assistant/conversation'); // This the app coversation
const functions = require('firebase-functions'); //These are the firebase functions
require('firebase-functions/lib/logger/compat'); // console.log compact
const axios = require('axios'); // This is axios to retrieve the data stream
// To here, there all the required libraries to be loaded

const app = conversation({debug: true}); // This instantiate the conversation

/* This function retrieve the data from the file stream */
async function getItem() {
    const res = await axios.get('https://sheetdb.io/api/v1/n3ol4hwmfsmqd');
   return res.data; // To use in your Action's response
}

/* This is the fuction to match user's responses and data stream*/
app.handle('getItem', async conv => { //getItem is the weekhook name used in Google Actions, conv is the conversation
  const data = await getItem(); // Here the data stream is retrieved and send to the data variable
//   console.log(data);
  const itemParam = conv.intent.params.Item.resolved; // This is the user's response, in other words, what item the user's want to know from the data.
  const itemIDParam = conv.intent.params.Item_ID.resolved.replace(/\s/g, ''); //This is the user's response for item ID
  const itemFromUser = itemParam + " " + itemIDParam;
  console.log(itemParam);
  console.log(itemIDParam);
  console.log(itemFromUser);
//   conv.add(`This test to see if we are accessing the webhook for ${itemParam}`); // This is to know if I was getting the correct item from the user. Currently this is working
//   console.log(data);
    data.map(item  => { //Then, I am trying to map the data stream to recognize the data headers and identify items
//     console.log(data);
//     console.log(item);
      if (item.Name.toLowerCase() === itemFromUser.toLowerCase()){
        console.log(item);
        conv.add(`These are the details for ${itemFromUser}. It is located in zone ${item.Zone}, at level ${item.Level}.`);
//         console.log(conv);
//          console.log(data);
      } 
    else {
      conv.add(`I am sorry. I could not find any information about that object. Please try with another construction object.`);
      }
  });
});

exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

现在我可以处理大部分问题,除非数据流中没有某些内容,这会使应用程序向我显示此错误:

"error": "Error adding simple response: Two simple responses already defined"

这与我之前遇到的错误相同,我还不确定如何修复它。我尝试为该条件实现一个 else 语句,如下所示:

else {
  conv.add(`I am sorry. I could not find any information about that object. Please try with another construction object.`);
  }

但我仍然遇到同样的错误。

我还在努力。