Webhook

为了让您更灵活地构建 Action,您可以将逻辑委托给 HTTPS 网络服务(执行方式)。你的 Action 可以触发 向 HTTPS 端点发出请求下面列举了一些示例来说明 履单包括:

  • 根据用户提供的信息生成动态提示。
  • 在外部系统中下单并确认操作成功。
  • 使用后端数据验证槽。
图 1. 调用 intent 和场景可以触发 webhook。

网络钩子触发器和处理程序

您的 Action 可以在调用 intent 或场景中触发网络钩子, 向您的 fulfillment 端点发送请求。您的 fulfillment 包含 webhook 用于处理请求中的 JSON 载荷的处理程序。您可以通过多种方法 以下情况:

  • 调用 intent 匹配后
  • 在场景的进入舞台上
  • 在场景的条件阶段某个条件评估为 true 后
  • 在场景的槽填充阶段
  • 在场景的输入阶段发生 intent 匹配后

当您在 Action 中触发网络钩子时,Google 助理会向 包含 JSON 载荷传递到您的执行方式,该执行方式包含 用于处理事件的处理程序的名称。你的执行端点可以 将事件路由至相应的处理程序,以执行逻辑并返回 包含 JSON 载荷的响应

载荷

以下代码段显示了您的 Action 发送到 fulfillment 以及您的 fulfillment 发回的响应。请参阅 参考文档 信息。

{
 
"handler": {
   
"name": "handler_name"
 
},
 
"intent": {
   
"name": "actions.intent.MAIN",
   
"params": {},
   
"query": ""
 
},
 
"scene": {
   
"name": "SceneName",
   
"slotFillingStatus": "UNSPECIFIED",
   
"slots": {}
 
},
 
"session": {
   
"id": "example_session_id",
   
"params": {},
   
"typeOverrides": []
 
},
 
"user": {
   
"locale": "en-US",
   
"params": {
     
"verificationStatus": "VERIFIED"
   
}
 
},
 
"home": {
   
"params": {}
 
},
 
"device": {
   
"capabilities": [
     
"SPEECH",
     
"RICH_RESPONSE",
     
"LONG_FORM_AUDIO"
   
]
 
}
}
{
 
"session": {
   
"id": "example_session_id",
   
"params": {}
 
},
 
"prompt": {
   
"override": false,
   
"firstSimple": {
     
"speech": "Hello World.",
     
"text": ""
   
}
 
},
 
"scene": {
   
"name": "SceneName",
   
"slots": {},
   
"next": {
     
"name": "actions.scene.END_CONVERSATION"
   
}
 
}
}

运行时交互

以下各部分介绍了您可以在 Google Cloud 控制台中执行的常见任务, webhook 处理程序。

发送提示

您可以使用简单文本、富文本、卡片甚至是完全成熟的提示创建提示 由使用 Interactive Canvas 的 Web 应用支持的 HTML 提示。提示文档中有 有关如何在处理 webhook 事件时创建提示的完整信息。 以下代码段显示了卡片提示:

app.handle('rich_response', conv => {
  conv
.add('This is a card rich response.');
  conv
.add(new Card({
    title
: 'Card Title',
    subtitle
: 'Card Subtitle',
    text
: 'Card Content',
    image
: new Image({
      url
: 'https://developers.google.com/assistant/assistant_96.png',
      alt
: 'Google Assistant logo'
   
})
 
}));
});
{
 
"session": {
   
"id": "example_session_id",
   
"params": {}
 
},
 
"prompt": {
   
"override": false,
   
"content": {
     
"card": {
       
"title": "Card Title",
       
"subtitle": "Card Subtitle",
       
"text": "Card Content",
       
"image": {
         
"alt": "Google Assistant logo",
         
"height": 0,
         
"url": "https://developers.google.com/assistant/assistant_96.png",
         
"width": 0
       
}
     
}
   
},
   
"firstSimple": {
     
"speech": "This is a card rich response.",
     
"text": ""
   
}
 
}
}

读取 intent 参数

当 Google 助理运行时与 intent 匹配时,它会提取任何已定义的 参数。原始属性是用户作为输入提供的内容, 解析属性是指 NLU 根据类型解析输入的属性 。

conv.intent.params['param_name'].original
conv
.intent.params['param_name'].resolved
{
 
"handler": {
   
"name": "handler_name"
 
},
 
"intent": {
   
"name": "intent_name",
   
"params": {
     
"slot_name": {
       
"original": "1",
       
"resolved": 1
     
}
   
},
   
"query": ""
 
},
 
"scene": {
   
"name": "SceneName",
   
"slotFillingStatus": "UNSPECIFIED",
   
"slots": {},
   
"next": {
     
"name": "actions.scene.END_CONVERSATION"
   
}
 
},
 
"session": {
   
"id": "session_id",
   
"params": {},
   
"typeOverrides": []
 
},
 
"user": {
   
"locale": "en-US",
   
"params": {
     
"verificationStatus": "VERIFIED"
   
}
 
},
 
"home": {
   
"params": {}
 
},
 
"device": {
   
"capabilities": [
     
"SPEECH",
     
"RICH_RESPONSE",
     
"LONG_FORM_AUDIO"
   
]
 
}
}

读取用户语言区域

此值对应于用户的 Google 助理语言区域设置。

conv.user.locale
{
 
"handler": {
   
"name": "handler_name"
 
},
 
"intent": {
   
"name": "actions.intent.MAIN",
   
"params": {},
   
"query": ""
 
},
 
"scene": {
   
"name": "SceneName",
   
"slotFillingStatus": "UNSPECIFIED",
   
"slots": {}
 
},
 
"session": {
   
"id": "session_id",
   
"params": {},
   
"typeOverrides": []
 
},
 
"user": {
   
"locale": "en-US",
   
"params": {
     
"verificationStatus": "VERIFIED"
   
}
 
},
 
"home": {
   
"params": {}
 
},
 
"device": {
   
"capabilities": [
     
"SPEECH",
     
"RICH_RESPONSE",
     
"LONG_FORM_AUDIO"
   
]
 
}
}

读取和写入存储空间

请参阅存储文档,全面了解如何 使用各种存储功能。

//read
conv
.session.params.key
conv
.user.params.key
conv
.home.params.key

// write
conv
.session.params.key = value
conv
.user.params.key = value
conv
.home.params.key = value
{
 
"handler": {
   
"name": "handler_name"
 
},
 
"intent": {
   
"name": "actions.intent.MAIN",
   
"params": {},
   
"query": ""
 
},
 
"scene": {
   
"name": "SceneName",
   
"slotFillingStatus": "UNSPECIFIED",
   
"slots": {}
 
},
 
"session": {
   
"id": "session_id",
   
"params": {
     
"key": "value"
   
},
   
"typeOverrides": [],
   
"languageCode": ""
 
},
 
"user": {
   
"locale": "en-US",
   
"params": {
     
"verificationStatus": "VERIFIED",
     
"key": "value"
   
}
 
},
 
"home": {
   
"params": {
     
"key": "value"
   
}
 
},
 
"device": {
   
"capabilities": [
     
"SPEECH",
     
"RICH_RESPONSE",
     
"LONG_FORM_AUDIO"
   
]
 
}
}
{
 
"session": {
   
"id": "session_id",
   
"params": {
     
"key": "value"
   
}
 
},
 
"prompt": {
   
"override": false,
   
"firstSimple": {
     
"speech": "Hello world.",
     
"text": ""
   
}
 
},
 
"user": {
   
"locale": "en-US",
   
"params": {
     
"verificationStatus": "VERIFIED",
     
"key": "value"
   
}
 
},
 
"home": {
   
"params": {
     
"key": "value"
   
}
 
}
}

检查设备功能

您可以查看设备的功能以提供不同的体验,或 对话流

const supportsRichResponse = conv.device.capabilities.includes("RICH_RESPONSE");
const supportsLongFormAudio = conv.device.capabilities.includes("LONG_FORM_AUDIO");
const supportsSpeech = conv.device.capabilities.includes("SPEECH");
const supportsInteractiveCanvas = conv.device.capabilities.includes("INTERACTIVE_CANVAS");
{
 
"handler": {
   
"name": "handler_name"
 
},
 
"intent": {
   
"name": "actions.intent.MAIN",
   
"params": {},
   
"query": ""
 
},
 
"scene": {
   
"name": "SceneName",
   
"slotFillingStatus": "UNSPECIFIED",
   
"slots": {}
 
},
 
"session": {
   
"id": "session_id",
   
"params": {},
   
"typeOverrides": [],
   
"languageCode": ""
 
},
 
"user": {
   
"locale": "en-US",
   
"params": {
     
"verificationStatus": "VERIFIED"
   
}
 
},
 
"home": {
   
"params": {}
 
},
 
"device": {
   
"capabilities": [
     
"SPEECH",
     
"RICH_RESPONSE",
     
"LONG_FORM_AUDIO",
     
"INTERACTIVE_CANVAS"
   
]
 
}
}

如需查看 Surface 功能的完整列表,请参阅 Capability 参考。

运行时类型替换项

通过运行时类型,您可以在运行时修改类型规范。您可以使用 功能从其他来源加载数据,以填充类型的有效值。对于 例如,您可以使用运行时类型替换项向调查问卷添加动态选项 问题或向菜单添加日常菜品。

如需使用运行时类型,您可以从调用 处理程序。在这里,您可以 session.typeOverrides 参数。可用 模式包括 TYPE_MERGE 以保留现有的类型条目,或 TYPE_REPLACE 以用替换项替换现有条目。

conv.session.typeOverrides = [{
    name
: type_name,
    mode
: 'TYPE_REPLACE',
    synonym
: {
      entries
: [
       
{
          name
: 'ITEM_1',
          synonyms
: ['Item 1', 'First item']
       
},
       
{
          name
: 'ITEM_2',
          synonyms
: ['Item 2', 'Second item']
       
},
       
{
          name
: 'ITEM_3',
          synonyms
: ['Item 3', 'Third item']
       
},
       
{
          name
: 'ITEM_4',
          synonyms
: ['Item 4', 'Fourth item']
       
},
   
]
 
}
}];
{
 
"session": {
   
"id": "session_id",
   
"params": {},
   
"typeOverrides": [
     
{
       
"name": "type_name",
       
"synonym": {
         
"entries": [
           
{
             
"name": "ITEM_1",
             
"synonyms": [
               
"Item 1",
               
"First item"
             
]
           
},
           
{
             
"name": "ITEM_2",
             
"synonyms": [
               
"Item 2",
               
"Second item"
             
]
           
},
           
{
             
"name": "ITEM_3",
             
"synonyms": [
               
"Item 3",
               
"Third item"
             
]
           
},
           
{
             
"name": "ITEM_4",
             
"synonyms": [
               
"Item 4",
               
"Fourth item"
             
]
           
}
         
]
       
},
       
"typeOverrideMode": "TYPE_REPLACE"
     
}
   
]
 
},
 
"prompt": {
   
"override": false,
   
"firstSimple": {
     
"speech": "This is an example prompt.",
     
"text": "This is an example prompt."
   
}
 
}
}

提供语音纠偏功能

借助语音自定义调整功能,您可以为 NLU 指定提示,以改进意图匹配。您 最多可以指定 1000 个条目

conv.expected.speech = ['value_1', 'value_2']
conv
.expected.language = 'locale_string'
{
 
"session": {
   
"id": "session_id",
   
"params": {}
 
},
 
"prompt": {
   
"override": false,
   
"firstSimple": {
     
"speech": "This is an example prompt.",
     
"text": "This is an example prompt."
   
}
 
},
 
"expected": {
   
"speech": "['value_1', 'value_2']",
   
"language": "locale_string"
 
}
}

过渡场景

除了在 Actions 项目中定义静态过渡之外,您还可以 会导致场景转换在运行时发生。

app.handle('transition_to_hidden_scene', conv => {
 
// Dynamic transition
  conv
.scene.next.name = "HiddenScene";
});
{
 
"session": {
   
"id": "session_id",
   
"params": {}
 
},
 
"prompt": {
   
"override": false,
   
"firstSimple": {
     
"speech": "This is an example prompt.",
     
"text": ""
   
}
 
},
 
"scene": {
   
"name": "SceneName",
   
"slots": {},
   
"next": {
     
"name": "HiddenScene"
   
}
 
}
}

读取场景槽

在槽位填充期间,您可以使用 fulfillment 来验证槽位或检查 槽填充状态 (SlotFillingStatus)。

conv.scene.slotFillingStatus  // FINAL means all slots are filled
conv
.scene.slots  // Object that contains all the slots
conv
.scene.slots['slot_name'].<property_name> // Accessing a specific slot's properties

例如,假设您想从响应中提取时区。在 在此示例中,槽名称为 datetime1。要获取时区,您需要 使用:

conv.scene.slots['datetime1'].value.time_zone.id
{
 
"handler": {
   
"name": "handler_name"
 
},
 
"intent": {
   
"name": "",
   
"params": {
     
"slot_name": {
       
"original": "1",
       
"resolved": 1
     
}
   
},
   
"query": ""
 
},
 
"scene": {
   
"name": "SceneName",
   
"slotFillingStatus": "FINAL",
   
"slots": {
     
"slot_name": {
       
"mode": "REQUIRED",
       
"status": "SLOT_UNSPECIFIED",
       
"updated": true,
       
"value": 1
     
}
   
},
   
"next": {
     
"name": "actions.scene.END_CONVERSATION"
   
}
 
},
 
"session": {
   
"id": "session_id",
   
"params": {
     
"slot_name": 1
   
},
   
"typeOverrides": []
 
},
 
"user": {
   
"locale": "en-US",
   
"params": {
     
"verificationStatus": "VERIFIED"
   
}
 
},
 
"home": {
   
"params": {}
 
},
 
"device": {
   
"capabilities": [
     
"SPEECH",
     
"RICH_RESPONSE",
     
"LONG_FORM_AUDIO"
   
]
 
}
}

使场景槽位失效

您可以使槽失效,并让用户提供新值。

conv.scene.slots['slot_name'].status = 'INVALID'
{
 
"session": {
   
"id": "session_id",
   
"params": {
     
"slot_name": 1
   
}
 
},
 
"prompt": {
   
"override": false,
   
"firstSimple": {
     
"speech": "This is an example prompt.",
     
"text": ""
   
}
 
},
 
"scene": {
   
"name": "SceneName",
   
"slots": {
     
"slot_name": {
       
"mode": "REQUIRED",
       
"status": "INVALID",
       
"updated": true,
       
"value": 1
     
}
   
},
   
"next": {
     
"name": "actions.scene.END_CONVERSATION"
   
}
 
}
}

开发选项

<ph type="x-smartling-placeholder"></ph>

Actions Builder 提供了一个名为 Cloud Functions 编辑器的内嵌编辑器, 让您可以在 Firebase 控制台中直接构建和部署 Cloud Functions for Firebase, 控制台。你还可以构建执行方式并将其部署到你选择的托管 并将您的 HTTPS 执行方式端点注册为 webhook 处理程序。

內嵌编辑器

如需使用 Cloud Functions 编辑器进行开发,请执行以下操作:

  1. 打开您的 Actions 项目,然后前往 Develop 标签页 >网络钩子 >更改 fulfillment 方法。系统随即会显示 Fulfillment methods 窗口。
  2. 选择内嵌 Cloud Functions,然后点击确认

外部 HTTPS 端点

本部分介绍如何以 对话型 Action 的 fulfillment 服务。不过,你可以将 fulfillment 至您选择的托管服务。

设置环境

如需设置您的环境,请按以下步骤操作:

  1. 下载并安装 Node.js
  2. 设置并初始化 Firebase CLI。如果以下命令失败并显示 EACCES 错误,您可能需要更改 npm 权限

    npm install -g firebase-tools
  3. 使用您的 Google 账号对 Firebase 工具进行身份验证:

    firebase login
  4. 启动您保存了 Actions 项目的项目目录。 系统会要求您选择要为哪些 Firebase CLI 功能设置 您的 Actions 项目。选择Functions以及你可能需要使用的其他功能 (如 Firestore),然后按 Enter 键确认并继续:

    $ cd <ACTIONS_PROJECT_DIRECTORY>
    $ firebase init
  5. 使用以下方法将 Firebase 工具与 Actions 项目相关联: 按箭头键可浏览项目列表:

  6. 选择项目后,Firebase 工具会启动 Functions 设置,并询问您要使用哪种语言。使用箭头键进行选择 然后按 Enter 键继续。

    === Functions Setup
    A functions directory will be created in your project with a Node.js
    package pre-configured. Functions can be deployed with firebase deploy.
    
    ? What language would you like to use to write Cloud Functions? (Use arrow keys)
    > JavaScript
    TypeScript
    
  7. 选择是否要使用 ESLint 捕获可能出现的 bug 并通过输入 YN 来强制执行样式:

    ? Do you want to use ESLint to catch probable bugs and enforce style? (Y/n)
  8. 在提示符中输入 Y 来获取项目依赖项:

    ? Do you want to install dependencies with npm now? (Y/n)

    设置完成后,您将看到类似于以下内容的输出:

      Firebase initialization complete!
  9. 安装 @assistant/conversation 依赖项:

    $ cd <ACTIONS_PROJECT_DIRECTORY>/functions
    $ npm install @assistant/
    conversation --save
  10. 获取 fulfillment 依赖项并部署 fulfillment 函数:

    $ npm install
    $ firebase deploy
    --only functions

    部署需要几分钟时间。完成后,您将看到类似于 更改为以下内容。您需要在 Dialogflow 中输入函数网址

    ✔  Deploy complete!
    Project Console: https://console.firebase.google.com/project/<PROJECT_ID>/overview Function URL (<FUNCTION_NAME>): https://us-central1-<PROJECT_ID>.cloudfunctions.net/<FUNCTION_NAME>
  11. 复制履单网址,以便在下一部分中使用。

注册网络钩子处理程序

如需将 Cloud Functions 函数端点注册为网络钩子处理程序,请执行以下操作:

  1. 在 Actions 控制台中,点击 Develop >网络钩子
  2. 点击更改履单方法Fulfillment methods 窗口 。
  3. 选择网络钩子,然后点击确认
  4. 将您的 Web 服务网址粘贴到 Webhook 字段中。
  5. 点击保存