为了让您更灵活地构建 Action,您可以将逻辑委托给 HTTPS 网络服务(执行方式)。你的 Action 可以触发 向 HTTPS 端点发出请求下面列举了一些示例来说明 履单包括:
- 根据用户提供的信息生成动态提示。
- 在外部系统中下单并确认操作成功。
- 使用后端数据验证槽。
网络钩子触发器和处理程序
您的 Action 可以在调用 intent 或场景中触发网络钩子, 向您的 fulfillment 端点发送请求。您的 fulfillment 包含 webhook 用于处理请求中的 JSON 载荷的处理程序。您可以通过多种方法 以下情况:
- 调用 intent 匹配后
- 在场景的进入舞台上
- 在场景的条件阶段某个条件评估为 true 后
- 在场景的槽填充阶段
- 在场景的输入阶段发生 intent 匹配后
当您在 Action 中触发网络钩子时,Google 助理会向 包含 JSON 载荷传递到您的执行方式,该执行方式包含 用于处理事件的处理程序的名称。您的 fulfillment 端点可以 将事件路由至相应的处理程序,以执行逻辑并返回 包含 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 事件时创建提示的完整信息。 以下代码段显示了卡片提示:
Node.js
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'
    })
  }));
});
响应 JSON
{
  "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 根据类型解析输入的属性 规范
Node.js
conv.intent.params['param_name'].original
conv.intent.params['param_name'].resolved
请求 JSON
{
  "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 助理语言区域设置。
Node.js
conv.user.locale
JSON
{
  "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"
    ]
  }
}
读取和写入存储空间
请参阅存储文档,全面了解如何 使用各种存储功能。
Node.js
//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 
请求 JSON
{
  "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"
    ]
  }
}
响应 JSON
{
  "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"
    }
  }
}
检查设备功能
您可以查看设备的功能以提供不同的体验,或 对话流。
Node.js
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");
请求 JSON
{
  "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
以用替换项替换现有条目。
Node.js
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']
        },
    ]
  }
}];
响应 JSON
{
  "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 个条目
Node.js
conv.expected.speech = ['value_1', 'value_2']
conv.expected.language = 'locale_string'
响应 JSON
{
  "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 项目中定义静态过渡之外,您还可以 会导致场景转换在运行时发生。
Node.js
app.handle('transition_to_hidden_scene', conv => {
  // Dynamic transition
  conv.scene.next.name = "HiddenScene";
});
响应 JSON
{
  "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)。
Node.js
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
请求 JSON
{
  "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"
    ]
  }
}
使场景槽位失效
您可以使槽失效,并让用户提供新值。
Node.js
conv.scene.slots['slot_name'].status = 'INVALID'
响应 JSON
{
  "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">Actions Builder 提供了一个名为 Cloud Functions 编辑器的内嵌编辑器, 让您可以在 Firebase 控制台中直接构建和部署 Cloud Functions for Firebase, 控制台。你还可以构建执行方式并将其部署到你选择的托管 并将您的 HTTPS 执行方式端点注册为 webhook 处理程序。
內嵌编辑器
如需使用 Cloud Functions 编辑器进行开发,请执行以下操作:
- 创建文件 sdk/webhooks/ActionsOnGoogleFulfillment.yaml。 以及定义 Action 的处理程序和使用的内嵌 Cloud Functions 函数 。handlers: - name: questionOnEnterFunc - name: fruitSlotValidationFunc inlineCloudFunction: executeFunction: ActionsOnGoogleFulfillment
- 创建文件夹 sdk/webhooks/ActionsOnGoogleFulfillment。 然后添加一个index.js文件来实现这些处理程序 定义 npm 的package.json文件 代码要求// index.js const {conversation} = require('@assistant/conversation'); const functions = require('firebase-functions'); const app = conversation(); app.handle('questionOnEnterFunc', conv => { conv.add('questionOnEnterFunc triggered on webhook'); }); app.handle('fruitSlotValidationFunc', conv => { conv.add('fruitSlotValidationFunc triggered on webhook'); }); exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app); // package.json { "name": "ActionsOnGoogleFulfillment", "version": "0.1.0", "description": "Actions on Google fulfillment", "main": "index.js", "dependencies": { "@assistant/conversation": "^3.0.0", "firebase-admin": "^5.4.3", "firebase-functions": "^0.7.1" } } 
外部 HTTPS 端点
本部分介绍如何以 对话型 Action 的 fulfillment 服务。不过,你可以将 fulfillment 至您选择的托管服务。
设置环境
在将 Cloud Functions 函数用于 将 Firebase 作为执行方式服务:
ProjectFolder - Root folder for the project sdk - Actions project configuration files functions - Cloud functions for Firebase files
如需设置您的环境,请按以下步骤操作:
- 下载并安装 Node.js。
- 设置并初始化 Firebase CLI。如果以下命令失败并显示 - EACCES错误,您可能需要更改 npm 权限。- npm install -g firebase-tools
- 使用您的 Google 账号对 Firebase 工具进行身份验证: - firebase login
- 启动您保存了 Actions 项目的项目目录。 系统会要求您选择要为哪些 Firebase CLI 功能设置 您的 Actions 项目。选择 - Functions以及你可能需要使用的其他功能 (如 Firestore),然后按 Enter 键确认并继续:- $ cd <ACTIONS_PROJECT_DIRECTORY> $ firebase init
- 使用以下方法将 Firebase 工具与 Actions 项目相关联: 按箭头键可浏览项目列表: 
- 选择项目后,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 
- 选择是否要使用 ESLint 捕获可能出现的 bug 并通过输入 Y 或 N 来强制执行样式: - ? Do you want to use ESLint to catch probable bugs and enforce style? (Y/n) 
- 在提示符中输入 Y 来获取项目依赖项: - ? Do you want to install dependencies with npm now? (Y/n) - 设置完成后,您将看到类似于以下内容的输出: - ✔ Firebase initialization complete!
- 安装 @assistant/conversation 依赖项: - $ cd <ACTIONS_PROJECT_DIRECTORY>/functions $ npm install @assistant/conversation --save
- 获取 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>
- 复制履单网址,以便在下一部分中使用。 
注册网络钩子处理程序
- 创建文件 sdk/webhooks/ActionsOnGoogleFulfillment.yaml,并定义 Action 的处理程序和 webhook 请求的网址。httpsEndpoint: baseUrl: https://my.web.hook/ActionsOnGoogleFulfillment endpointApiVersion: 2 handlers: - name: questionOnEnterFunc - name: fruitSlotValidationFunc 
