使用 Google 助理和 Cloud Firestore 的拼字練習遊戲

1. 總覽

Google 助理開發人員平台可讓您建立軟體,在超過 10 億部裝置上擴充 Google 助理 (虛擬個人助理) 的功能,包括智慧音箱、手機、汽車、電視、耳機等。使用者可以透過對話與 Google 助理互動,完成購物或預約車輛等事項。開發人員可以透過 Google 助理開發人員平台,輕鬆建立及管理使用者與第三方服務之間,令人愉悅且有效的對話體驗。

本程式碼研究室涵蓋使用 Google 助理、Cloud Functions 和 Cloud Firestore 開發的中級概念。在本程式碼研究室中,您將建構名為「Spelling Practice」的遊戲,讓 Google 助理要求使用者拼出單字。

建構項目

在本程式碼研究室中,您將建構功能完善的遊戲,具備下列功能:

  • 接收使用者的拼字回應,並視值而定修改對話提示
  • 提供與字詞拼寫相關的提示,例如定義或重複字詞
  • 建立遊戲迴圈,讓使用者在拼出單字後再次與 Google 助理互動

開始建構前,你可以在支援 Google 助理的裝置上說出「Ok Google,和 Spelling Practice 對話」,與該動作互動。回訪使用者透過這項動作的預設路徑如下:

完成本程式碼研究室後,您完成的動作會包含下列對話流程:

2e9f94dc0ceafc96.png

課程內容

  • 如何與 Cloud Firestore 互動
  • 如何使用「位置」收集使用者資料
  • 如何處理使用者輸入內容並傳回回應
  • 如何使用條件在場景中新增邏輯
  • 如何新增遊戲迴圈

軟硬體需求

本程式碼研究室的先決條件包括:

  • 網路瀏覽器,例如 Google Chrome
  • 用於編寫 Cloud Functions 的 IDE。
  • 付款方式。本程式碼研究室會使用 Cloud Functions for Firebase,因此專案必須採用 Firebase Blaze 定價方案 ( 瞭解詳情)。
  • 用於執行殼層指令的終端機
  • Node.js 10 以上版本

2. 取得函式程式碼

從指令列複製 GitHub 存放區

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

3. 建立 Firebase 專案並設定應用程式

建立 Firebase 專案

  1. 登入 Firebase
  2. 在 Firebase 控制台中,按一下「新增專案」 (或「建立專案」),然後將 Firebase 專案命名為 Spelling-Practice

66ae8d1894f4477.png

  1. 點選專案建立選項。當系統顯示提示時,請接受 Firebase 條款。略過設定 Google Analytics,因為這個應用程式不會用到 Analytics。

如要進一步瞭解 Firebase 專案,請參閱「瞭解 Firebase 專案」一文。

升級至 Blaze 定價方案

如要使用 Cloud Functions for Firebase,請將 Firebase 專案升級至 Blaze 定價方案,也就是將 Google Cloud 帳單帳戶連結至專案。您必須提供信用卡或其他付款方式。

所有 Firebase 專案 (包括 Blaze 方案) 仍可享有 Cloud Functions 的免付費用量配額。本程式碼研究室中列出的步驟不會超出免費用量限制。不過,您會看到 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. 函式目錄

現在,您將使用 Cloud Functions 專用的 Firebase SDK 新增功能,為遊戲「Spelling Practice」建構後端。

Cloud Functions 可讓您在雲端執行程式碼,不必設定伺服器。本程式碼研究室將說明如何建構函式,以回應 Firebase Authentication、Cloud Storage 和 Firebase 即時資料庫事件。我們先從驗證開始。

使用 Cloud Functions 專用的 Firebase SDK 時,函式程式碼會位於 functions 目錄 (預設)。為方便您操作,我們已建立 functions/index.js 檔案,您可以在其中編寫程式碼。請隨意檢查 functions 目錄,再繼續進行後續步驟。

$ cd functions
$ ls

函式程式碼也是 Node.js 應用程式,因此需要 package.json 提供應用程式的相關資訊,並列出依附元件。

如果您不熟悉 Node.js,建議先進一步瞭解,再繼續進行本程式碼研究室。

package.json 檔案已列出兩項必要依附元件:Cloud Functions 專用的 Firebase SDKFirebase 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 項目,編寫四個函式。繼續執行程式碼研究室的下一個步驟,匯入模組。

6. 匯入必要模組

本程式碼研究室需要三個模組。

  • 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 Function,每當 Cloud Firestore 中建立新文件時,就會觸發該函式。這會呼叫 dictionaryapi.dev API,透過我們剛才編寫的 getWordDetailsFromDictionaryAPI 函式取得字詞定義。

index.js 檔案中,將 createSpellingPracticeWord 的 TODO 替換為下列程式碼:

index.js

// Firestore trigger that fetches word definitions through getWordDetailsFromDictionaryAPI for every new Firestore document

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 函式,從字詞清單傳回下一個拼字字詞。

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 函式,讓遊戲重複唸出目前單字。

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 函式,驗證使用者對遊戲中目前字詞的拼字回應。

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 控制台的「Build」專區中,按一下「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. 在「Collection ID」文字方塊中輸入 wordlist,然後點選「Next」

1b4ccadb90f52f02.png

接著,我們要為「agreement」一字建立文件:

  1. 在「Document ID」(文件 ID) 文字方塊中,輸入 agreement
  2. 在「Field」(欄位) 文字方塊中輸入 word,在「Value」(值) 文字方塊中輸入 agreement
  3. 按一下 [儲存]

379037e011e8511e.png

將這份文件新增至 Cloud Firestore 時,系統會觸發 createSpellingPracticeWord 函式,擷取該單字的定義詳細資料。為每個字詞建立新文件,即可新增更多字詞 (例如:awe、car、true、tell、better、commute 等)。

10. 設定 Google 助理

以下各節說明如何設定 Google 助理開發環境,以及建立 Actions 專案。

檢查 Google 權限設定

如要測試在本程式碼研究室中建構的動作,您必須啟用必要權限,模擬器才能存取動作。如要啟用權限,請按照下列步驟操作:

  1. 前往「活動控制項」頁面。
  2. 如果尚未登入,請使用 Google 帳戶登入。
  3. 啟用下列權限:
  • 網路和應用程式活動
  • 在「網路和應用程式活動」下方,勾選「包括 Chrome 歷史記錄以及採用 Google 服務的網站、應用程式和裝置中的活動記錄」旁的核取方塊。

c988e1e639e6d6e1.png

建立 Actions 專案

動作專案是動作的容器。如要為本程式碼研究室建立 Actions 專案,請按照下列步驟操作:

  1. 開啟 Actions 管理中心
  2. 按一下「新專案」
  3. 接受服務條款

b174d45710b8086b.png

  1. 輸入或選取您使用 Firebase 控制台建立的 spelling-practice-codelab。(這個名稱僅供內部參考,稍後,您可以為專案設定外部名稱。)

a2951de5d2001fac.png

  1. 按一下「匯入專案」
  2. 在「您要建構哪種動作?」畫面中,選取「自訂」資訊卡。
  3. 點選「下一步」。
  4. 選取「空白專案」資訊卡。
  5. 按一下「開始建構」
  6. 輸入「拼字練習」做為顯示名稱,然後按一下「儲存」。

使用者會透過呼叫與動作展開對話。舉例來說,使用者可以說出「Ok Google,與 Spelling Practice 對話」等句子來叫用動作,其中「Spelling Practice」顯示名稱

如要將動作部署至正式環境,必須設定顯示名稱;但如要測試動作,則不需要定義顯示名稱。您可以在模擬器中使用「Talk to my test app」(與我的測試應用程式對話) 片語,叫用動作。

設定執行要求

您需要將 Cloud Functions 的事件處理常式連結至 Google 助理,這些函式是您在本程式碼研究室稍早編寫及部署的。

如要設定執行要求,請按照下列步驟操作:

  1. 按一下側邊導覽列中的「Webhook」
  2. 選取「Https endpoint」(HTTPS 端點) 做為執行要求選項:

d523bf003e96e66f.png

  1. 在「HTTPs endpoint」文字方塊中輸入函式端點的網址,然後按一下「Save」

be53e2cd0d914d54.png

在下一節中,您將在 Actions 控制台中自訂主要呼叫的提示。

設定主要叫用

您必須編輯主要叫用,定義使用者叫用動作後會發生的情況。

根據預設,Actions Builder 會在觸發叫用時提供一般提示 (「Start building your Action by defining main invocation.」)。

如要修改使用者叫用動作時,動作傳回給使用者的提示,請按照下列步驟操作:

  1. 按一下導覽列中的「主要叫用」

9ff088c04c995cde.png

  1. 勾選 Call your webhook,並在文字方塊中新增事件處理常式名稱 getSpellingWordList
  2. 在程式碼編輯器中,將「speech」欄位中的文字替換為下列歡迎訊息:Welcome to Spelling Practice

注意:你可以使用 YAMLJSON 格式編輯提示。

  1. 按一下 [儲存]

在模擬工具中測試主要叫用

Actions 管理中心提供名為「模擬器」的網頁工具,可供測試動作。這個介面會模擬硬體裝置及其設定,因此您可以與動作對話,就像動作在智慧螢幕、手機、音箱或 KaiOS 上執行一樣。

如要在模擬器中測試動作的主要叫用方式,請按照下列步驟操作:

  1. 按一下頂端導覽列的「測試」,前往模擬器。
  2. 如要在模擬器中叫用動作,請在左上方的輸入欄中輸入 Talk to Spelling Practice,然後按下鍵盤上的 Enter 鍵。

651fc8da1ac9aa0a.png

觸發動作的主要叫用時,Google 助理會以自訂的歡迎訊息回應。此時,Google 助理會說出問候語,然後結束對話。

查看事件記錄

在「測試」分頁中,右側面板會顯示事件記錄,以事件記錄的形式顯示對話記錄。每個事件記錄都會顯示該輪對話期間發生的事件。如要查看事件記錄,請按一下事件前的灰色圖示。

您的動作目前有一個事件記錄,其中顯示使用者的輸入內容 (「Talk to Spelling Practice」) 和動作的回應。下圖顯示動作的事件記錄:

a6fb192f94426824.png

11. 為拼字練習建立對話

定義使用者叫用動作後會發生的情況後,您就可以建構動作對話的其餘部分。拼字練習有四個場景,你必須先啟用每個場景,才能執行。啟用場景最常見的方式是設定動作,讓使用者意圖與場景中的意圖相符時,觸發轉換至另一個場景並啟用該場景。

從主要叫用轉換至開始場景

在本節中,您將建立名為 Start 的新場景,向使用者傳送提示,詢問是否要開始玩「拼字練習」。您也會從主要呼叫新增至新的 Start 場景。

如要建立這個場景並加入轉場效果,請按照下列步驟操作:

  1. 按一下頂端導覽列中的「開發」。然後按一下左側導覽列中的「主要呼叫」
  2. 在右側的「轉場效果」部分,按一下下拉式選單,然後在文字欄位中輸入 Start

dd4f1807a57f794d.png

  1. 按一下「Add」(新增)。這會建立名為 Start 的場景,並指示動作在向使用者顯示歡迎提示後,轉換至 Start 場景。
  2. 按一下左側導覽列中的「場景」,即可顯示場景清單。
  3. 在「場景」下方,按一下「開始」即可查看 Start 場景。
  4. 在「Start」場景的「On enter」部分中,按一下「+」
  5. 選取「傳送提示」
  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?

建議晶片會向使用者提供可點選的建議,供動作處理為使用者輸入內容。在本節中,您將新增建議晶片,顯示在剛設定的提示下方 (Do you want to play

Spelling Practice

?) 支援螢幕裝置上的使用者。

如要將建議方塊新增至 Start 場景的提示,請按照下列步驟操作:

  1. Start 場景中,按一下程式碼編輯器下方的建議。這項操作會新增單一建議方塊。
  2. 在「title」欄位中,將 Suggested Response 替換為 'Yes'
  3. 使用相同格式,手動新增名為「'No'」和「'Help with Phonetics'」的建議晶片。您的程式碼應如下列程式碼片段所示:
  4. 按一下 [儲存]

5ff2ecdc56801b91.png

在模擬工具中測試動作

此時,動作應從主要叫用轉換至「開始」場景,並詢問使用者是否要繼續。模擬畫面中也應會顯示建議方塊。

如要在模擬器中測試動作,請按照下列步驟操作:

  1. 按一下導覽列中的「測試」,即可前往模擬器。
  2. 如要在模擬器中測試動作,請在「輸入」欄位中輸入 Talk to Spelling Practice
  3. 按下 Enter 鍵,動作應回應 Main invocation 提示和新增的 Start 場景提示,「歡迎使用拼字練習。使用語音字母拼出單字。例如:a 是 alpha、b 是 bravo、c 是 charlie 等。要繼續嗎?"

以下螢幕截圖顯示這項互動:

338c9570b02a618e.png

  1. 按一下 YesNoHelp with Phonetics 建議方塊,即可回覆提示。(你也可以說「是」或「否」或「協助發音」,或在「輸入」欄位中輸入 YesNoHelp with Phonetics。)

當你回覆提示時,動作會傳送訊息,指出無法理解你的輸入內容:「很抱歉,我沒聽清楚。可以請你再試一次嗎?」由於您尚未設定 Action,讓 Action 瞭解並回覆「是」或「否」輸入內容,因此 Action 會將您的輸入內容與 NO_MATCH 意圖相符。

根據預設,NO_MATCH 系統意圖會提供一般回應,但您可以自訂這些回應,向使用者表示您不瞭解他們輸入的內容。如果 Google 助理無法比對使用者輸入內容,就會在三次後結束與你 Action 的對話。

新增「否」和語音意圖

現在使用者可以回應動作提出的問題,因此您可以設定動作來瞭解使用者的回應 (「是」、「否」或「協助發音」)。在下列章節中,您將建立使用者意圖,當使用者說出「是」、「否」或「需要語音協助」時,系統就會比對這些意圖,並將這些意圖新增至 Start 場景。我們會使用系統意圖 yes,並建立其他意圖。

建立 no 意圖

現在,您需要建立 no 意圖,以便在使用者不想玩遊戲時瞭解並回應。如要建立這項意圖,請按照下列步驟操作:

  1. 按一下導覽列中的「開發」
  2. 按一下導覽列中的「自訂意圖」,開啟意圖清單。
  3. 在意圖清單結尾處,按一下「+」(加號)。為新意圖命名 no,然後按下 Enter 鍵。
  4. 按一下「否」即可開啟 no 意圖頁面。
  5. 在「新增訓練詞組」部分中,按一下「輸入詞組」文字方塊,然後輸入下列詞組:
  • No
  • N
  • I don't want
  • nope

98b0c9a7b67ea9b9.png

  1. 按一下 [儲存]

no意圖新增至Start場景

現在,動作可以瞭解使用者何時表達「否」或類似「否」的內容,例如「不要」您需要在 Start 場景中新增 no 使用者意圖,因為使用者正在回應 Start 提示 (「歡迎使用拼字練習。使用語音字母拼出單字。例如,a 是 alpha,b 是 bravo,c 是 charlie 等。要繼續嗎?")。

如要為 Start 場景新增這項意圖,請按照下列步驟操作:

  1. 按一下導覽列中的「Start」(開始) 場景。
  2. 在「User intent handling」Start 場景中,按一下 + (加號)
  3. 在「意圖」部分,從下拉式選單中選取「否」

51f752e78c8b4942.png

  1. 按一下「傳送提示」,然後將「speech」欄位更新為下列文字:Good Bye

編輯器中的程式碼應如下列程式碼片段所示:

candidates:
  - first_simple:
      variants:
        - speech: >-
             Goodbye.
  1. 在「轉移」部分,從下拉式選單選取「結束對話」
  2. 按一下 [儲存]

在模擬工具中測試 no 意圖

此時,動作會瞭解使用者不想玩遊戲,並傳回適當的回應。

如要在模擬器中測試這項意圖,請按照下列步驟操作:

  1. 在導覽列中,按一下「測試」
  2. 在「輸入」欄位中輸入 Talk to Spelling Practice,然後按下 Enter
  3. 在「Input」欄位中輸入 No,然後按下 Enter 鍵。或者,按一下「沒有建議」資訊方塊。

7727a456b522f31b.png

將系統 YES 意圖新增至 Start 場景

現在,我們要將 SYSTEM 意圖 "YES" 新增至 Start 場景,因為使用者會對 Start 提示 (「歡迎使用拼字練習。使用語音字母拼出單字。例如,a 是 alpha,b 是 bravo,c 是 charlie 等。要繼續嗎?")。

如要將這個使用者意圖新增至 Start 場景,請按照下列步驟操作:

  1. 按一下導覽列中的「Start」(開始) 場景。
  2. 在「User intent handling」旁的 Start 場景中,按一下「+」(加號)
  3. 在「所有系統意圖」下方,從意圖下拉式選單中選取「是」

f6cbe789cde49e8f.png

  1. 按一下「呼叫 Webhook」,然後使用先前建立的函式更新 event handler 文字方塊:getSpellingWordList
  2. 在「轉移」部分中,按一下下拉式選單,然後選取「結束對話」
  3. 按一下 [儲存]

在模擬工具中測試 YES 意圖

此時,Action 就能瞭解使用者何時想玩遊戲,並傳回適當的回應。

如要在模擬器中測試這項意圖,請按照下列步驟操作:

  1. 在導覽列中,按一下「測試」
  2. 如要在模擬器中測試動作,請在「輸入內容」欄位中輸入 Talk to Spelling Practice,然後按下 Enter 鍵。
  3. 在「Input」欄位中輸入 Yes,然後按下 Enter 鍵。或者,按一下 Yes 建議方塊。

你的動作會擷取所有拼字練習字詞的清單,並將這些字詞儲存在工作階段中。由於您為 YES 意圖選取 End conversation 轉移,因此 Action 會結束工作階段。

建立 Phonetics 意圖

如要建立 Phonetics 意圖,請按照下列步驟操作:

  1. 按一下導覽列中的「開發」
  2. 按一下導覽列中的「自訂意圖」,開啟意圖清單。
  3. 在意圖清單結尾處,按一下「+」(加號)。為新意圖命名 phonetics,然後按下 Enter
  4. 按一下 phonetics 意圖,開啟 phonetics 意圖頁面。
  5. 在「新增訓練詞組」部分中,按一下「輸入詞組」文字方塊,然後輸入下列詞組:
  • how do I spell words
  • phonetics
  • help me with phonetics
  • phonetic alphabet

1455bdfca8dae46.png

  1. 按一下 [儲存]

phonetics意圖新增至Start場景

現在,動作可以瞭解使用者何時表達「語音」意圖。您可以將 phonetics 使用者意圖新增至 Start 場景,因為使用者正在回應 Start 提示 (「歡迎使用拼字練習。使用語音字母拼出單字。例如,a 是 alpha,b 是 bravo,c 是 charlie 等。要繼續嗎?")。

如要將這個使用者意圖新增至 Start 場景,請按照下列步驟操作:

  1. 按一下導覽列中的「Start」(開始) 場景。
  2. 按一下「使用者意圖處理」旁的 Start 符號。
  3. 在意圖下拉式選單中選取「語音」。

67ee2e08000b2aee.png

  1. 在「轉移」部分中,按一下下拉式選單,然後選取「結束對話」
  2. 按一下 [儲存]

從「Start」場景轉換至「Spelling」場景

在本節中,您將建立名為「Spelling」的新場景,提示使用者以語音字母拼出單字。

如要建立這個場景並加入轉場效果,請按照下列步驟操作:

  1. 按一下頂端導覽列中的「開發」。接著,按一下左側導覽列中的「開始」場景。
  2. 在「使用者意圖處理」部分中,按一下 when actions.intent.YES is matched,然後在右側的「轉移」部分中,按一下下拉式選單,並在文字欄位中輸入 Spelling
  3. 按一下「Add」(新增)。這會建立名為 Spelling 的場景,並告知動作在與 YES 意圖相符後,轉換至 Spelling 場景。
  4. 展開左側導覽中的「場景」,即可顯示場景清單。
  5. 在「場景」下方,按一下「拼字」即可查看 Spelling 場景。
  6. 在「Spelling」場景的「On enter」部分中,按一下「+」
  7. 按一下「Call your webhook」(呼叫 Webhook),然後在事件處理常式文字方塊中輸入 getSpellingWord
  8. 選取「傳送提示」
  9. speech 欄位 (Enter the response that users will see or hear...) 中的句子替換為 {}。實際提示會由 Webhook 填入。

建議晶片會向使用者提供可點選的建議,供動作處理為使用者輸入內容。

如要將建議方塊新增至 Spelling 場景的提示,請按照下列步驟操作:

  1. Spelling 場景中,按一下程式碼編輯器下方的建議。這項動作會新增三個建議方塊。
  2. 在「title」欄位中,將 Suggested Response 替換為 'Repeat'
  3. 使用相同格式,手動新增名為「'Skip'」的建議晶片。
  4. 使用相同格式手動新增名為「'Quit'」的建議晶片。您的程式碼應如下列程式碼片段所示:
  5. 按一下 [儲存]
suggestions:
      - title: 'Repeat'
      - title: 'Skip'
      - title: 'Quit'

e1d437f714ea1539.png

建立 Repeat 意圖

如要建立 repeat 意圖,請按照下列步驟操作:

  1. 按一下導覽列中的「開發」
  2. 按一下導覽列中的「自訂意圖」,開啟意圖清單。
  3. 在意圖清單結尾處,按一下「+」(加號)。為新意圖命名 repeat,然後按下 Enter
  4. 按一下 repeat 意圖,開啟 definition 意圖頁面。
  5. 在「新增訓練詞組」部分,按一下「輸入詞組」文字方塊,然後輸入下列詞組:
  • one more time please
  • say the word again
  • repeat the word
  • tell me again
  • repeat

e61f0b9f80510bc9.png

  1. 按一下 [儲存]

repeat意圖新增至Spelling場景

現在,動作可以瞭解使用者何時表達「重複」意圖。由於使用者會回應 Spelling 提示 (「Spell the word using phonetic alphabet」),因此您可以將 repeat 使用者意圖新增至 Spelling 場景。

如要將這個使用者意圖新增至 Spelling 場景,請按照下列步驟操作:

  1. 按一下導覽中的「Spelling」(拼字) 場景。
  2. 在「User intent handling」旁的 Spelling 場景中,按一下「+」(加號)
  3. 在意圖下拉式選單中選取「repeat」

5cfd623b25bedbed.png

  1. 勾選「Call your webhook」(呼叫 Webhook),並在事件處理常式文字方塊中輸入「repeatSpellingWord」,即可取得單字定義。
  2. 勾選「傳送提示」
  3. speech 欄位 (Enter the response that users will see or hear...) 中的句子換成「'」。實際提示會由 Webhook 填入。

在「當重複項目相符時」新增建議晶片

  1. 在「使用者意圖處理」下方的「當系統比對出『重複』意圖時」,按一下程式碼編輯器下方的「建議」。這項動作會新增三個建議方塊。
  2. 在「title」欄位中,將 Suggested Response 替換為 'Skip'
  3. 使用相同格式,手動新增名為「'Quit'」的建議方塊。您的程式碼應如以下程式碼片段所示:
suggestions:
      - title: 'Skip'
      - title: 'Quit'

ab40e4b0c432b97c.png

  1. 按一下「儲存」

建立 definition 意圖

如要建立 definition 意圖,請按照下列步驟操作:

  1. 按一下導覽列中的「開發」
  2. 按一下導覽列中的「自訂意圖」,開啟意圖清單。
  3. 在意圖清單結尾處,按一下「+」(加號)。為新意圖命名 definition,然後按下 Enter
  4. 按一下 definition 意圖,開啟 definition 意圖頁面。
  5. 在「新增訓練詞組」部分,按一下「輸入詞組」文字方塊,然後輸入下列詞組:
  • I would like to know the definition
  • tell me the definition
  • what does it mean
  • meaning
  • definition
  • what is the definition?

c1b88a9c0b1ac082.png

  1. 按一下 [儲存]

definition意圖新增至Spelling場景

現在,動作可以瞭解使用者何時表達「定義」意圖。由於使用者會回應 Spelling 提示 (「Spell the word using phonetic alphabet」),因此您可以將 definition 使用者意圖新增至 Spelling 場景。

如要將這個使用者意圖新增至 Spelling 場景,請按照下列步驟操作:

  1. 按一下導覽中的「Spelling」(拼字) 場景。
  2. 在「User intent handling」旁的 Spelling 場景中,按一下「+」(加號)
  3. 在意圖下拉式選單中選取「定義」

646bdcac3ad3eb0c.png

  1. 勾選「Call your webhook」,並在事件處理常式文字方塊中輸入 definitionOfSpellingWord,即可取得單字定義。
  2. 勾選「傳送提示」
  3. 將「speech」欄位 (Enter the response that users will see or hear...) 中的句子替換為「``」。實際提示會由 Webhook 填入。

在 Webhook 回應中新增建議方塊

  1. Start 場景中,按一下程式碼編輯器下方的「建議」。這項動作會新增三個建議方塊。
  2. 在「title」欄位中,將 Suggested Response 替換為 'Skip'
  3. 使用相同格式,手動新增名為「'Quit'」的建議方塊。您的程式碼應如以下程式碼片段所示:
suggestions:
      - title: 'Skip'
      - title: 'Quit'

25227545839d933f.png

  1. 按一下 [儲存]

建立 skip 意圖

如要建立 skip 意圖,請按照下列步驟操作:

  1. 按一下導覽列中的「開發」
  2. 按一下導覽區中的「意圖」,開啟意圖清單。
  3. 在意圖清單結尾處,按一下「+」(加號)。為新意圖命名 skip,然後按下 Enter
  4. 按一下 skip 意圖,開啟 skip 意圖頁面。
  5. 在「新增訓練詞組」部分,按一下「輸入詞組」文字方塊,然後輸入下列詞組:
  • next word
  • go next
  • next
  • skip
  • skip word

d1c4908a3d7882f8.png

  1. 按一下 [儲存]

Skip意圖新增至Spelling場景

現在,動作可以瞭解使用者何時表達「略過」意圖。由於使用者會回應 Spelling 提示 (「Spell the word using phonetic alphabet」),因此您可以將 skip 使用者意圖新增至 Spelling 場景。

如要將這個使用者意圖新增至 Spelling 場景,請按照下列步驟操作:

  1. 按一下導覽中的「Spelling」(拼字) 場景。
  2. 在「User intent handling」(處理使用者意圖) 旁邊的 Spelling 場景中,按一下「+」(加號)
  3. 在意圖下拉式選單中選取「略過」

5465f97542217964.png

  1. 在右側的「轉場效果」部分,按一下下拉式選單,然後選取 Spelling

c8072485ca82bd3f.png

  1. 按一下 [儲存]

建立 quit 意圖

如要建立 Quit 意圖,請按照下列步驟操作:

  1. 按一下導覽列中的「開發」
  2. 按一下導覽區中的「意圖」,開啟意圖清單。
  3. 在意圖清單結尾處,按一下「+」(加號)。為新意圖命名 Quit,然後按下 Enter
  4. 按一下 Quit 意圖,開啟定義意圖頁面。
  5. 在「新增訓練詞組」部分,按一下「輸入詞組」文字方塊,然後輸入下列詞組:
  • I quit
  • Goodbye
  • Cancel
  • Exit
  • Quit

9916f77b8766541e.png

  1. 按一下「儲存」

Quit意圖新增至Spelling場景

現在,動作可以瞭解使用者何時表達「退出」意圖。由於使用者會回應 Spelling 提示 (「Spell the word using phonetic alphabet」),因此您可以將 quit 使用者意圖新增至 Spelling 場景。

如要將這個使用者意圖新增至 Spelling 場景,請按照下列步驟操作:

  1. 按一下導覽中的「Spelling」(拼字) 場景。
  2. 在「User intent handling」旁的 Spelling 場景中,按一下「+」(加號)
  3. 在意圖下拉式選單中選取「quit」

5f62fb18a3653d66.png

  1. 在右側的「轉場效果」部分,按一下下拉式選單,然後選取 End conversation1ffbe35a7bbbb4b0.png
  2. 按一下 [儲存]

建立 phonetic_alphabet 類型

在本節中,您將建立名為 phonetic_alphabet 的新類型,指定使用者可選擇的語音字母選項,用來拼出單字。您也可以為這些選項定義幾個同義詞,以防使用者說出類似的內容。在後續章節中,您會將 phonetic_alphabet 型別新增至時段,指定要取得使用者的回覆。

如要建立 phonetic_alphabet 類型,請按照下列步驟操作:

  1. 按一下導覽列中的「開發」
  2. 按一下「類型」下方的 + (加號)
  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

whiskey、william、washington

x

X 射線

y

yankee、yellow、yorker

z

zulu、zebra、zurich

鍵/值資料表應如下所示:

5b5a5cd9fa557e1b.png

  1. 按一下 [儲存]

設定運算單元填充

接著,您需要在 Spelling 場景中設定填寫空位。如要設定填滿空位的邏輯,請按照下列步驟操作:

  1. 按一下導覽中的「Spelling」(拼字) 場景。
  2. Spelling 場景中,按一下 + (加號),即可進行填寫空位
  3. 在「Enter slot name」(輸入廣告空間名稱) 欄位中,新增 userresponse 做為廣告空間名稱。
  4. 在「Select type」(選取類型) 下拉式選單中,選取「phonetic_alphabet」做為 slot 類型。
  5. 勾選「這個時段接受值清單」
  6. 勾選「This slot is required」(這是必要位置)
  7. 選取「自訂時段值回寫」選項,並在工作階段參數文字方塊中輸入 userresponse。

ba57a419877a07f3.png

  1. 按一下 [儲存]

在「Spelling」畫面中新增條件

如要將 Condition 新增至 Spelling 場景,請按照下列步驟操作:

  1. 按一下導覽中的「Spelling」(拼字) 場景。
  2. 按一下「條件」旁邊 Spelling 場景中的「+」(加號)
  3. 輸入 scene.slots.status == "FINAL" 做為條件
  4. 勾選「Call your webhook」(呼叫 Webhook),並在事件處理常式文字方塊中輸入「verifySpellingWord」,驗證使用者回應。
  5. 勾選「傳送提示」
  6. speech欄位 (Enter the response that users will see or hear...) 中的句子替換為 {}。系統會透過 Webhook 填入實際提示。

在 Webhook 回應中新增建議方塊

  1. Start 場景中,按一下程式碼編輯器下方的「建議」。這項動作會新增三個建議方塊。
  2. 在「title」欄位中,將 Suggested Response 替換為 'Next'
  3. 使用相同格式,手動新增名為「'Quit'」的建議方塊。您的程式碼應如以下程式碼片段所示:
suggestions:
      - title: 'Next'
      - title: 'Quit'

ac3d7a9366ebc1b1.png

  1. 按一下 [儲存]

12. 在模擬工具中測試拼字練習

如要在模擬器中測試動作,請按照下列步驟操作:

  1. 按一下導覽列中的「測試」,即可前往模擬器。
  2. 如要在模擬器中測試動作,請在「輸入」欄位中輸入 Talk to Spelling Practice
  3. 按下 Enter 鍵,動作應回應 Main invocation 提示和新增的 Start 場景提示,「歡迎使用拼字練習。使用語音字母拼出單字。例如:a 是 alpha、b 是 bravo、c 是 charlie 等。要繼續嗎?"
  4. 說出「是」即可繼續操作
  5. 模擬器會播放單字音效,協助你拼出單字
  6. 你可以使用語音字母拼出該字,舉例來說,如要輸入「better」,請說出或輸入「bravo echo tango tango echo romeo」
  7. 模擬器會回覆正確或不正確的回應。
  8. 說出「下一個」即可繼續下一個字詞,說出「結束」即可退出遊戲循環。

13. 恭喜

恭喜,您已成功建構遊戲「Spelling Practice」

您現在已瞭解使用 Cloud Firestore、Cloud Functions 和 Google 助理動作建構工具建構遊戲的必要步驟。

涵蓋內容

  • 如何與 Cloud Firestore 互動
  • 如何使用「位置」收集使用者資料
  • 如何處理使用者輸入內容並傳回回應
  • 如何使用條件在場景中新增邏輯
  • 如何新增遊戲迴圈

其他學習資源

如要瞭解如何建構 Google 助理動作,請參閱下列資源:

清除專案所用資源 (建議)

為避免產生可能的費用,建議您移除不打算使用的專案。如要刪除您在本程式碼研究室中建立的專案,請按照下列步驟操作:

  1. 如要刪除 Firebase 專案和資源,請完成「關閉 (刪除) 專案」一節列出的步驟。

注意:請務必在 Google Cloud 控制台的「設定」頁面中,選取要刪除的正確專案。

  1. 選用:如要立即從 Actions 管理中心移除專案,請完成「刪除專案」一節列出的步驟。如果未完成這個步驟,系統會在約 30 天後自動移除專案。

在 Twitter 上追蹤 @ActionsOnGoogle@Firebase,隨時掌握最新消息,並在推文中加上 #GoogleIO,分享您開發的內容!