建议使用 Actions on Google Node.js 客户端库来访问和 与 Actions on Google 平台交互 执行 webhook。
简介
Node.js 客户端库是适用于 提供以下功能的 Actions on Google:
- 支持所有 Actions on Google 功能,包括文本和富媒体响应、 账号登录、数据存储、事务处理等。
- 在 JavaScript 中提供了一个惯用的抽象层,用于封装 对话 HTTP/JSON webhook API。
- 处理 fulfillment 与 Actions on Google 平台。
- 可以使用熟悉的软件包管理工具进行安装,例如
npm
或yarn
。 - 让您可以在无服务器计算平台上轻松部署 fulfillment webhook 例如 Cloud Functions for Firebase 或 AWS Lambda。您还可以托管您的 fulfillment webhook 在云服务提供商或自行托管且自行管理的环境中使用。
- 与 Node.js v6.0.0 及更高版本兼容。
您可以将客户端库与 适用于 Actions on Google 的 Dialogflow 集成 或者使用 Actions SDK 进行设置。
要查看使用客户端库的完整代码示例,您可以访问 示例页面。
查看 API 参考文档
API 参考文档托管在 Actions on Google Node.js 客户端库上 GitHub 页面。
您还可以运行以下命令来生成引用的本地副本 命令。 代码:
yarn docs
生成的文档将出现在目录的 docs
文件夹中
您下载客户端库代码的位置
了解工作原理
在使用客户端库之前,最好先了解一下 fulfillment webhook 使用客户端库来处理 Actions on Google 向您的执行方式发送。
使用 JavaScript 创建 fulfillment webhook 时,您可以部署和托管代码 无服务器计算环境(例如 Google 的 Cloud Functions for Firebase 或 AWS Lambda。您还可以自行托管代码,无需执行额外的工作 使用 Express Web 框架。
在运行时,fulfillment webhook 可以调用 客户端库处理用户请求并将响应发回 Actions on Google,用于渲染到用户输出中。
您的 fulfillment 网络钩子借助 客户端库简述如下:
![](https://developers.google.cn/static/assistant/actions/images/aog_nodejs_architecture.png?authuser=7&hl=el)
- </ph>
- 接收用户请求:当用户向 Google 助理发出请求时, Actions on Google 平台会向您的 fulfillment webhook 发送 HTTP 请求;请求 包括一个包含 intent 和其他数据(例如原始数据)的 JSON 载荷, 用户输入的文本以及用户设备的 Surface 功能。 如需查看 JSON 载荷内容的更多示例,请参阅 Dialogflow webhook 格式和 会话网络钩子格式 指南。
- 框架调用格式检测:对于受支持的框架, 客户端库会自动检测框架的调用格式(例如, 如果请求来自 Express Web 框架或 AWS Lambda),并且知道 如何无缝处理与 Actions on Google 平台的通信。
- 服务处理程序处理:客户端库代表
适用于 Dialogflow 和 Actions SDK 的对话 HTTP/JSON webhook API
即服务函数您的 fulfillment webhook 会使用相应的服务
创建全局
app
实例。app
实例充当 HTTP 的处理程序 请求并了解服务的具体协议。 - 对话处理:客户端库代表
以
Conversation
对象的形式提供每个会话的信息,并附加到app
实例。您的 fulfillment webhook 可以使用Conversation
对象执行以下操作: 检索跨对话存储的数据或状态信息、发送响应 或关闭麦克风。 - 中间件处理:借助客户端库,您可以创建自己的
自己的对话服务中间件,包含一个或多个函数
则您可以定义客户端库在调用
intent 处理程序。您的 fulfillment webhook 可以使用中间件添加属性
或辅助类添加到
Conversation
对象中。 - Intent 处理程序处理:利用客户端库,您可以定义
您的 fulfillment webhook 理解的 intent 的处理程序。对于 Dialogflow,
客户端库通过以下方式将请求路由到正确的 intent 处理程序:
映射到
Dialogflow 控制台。对于 Actions SDK,系统会根据发送的
intent
属性来路由请求 来自 Actions on Google。 - 向用户发送响应:为了构建响应,您的 fulfillment webhook
调用
Conversation#ask()
函数。ask()
函数可以 多次调用以逐步构建响应。通过 客户端库将响应序列化为 HTTP 请求,其中包含 JSON 载荷,并将其发送到 Actions on Google。close()
函数具有 行为与ask()
类似,但会关闭对话。
设置本地开发环境
在实现 fulfillment webhook 之前,请务必先安装 客户端库。
安装客户端库
将客户端库安装到本地开发环境的最简单方法
环境使用软件包管理器,例如 npm
或 yarn
。
如需安装,请从终端运行以下命令之一:
- 如果使用 npm:
npm install actions-on-google
- 如果使用 yarn:
yarn add actions-on-google
设置项目文件夹
根据您计划部署 fulfillment webhook 的位置(Google 的 Cloud Functions) (例如 Firebase、AWS Lambda 或自托管 Express),您可能需要创建一个 特定的项目文件夹结构来保存您的文件。
例如,如果您使用的是 Cloud Functions for Firebase,则可以设置
所需的项目文件夹,具体如
设置 Node.js 和 Firebase CLI 并
初始化 Firebase for Cloud Functions。对于 Cloud Functions for Firebase,您通常需要编写
/functions/index.js
文件中的 fulfillment webhook。
构建应用实例
Actions on Google 使用特定的消息格式来交换请求和响应 您的 fulfillment webhook,具体取决于您是否正在构建对话 使用 Dialogflow 或 Actions SDK 执行操作 或构建智能家居 Action。
为了表示这些不同的请求和响应协议, 客户端库提供三种服务功能:
对话 webhook 协议 两种对话服务(Dialogflow 和 Actions SDK)均使用, 服务采用不同的方式封装消息。
您可以使用服务创建 app
实例。app
实例用于封装
webhook 的全局状态和 fulfillment 逻辑,并处理
使用
协议。
您可以配置 app
实例的属性并调用其方法来
指导 fulfillment webhook 的行为。您还可以轻松插入 app
实例
无服务器计算环境,例如 Cloud Functions for Firebase,
它接受 JavaScript 函数作为 HTTP 请求的处理程序。
如需在 fulfillment webhook 中构建 app
实例,请按以下步骤操作:
调用
require()
函数以导入“actions-on-google”模块和 加载所需的服务例如,以下代码段展示了如何 可能会加载dialogflow
服务以及一些用于构建响应的元素, 并将其赋值给名为dialogflow
的常量:// Import the service function and various response classes const { dialogflow, actionssdk, Image, Table, Carousel, } = require('actions-on-google');
在这里,
actions-on-google
是指在package.json
文件中的 项目文件夹(您可以参阅 此示例package.json
文件 )。获取
app
实例时,您可以选择指定类 表示富响应、 辅助 intent 和您想使用的其他 Actions on Google 功能。对于 可加载的有效类的完整列表,请参阅有关 对话响应 和辅助意图 模块。通过调用您加载的服务来创建
app
实例。例如:const app = dialogflow();
如需在初始化时配置
app
实例,您可以提供一个options
对象作为第一个参数。(请参阅DialogflowOptions
了解更多详情。) 例如,以下代码段展示了如何在日志中记录原始 JSON 载荷: 通过设置{ debug: true }
标志来响应用户请求或响应:
const app = dialogflow({ debug: true });
设置事件处理脚本
为了处理在 用户与 Action 互动的整个生命周期中,您将使用 客户端库构建用于处理用户请求并将用户请求返回 响应。
您可以创建函数来充当以下主要类型的事件的处理程序 客户端库可识别的以下任何一项:
- intent 事件:intent 是 Actions on Google 发送的唯一标识符 您的执行方式。如果 这对应于 Dialogflow 与用户查询 添加到 Dialogflow 代理中的一个意图。
- 错误事件:当发生 JavaScript 或客户端库错误时,
可以使用
app
实例的catch
函数处理错误异常 。您应该实现单个catch
函数来处理所有 你的执行方式关注的错误 - 后备事件:当用户执行以下操作时,系统会发生后备事件
发送 Actions on Google 无法识别的查询。您可以使用
app
实例的fallback
函数来注册一个通用后备处理程序,该处理程序 如果没有与传入的执行匹配的任何 intent 处理程序,则会触发 请求。您应该实现单个fallback
函数来处理所有 后备广告事件。如果您使用的是 Dialogflow,Dialogflow 可触发特定的 后备意图。您应该创建一个 相应后备 intent 的相应 intent 处理程序。
每当用户向您的 Action 发送请求时,app
实例都会创建一个
Conversation
代表该对话会话的对象。可通过以下方式访问此对象:
conv
变量名称作为
第一个函数参数。您通常会使用 conv
对象向用户发送响应。
用户查询还可以包含您的 Action 可以提取和使用的参数 来优化回答。
- 如果您使用 Actions SDK,则可以在 Action 软件包中定义参数。 如需查看有关如何从 intent 中提取参数的示例,请参阅 Eliza 代码示例。
- 如果您使用的是 Dialogflow,则可以通过
params
变量。如需查看使用 请参阅访问参数和上下文。
为 intent 设置处理程序
如需为 intent 设置处理程序,请调用 app
的 intent()
函数
实例。例如,如果您使用的是 Dialogflow,则
DialogflowApp#intent()
函数。在参数中,指定 intent 名称并提供处理程序函数。
如果您使用的是 Dialogflow,则无需为 您的代理。作为替代方案,您可以利用 Dialogflow 的内置响应 处理程序自动处理 intent,而无需实现自己的处理程序 函数。例如, 默认欢迎意图可以是 以这种方式委托给 Dialogflow。
以下示例显示了适用于“greeting”的 intent 处理程序和“再见”
intent。其匿名处理程序函数接受 conv
参数并发回
通过 conv.ask()
函数向用户发送简单的字符串响应:
app.intent('Default Welcome Intent', (conv) => { conv.ask('How are you?'); }); app.intent('bye', (conv) => { conv.close('See you later!'); });
请注意,close()
函数类似于 ask()
,只不过它会关闭
麦克风和对话结束了。
如需详细了解如何为 intent 构建处理程序,请参阅 构建 intent 处理程序。
为错误事件设置处理程序
如需设置错误处理程序,请调用 app
的 catch()
函数
实例。(例如,如果您使用的是 Dialogflow,则
DialogflowApp#catch()
function.)
以下示例展示了一个简单的捕获错误处理程序,该处理程序将错误发送到
控制台输出并发回简单的字符串响应,
conv.ask()
函数:
app.catch((conv, error) => { console.error(error); conv.ask('I encountered a glitch. Can you say that again?'); });
设置后备事件的处理脚本
要在没有 intent 与
传入的 fulfillment 请求,请调用 的 fallback()
函数
您的 app
实例。(例如,如果您使用的是 Dialogflow,则
DialogflowApp#fallback()
function.)
以下示例展示了一个简单的回退处理程序,该处理程序将发送一个简单的
字符串响应,通过 conv.ask()
函数提示用户:
app.fallback((conv) => { conv.ask(`I couldn't understand. Can you say that again?`); });
构建 intent 处理程序
本部分介绍了实现 intent 处理程序的一些常见用例 使用客户端库查看客户端库如何匹配 请参阅“intent 处理程序处理”部分 了解运作方式。
访问参数和上下文
如果您使用的是 Dialogflow,则可以定义 parameters 和 上下文,以维护 状态信息并控制对话流
参数对于捕获用户中的重要字词、短语或值非常有用 查询。Dialogflow 会从以下位置的用户查询中提取相应的参数: 并且您可以在 fulfillment webhook 中处理这些参数值,以 决定如何响应用户。
每当用户向您的 Action 发送请求时,DialogflowApp
实例都会
用于创建 parameters
对象,该对象表示 Dialogflow 从中提取的参数值
请求。您可以通过 params
变量名称访问此对象。
以下代码段展示了如何从name
params
对象:
app.intent('Default Welcome Intent', (conv, params) => { conv.ask(`How are you, ${params.name}?`); });
下面是一个执行相同操作的替代代码段。大括号
({}
) 执行 JavaScript 解构
从 parameters
对象中获取 name
属性,并将其用作本地变量
变量:
app.intent('Default Welcome Intent', (conv, {name}) => { conv.ask(`How are you, ${name}?`); });
在以下代码段中,参数名称为 full-name
,但为
解构并赋值给名为 name
的局部变量:
app.intent('Default Welcome Intent', (conv, {'full-name': name}) => { conv.ask(`How are you, ${name}?`); });
上下文是
Dialogflow。您可以使用上下文来管理对话状态、流程和
分支。客户端库通过
DialogflowConversation#contexts
对象。以下代码段展示了如何以编程方式设置上下文
如何检索上下文对象:
app.intent('intent1', (conv) => { const lifespan = 5; const contextParameters = { color: 'red', }; conv.contexts.set('context1', lifespan, contextParameters); // ... conv.ask('...'); }); app.intent('intent2', (conv) => { const context1 = conv.contexts.get('context1'); const contextParameters = context1.parameters; // ... conv.ask('...'); }); app.intent('intent3', (conv) => { conv.contexts.delete('context1'); // ... conv.ask('...'); });
访问帮助程序 intent 结果
为方便起见,客户端库提供 辅助 intent 类 用于封装 Action 经常请求的常见用户数据类型。这些 包含表示各种 Actions on Google 结果的类 辅助意图。当您执行以下操作时,可以使用辅助 intent。 用户必须让 Google 助理来处理对话的部分内容, 提供输入继续对话。
示例:确认帮助程序结果
确认帮助程序 intent 可让
您可以要求用户作出“是/否”确认,并得到最终答案。
以下代码段展示了网络钩子如何根据自己的响应自定义
确认帮助程序 intent 返回的结果。对于
更完整的示例,请参阅
Confirmation
类参考文档。
// Create Dialogflow intent with `actions_intent_CONFIRMATION` event app.intent('get_confirmation', (conv, input, confirmation) => { if (confirmation) { conv.close(`Great! I'm glad you want to do it!`); } else { conv.close(`That's okay. Let's not do it now.`); } });
示例:轮播结果
以下代码段展示了 fulfillment 网络钩子如何自定义其响应
基于用户的输入
轮播界面。借助轮播组件
您的 Action 会提供一系列选项供用户选择。有关
完整示例,请参阅 Carousel
类参考文档。
app.intent('carousel', (conv) => { conv.ask('Which of these looks good?'); conv.ask(new Carousel({ items: { car: { title: 'Car', description: 'A four wheel vehicle', synonyms: ['automobile', 'vehicle'], }, plane: { title: 'Plane', description: 'A flying machine', synonyms: ['aeroplane', 'jet'], } } })); }); // Create Dialogflow intent with `actions_intent_OPTION` event app.intent('get_carousel_option', (conv, input, option) => { if (option === 'one') { conv.close(`Number one is a great choice!`); } else { conv.close(`Number ${option} is a great choice!`); } });
配置对话响应对象
客户端库提供了 对话响应类别 ,用于表示您的 Action 可以发送的富响应或多媒体元素。 通常在用户不需要提供回答时,您就会发送这些回复或元素 任何输入以继续对话。
示例:图片
以下代码段展示了 fulfillment webhook 如何发送
Image
响应后,系统会自动将其附加到 BasicCard
响应中。
库:
app.intent('Default Welcome Intent', (conv) => { conv.ask('Hi, how is it going?'); conv.ask(`Here's a picture of a cat`); conv.ask(new Image({ url: '/web/fundamentals/accessibility/semantics-builtin/imgs/160204193356-01-cat-500.jpg', alt: 'A cat', })); });
进行异步函数调用
Actions on Google Node.js 客户端库是专为异步而设计的 intent 处理程序可以返回一个 promise,当您的 fulfillment webhook 生成了响应。
以下代码段展示了如何对 返回一个 promise 对象,然后返回一个消息作为 fulfillment webhook 收到“问候”intent。在此代码段中,promise 可确保 fulfillment webhook 仅在收到对 外部 API 调用已解决。
在此示例中,我们使用虚构 API 来获取天气数据。
/** * Make an external API call to get weather data. * @return {Promise<string>} */ const forecast = () => { // ... }; app.intent('Default Welcome Intent', (conv) => { return forecast().then((weather) => { conv.ask('How are you?'); conv.ask(`Today's weather is ${weather}.`); }); });
以下经过简化的代码段具有相同的效果,但使用的是
async
ECMA 2017(Node.js 版本 8)中引入的 await
功能。要使用
与 Cloud Functions for Firebase 搭配使用此代码,请确保您使用的是
firebase-tools 的正确版本
并且具有正确的配置
app.intent('Default Welcome Intent', async (conv) => { const weather = await forecast(); conv.ask('How are you?'); conv.ask(`Today's weather is ${weather}.`); });
存储对话数据
客户端库允许您的 fulfillment webhook 在对话中保存数据 供日后使用。可用于数据存储的关键对象包括:
DialogflowConversation#data
或ActionsSdkConversation#data
: 在单个对话会话期间以 JSON 格式保存数据 用户与您的 Action 之间的差距。Conversation#user.storage
: 以 JSON 格式保存多个 对话会话。
以下代码段展示了 fulfillment webhook 如何将数据存储在
您定义的任意属性 (someProperty
),并将其附加到
Conversation#user.storage
对象。有关更完整的示例,请参阅
Conversation#user.storage
类参考文档。
app.intent('Default Welcome Intent', (conv) => { conv.user.storage.someProperty = 'someValue'; conv.ask('...'); });
您可以使用 Conversation#user
对象来获取用户的相关信息,包括字符串标识符和
个人信息。某些字段,例如 conv.user.name.display
和
conv.user.email
要求申请conv.ask(new Permission)
支付
分别为 Google 登录的 NAME 和conv.ask(new SignIn)
。
const {Permission} = require('actions-on-google'); app.intent('Default Welcome Intent', (conv) => { if (conv.user.last.seen) { conv.ask('Welcome back! How are you?'); } else { conv.ask('Nice to meet you! How are you doing?'); } }); app.intent('permission', (conv) => { conv.ask(new Permission({ context: 'To greet you personally', permissions: 'NAME', })); }); // Create Dialogflow intent with `actions_intent_PERMISSION` event app.intent('get_permission', (conv, input, granted) => { if (granted) { conv.close(`Hi ${conv.user.name.display}!`); } else { // User did not grant permission conv.close(`Hello!`); } });
使用中间件进行扩缩
您可以通过中间件扩展客户端库。
中间件层由您定义的一个或多个函数组成,
在调用
intent 处理程序。通过使用中间件层,您可以修改 Conversation
实例并添加其他功能。
Dialogflow 和 Actions SDK 服务公开一个 app.middleware()
函数
用于向 Conversation
添加属性或辅助类
实例。
以下代码段举例说明了如何使用中间件:
class Helper { constructor(conv) { this.conv = conv; } func1() { this.conv.ask(`What's up?`); } } app.middleware((conv) => { conv.helper = new Helper(conv); }); app.intent('Default Welcome Intent', (conv) => { conv.helper.func1(); });
导出应用
如需为 Web 框架或无服务器计算平台公开 fulfillment webhook,请执行以下操作:
您必须将 app
对象导出为可公开访问的网络钩子。通过
客户端库支持部署到多种环境
。
以下代码段展示了如何在不同运行时中导出 app
:
示例:Cloud Functions for Firebase
const functions = require('firebase-functions'); // ... app code here exports.fulfillment = functions.https.onRequest(app);
示例:Dialogflow 内嵌编辑器
const functions = require('firebase-functions'); // ... app code here // Exported function name must be 'dialogflowFirebaseFulfillment' exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
示例:自托管的 Express 服务器(简单)
const express = require('express'); const bodyParser = require('body-parser'); // ... app code here express().use(bodyParser.json(), app).listen(3000);
示例:自托管的 Express 服务器(多条路线)
const express = require('express'); const bodyParser = require('body-parser'); // ... app code here const expressApp = express().use(bodyParser.json()); expressApp.post('/fulfillment', app); expressApp.listen(3000);
示例:AWS Lambda API 网关
// ... app code here exports.fulfillment = app;