【问题标题】:Google Actions API webhook response on Heroku nodejsHeroku nodejs 上的 Google Actions API webhook 响应
【发布时间】:2017-04-30 19:17:08
【问题描述】:

问题: Google Actions 是否总是通过在每个用户输入上触发 webhook 帖子来工作,我只需要处理逻辑以便每次解析 json 并仅在找到我感兴趣的参数时才做出反应?或者有没有办法控制 Google Actions API 发出的 webhook 帖子,以便仅在通过包含感兴趣参数的值完全填充操作时才发出它?

#

详情: 我在 Heroku 上部署了这个 nodejs 应用程序: https://github.com/quique123/myjsonparser/blob/master/app.js

我将它用作 Google Actions API(数字精灵)示例的 webhook。在数字精灵中,用户以“与数字精灵交谈”开始游戏。精灵的回应是我在想一个数字……猜猜看。用户回复一个数字,然后(并且只有这样)运行逻辑以将猜测与答案进行比较。

但我对来自谷歌主页的每个帖子请求都进行了 api 调用。换句话说,每次用户与对话 api 交互时都会创建 webhook 帖子。可以在这里看到 body 不包含用户输入参数并且 Heroku 响应“与数字精灵交谈”:

2017-04-30T18:59:19.480900+00:00 heroku[router]: at=info method=POST path="/API/switches/sw1?password=123456" host=myjsonparser.herokuapp.com request_id=64d51b1c-3253-4a64-b7f5-a29a7750945b fwd="54.224.155.160" dyno=web.1 connect=1ms service=35ms status=200 bytes=254 protocol=https
2017-04-30T18:59:19.473973+00:00 app[web.1]: headers: {"host":"myjsonparser.herokuapp.com","connection":"close","accept":"*/*","content-type":"application/json; charset=UTF-8","cache-control":"no-cache","pragma":"no-cache","user-agent":"Java/1.8.0_112","x-request-id":"64d51b1c-3253-4a64-b7f5-a29a7750945b","x-forwarded-for":"54.224.155.160","x-forwarded-proto":"https","x-forwarded-port":"443","via":"1.1 vegur","connect-time":"1","x-request-start":"1493578759443","total-route-time":"0","content-length":"575"}
2017-04-30T18:59:19.474002+00:00 app[web.1]: body: {"id":"14797289-b0b8-492a-b030-bf9f05c7ea17","timestamp":"2017-04-30T18:59:19.413Z","lang":"en","result":{"source":"agent","resolvedQuery":"talk to number genie","speech":"","action":"generate_answer","actionIncomplete":false,"parameters":{},"contexts":[],"metadata":{"intentId":"688b0da5-547e-4c7a-8adc-189844834bcc","webhookUsed":"true","webhookForSlotFillingUsed":"false","intentName":"start_game"},"fulfillment":{"speech":"","messages":[{"type":0,"speech":""}]},"score":0.61},"status":{"code":200,"errorType":"success"},"sessionId":"ff2e0c97-552b-40d3-8f06-32e612476897"}
2017-04-30T18:59:19.477116+00:00 app[web.1]: postSwitch {"id":"sw1","state":"off","name":"Koko's Lamp"}

当我使用 Google Actions API 上的数字对其进行测试时,您可以在 Heroku 对“44”的响应中看到包含 check_guess:

2017-04-30T19:00:31.901297+00:00 app[web.1]: headers: {"host":"myjsonparser.herokuapp.com","connection":"close","accept":"*/*","content-type":"application/json; charset=UTF-8","cache-control":"no-cache","pragma":"no-cache","user-agent":"Java/1.8.0_112","x-request-id":"5a7a2c31-9ce5-4b02-9bac-bcef55ad6818","x-forwarded-for":"54.224.155.160","x-forwarded-proto":"https","x-forwarded-port":"443","via":"1.1 vegur","connect-time":"1","x-request-start":"1493578831899","total-route-time":"0","content-length":"573"}
2017-04-30T19:00:31.901347+00:00 app[web.1]: body: {"id":"5478dfb5-54f3-451d-b975-4f984d1ce3cb","timestamp":"2017-04-30T19:00:31.858Z","lang":"en","result":{"source":"agent","resolvedQuery":"44","speech":"","action":"check_guess","actionIncomplete":false,"parameters":{"check_guess":"44"},"contexts":[],"metadata":{"intentId":"c863e1e2-c850-45d8-9b96-b57e0b1ee77e","webhookUsed":"true","webhookForSlotFillingUsed":"false","intentName":"provide_guess"},"fulfillment":{"speech":"","messages":[{"type":0,"speech":""}]},"score":1},"status":{"code":200,"errorType":"success"},"sessionId":"ff2e0c97-552b-40d3-8f06-32e612476897"}
2017-04-30T19:00:31.903553+00:00 app[web.1]: postSwitch {"id":"sw1","state":"on","name":"Koko's Lamp"}
2017-04-30T19:00:31.907017+00:00 heroku[router]: at=info method=POST path="/API/switches/sw1?password=123456" host=myjsonparser.herokuapp.com request_id=5a7a2c31-9ce5-4b02-9bac-bcef55ad6818 fwd="54.224.155.160" dyno=web.1 connect=1ms service=5ms status=200 bytes=253 protocol=https

问题在于 postSwitch{} 在这两种情况下都会发生。

这是 Google Actions 始终工作的方式吗,我只需要处理逻辑以便每次解析 json 并仅在找到 check_guess 时才做出反应?或者有没有办法通过包含参数 check_guess 的值来控制 Google Actions API 发出的 webhook 帖子,以便仅在操作完全填充时才发出它?

【问题讨论】:

  • 你在使用 API.AI 吗?您还可以添加触发此功能的意图的屏幕截图吗?如果您没有使用 API.AI,您可以添加您正在使用的操作包。
  • 此时他们的文章实际上有很多错误。他们在没有完全更新教程的情况下更新了示例代码。但是,如果您有其他问题,最好在其他 SO 问题中提出。这个最好留在尝试处理您关于路由的问题。
  • “动作包”仅用于使用非 API.AI 方法实现动作。如果您使用的是 API.AI,请不要担心。

标签: node.js heroku actions-on-google google-home


【解决方案1】:

您只能设置一个 Webhook(一个静态 URL),该 Webhook(一个静态 URL)将被 API.AI 触发的所有操作调用。虽然您需要解析 JSON(您使用的是 node.js,JSON.parse() 并不难),但您应该使用 result.action 字段而不是试图找出设置了哪些参数。这将对应于您在 API.AI 中设置的 Action 字段。

当然,这假定您已选中 webhook 框以执行您的操作。否则,您将根本不会收到 webhook 调用。

因此,例如,开始意图配置如下:

它会将此 JSON 发送到您的 webhook。


{
 "originalRequest": {
  "source": "google",
  "data": {
   "surface": {
    "capabilities": [
     {
      "name": "actions.capability.AUDIO_OUTPUT"
     }
    ]
   },
   "inputs": [
    {
     "arguments": [],
     "intent": "assistant.intent.action.MAIN",
     "raw_inputs": [
      {
       "query": "talk to number genie",
       "input_type": 2,
       "annotation_sets": []
      }
     ]
    }
   ],
   "user": {
    "user_id": "kQmX8nX9ovcS9jfb3WKmwLk9YFlHGZH05YGbc8muNI8=",
    "permissions": []
   },
   "device": {
    "locale": "en-US"
   },
   "is_in_sandbox": true,
   "conversation": {
    "conversation_id": "1493637016599",
    "type": 1
   }
  }
 },
 "id": "9444bfe4-3c23-487a-84e7-fcbf1708d9e3",
 "timestamp": "2017-05-01T11:10:16.694Z",
 "lang": "en",
 "result": {
  "source": "agent",
  "resolvedQuery": "GOOGLE_ASSISTANT_WELCOME",
  "speech": "",
  "action": "generate_answer",
  "actionIncomplete": false,
  "parameters": {},
  "contexts": [
   {
    "name": "game",
    "parameters": {},
    "lifespan": 5
   },
   {
    "name": "google_assistant_welcome",
    "parameters": {},
    "lifespan": 0
   },
   {
    "name": "actions_capability_audio_output",
    "parameters": {},
    "lifespan": 0
   }
  ],
  "metadata": {
   "intentId": "56da4637-0419-46b2-b851-d7bf726b1b1b",
   "webhookUsed": "true",
   "webhookForSlotFillingUsed": "false",
   "intentName": "start_game"
  },
  "fulfillment": {
   "speech": "",
   "messages": [
    {
     "type": 0,
     "speech": ""
    }
   ]
  },
  "score": 1
 },
 "status": {
  "code": 200,
  "errorType": "success"
 },
 "sessionId": "1493637016599"
}

provide_guess 意图可能是这样配置的

并将此 JSON 提供给 webhook:


{
 "originalRequest": {
  "source": "google",
  "data": {
   "surface": {
    "capabilities": [
     {
      "name": "actions.capability.AUDIO_OUTPUT"
     }
    ]
   },
   "inputs": [
    {
     "arguments": [
      {
       "raw_text": "42",
       "text_value": "42",
       "name": "text"
      }
     ],
     "intent": "assistant.intent.action.TEXT",
     "raw_inputs": [
      {
       "query": "42",
       "input_type": 2,
       "annotation_sets": []
      }
     ]
    }
   ],
   "user": {
    "user_id": "kQmX8nX9ovcS9jfb3WKmwLk9YFlHGZH05YGbc8muNI8=",
    "permissions": []
   },
   "device": {
    "locale": "en-US"
   },
   "is_in_sandbox": true,
   "conversation": {
    "conversation_token": "[\"_actions_on_google_\",\"game\"]",
    "conversation_id": "1493637749915",
    "type": 2
   }
  }
 },
 "id": "09997ef5-5c0f-4c60-a69f-af06d6e4e3f5",
 "timestamp": "2017-05-01T11:22:34.377Z",
 "lang": "en",
 "result": {
  "source": "agent",
  "resolvedQuery": "42",
  "speech": "",
  "action": "check_guess",
  "actionIncomplete": false,
  "parameters": {
   "guess": "42"
  },
  "contexts": [
   {
    "name": "game",
    "parameters": {
     "guess.original": "42",
     "guess": "42"
    },
    "lifespan": 5
   },
   {
    "name": "_actions_on_google_",
    "parameters": {
     "guessCount": 0,
     "printed": "Welcome back to Number Genie. I'm thinking of a number from %s to %s. What's your first guess?",
     "guess.original": "42",
     "answer": 74,
     "guess": "42",
     "lastPrompt": "Welcome back to Number Genie. I'm thinking of a number from %s to %s. What's your first guess?",
     "steamSoundCount": 0,
     "fallbackCount": 0
    },
    "lifespan": 99
   },
   {
    "name": "actions_capability_audio_output",
    "parameters": {
     "guess.original": "42",
     "guess": "42"
    },
    "lifespan": 0
   }
  ],
  "metadata": {
   "intentId": "1e46ffc2-651f-4ac0-a54e-9698feb88880",
   "webhookUsed": "true",
   "webhookForSlotFillingUsed": "false",
   "intentName": "provide_guess"
  },
  "fulfillment": {
   "speech": "",
   "messages": [
    {
     "type": 0,
     "speech": ""
    }
   ]
  },
  "score": 1
 },
 "status": {
  "code": 200,
  "errorType": "success"
 },
 "sessionId": "1493637749915"
}

在您的代码中,您将在 postSwitch() 方法中检查 result.action 的值,然后可以根据此操作选择您端的确切操作(generateAnswer()checkGuess() 根据您的评论出代码)。

【讨论】:

  • 哦,好的,所以 result.action 用于检查特定的意图结果,这就是为什么它在 console.api.ai 中称为意图的动作。昨晚很好地摆弄它,我通过执行 assistant.getArgument('check_guess') 获得了价值,并且我能够使用我在 github 上的最新代码将它登录到 Heroku。
  • 这是访问这些值的正确方法吗?
  • 哪些值? result.action?
  • 我试图访问用户的输入,在数字精灵示例中是 check_guess 参数,它也恰好是 result.action 中的操作名称。所以它会类似于 result.action.check_guess:65。但我没有将 json 解析为字典,而是使用了 Google Actions Number Genie 教程中的示例代码 let guess = parseInt(assistant.getArgument('check_guess'));
  • 听起来你在问一个不同的问题。一个很好的问题 - 但与这里提出的问题不同。请在一个新的 SO 问题中提出它,以便为有相同问题的其他人正确保留这个问题。
猜你喜欢
  • 2018-08-10
  • 1970-01-01
  • 2017-10-28
  • 2017-09-27
  • 2017-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多