使用云函数模拟器在本地测试 Dialogflow 实现

Using the cloud functions emulator to test Dialogflow fulfillment locally

是否可以使用云函数模拟器在本地测试您的 Dialogflow fulfillment webhook?如果可以,我应该如何格式化请求?

我通读了我能找到的所有文档,包括 https://firebase.google.com/docs/functions/local-emulator 上的指南,特别感兴趣的是之前的这个问题,它似乎触及了类似的观点:

我可以使用函数 shell 调用我的实现函数,但是无论我如何尝试格式化正文,我似乎只能触发我的回退意图或错误捕获意图。

我可以在 Actions on Google 模拟器上验证,当给定输入 "hello" 时,我的 webhook 成功响应了默认的欢迎意图,但是当使用相同的请求 JSON 数据时作为本地函数的输入,我被引导到后备意图。

是不是功能模拟器无法在本地执行正确的意图匹配,因此总是触发后备意图,或者我只是没有正确格式化我的请求?任何帮助将不胜感激!

这是我正在使用的调用格式,以及来自 shell 的响应:

firebase > fulfillment({method: 'POST',json: true,body: 
require("project/collabrec/testData.json")});
Sent request to function.
firebase > info: User function triggered, starting execution
info: Fallback intent triggered.
info: Execution took 15 ms, user function completed successfully

RESPONSE RECEIVED FROM FUNCTION: 200, {
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "I didn't quite catch that. Could you say that again?"
            }
          }
        ]
      }
    }
  }
}

这里是testData.json内容:

{
  "user": {
    "userId": "ABwppHFR0lfRsG_UM3NkvAptIkD2iUpIUNxFt-ia05PFuPajV6kRQKXu_H_ECMMe0lP_WcCsK64sH2MEIg8eqA",
    "locale": "en-US",
    "lastSeen": "2018-10-19T15:20:12Z"
  },
  "conversation": {
    "conversationId": "ABwppHHerN4CIsBZiWg7M3Tq6NwlTWkfN-_zLIIOBcKbeaz4ruymv-nZ4TKr6ExzDv1tOzszsfcgXikgqRJ9gg",
    "type": "ACTIVE",
    "conversationToken": "[]"
  },
  "inputs": [
    {
      "intent": "actions.intent.TEXT",
      "rawInputs": [
        {
          "inputType": "KEYBOARD",
          "query": "hello"
        }
      ],
      "arguments": [
        {
          "name": "text",
          "rawText": "hello",
          "textValue": "hello"
        }
      ]
    }
  ],
  "surface": {
    "capabilities": [
      {
        "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
      },
      {
        "name": "actions.capability.SCREEN_OUTPUT"
      },
      {
        "name": "actions.capability.AUDIO_OUTPUT"
      },
      {
        "name": "actions.capability.WEB_BROWSER"
      }
    ]
  },
  "isInSandbox": true,
  "availableSurfaces": [
    {
      "capabilities": [
        {
          "name": "actions.capability.SCREEN_OUTPUT"
        },
        {
          "name": "actions.capability.AUDIO_OUTPUT"
        },
        {
          "name": "actions.capability.WEB_BROWSER"
        }
      ]
    }
  ],
  "requestType": "SIMULATOR"
}

这是我的云函数 webhook:

const {dialogflow, Image} = require('actions-on-google');
const admin = require('firebase-admin');
const functions = require('firebase-functions');
const app = dialogflow();


app.catch((conv, error) => {
  console.log("Error intent triggered.")
  console.error(error);
  conv.ask('Sorry, I ran into an error. Please try that again.');
});

app.fallback((conv) => {
  console.log("Fallback intent triggered.")
  conv.ask("I didn't quite catch that. Could you say that again?");
})

app.intent('Default Welcome Intent', (conv) => {
  console.log("Welcome intent triggered.")
    conv.ask("Welcome!!");
});

exports.fulfillment = functions.region('europe-west1').https.onRequest(app);

使用 Node v8.1.4 和软件包版本:

"@google-cloud/common-grpc": "^0.9.0",
"@google-cloud/firestore": "^0.17.0",
"@google-cloud/functions-emulator": "^1.0.0-beta.5",
"actions-on-google": "^2.4.1",
"firebase-admin": "^6.0.0",
"firebase-functions": "^2.0.5"

问题是您使用的是来自 AoG 模拟器的 JSON,但这显示了 AoG 发送到 Dialogflow 的 JSON。 Dialogflow 对此进行处理并向您的 webhook 发送一个不同的 JSON,其中包括处理 AoG JSON 和确定意图、参数和其他信息的结果。

如果您有 Dialogflow JSON,您正在做的应该有效。您有几种方法可以做到这一点:

  • 最直接的是 运行 你的 webhook 放在一个可以从 Dialogflow 接收 POST 的地方并查看 conv.request 对象,这应该是能够给你JSON你需要的。

  • 如果您 运行 在本地开发机器上使用 webhook(正如您所暗示的那样),我倾向于启动一个 ngrok 隧道。隧道提供了一个 public HTTPS 服务器,这非常有用,并且具有给我一个控制台的副作用,我可以使用它来准确查看请求和响应的内容 JSON.

  • 最后,您应该能够进入 Dialogflow 中的项目设置并打开 Cloud Logging。该日志包括发送到您的 webhook 的请求以及您从中获得的响应。