繼續透過用戶端或伺服器端執行要求進行建構

現在您已經瞭解基本概念,現在可以強化及自訂動作了 搭配 Canvas 專用方法使用您可以選擇使用 用戶端執行要求模型 或伺服器端的執行要求模型。適用對象 如要進一步瞭解這些選項,請參閱 啟用互動式畫布

如果選取用戶端執行要求模型選項,可以在以下位置使用 您的動作:

  • 「Build with 用戶端執行要求」下方列出的所有 API
  • 「Build with Server-side fulfillment」下方列出的所有 API

  • onTtsMark() 回呼

如果選取伺服器執行要求模型選項,可以在以下位置使用 您的動作:

  • 「Build with Server-side fulfillment」下方列出的所有 API
  • 回呼

某些互動式 Canvas API 不適合用於特定 執行要求模型下表列出點選後已啟用的 API 用戶端執行要求選項,以及這些 API 是建議使用還是 不建議採用以下方法:

API 名稱 伺服器執行要求模型是否支援? 用戶端執行要求模型是否支援?
sendTextQuery() 支援但不建議使用 (請參閱 sendtextQuery() )
outputTts()
triggerScene()
createIntentHandler(), expect(), clearExpectations(), prompt()
createNumberSlot(),createTextSlot, createConfirmationSlot, createOptionsSlot()
setHomeParam(), getHomeParam(), setUserParam(), getUserParam()

以下各節將說明如何為用戶端和 互動式畫布動作的伺服器端執行要求模型。

透過用戶端執行要求建構

您可以在網頁應用程式邏輯中,實作下列互動式畫布 API:

outputTts()

這個 API 可讓你從裝置輸出文字轉語音 (TTS),不必傳送 Actions Builder 的靜態提示或叫用 Webhook如果沒有伺服器端 需要使用與 TTS 相關聯的邏輯,因此您可以使用 outputTts() 用戶端便能略過伺服器行程,並快速回應 對使用者的影響。

用戶端outputTts()可能會中斷或取消伺服器端 TTS。請避免 中斷伺服器端 TTS,請採取這些預防措施:

  • 避免在工作階段開始時呼叫 outputTts()。建議改用伺服器端 TTS。
  • 請避免在使用者未操作的情況下連續呼叫 outputTts()

下列程式碼片段說明如何使用 outputTts() 從 用戶端:

interactiveCanvas.outputTts(
      '<speak>This is an example response.</speak>', true);

您也可以將 outputTts()onTtsMark() 搭配使用 將 SSML 標記放在文字序列中使用 onTtsMark() 可同步處理你的網路 應用程式動畫或遊戲狀態在 SSML TTS 字串的特定時間點,如圖所示 在以下程式碼片段中:

interactiveCanvas.outputTts(
      '<speak>Speak as <mark name="number" /> number <break time="700ms"/>' +
      '<say-as interpret-as="cardinal">12345</say-as> <break time="300ms"/> ' +
      'Speak as <mark name="digits" /> digits <break time="700ms"/>' +
      '<say-as interpret-as="characters">12345</say-as></speak>', true);

上述範例中的兩個標記 自訂回應會傳送至網頁應用程式,且回應要求傳送至 TTS。

在用戶端處理意圖執行要求

在互動式畫布的伺服器執行要求模型中,所有意圖 無須由 Webhook 處理,因此動作的延遲時間會增加。改為 您可以在網頁應用程式內處理意圖的執行要求。

如要在用戶端處理意圖,您可以使用下列 API:

  • createIntentHandler():一種方法,可讓您在自己的 網頁應用程式程式碼 (適用於 Actions Builder 中定義的自訂意圖)。
  • expect():可啟動/註冊意圖處理常式的方法, 使用者比對意圖
  • clearExpectations():這個方法能取消所有對 以便系統比對意圖 使用者說出的內容符合意圖。
  • deleteHandler():可停用個別意圖處理常式的方法, 也無法比對意圖

透過這些 API,您可以依據不同的需求,選擇要啟用或停用意圖 互動畫布動作的狀態您必須在意圖上使用 expect() 處理常式來啟用這些意圖

啟用意圖處理常式

啟用意圖處理常式分為兩個步驟。首先,您必須定義 意圖。接下來,如要讓意圖可比對,您必須 在意圖處理常式上呼叫 expect()

如要在用戶端設定並啟用意圖處理常式,請按照下列步驟操作: 步驟如下:

  1. 在 Actions 主控台中開啟專案,並新增自訂意圖
  2. 在「Is this Global intent?」部分選取「Yes」

  3. 設定意圖,然後按一下「Save」

  4. 在網頁應用程式邏輯中,定義意圖的處理常式,如以下程式碼片段所示:

    /**
    * Define handler for intent.
    */
    const bookTableIntent = interactiveCanvas.createIntentHandler('reserveTable',
      matchedIntent => {
        console.log("Intent match handler to reserve a table was triggered!");
      });
    
    /**
    * Define handler for intent with an argument.
    */
    const bookTableIntent = interactiveCanvas.createIntentHandler('reserveTable',
      matchedIntent => {
        const numberOfPeople = matchedIntent.getIntentArg('numberOfPeople');
        console.log(`Intent match handler to reserve a table for ${number of people} was triggered!`);
      });
    
  5. 呼叫 expect() 方法以註冊意圖處理常式,如 程式碼片段:

    /**
    * Define handler for intent and expect() it.
    */
    const bookTableIntent = interactiveCanvas.createIntentHandler('reserveTable',
      matchedIntent => {
        console.log("Intent match handler to reserve a table was triggered!");
      });
    var handler = interactiveCanvas.expect(bookTableIntent);
    

停用意圖處理常式

定義意圖處理常式後,您可以啟用或停用意圖處理常式 將意圖視為動作所需的意圖呼叫 expect() 啟動 意圖後,它會傳回含有 deleteHandler() 方法的物件,供您用於 停用新建立的處理常式。即使意圖處理常式定義仍存在 如果意圖目前為未啟用狀態,您可以在以下情況再次啟用意圖: 。

如要停用意圖處理常式,請在意圖處理常式上呼叫 deleteHandler()。 如以下程式碼片段所示:

    /**
    * Define handler for intent and expect() it.
    */
    const bookTableIntent = interactiveCanvas.createIntentHandler('reserveTable',
      matchedIntent => {
        console.log("Intent match handler to reserve a table was triggered!");
      });
    var handler = interactiveCanvas.expect(bookTableIntent);
    
    // Delete the handler for `bookTableIntent`.
    handler.deleteHandler();
    

您可以呼叫 expect() 來重新新增已停用的意圖處理常式,如 程式碼片段:

    // Re-add the `bookTableIntent` handler.
    handler = interactiveCanvas.expect(bookTableIntent);

如要大量停用意圖,您可以使用 clearExpectations() 方法。 會停用所有目前啟用的意圖。下列程式碼片段說明如何 清楚說明所有意圖處理常式的期望:

interactiveCanvas.clearExpectations();

在用戶端處理運算單元填充

除了在 Actions Builder 中為場景新增運算單元填充以外, 直接處理運算單元填充作業

如要在用戶端處理運算單元填充作業,您必須先使用 下列任一 API:

  • createNumberSlot(callback, hints):這個方法可讓您定義 正確編號。用於提示使用者輸入號碼。
  • createTextSlot(callback, hints):此方法可讓您定義文字 加入原始碼用來提示使用者輸入字詞。
  • createConfirmationSlot(callback, hints):這個方法可讓您 在網頁應用程式程式碼中定義確認版位。用於提示使用者 以確認 (是/否)。
  • createOptionsSlot(options, callback, hints):這個方法可讓您 在網頁應用程式程式碼中定義選項版位。用來提示使用者 然後從預先定義的選項清單中選取

建立運算單元時,您可以選擇定義 triggerHints 改善自然語言理解 (NLU) 系統的關鍵字 開拍這些關鍵字應該是使用者在網站上可能說的簡短字詞 填滿運算單元。舉例來說,數字版位的 triggerHints 關鍵字可以 應為 years。使用者在對話中回覆有關年齡的問題 並在回應中加上「我三十歲」回應,表示您的動作 以便識別使用者填入版位的正確性

建立運算單元後,您可以透過 prompt API 提示使用者預約版位:

  • prompt(tts, slot):這個方法會將 TTS 輸出給使用者,提示使用者要填入預期的版位。

呼叫 prompt() 會傳回承諾產品的狀態及值 廣告空缺

建立號碼版位

您可以用數字版位,在活動期間提示使用者輸入電話號碼 對話。如要進一步瞭解運算單元填充,請參閱 運算單元填充部分 操作建構工具的說明文件

如要提示使用者在用戶端填入號碼版位,請按照下列步驟操作:

  1. 呼叫 createNumberSlot() 方法,在網頁建立號碼版位 應用程式邏輯:

    /**
     * Create number slot.
     */
    const triggerHints = { associatedWords: ['guess number', 'number'] };
    const slot = interactiveCanvas.createNumberSlot(
      number => {
        console.log(`Number guessed: ${number}.`);
      }, triggerHints);
    
    
  2. 呼叫 prompt() 方法,提示使用者提供版位,並處理 運算單元值,如以下程式碼片段所示:

    const promptPromise = interactiveCanvas.prompt(
      { text: 'What number am I thinking of between 1 and 10?' }, slot);
    
    promptPromise.then(
      answer => {
        if (answer.status == interactiveCanvas.AnswerStatus.ANSWERED) {
          // answer === {value: 5, status: ANSWERED}
          // Do something with answer.value
        } else {
          console.error('Promise returned unsuccessful status ' + answer.status);
        }
      });
    

建立文字位置

文字版位可讓您在搜尋期間提示使用者輸入字詞 對話。如要進一步瞭解運算單元填充,請參閱 運算單元填充部分 操作建構工具的說明文件

如要提示使用者在用戶端填入文字版位,請按照下列步驟操作:

  1. 呼叫 createTextSlot() 方法,在網頁應用程式邏輯中建立文字版位:

    /**
     * Create text slot.
     */
    const triggerHints = { associatedWords: ['favorite color', 'color'] };
    const slot = interactiveCanvas.createTextSlot(
      text => {
        console.log(`Favorite color: ${text}.`);
      }, triggerHints);
    
    
  2. 呼叫 prompt() 方法,提示使用者提供版位,並處理 運算單元值,如以下程式碼片段所示:

    const promptPromise = interactiveCanvas.prompt(
      { text: 'What is your favorite color?' }, slot);
    
    promptPromise.then(
      answer => {
        if (answer.status == interactiveCanvas.AnswerStatus.ANSWERED) {
          // answer === {value: "red", status: ANSWERED}
          // Do something with answer.value
        } else {
          console.error('Promise returned unsuccessful status ' + answer.status);
        }
      });
    

建立確認運算單元

透過確認版位,您可以提示使用者確認 回覆「是」或「否」填滿版位)。如要進一步瞭解運算單元填充,請參閱 運算單元填充部分 操作建構工具的說明文件

如要提示使用者在用戶端填寫確認版位,請遵循 步驟如下:

  1. 呼叫 createConfirmationSlot() 方法,在以下位置建立確認版位 您的網頁應用程式邏輯:

    /**
     * Create confirmation slot (boolean).
     */
    const triggerHints = { associatedWords: ['user confirmation', 'confirmation'] };
    const slot = interactiveCanvas.createConfirmationSlot(
      yesOrNo => {
        console.log(`Confirmation: ${yesOrNo}`);
      }, triggerHints);
    
    
  2. 呼叫 prompt() 方法,提示使用者提供版位,並處理 運算單元值,如以下程式碼片段所示:

    const promptPromise = interactiveCanvas.prompt(
      { text: 'Do you agree to the Terms of Service?' }, slot);
    
    promptPromise.then(
      answer => {
        if (answer.status == interactiveCanvas.AnswerStatus.ANSWERED) {
          // answer === {value: true, status: ANSWERED}
          // Do something with answer.value
        } else {
          console.error('Promise returned unsuccessful status ' + answer.status);
        }
      });
    

建立選項版位

選項版位可讓您提示使用者從清單中選取 預先定義的選項如要進一步瞭解運算單元填充,請參閱 運算單元填充部分 操作建構工具的說明文件

如要提示使用者在用戶端填入選項版位,請按照下列步驟操作:

  1. 呼叫 createOptionsSlot() 方法,在 網頁應用程式邏輯:

    /**
     * Create options slot (list selection).
     */
    const triggerHints = { associatedWords: ['select fruit', 'choose fruit'] };
    // Define selectable options
    const options = [{
      key: 'apple',
      synonyms: ['apple', 'large apple', 'gala apple'],
    }, {
      key: 'banana',
      synonyms: ['banana', 'green banana', 'plantain'],
    }];
    const slot = interactiveCanvas.createOptionsSlot(
      options,
      selectedOption => {
        console.log(`You have selected ${selectedOption} as your fruit.`);
      }, triggerHints);
    
    
  2. 呼叫 prompt() 方法,提示使用者提供版位,並處理 運算單元值,如以下程式碼片段所示:

    const promptPromise = interactiveCanvas.prompt(
      { text: 'Would you like a banana or an apple?' }, slot);
    
    promptPromise.then(
      answer => {
        if (answer.status == interactiveCanvas.AnswerStatus.ANSWERED) {
          // answer === {value: 'apple', status: ANSWERED}
          // Do something with answer.value
        } else {
          console.error('Promise returned unsuccessful status ' + answer.status);
        }
      });
    

triggerScene()

triggerScene() API 可用來轉換至 透過用戶端執行要求執行互動式畫布動作。取代為 triggerScene(),您也可以從用戶端執行要求切換為伺服器端 當使用者需要存取 Actions Builder 中的系統情境 也需要使用 Webhook例如,您可以在使用者呼叫 triggerScene() 時呼叫 需要連結帳戶或接收通知;接著,您可以從 並在用戶端執行要求時輸入 Canvas 提示。

下列程式碼片段說明如何在動作中實作 triggerScene()

interactiveCanvas.triggerScene('SceneName').then((status) => {
  console.log("sent the request to trigger scene.");
}).catch(e => {
  console.log("Failed to trigger a scene.");
})

用戶端的住家和使用者儲存空間

您不必使用 Webhook 取得及設定住家和使用者儲存空間值,您可以 呼叫用戶端 API,處理網頁應用程式中的主畫面和使用者儲存空間。你的網路 便可將這些儲存的值用於多個工作階段 (例如 提示和條件),以及存取特定住家或 使用者。使用這些 API 可縮短互動式畫布的延遲時間 操作:您不再需要呼叫 Webhook 即可取得及設定 Storage 值

網頁應用程式首頁和使用者儲存空間的一般原則與 將資料儲存在 Webhook 中如要進一步瞭解住家和使用者儲存空間,請參閱: 「住家儲存空間」說明文件 和使用者儲存空間

用戶端住家儲存空間

你可以在家用儲存空間中,根據 首頁圖 等 在家中各不間斷。舉例來說,如果使用者播放互動式畫布 遊戲的得分可儲存在家庭儲存空間中 其他家庭成員可以根據儲存的分數繼續玩這款遊戲。

如要讓動作支援住家儲存空間,請按照下列步驟操作:

  1. 在「Actions」控制台中,前往「部署」部署>目錄資訊 > 其他資訊
  2. 勾選「您的動作會使用住家儲存空間嗎?」的「是」方塊。

如要在網頁應用程式寫入家用儲存空間的值,請呼叫 setHomeParam() 方法,如以下程式碼片段所示:

interactiveCanvas.setHomeParam('familySize',  10).then(
      result => {
        console.log('Set home param success');
      },
      fail => {
        console.error(err);
      });

如要在網頁應用程式讀取家用儲存空間的值,請呼叫 getHomeParam() 方法,如以下程式碼片段所示:

interactiveCanvas.getHomeParam('familySize').then(
      value => {
        console.log(JSON.stringify(result));
      },
      err => {
        console.error(err);
      }
  );

如要清除所有現有住家儲存空間,請呼叫 resetHomeParam() 方法,如下所示 在以下程式碼片段中:

interactiveCanvas.resetHomeParam();

用戶端使用者儲存空間

使用者儲存空間可讓你儲存特定已驗證使用者的參數值 跨多個工作階段例如,如果玩家正在玩遊戲, 遊戲就會為該使用者儲存在後續的遊戲工作階段中,使用者 就能繼續以相同的分數繼續玩遊戲

如要在網頁應用程式中的使用者儲存空間寫入值,請呼叫 setUserParam() 方法,如以下程式碼片段所示:

interactiveCanvas.setUserParam('color',  'blue').then(
      result => {
        console.log('Set user param success');
      },
      err => {
        console.error(err);
      });

如要讀取網頁應用程式中的使用者儲存空間值,請呼叫 getUserParam() 方法,如以下程式碼片段所示:

interactiveCanvas.getUserParam('color').then(
      value => {
        console.log(JSON.stringify(result));
      },
      err => {
        console.error(err);
      }
  );

如要清除所有現有使用者儲存空間,請呼叫 resetUserParam() 方法,如下所示 在以下程式碼片段中:

interactiveCanvas.resetUserParam();

setCanvasState()

setCanvasState() 方法可讓您透過 Interactive 傳送狀態資料 將 Canvas 網頁應用程式新增至執行要求,並通知 Google 助理網頁應用程式 更新狀態網頁應用程式會以 JSON 物件的形式傳送更新狀態。

呼叫 setCanvasState() 並不會叫用意圖。更新後 如果叫用 sendTextQuery() 或使用者查詢,則叫用 setCanvasState() 符合對話中的意圖,即使用 setCanvasState() 設定的資料 就能從上一個對話回合 對話。

在下列程式碼片段中,網頁應用程式使用 setCanvasState() 設定 Canvas 狀態 資料:

JavaScript

this.action.canvas.setCanvasState({ score: 150 })
    

來自 Webhook 的參照畫布狀態

您可以在執行要求程式碼中參照已儲存的 Canvas 狀態值。如要參照 值,請使用 conv.context.canvas.state.KEY 語法,其中 KEY 是設定 Canvas 狀態值時所給定的鍵。

舉例來說,如果您先前在 Canvas 中儲存了某款遊戲的最高分 狀態做為參數 score,請使用 使用 conv.context.canvas.state.score 即可在執行要求中存取該值:

Node.js

app.handle('webhook-name', conv => {
    console.log(conv.context.canvas.state.score);
})
    

在提示中參照 Canvas 狀態

您可以在提示中參照已儲存的 Canvas 狀態值。如要參照 值,請使用 $canvas.state.KEY 語法,其中 KEY 是設定 Canvas 狀態值時所給定的鍵。

舉例來說,如果您先前在 Canvas 中儲存了某款遊戲的最高分 狀態做為參數 score,請使用 $canvas.state.score 參照該值 在提示中存取該值:

JSON

{
  "candidates": [{
    "first_simple": {
      "variants": [{
        "speech": "Your high score is $canvas.state.score."
      }]
    }
  }]
}
    

參照畫布狀態在條件下

您也可以在條件中參照已儲存的 Canvas 狀態值。目的地: 參照該值,請使用 canvas.state.KEY 語法,其中 KEY 是 Canvas 狀態值設定完成。

舉例來說,如果您先前在 Canvas 中儲存了某款遊戲的最高分 做為參數 score,而您想要與 999 值 條件式清單,您可以使用 canvas.state.score。條件運算式如下所示:

條件語法

canvas.state.score >= 999
    

sendTextQuery()

sendTextQuery() 方法會將文字查詢傳送至對話動作 透過程式輔助方式比對意圖這個範例使用 sendTextQuery() 重新啟動 當使用者點選按鈕時,就會出現三角形轉動的遊戲。使用者點擊 「重新開始遊戲」按鈕,sendTextQuery() 會傳送文字查詢 符合 Restart game 意圖並傳回承諾。這個承諾會導致 如果意圖已觸發,則為 SUCCESS;如果不觸發,則為 BLOCKED。下列 程式碼片段會比對意圖,並處理 承諾:

JavaScript

…
/**
* Handle game restarts
*/
async handleRestartGame() {
    console.log(`Request in flight`);
    this.button.texture = this.button.textureButtonDisabled;
    this.sprite.spin = false;
    const res = await this.action.canvas.sendTextQuery('Restart game');
    if (res.toUpperCase() !== 'SUCCESS') {
        console.log(`Request in flight: ${res}`);
        return;
    }
    console.log(`Request in flight: ${res}`);
    this.button.texture = this.button.textureButtonDisabled;
    this.sprite.spin = false;
}
…
    

如果承諾的結果產生 SUCCESSRestart game Webhook 處理常式就會傳送 網頁應用程式的 Canvas 回應:

JavaScript

…
app.handle('restart', conv => {
  conv.add(new Canvas({
    data: {
      command: 'RESTART_GAME'
    }
  }));
});
…
    

這個 Canvas 回應會觸發 onUpdate() 回呼,而後者會執行 將程式碼加到以下 RESTART_GAME 程式碼片段中:

JavaScript

…
RESTART_GAME: (data) => {
    this.scene.button.texture = this.scene.button.textureButton;
    this.scene.sprite.spin = true;
    this.scene.sprite.tint = 0x00FF00; // green
    this.scene.sprite.rotation = 0;
},
…
    

使用伺服器端執行要求建構

您可以在 Webhook 中實作下列互動式 Canvas API:

啟用全螢幕模式

根據預設,互動式畫布網頁應用程式會納入一個「標頭」 查看動作名稱。您可以使用「enableFullScreen」 移除標頭並替換為 載入畫面,可讓使用者享有全螢幕體驗 互動情形浮動式訊息顯示 Action 的顯示畫面 名稱、開發人員名稱、退出動作的操作說明,以及浮動式訊息 色彩會隨著使用者在裝置上選擇的主題而改變。

圖 1. 動作載入畫面上的浮動式訊息。
,瞭解如何調查及移除這項存取權。

如果使用者經常與動作互動,浮動式訊息會暫時顯示 停止出現在載入畫面上。如果使用者未在 執行動作一段時間後,浮動式訊息會再次出現,

您可以在 Webhook 或在靜態提示訊息中啟用全螢幕模式 。

如要在 Webhook 中啟用全螢幕模式,請按照下列步驟操作:

  1. 將第一個 canvas 回應中的 enableFullScreen 欄位設為 true 包含在工作階段中 Webhook 傳回的字串以下程式碼片段為範例 使用 Node.js 用戶端程式庫進行實作:

     const { conversation, Canvas } = require('@assistant/conversation');
     const functions = require('firebase-functions');
    
     const app = conversation();
    
     app.handle('invocation_fullscreen', conv => {
       conv.add(new Canvas(
         {
           url: 'https://example-url.com',
           enableFullScreen: true
         }));
     });
    
     exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
    

如要在 Actions Builder 的靜態提示中啟用全螢幕模式,請按照下列步驟操作:

  1. Actions 主控台中開啟專案。
  2. 按一下導覽列中的「開發」,然後開啟包含 前 canvas 則回應。
  3. enable_full_screen 設為 true,如以下程式碼片段所示:

     {
      "candidates": [
        {
          "canvas": {
            "url": "https://example-url.com",
            "enable_full_screen": true
          }
        }
      ]
    }
    

continueTtsDuringTouch

根據預設,使用者在使用互動式畫布時輕觸螢幕時 動作遊戲, TTS 會停止播放。你可以啟用文字轉語音功能繼續播放 當使用者透過 continueTtsDuringTouch 輕觸螢幕時。這項行為不得 您可以在同一個工作階段中 開啟或關閉這項設定

您可以在 Webhook 或靜態提示中實作這項行為 。

如要啟用 TTS 以便在使用者輕觸 Webhook 畫面後繼續操作,請按照 這個步驟:

  • 將第一個 canvas 回應中的 continueTtsDuringTouch 欄位設為 true 包含在工作階段中 Webhook 傳回的字串以下程式碼片段為範例 使用 Node.js 用戶端程式庫進行實作:

    const { conversation, Canvas } = require('@assisant/conversation');
    const functions = require('firebase-functions');
    
    const app = conversation();
    
    app.handle('intent-name', conv => {
      conv.add(new Canvas(
        {
          url: 'https://example-url.com',
          continueTtsDuringTouch: true
        }));
    });
    
    exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
    

如要啟用文字轉語音功能,在使用者輕觸 操作建立工具,請按照下列步驟操作:

  1. Actions 主控台中開啟專案。
  2. 按一下導覽列中的「Develop」(開發),開啟包含 前 canvas 則回應。
  3. continue_tts_during_touch 設為 true,如以下程式碼片段所示:

      {
       "candidates": [
         {
           "canvas": {
             "url": "https://example-url.com",
             "continue_tts_during_touch": true
           }
         }
       ]
     }