使用 Google 助理和 Cloud Firestore 进行拼写练习游戏

1. 概览

Google 助理是一款虚拟智能个人助理,借助 Google 助理开发者平台,您可以打造软件,从而为超过 10 亿台设备(包括智能音箱、手机、汽车、电视、头戴式耳机等)扩展 Google 助理的功能。用户可通过对话与 Google 助理互动,以这种方式处理各种事务,例如购买日用品或约车。作为开发者,您可以使用 Google 助理开发者平台在用户和您自己的第三方履约服务之间轻松打造并管理愉悦、高效的对话体验。

本 Codelab 介绍了 Google 助理、Cloud Functions 和 Cloud Firestore 相关开发的中级概念。在此 Codelab 中,您将构建一款名为“拼写练习”的游戏,该游戏使用 Google 助理要求用户拼写单词。

构建内容

在此 Codelab 中,您将构建一个具有以下功能的复杂游戏:

  • 接收用户的拼写回答,并根据收集到的值修改对话提示
  • 提供与单词拼写相关的提示,例如单词的定义或重复单词
  • 创建游戏循环,以便用户能够在拼写完单词后再次与 Google 助理互动

开始构建之前,您可以在内置 Google 助理的设备上与实际 Action 进行互动,只需说出“Hey Google,跟 Spelling Practice 聊聊”即可。回访用户与该 Action 互动的默认路径如下所示:

完成本 Codelab 的学习后,您构建的 Action 将具有以下对话流:

2e9f94dc0ceafc96.png

学习内容

  • 如何与 Cloud Firestore 互动
  • 如何使用槽向用户收集数据
  • 如何处理用户的输入并返回回应
  • 如何使用条件向场景添加逻辑
  • 如何添加游戏循环

所需条件

学习本 Codelab 前,您需要做好以下准备:

  • 网络浏览器,例如 Google Chrome
  • 用于编写 Cloud Functions 函数的 IDE。
  • 付款方式。此 Codelab 使用 Cloud Functions for Firebase,因此您的项目必须采用 Firebase Blaze 定价方案(了解详情)。
  • 用于运行 shell 命令的终端
  • Node.js 10 或更高版本

2. 获取函数代码

从命令行克隆 GitHub 代码库

$ git clone https://github.com/FirebaseExtended/codelab-actions-firestore

3. 创建 Firebase 项目并设置应用

创建 Firebase 项目

  1. 登录 Firebase
  2. 在 Firebase 控制台中,点击 Add Project(或 Create a project),然后将您的 Firebase 项目命名为 Spelling-Practice

66ae8d1894f4477.png

  1. 点击各个项目创建选项。如果系统提示,请接受 Firebase 条款。跳过设置 Google Analytics 的步骤,因为您不会对此应用使用 Google Analytics。

如需详细了解 Firebase 项目,请参阅了解 Firebase 项目

升级到 Blaze 定价方案

如需使用 Cloud Functions for Firebase,您需要将 Firebase 项目升级到 Blaze 定价方案,这意味着您需要将 Google Cloud 结算账号附加到您的项目。这需要您提供信用卡或其他付款方式。

所有 Firebase 项目(包括采用 Blaze 方案的项目)仍然可以享受 Cloud Functions 的免费用量配额。此 Codelab 中列出的步骤将不会超出免费用量限额。不过,您会看到 Cloud Storage 产生少量费用(约 0.03 美元),该费用用于托管 Cloud Functions 构建映像。

4. 安装 Firebase CLI

借助 Firebase CLI(命令行界面),您可以部署 Cloud Functions。

您可以根据自己的操作系统和使用情形,选择多种安装 Firebase CLI 的方式。如果您还使用 Cloud Functions,以下步骤介绍了最常见的选项。

  1. 请务必安装 npm(通常随 Node.js 一起安装)。
  2. 运行以下 npm 命令来安装或升级 CLI:
$ npm -g install firebase-tools
  1. 通过运行以下命令来验证 CLI 是否已正确安装:
$ firebase --version

确保 Firebase CLI 的版本为 9.0.0 或更高版本,这样它才具备 Cloud Functions 所需的全部最新功能。如果不是,请运行 npm install -g firebase-tools 进行升级,如上所示。

  1. 运行以下命令,向 Firebase CLI 授权:
$ firebase login
  1. 从 spelling-functions-start 目录中,设置 Firebase CLI 以使用您的 Firebase 项目。运行以下命令,选择您的项目 ID,然后按照说明操作。当系统提示您输入别名时,您可以选择任意别名,例如 codelab
$ firebase use --add

5. functions 目录

现在,您将使用 Firebase SDK for Cloud Functions 添加功能,以构建游戏拼写练习的后端。

借助 Cloud Functions,您可以让代码在云端运行,而无需设置服务器。此 Codelab 将向您展示如何构建对 Firebase 身份验证、Cloud Storage 和 Firebase 实时数据库事件做出响应的函数。我们先从身份验证开始。

使用 Firebase SDK for Cloud Functions 时,您的函数代码将位于 functions 目录(默认情况下)。为方便起见,我们已创建 functions/index.js 文件,您可以在其中编写代码。在继续操作之前,您可以先检查 functions 目录。

$ cd functions
$ ls

函数代码也是一个 Node.js 应用,因此需要一个 package.json 来提供有关应用的一些信息并列出依赖项。

如果您不熟悉 Node.js,建议您先详细了解它,然后再继续学习本 Codelab。

package.json 文件已列出两个必需的依赖项:Firebase SDK for Cloud FunctionsFirebase Admin SDK。如需在本地安装这些软件包,请从 functions 目录运行 npm install

$ npm install

现在,我们来看看 index.js 文件:

index.js

/**
 * Copyright 2021 Google Inc. All Rights Reserved.
 * ...
 */
// TODO(DEVELOPER): Import the Cloud Functions for Firebase and Firebase Admin modules here. Also import the Actions SDK here.
// TODO(DEVELOPER): Write the getWordDetailsFromDictionaryAPI function here.
// TODO(DEVELOPER): Write the createSpellingPracticeWord function here.
// TODO(DEVELOPER): Write the app Handle getSpellingWordList function here.
// TODO(DEVELOPER): Write the app Handle getSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle repeatSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle definitionOfSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle verifySpellingWord function here.

您将首先导入所需的模块,然后编写四个函数来替换 TODO。继续执行此 Codelab 的下一步,以导入模块。

6. 导入所需的模块

此 Codelab 需要三个模块。

  • 借助 firebase-functions 模块,我们可以为 Cloud Functions 编写触发器
  • 借助 firebase-admin 模块,我们可以在具有管理员访问权限的服务器上使用 Firebase 平台,例如写入 Cloud Firestore。
  • Actions SDK Node.js 执行方式库可为 Google 助理实现 Actions SDK 处理程序。
  1. 运行以下 npm 命令来安装 Actions SDK:
$ npm install @assistant/conversation
  1. index.js 文件中,将第一个 TODO 替换为以下内容。

这些更改会导入每个必需的模块。

此外,当部署在 Cloud Functions 环境或其他 Google Cloud 容器中时,Firebase Admin SDK 可以自动配置。以下更改中调用 admin.initializeApp(); 时会发生这种情况。

index.js

/**
 * Copyright 2021 Google Inc. All Rights Reserved.
 * ...
 */

// Import the Actions SDK
const {conversation} = require('@assistant/conversation');
const https = require('https');
const app = conversation();
const cors = require('cors')({origin: true});

// Import the Firebase SDK for Cloud Functions.
const functions = require('firebase-functions');
// Import and initialize the Firebase Admin SDK.
const admin = require('firebase-admin');
admin.initializeApp();
// To access Cloud Firestore
const db = admin.firestore();
// TODO(DEVELOPER): Write the getWordDetailsFromDictionaryAPI function here.
// TODO(DEVELOPER): Write the createSpellingPracticeWord function here.
// TODO(DEVELOPER): Write the shuffleWordList function here.
// TODO(DEVELOPER): Write the app Handle getSpellingWordList function here.
// TODO(DEVELOPER): Write the app Handle getSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle repeatSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle definitionOfSpellingWord function here.
// TODO(DEVELOPER): Write the app Handle verifySpellingWord function here.

现在,我们来添加使用函数支持 Google 助理操作的业务逻辑。

7. 创建函数

获取字词释义并将其写入 Cloud Firestore

您将使用 dictionaryapi.dev 公共 API 获取字词定义。

index.js 文件中,将 getWordDetailsFromDictionaryAPI 的 TODO 替换为以下内容:

index.js

// Retrieves word definition and audio pronunciation from api.dictionaryapi.dev service
// Function uses service provided by https://dictionaryapi.dev/
async function getWordDetailsFromDictionaryAPI(word) {
  let responseData="";
  let req = https.request({
    host: 'api.dictionaryapi.dev',
    port: 443,
    path:'/api/v2/entries/en/' + word,
    method:'GET'
  }, (res) => {
    res.setEncoding('utf8');
    res.on('data', d => {
        responseData+=d;
    })
    res.on('end',function(){
        let object = JSON.parse(responseData)
        const wordListRef = db.collection('wordlist');
        wordListRef.doc(object[0].word).set(
          object[0]
        );
       return responseData;
     });
  });
  req.end();
}

添加 Cloud Firestore 触发器

接下来,您将创建一个 Cloud Functions 函数,该函数会在 Cloud Firestore 中创建新文档时触发。它将调用 dictionaryapi.dev API,通过我们刚刚编写的 getWordDetailsFromDictionaryAPI 函数获取字词定义。

index.js 文件中,将 createSpellingPracticeWord 的 TODO 替换为以下内容:

index.js

// Firestore 触发器,用于通过 getWordDetailsFromDictionaryAPI 为每个新的 Firestore 文档获取字词定义

exports.createSpellingPracticeWord = functions.firestore
  .document('wordlist/{word}')
  .onCreate((snap, context) => {
    const newValue = snap.data();
    const word = newValue.word;
    getWordDetailsFromDictionaryAPI(word);
});

获取游戏用字词列表

您可以编写一个 Cloud Functions 函数,用于从 Cloud Firestore 中检索拼写练习字词列表,以供 Google 助理使用。为此,我们使用应用处理程序。

index.js 文件中,将 getSpellingWordList 的 TODO 替换为以下内容。

将此函数添加到特殊 app.handle 中,即可通过 Google 助理访问该函数。

index.js

// Store the list of spelling words in Assistant session
app.handle('getSpellingWordList', conv => {
  const wordListRef = db.collection('wordlist').limit(50);
  const snapshot = wordListRef;

  if (snapshot.empty) {
    console.log('No matching documents.');
    return;
  }
  VocabularyList = []

  return snapshot.get().then(snapshot => {
    snapshot.forEach(doc => {
      if (doc.data().word) {
          let definition = 'unknown';
          let audio = 'unknown';
          try {
            if(doc.data().hasOwnProperty('meanings')) {
              if(doc.data().meanings[0].hasOwnProperty('definitions')) {
                  definition = doc.data().meanings[0].definitions[0].definition;
              }
            }
            if(doc.data().hasOwnProperty('phonetics')) {
              if(doc.data().phonetics.length > 0)
                audio = doc.data().phonetics[0].audio;
            }
          } catch (error) {
            console.log(error);
          }

          let obj = {
            word: doc.data().word,
            answer: doc.data().word.split("").join(" "),
            definition: definition,
            audio: audio
          }
          VocabularyList.push(obj);
      }
      // Shuffle the array
      let currentIndex = VocabularyList.length, temporaryValue, randomIndex;
      while (0 !== currentIndex) {
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;
        temporaryValue = VocabularyList[currentIndex];
        VocabularyList[currentIndex] = VocabularyList[randomIndex];
        VocabularyList[randomIndex] = temporaryValue;
      }
      conv.session.params.vocabWord = VocabularyList;
      conv.session.params.vocabWordIndex = 0;
    });
  });
})

从 Google 助理会话中获取字词

您可以编写一个 Cloud Functions 函数,用于从单词列表中返回下一个拼写单词。

index.js 文件中,将 getSpellingWord 的 TODO 替换为以下内容:

index.js

// Returns a spelling practice word to Google Assistant and uses Speech Synthesis Markup Language (SSML) to format the response
app.handle('getSpellingWord',  conv => {
  if (!conv.session.params.vocabWord.empty) {
    conv.session.params.vocabWordIndex+=1;
    const ssml = '<speak>' +
    '<audio src="'+ conv.session.params.vocabWord[conv.session.params.vocabWordIndex].audio +'">Use phonetics to spell the word.</audio> ' +
    '</speak>';
    conv.add(ssml);
  }
  else
    conv.add('Great job! You completed the Spelling practice');
});

让游戏重复播放字词

您可以编写一个 Cloud Functions 函数,用于重复游戏中的当前字词。

index.js 文件中,将 repeatSpellingWord 的 TODO 替换为以下内容:

index.js

// Returns current spelling word
app.handle('repeatSpellingWord',  conv => {
  if (!conv.session.params.vocabWord.empty) {
    const ssml = '<speak>' +
    '<audio src="'+ conv.session.params.vocabWord[conv.session.params.vocabWordIndex].audio +'">Use phonetics to spell the word. </audio> ' +
    '</speak>';
    conv.add(ssml);
  }
  else
    conv.add('Great job! You completed the Spelling practice');
});

获取字词的定义

您可以编写一个 Cloud Functions 函数,用于提供游戏当前字词的定义。

index.js 文件中,将 definitionOfSpellingWord 的 TODO 替换为以下内容:

index.js

// Returns spelling word definition from Assistant session parameter
app.handle('definitionOfSpellingWord',  conv => {
  conv.add( 'It means ' + conv.session.params.vocabWord[conv.session.params.vocabWordIndex].definition);
});

检查用户的拼写回答

您可以编写一个 Cloud Functions 函数,用于验证用户对游戏当前单词拼写方式的回答。

index.js 文件中,将 verifySpellingWord 的 TODO 替换为以下内容:

index.js

// Verifies user spelling response
app.handle('verifySpellingWord', conv => {
  try {
    userResponse = conv.intent.params.userresponse.resolved.join("");
    if (userResponse.toLowerCase() === conv.session.params.vocabWord[conv.session.params.vocabWordIndex].word.toLowerCase()) {
      conv.add('You are correct. Say next to continue.');
    }
    else {
      conv.add('Sorry, wrong answer. The correct answer is ' + conv.session.params.vocabWord[conv.session.params.vocabWordIndex].answer + ' . Say next to continue.');
    }
  } catch (error) {
    conv.add('Sorry. I did not understand your response' );
  }
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

部署所有函数

只有在将 Cloud Functions 部署到 Firebase 后,它们才会处于有效状态。

spelling-functions-start 目录的根目录中,运行以下命令:

$ firebase deploy --only functions

您应该会看到以下控制台输出:

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
⚠  functions: missing necessary APIs. Enabling now...
i  env: ensuring necessary APIs are enabled...
⚠  env: missing necessary APIs. Enabling now...
i  functions: waiting for APIs to activate...
i  env: waiting for APIs to activate...
✔  env: all necessary APIs are enabled
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (X.XX KB) for uploading
✔  functions: functions folder uploaded successfully
i  starting release process (may take several minutes)...
i  functions: creating function createSpellingPracticeWord(us-central1)...
✔  functions[createSpellingPracticeWord(us-central1)]: Successful create operation.
i  functions: creating function ActionsOnGoogleFulfillment(us-central1)...
✔  functions[ActionsOnGoogleFulfillment(us-central1)]: Successful create operation.

✔  Deploy complete!
Project Console: https://console.firebase.google.com/project/spelling-practice-1234/overview

记下 ActionsOnGoogleFulfillment 函数的 HTTP 端点网址,以备后用。如需获取端点,请打开 Firebase 控制台,然后点击 spelling-practice 项目。打开 Functions 信息中心以查看函数端点。

332cb0437411a242.png

您已完成添加所有必需的函数。现在,我们来设置 Cloud Firestore。

8. 启用 Cloud Firestore

您需要启用 Cloud Firestore。

在 Firebase 控制台的构建部分中,点击 Firestore。然后,点击创建数据库

5c0b4abf4410ffcf.png

对 Cloud Firestore 中数据的访问受到安全规则控制。首先,您需要针对数据设置一些基本规则。点击 Firestore,然后在 Firebase 控制台的“规则”标签页中,添加以下规则,然后点击发布

以下规则会限制已登录用户对数据的访问,以防止未经身份验证的用户执行读写操作。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      //
      // WARNING: These rules are insecure! We will replace them with
      // more secure rules later in the codelab
      //
      allow read, write: if request.auth != null;
    }
  }
}

9. 向 Cloud Firestore 添加拼写字词数据

在此步骤中,您将把拼写单词数据写入 Cloud Firestore,以便为 Google 助理(和游戏)生成单词列表。

Cloud Firestore 数据分为集合、文档、字段和子集合。游戏中的每个字词都将以单独的文档形式存储在名为 wordlist 的顶级集合中。对于 Firestore 集合中的每个新文档,系统都会触发 createSpellingPracticeWord 函数,以从 Dictionary API 服务获取字词详细信息。

创建 Cloud Firestore 集合

  1. 在 Firebase 控制台中,前往 Cloud Firestore 部分。
  2. 点击 + 开始使用集合
  3. 集合 ID 文本框中,输入 wordlist,然后点击下一步

1b4ccadb90f52f02.png

接下来,我们将为单词“agreement”创建文档:agreement

  1. 文档 ID 文本框中,输入 agreement
  2. 字段文本框中,输入 word;在文本框中,输入 agreement
  3. 点击保存

379037e011e8511e.png

当您将此文档添加到 Cloud Firestore 时,系统会触发 createSpellingPracticeWord 函数来获取相应字词的定义详情。为每个字词创建一个新文档,添加更多字词(例如:awe、car、true、tell、better、commute 等)。

10. 设置 Google 助理

以下部分介绍了如何设置 Google 助理开发环境,以及如何创建 Actions 项目。

检查 Google 权限设置

如需测试您在本 Codelab 中构建的 Action,您需要启用必要的权限,以便模拟器能够访问您的 Action。如需启用权限,请按以下步骤操作:

  1. 前往活动控件页面。
  2. 使用您的 Google 账号登录(如果您尚未登录的话)。
  3. 启用以下权限:
  • 网络与应用活动记录
  • 网络与应用活动记录下,选中包括 Chrome 历史记录和使用 Google 服务的网站、应用和设备上的活动记录旁边的复选框。

c988e1e639e6d6e1.png

创建一个 Actions 项目

您的 Actions 项目是您的 Action 的容器。如需为本 Codelab 创建 Actions 项目,请按以下步骤操作:

  1. 打开 Actions 控制台
  2. 点击 New project
  3. 接受服务条款

b174d45710b8086b.png

  1. 输入或选择您使用 Firebase 控制台创建的 spelling-practice-codelab。(该名称供内部参考。之后您还可以为项目设置外部名称。)

a2951de5d2001fac.png

  1. 点击导入项目
  2. What kind of Action do you want to build? 界面中,选择 Custom 卡片。
  3. 点击下一步
  4. 选择 Blank project 卡片。
  5. 点击 Start building
  6. 输入 Spelling Practice 作为显示名称,然后点击“保存”。

用户通过调用与您的 Action 开始对话。例如,用户可以使用如下指令调用您的 Action:“Hey Google, talk to Spelling Practice”,其中“Spelling Practice”为显示名。

如果您要将 Action 部署到生产环境,则该 Action 必须具有显示名;不过,您无需定义显示名即可测试 Action。相反,您可以在模拟器中使用指令“Talk to my test app”来调用 Action。

配置 fulfillment

您需要连接到在本 Codelab 前面部分编写和部署的 Cloud Functions 的事件处理程序。

如需配置执行方式,请按以下步骤操作:

  1. 点击侧边导航栏中的 Webhook
  2. 选择 Https 端点作为实现选项:

d523bf003e96e66f.png

  1. HTTPs 端点文本框中输入函数端点的网址,然后点击保存

be53e2cd0d914d54.png

在下一部分中,您将在 Actions 控制台中为主调用自定义提示。

设置主调用

您必须修改主调用,定义在用户调用您的 Action 后会发生什么。

默认情况下,Actions Builder 会在您的调用触发后提供通用提示(“Start building your Action by defining main invocation.”)。

如需修改 Action 在被用户调用后向用户发回的提示,请按以下步骤操作:

  1. 点击导航栏中的 Main invocation

9ff088c04c995cde.png

  1. 选中 Call your webhook,然后在文本框中添加事件处理脚本名称 getSpellingWordList
  2. 在代码编辑器中,将 speech 字段中的文本替换为以下欢迎消息:Welcome to Spelling Practice

注意:您可以使用 YAMLJSON 格式修改提示。

  1. 点击保存

在模拟器中测试主调用

Actions 控制台提供了用于测试 Action 的网络工具,称为模拟器。界面会模拟硬件设备及其设置,让您可以与 Action 进行对话,就像该 Action 在智能显示屏、手机、音箱或 KaiOS 上运行时一样。

若要在模拟器中测试 Action 的主调用,请按以下步骤操作:

  1. 在顶部导航栏中,点击 Test 以转到模拟器。
  2. 如需在模拟器中调用您的 Action,请在左上角的输入字段中输入 Talk to Spelling Practice,然后按键盘上的 Enter 键。

651fc8da1ac9aa0a.png

在您触发 Action 的主调用后,Google 助理会使用您的自定义欢迎消息进行回应。此时,对话会在 Google 助理使用问候语进行回应后结束。

查看事件日志

进入 Test 标签页后,右侧面板会显示事件日志,此类日志会以事件日志形式显示对话记录。每个事件日志都会显示相应对话期间发生的事件。如需查看活动日志,请点击活动前的灰色图标。

您的 Action 目前有一个事件日志,它显示了用户的输入(“Talk to Spelling Practice”)和 Action 的回应。下方的屏幕截图显示了该 Action 的事件日志:

a6fb192f94426824.png

11. 为拼写练习构建对话

您已经定义了用户调用您的 Action 后会发生什么,可以构建 Action 会话的其余内容了。拼写练习有四个场景,您必须先激活各个场景,Action 才能运行。激活场景的最常用方法是配置 Action,使得在用户说出的话语与场景中的用户 intent 匹配时,相应 intent 会触发向另一个场景的过渡并激活该场景。

从主调用过渡到起始场景

在本部分中,您将创建一个名为 Start 的新场景,它会向用户发送提示,以询问用户是否要开始玩拼写练习。您还可以添加从主调用向新的 Start 场景的过渡。

如需创建该场景并添加向该场景的过渡,请按以下步骤操作:

  1. 点击顶部导航栏中的 Develop。然后,点击左侧导航栏中的 Main invocation
  2. 在右侧的 Transition 部分中,点击下拉菜单,然后在文本字段中输入 Start

dd4f1807a57f794d.png

  1. 点击 Add(添加)。这样即可创建一个名为“Start”的场景,并告知 Action 在向用户发送欢迎提示后过渡到 Start 场景。
  2. 点击左侧导航栏中的 Scenes 以显示场景列表。
  3. Scenes 下,点击 Start 以查看 Start 场景。
  4. 点击 Start 场景的 On enter 部分中的 +
  5. 选择 Send prompts
  6. speech 字段中的句子 (Enter the response that users will see or hear...) 替换为向用户询问的问题:Use phonetic alphabet to spell the word. For example alpha for a, bravo for b, charlie for c etc. Do you want to continue?

建议内容信息卡可以为用户提供可点击的建议内容,而您的 Action 可以将此类内容作为用户输入进行处理。在本部分中,您将添加在刚才配置的提示 (Do you want to play

Spelling Practice

?)以支持使用带屏幕设备的客户。

如需在 Start 场景的提示中添加建议内容信息卡,请按以下步骤操作:

  1. Start 场景中,点击代码编辑器下方的建议。该操作可以添加一个建议内容信息卡。
  2. title 字段中,将 Suggested Response 替换为 'Yes'
  3. 按相同的格式手动添加标题为“'No'”和“'Help with Phonetics'”的建议内容信息卡。您的代码应类似于以下代码段:
  4. 点击保存

5ff2ecdc56801b91.png

在模拟器中测试您的 Action

此时,您的 Action 应该从主调用过渡为 Start 场景,并询问用户是否要继续。模拟显示屏中还应显示建议内容信息条。

如需在模拟器中测试您的 Action,请按以下步骤操作:

  1. 在导航栏中,点击 Test 以转到模拟器。
  2. 如需在模拟器中测试您的 Action,请在“输入”字段中输入 Talk to Spelling Practice
  3. Enter 键。您的 Action 应该以 Main invocation 提示和添加的 Start 场景提示(“Welcome to Spelling Practice. 使用音标拼写该字词。例如,a 为 alpha,b 为 bravo,c 为 charlie 等。您要继续吗?”

以下屏幕截图显示了该互动情况:

338c9570b02a618e.png

  1. 点击 YesNoHelp with Phonetics 建议内容信息卡以回应提示。(您也可以说“Yes”或“No”或“Help with Phonetics”,或在 Input 字段中输入 YesNoHelp with Phonetics。)

在您回应提示后,您的 Action 会以一条消息作为回应,指出其无法解读您的输入:“Sorry, I didn't catch that. Can you try again?”由于您尚未配置 Action 来使其理解和回应“Yes”或“No”输入,因此该 Action 会将您的输入匹配到 NO_MATCH intent。

默认情况下,NO_MATCH 系统 intent 会提供通用回应,但您可以自定义此类回应,以向用户表明您无法理解其输入。如果无法匹配用户输入的次数达到 3 次,Google 助理就会结束用户与 Action 之间的对话。

添加“否”和拼音 intent

现在,用户可以回应您的 Action 提出的问题了,接下来您可以配置该 Action,使其能够理解用户的回应(“Yes”“No”或“Help with Phonetics”)。在后面的部分中,您将创建在用户说出“Yes”“No”或“Help with Phonetics”后系统所匹配的用户 intent,然后向 Start 场景添加相应 intent。我们将使用系统 intent yes 并创建其他 intent。

创建 no intent

现在,您需要创建 no intent,以使 Action 在用户不想玩游戏时正确理解并做出响应。如需创建此 intent,请按以下步骤操作:

  1. 点击导航栏中的 Develop
  2. 点击导航栏中的 Custom Intents 以打开 intent 列表。
  3. 点击 intent 列表底部的 +(加号)。将新 intent 命名为 no,然后按 Enter 键。
  4. 点击 no 以打开 no intent 页面。
  5. Add training phrases 部分中,点击 Enter Phrase 文本框,然后输入以下短语:
  • No
  • N
  • I don't want
  • nope

98b0c9a7b67ea9b9.png

  1. 点击保存

Start 场景添加 no intent

现在,如果用户表达“no”或类似于“no”的内容(例如“nope”),该 Action 便可以作出正确理解。您需要向 Start 场景添加 no 用户 intent,因为用户响应的是 Start 提示(“Welcome to Spelling Practice. 使用音标拼写该字词。例如,a 为 alpha,b 为 bravo,c 为 charlie 等。您要继续吗?”)。

如需为 Start 场景添加此 intent,请按以下步骤操作:

  1. 点击导航栏中的 Start 场景。
  2. 点击 Start 场景中的“User intent handling”旁边的 +(加号)
  3. Intent 部分中,从下拉菜单中选择 no

51f752e78c8b4942.png

  1. 点击 Send prompts,然后将 speech 字段更新为以下文本:Good Bye

编辑器中的代码应类似于以下代码段:

candidates:
  - first_simple:
      variants:
        - speech: >-
             Goodbye.
  1. Transition 部分中,从下拉菜单中选择 End conversation
  2. 点击保存

在模拟器中测试 no intent

此时,您的 Action 会了解用户何时不想玩游戏并返回相应的回应。

如需在模拟器中测试此 intent,请按以下步骤操作:

  1. 在导航栏中,点击 Test
  2. 在“Input”字段中输入 Talk to Spelling Practice,然后按 Enter
  3. Input 字段中输入 No,然后按 Enter 键。或者,点击“否”建议内容信息卡。

7727a456b522f31b.png

Start 场景添加系统 YES intent

现在,我们将 SYSTEM intent "YES" 添加到 Start 场景,因为用户对 Start 提示(“Welcome to Spelling Practice. 使用音标拼写该字词。例如,a 为 alpha,b 为 bravo,c 为 charlie 等。您要继续吗?”)。

如需向 Start 场景添加该用户 intent,请按以下步骤操作:

  1. 点击导航栏中的 Start 场景。
  2. 点击 Start 场景中的 User intent handling 旁边的 +(加号)
  3. 在“所有系统 intent”下,从 intent 下拉菜单中选择 YES

f6cbe789cde49e8f.png

  1. 点击 Call your webhook,然后使用您之前创建的函数更新 event handler 文本框:getSpellingWordList
  2. Transition 部分中,点击下拉菜单,然后选择 End conversation
  3. 点击保存

在模拟器中测试 YES intent

此时,如果用户要玩游戏,您的 Action 便可以正确理解并返回适当回应了。

如需在模拟器中测试此 intent,请按以下步骤操作:

  1. 在导航栏中,点击 Test
  2. 如需在模拟器中测试您的 Action,请在 Input 字段中输入 Talk to Spelling Practice,然后按 Enter 键。
  3. Input 字段中输入 Yes,然后按 Enter 键。或者,点击 Yes 建议内容信息卡。

您的操作会提取所有拼写练习字词的列表,并将其存储在会话中。然后,Action 会终止对话,因为您为 YES intent 选择了 End conversation 过渡。

创建 Phonetics intent

如需创建 Phonetics intent,请按以下步骤操作:

  1. 点击导航栏中的 Develop
  2. 点击导航栏中的 Custom Intents 以打开 intent 列表。
  3. 点击 intent 列表底部的 +(加号)。将新 intent 命名为 phonetics,然后按 Enter
  4. 点击 phonetics intent 以打开 phonetics intent 页面。
  5. 在“添加训练短语”部分中,点击输入短语文本框,然后输入以下短语:
  • how do I spell words
  • phonetics
  • help me with phonetics
  • phonetic alphabet

1455bdfca8dae46.png

  1. 点击保存

Start 场景添加 phonetics intent

现在,如果用户表达“phonetics”intent,该 Action 便可以作出正确理解。您可以向 Start 场景添加 phonetics 用户 intent,因为用户会回应 Start 提示(“Welcome to Spelling Practice. 使用音标拼写该字词。例如,a 为 alpha,b 为 bravo,c 为 charlie 等。您要继续吗?”)。

如需向 Start 场景添加该用户 intent,请按以下步骤操作:

  1. 点击导航栏中的 Start 场景。
  2. 点击 Start 场景中“User intent handling”旁边的 +(加号)。
  3. 在 intent 下拉菜单中选择 phonetics

67ee2e08000b2aee.png

  1. Transition 部分中,点击下拉菜单,然后选择 End conversation
  2. 点击保存

从“开始”场景过渡到“拼写”场景

在本部分中,您将创建一个名为 Spelling 的新场景,该场景会向用户发送提示,要求用户使用音标拼写单词。

如需创建该场景并添加向该场景的过渡,请按以下步骤操作:

  1. 点击顶部导航栏中的 Develop。然后,点击左侧导航栏中的 Start 场景。
  2. 用户意图处理部分中,点击 when actions.intent.YES is matched,然后在右侧的过渡部分中,点击下拉菜单,并在文本字段中输入 Spelling
  3. 点击 Add(添加)。这样即可创建一个名为“Spelling”的场景,并告知 Action 在匹配到 YES 意图后过渡到 Spelling 场景。
  4. 展开左侧导航栏中的场景以显示场景列表。
  5. Scenes 下,点击“拼写”以查看 Spelling 场景。
  6. 点击 Spelling 场景的 On enter 部分中的 +
  7. 点击 Call your webhook,然后在事件处理脚本文本框中输入 getSpellingWord
  8. 选择 Send prompts
  9. speech 字段中的句子 (Enter the response that users will see or hear...) 替换为 {}。实际提示将通过网络钩子填充。

建议内容信息卡可以为用户提供可点击的建议内容,而您的 Action 可以将此类内容作为用户输入进行处理。

如需在 Spelling 场景的提示中添加建议内容信息卡,请按以下步骤操作:

  1. Spelling 场景中,点击代码编辑器下方的建议。该操作可以添加三个建议内容信息卡。
  2. title 字段中,将 Suggested Response 替换为 'Repeat'
  3. 按相同的格式手动添加标题为“'Skip'”的建议内容信息卡。
  4. 按相同的格式手动添加标题为“'Quit'”的建议内容信息卡。您的代码应类似于以下代码段:
  5. 点击保存
suggestions:
      - title: 'Repeat'
      - title: 'Skip'
      - title: 'Quit'

e1d437f714ea1539.png

创建 Repeat intent

如需创建 repeat intent,请按以下步骤操作:

  1. 点击导航栏中的 Develop
  2. 点击导航栏中的 Custom Intents 以打开 intent 列表。
  3. 点击 intent 列表底部的 +(加号)。将新 intent 命名为 repeat,然后按 Enter
  4. 点击 repeat intent 以打开 definition intent 页面。
  5. Add training phrases 部分中,点击 Enter Phrase 文本框,然后输入以下短语:
  • one more time please
  • say the word again
  • repeat the word
  • tell me again
  • repeat

e61f0b9f80510bc9.png

  1. 点击保存

Spelling 场景添加 repeat intent

现在,如果用户表达“repeat”intent,该 Action 便可以作出正确理解。您可以向 Spelling 场景添加 repeat 用户 intent,因为用户响应的是 Spelling 提示(“Spell the word using phonetic alphabet”)。

如需向 Spelling 场景添加该用户 intent,请按以下步骤操作:

  1. 点击导航栏中的 Spelling 场景。
  2. 点击 Spelling 场景中的 User intent handling 旁边的 +(加号)
  3. 在 intent 下拉菜单中选择 repeat

5cfd623b25bedbed.png

  1. 勾选调用 Webhook,然后在事件处理脚本文本框中输入 repeatSpellingWord,以获取单词定义。
  2. 勾选 Send prompts
  3. speech 字段中的句子 (Enter the response that users will see or hear...) 替换为“'”。实际提示将由网络钩子填充。

向“当重复项匹配时”添加建议内容信息卡

  1. 在“用户意图处理”下的“当重复匹配时”中,点击代码编辑器下方的建议。该操作可以添加三个建议内容信息卡。
  2. title 字段中,将 Suggested Response 替换为 'Skip'
  3. 按相同的格式手动添加标题为“'Quit'”的建议内容信息卡。您的代码应类似于以下代码段:
suggestions:
      - title: 'Skip'
      - title: 'Quit'

ab40e4b0c432b97c.png

  1. 点击保存

创建 definition intent

如需创建 definition intent,请按以下步骤操作:

  1. 点击导航栏中的 Develop
  2. 点击导航栏中的 Custom Intents 以打开 intent 列表。
  3. 点击 intent 列表底部的 +(加号)。将新 intent 命名为 definition,然后按 Enter
  4. 点击 definition intent 以打开 definition intent 页面。
  5. Add training phrases 部分中,点击 Enter Phrase 文本框,然后输入以下短语:
  • I would like to know the definition
  • tell me the definition
  • what does it mean
  • meaning
  • definition
  • what is the definition?

c1b88a9c0b1ac082.png

  1. 点击保存

Spelling 场景添加 definition intent

现在,如果用户表达“definition”intent,该 Action 便可以作出正确理解。您可以向 Spelling 场景添加 definition 用户 intent,因为用户响应的是 Spelling 提示(“Spell the word using phonetic alphabet”)。

如需向 Spelling 场景添加该用户 intent,请按以下步骤操作:

  1. 点击导航栏中的 Spelling 场景。
  2. 点击 Spelling 场景中的 User intent handling 旁边的 +(加号)
  3. 在 intent 下拉菜单中选择 definition

646bdcac3ad3eb0c.png

  1. 勾选 Call your webhook,然后在事件处理脚本文本框中输入 definitionOfSpellingWord 以获取单词定义。
  2. 勾选 Send prompts
  3. speech 字段 (Enter the response that users will see or hear...) 中的句子替换为“`”。实际提示将由网络钩子填充。

向 webhook 响应添加建议内容信息卡

  1. Start 场景中,点击代码编辑器下方的建议。该操作可以添加三个建议内容信息卡。
  2. title 字段中,将 Suggested Response 替换为 'Skip'
  3. 按相同的格式手动添加标题为“'Quit'”的建议内容信息卡。您的代码应类似于以下代码段:
suggestions:
      - title: 'Skip'
      - title: 'Quit'

25227545839d933f.png

  1. 点击保存

创建 skip intent

如需创建 skip intent,请按以下步骤操作:

  1. 点击导航栏中的 Develop
  2. 点击导航栏中的 Intents 以打开 intent 列表。
  3. 点击 intent 列表底部的 +(加号)。将新 intent 命名为 skip,然后按 Enter
  4. 点击 skip intent 以打开 skip intent 页面。
  5. Add training phrases 部分中,点击 Enter Phrase 文本框,然后输入以下短语:
  • next word
  • go next
  • next
  • skip
  • skip word

d1c4908a3d7882f8.png

  1. 点击保存

Spelling 场景添加 Skip intent

现在,如果用户表达“跳过”intent,该 Action 便可以作出正确理解。您可以向 Spelling 场景添加 skip 用户 intent,因为用户响应的是 Spelling 提示(“Spell the word using phonetic alphabet”)。

如需向 Spelling 场景添加该用户 intent,请按以下步骤操作:

  1. 点击导航栏中的 Spelling 场景。
  2. 点击 Spelling 场景中的 User intent handling 旁边的 +(加号)
  3. 在 intent 下拉菜单中选择 skip

5465f97542217964.png

  1. 在右侧的 Transition 部分中,点击下拉菜单,然后选择 Spelling

c8072485ca82bd3f.png

  1. 点击保存

创建 quit intent

如需创建 Quit intent,请按以下步骤操作:

  1. 点击导航栏中的 Develop
  2. 点击导航栏中的 Intents 以打开 intent 列表。
  3. 点击 intent 列表底部的 +(加号)。将新 intent 命名为 Quit,然后按 Enter
  4. 点击 Quit intent 以打开定义 intent 页面。
  5. Add training phrases 部分中,点击 Enter Phrase 文本框,然后输入以下短语:
  • I quit
  • Goodbye
  • Cancel
  • Exit
  • Quit

9916f77b8766541e.png

  1. 点击保存

Spelling 场景添加 Quit intent

现在,如果用户表达“quit”intent,该 Action 便可以作出正确理解。您可以向 Spelling 场景添加 quit 用户 intent,因为用户响应的是 Spelling 提示(“Spell the word using phonetic alphabet”)。

如需向 Spelling 场景添加该用户 intent,请按以下步骤操作:

  1. 点击导航栏中的 Spelling 场景。
  2. 点击 Spelling 场景中的 User intent handling 旁边的 +(加号)
  3. 在 intent 下拉菜单中选择 quit

5f62fb18a3653d66.png

  1. 在右侧的 Transition 部分中,点击下拉菜单,然后选择 End conversation1ffbe35a7bbbb4b0.png
  2. 点击保存

创建 phonetic_alphabet 类型

在本部分中,您将创建一个名为 phonetic_alphabet 的新类型,该类型可以指定用户在拼写单词时可以选择的语音字母选项。您还可以为这些选项定义几个同义词,以便在用户说出类似内容时也能识别。在后续部分中,您要将 phonetic_alphabet 类型添加到某个槽中,以便指明您想要获取用户的回答。

如需创建 phonetic_alphabet 类型,请按以下步骤操作:

  1. 点击导航栏中的 Develop
  2. 点击 Types 下的 +(加号)
  3. 输入 phonetic_alphabet,然后按 Enter
  4. 点击 phonetic_alphabet 以打开相关选项。
  5. 此类型将支持哪种类型的值?部分中,选择字词和同义词选项
  6. Add entries 部分中输入以下条目和相应的值:

a

alpha、apple、amsterdam

b

bravo、butter、baltimore

c

charlie, cat, casablanca

d

delta, dog, denmark

e

echo、edward、edison

f

foxtrot、fox、florida

g

golf, george, gallipoli

小时

hotel, harry, havana

i

india, ink, italia

j

juliette, johnny, jerusalem

k

kilo、king、kilogramme

l

lima, love, london

分钟

mike, money, madagascar

n

november, new york, nancy

o

oscar、orange、oslo

p

papa、paris、peter

q

quebec, queen

r

romeo、roma、robert

sierra、sugar、santiago

t

tango、tommy、tripoli

u

uniform、umbrella、uncle

v

victor、vinegar、Valencia

w

威士忌、威廉、华盛顿

x

X 射线

y

yankee、yellow、yorker

z

zulu、zebra、zurich

键值对表格应该大致如下所示:

5b5a5cd9fa557e1b.png

  1. 点击保存

配置槽填充

接下来,您需要在“拼写”场景中配置槽填充。如需配置槽填充逻辑,请按以下步骤操作:

  1. 点击导航栏中的 Spelling 场景。
  2. Spelling 场景中,点击 Slot filling 对应的 +(加号)
  3. Enter slot name 字段中,添加 userresponse 作为槽名称。
  4. Select type 下拉菜单中,选择 phonetic_alphabet 作为槽类型。
  5. 勾选此 slot 接受值列表
  6. 勾选 This slot is required
  7. 选择自定义槽值回写选项,然后在会话参数文本框中输入 userresponse。

ba57a419877a07f3.png

  1. 点击保存

Spelling 界面添加条件

如需向 Spelling 场景添加条件,请按以下步骤操作:

  1. 点击导航栏中的 Spelling 场景。
  2. 点击 Spelling 场景中“Condition”旁边的 +(加号)
  3. 输入 scene.slots.status == "FINAL" 作为条件
  4. 检查调用网络钩子,然后在事件处理程序文本框中输入 verifySpellingWord,以验证用户回答。
  5. 勾选 Send prompts
  6. speech字段 (Enter the response that users will see or hear...) 中的句子替换为 {}。实际提示将由网络钩子填充。

向 webhook 响应添加建议内容信息卡

  1. Start 场景中,点击代码编辑器下方的建议。该操作可以添加三个建议内容信息卡。
  2. title 字段中,将 Suggested Response 替换为 'Next'
  3. 按相同的格式手动添加标题为“'Quit'”的建议内容信息卡。您的代码应类似于以下代码段:
suggestions:
      - title: 'Next'
      - title: 'Quit'

ac3d7a9366ebc1b1.png

  1. 点击保存

12. 在模拟器中测试拼写练习

如需在模拟器中测试您的 Action,请按以下步骤操作:

  1. 在导航栏中,点击 Test 以转到模拟器。
  2. 如需在模拟器中测试您的 Action,请在“输入”字段中输入 Talk to Spelling Practice
  3. Enter 键。您的 Action 应该以 Main invocation 提示和添加的 Start 场景提示(“Welcome to Spelling Practice. 使用音标拼写该字词。例如,a 为 alpha,b 为 bravo,c 为 charlie 等。您要继续吗?”
  4. 即可继续
  5. 模拟器将播放一个单词的声音以供拼写
  6. 您可以使用音标字母拼写该字词。例如,对于 better,请说出或输入“bravo echo tango tango echo romeo”
  7. 模拟器将以正确或错误的响应进行回复。
  8. 说出下一个继续下一个单词,或说出退出退出游戏循环。

13. 恭喜

恭喜,您已成功构建游戏拼写练习

现在,您已了解使用 Cloud Firestore、Cloud Functions 和 Google Assistant Action Builder 构建游戏所需的主要步骤。

所学内容

  • 如何与 Cloud Firestore 互动
  • 如何使用槽向用户收集数据
  • 如何处理用户的输入并返回回应
  • 如何使用条件向场景添加逻辑
  • 如何添加游戏循环

其他学习资源

您可以探索以下资源,了解如何构建适用于 Google 助理的 Action:

清理项目 [推荐]

为避免可能产生的费用,建议您移除不想使用的项目。如需删除您在本 Codelab 中创建的项目,请按以下步骤操作:

  1. 如需删除 Firebase 项目和资源,请完成关停(删除)项目部分中所列的步骤。

注意:请确保在 Google Cloud 控制台的设置页面中正确选择要删除的项目。

  1. 可选:如需立即从 Actions 控制台移除您的项目,请完成删除项目部分中所列的步骤。如果您未完成该步骤,系统会在大约 30 天后自动移除您的项目。

欢迎关注我们的 Twitter 账号 @ActionsOnGoogle@Firebase,及时了解我们的最新公告,还可以使用 #GoogleIO 标签发推文,分享您构建的成果!