對話動作將於 2023 年 6 月 13 日淘汰。詳情請參閱對話動作停用

使用 Actions on Google Node.js 用戶端程式庫 (Dialogflow) 打造執行要求

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

如要在 JavaScript 建立執行要求 Webhook,建議您使用 Actions on Google Node.js 用戶端程式庫,並與 Actions on Google 平台互動。

簡介

Node.js 用戶端程式庫是 Actions on Google 的出貨程式庫,可提供下列功能:

  • 支援 Actions on Google 的所有功能,包括文字和多媒體內容回應、帳戶登入、資料儲存、交易等。
  • 提供以 JavaScript 表達的抽象層,用來包裝對話 HTTP/JSON Webhook API
  • 處理出貨和 Actions on Google 平台之間的低階通訊詳細資料。
  • 可以使用 npmyarn 等熟悉的套件管理工具安裝。
  • 您可以在 Cloud Functions for FirebaseAWS Lambda 等無伺服器運算平台上,輕鬆部署執行要求 Webhook。您也可以將出貨 Webhook 託管於雲端服務供應商,或自行管理的自行管理環境。
  • Node.js 6.0.0 以上版本相容。

您可以將用戶端程式庫與 Actions on Google 整合 DialogflowActions SDK 搭配使用。

如要查看使用用戶端程式庫的完整程式碼範例,請造訪範例頁面

查看 API 參考資料

API 參考資料由 Actions on Google Node.js 用戶端程式庫 GitHub 頁面代管。

您也可以在您下載用戶端程式庫程式碼的目錄中執行下列指令,藉此產生參照的本機副本:

yarn docs

產生的文件會顯示在您下載用戶端程式庫程式碼目錄的 docs 資料夾中。

瞭解運作方式

使用用戶端程式庫之前,建議您先瞭解執行要求 Webhook 如何使用用戶端程式庫處理使用者動作,傳送至 Actions on Google 的使用者要求。

使用 JavaScript 建立執行要求 Webhook 時,您可以在 Google 的 Cloud Functions for Firebase 或 AWS Lambda 等無伺服器運算環境中部署及代管程式碼。您也可以利用 Express 網路架構,自行代管程式碼。

在執行階段環境中,執行要求 Webhook 可以呼叫用戶端程式庫中的函式來處理使用者要求,並將回應傳回至 Actions on Google,以便轉譯成使用者輸出內容。

您的 Webhook 將透過用戶端程式庫協助處理的關鍵工作概述了下列摘要:

圖 1. Node.js 用戶端程式庫的高階架構
  1. 接收使用者要求:當使用者向 Google 助理提出查詢時,Actions on Google 平台會向執行要求 Webhook 傳送 HTTP 要求;該要求包含 JSON 酬載,當中包含意圖和其他資料 (例如使用者輸入內容的原始文字,以及使用者裝置的表面功能)。如需更多 JSON 酬載內容的範例,請參閱 Dialogflow Webhook 格式對話 Webhook 格式指南。
  2. 架構呼叫格式偵測:針對支援的架構,用戶端程式庫會自動偵測架構的呼叫格式 (例如,要求來自 Express 網路架構或 AWS Lambda),並瞭解如何順暢地與 Actions on Google 平台進行通訊。
  3. 服務處理常式處理:用戶端程式庫將 Dialogflow 和 Actions SDK 的對話 HTTP/JSON Webhook API 呈現為服務函式。出貨 Webhook 會使用適當的服務來建立全域 app 執行個體。app 執行個體是 HTTP 要求的處理常式,並瞭解服務的特定通訊協定。
  4. 對話處理:用戶端程式庫將每個對話資訊表示為附加至 app 執行個體的 Conversation 物件。出貨 Webhook 可以使用 Conversation 物件來擷取跨融合的儲存資料或狀態資訊、傳送回應給使用者,或關閉麥克風。
  5. 中介軟體處理:用戶端程式庫可讓您建立自己的對話服務中介軟體,其中包含一或多個定義,這些函式在您定義意圖處理常式之前,這些函式會自動執行。出貨 Webhook 可以使用中介軟體,在 Conversation 物件中新增屬性或輔助類別。
  6. 意圖處理常式處理:用戶端程式庫可讓您針對執行要求 Webhook 理解的意圖定義處理常式。如為 Dialogflow,用戶端程式庫會將要求對應至 Dialogflow 主控台中定義之意圖名稱的確切字串,藉此將要求轉送至正確的意圖處理常式。針對 Actions SDK,系統會根據 Actions on Google 傳送的 intent 屬性來轉送 SDK。
  7. 向使用者傳送回應:如要建立回應,您的執行要求 Webhook 會呼叫 Conversation#ask() 函式。您可以多次呼叫 ask() 函式,以逐步建構回應。用戶端程式庫會將回應序列化為包含 JSON 酬載的 HTTP 要求,並傳送至 Actions on Google。close() 函式的行為與 ask() 類似,但會關閉對話。

設定本機開發環境

實作出貨 Webhook 之前,請務必先安裝用戶端程式庫。

安裝用戶端程式庫

想要將用戶端程式庫安裝到本機開發環境,最簡單的方法是使用套件管理員,例如 npmyarn

如要安裝,請在終端機中執行下列其中一項指令:

  • 如果您使用的是 npmnpm install actions-on-google
  • 如果使用毛線yarn add actions-on-google

設定專案資料夾

視您規劃的執行要求 Webhook (Google 的 Cloud Functions for Firebase、AWS Lambda 或自行代管的 Express 而定),您可能需要建立特定專案資料夾結構來儲存檔案。

例如,如果您使用的是 Cloud Functions for Firebase,可以執行設定 Node.js 和 Firebase CLI 以及初始化 Firebase for Cloud Functions 中所述的步驟,設定必要的專案資料夾。針對 Cloud Functions for Firebase,您通常可以在 /functions/index.js 檔案中編寫出貨 Webhook。

建構應用程式執行個體

Actions on Google 會使用特定訊息格式交換執行要求和回應,其中包含您的出貨 Webhook,視您想使用 DialogflowActions SDK 建構對話動作,還是建立智慧型住宅動作而定。

為了顯示不同的要求與回應通訊協定,用戶端程式庫提供三種服務函式:

對話式 Webhook 通訊協定由兩個對話服務 (Dialogflow 和 Actions SDK) 使用,但每項服務包裝訊息的方式不同。

您可以使用服務建立 app 執行個體。app 執行個體會封裝 Webhook 的全域狀態和執行邏輯,並處理採用特定服務通訊協定的 Actions on Google 與出貨之間的通訊。

您可以設定 app 執行個體的屬性,並呼叫其方法以指示執行要求 Webhook 的行為。您還可以輕鬆將 app 執行個體插入無伺服器運算環境 (例如 Cloud Functions for Firebase),這個環境可接受 JavaScript 函式做為 HTTP 要求的處理常式。

如要在出貨 Webhook 中建構 app 執行個體,請按照下列步驟操作:

  1. 呼叫 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 執行個體時,您可以視需要指定您要使用的豐富回應、輔助意圖和其他 Actions on Google 功能的類別。如需可載入的有效類別的完整清單,請參閱對話回應輔助意圖模組的參考說明文件。

  2. 呼叫您載入的服務來建立 app 執行個體。例如:

    const app = dialogflow();

  3. 如要在初始化時設定 app 執行個體,您可以在呼叫服務時提供 options 物件做為第一個引數。(詳情請參閱 DialogflowOptions)。例如,以下程式碼片段示範如何設定 { debug: true } 標記,從使用者要求或回應記錄原始 JSON 酬載:

const app = dialogflow({
  debug: true
});

為事件設定處理常式

如要處理使用者與動作互動的生命週期中,由用戶端程式庫建立的 Actions on Google 相關事件,您會使用用戶端程式庫建構處理常式來處理使用者要求並傳回回應。

您可以建立下列函式,讓用戶端程式庫識別下列主要事件類型的處理常式:

  • 意圖事件:每當使用者要求某些特定功能時,Intents on 就會傳送一個專屬 ID 給 Actions on Google 來傳送至您的執行要求。如果您是使用 Dialogflow,則需要對應至使用者查詢與 Dialogflow 代理程式中的意圖的 Dialogflow。
  • 錯誤事件:當 JavaScript 或用戶端程式庫發生錯誤時,您可以使用 app 執行個體的 catch 函式,以適當方式處理錯誤例外狀況。您應實作單一 catch 函式來處理所有與出貨要求相關的錯誤。
  • 備用事件:當使用者傳送查詢時,如果 Actions on Google 無法辨識該查詢,就會發生備用事件。您可以使用 app 執行個體的 fallback 函式來註冊一般備用處理常式,如果傳入的 要求要求沒有相符的意圖處理常式,即會觸發這個處理常式。您應實作單一的 fallback 函式來處理所有備用事件。如果您使用的是 Dialogflow,當沒有其他意圖相符時,Dialogflow 可觸發特定的備用意圖。建議您為該備用意圖建立對應的意圖處理常式。

每次使用者傳送要求到您的動作時,app 執行個體就會建立代表該對話工作階段的 Conversation 物件。這個物件可透過在意圖處理常式函式中傳遞的 conv 變數名稱做為第一個函式引數存取。您通常會在處理常式中使用 conv 物件,以便向使用者傳送回應。

使用者查詢也可以包含您的動作可擷取及用來修正回應的參數。

  • 如果您使用 Actions SDK,可以在動作套件中定義參數。請參閱 Eliza 程式碼範例,瞭解如何從意圖擷取參數。
  • 如果您使用的是 Dialogflow,可以透過 params 變數存取參數值。如要查看在 Dialogflow 中使用參數處理意圖的範例,請參閱存取參數和結構定義一文。

設定意圖的處理常式

如要為意圖設定處理常式,請呼叫 app 執行個體的 intent() 函式。舉例來說,如果您使用 Dialogflow,這是 DialogflowApp#intent() 函式。在引數中指定意圖名稱並提供處理常式函式。

如果您使用的是 Dialogflow,就不需要為代理程式中的每個意圖設定處理常式。您可以改為運用 Dialogflow 內建的回應處理常式,在不實作自己的處理常式函式的情況下自動處理意圖。例如,可以用這種方式將預設歡迎意圖委派給 Dialogflow。

以下範例顯示「問候」和「再見」的意圖處理常式。其匿名處理常式函式採用 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() 類似,只是會關閉麥克風且對話已結束。

如要進一步瞭解如何建構意圖的處理常式,請參閱建構意圖處理常式一文。

為錯誤事件設定處理常式

如要設定錯誤的處理常式,請呼叫 app 執行個體的 catch() 函式。(例如,如果您使用 Dialogflow,則需要 DialogflowApp#catch() 函式)。

下列範例顯示一個簡單的擷取錯誤處理常式,該錯誤會將錯誤傳送至主控台輸出內容,並傳回簡單的字串回應,透過 conv.ask() 函式提示使用者:

app.catch((conv, error) => {
  console.error(error);
  conv.ask('I encountered a glitch. Can you say that again?');
});

設定備用事件的處理常式

如要設定在沒有任何意圖與傳入要求相符的意圖時設定一般備用處理常式,請呼叫 app 執行個體的 fallback() 函式。(例如,如果您使用 Dialogflow,則需要 DialogflowApp#fallback() 函式)。

以下範例顯示一個簡單的備用處理常式,其透過 conv.ask() 函式傳回簡單的字串回應,提示使用者:

app.fallback((conv) => {
  conv.ask(`I couldn't understand. Can you say that again?`);
});

建立意圖處理常式

本節說明使用用戶端程式庫實作意圖處理常式時的一些常見用途。如要瞭解用戶端程式庫如何比對意圖,請參閱瞭解其運作方式中的「意圖處理常式處理」一節。

存取參數和背景資訊

如果您使用的是 Dialogflow,您可以在 Dialogflow 代理程式中定義參數結構定義,藉此維護狀態資訊及控制對話流程。

參數可用來擷取使用者查詢中的重要字詞、詞組或值。Dialogflow 會在執行階段從使用者查詢中擷取對應的參數,方便您在執行要求 Webhook 中處理這些參數,以便決定回應使用者的方式。

每次使用者傳送要求到您的動作時,DialogflowApp 執行個體會建立 parameters 物件,代表 Dialogflow 從該要求中擷取的參數值。您可以透過 params 變數名稱存取這個物件。

下列程式碼片段說明如何在使用者傳送要求時,從 params 物件存取 name 屬性:

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 物件存取的內容。下列程式碼片段展示如何在程式輔助 Webhook 中透過程式輔助設定結構定義,以及如何擷取結構定義物件:

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('...');
});

存取輔助意圖結果

為了方便起見,用戶端程式庫提供輔助意圖類別,納入經常觸發要求的使用者資料類型。這些類別包含各種 Actions on Google 輔助意圖的結果。如果您希望 Google 助理處理對話中的部分,使用者必須提供輸入內容才能繼續對話,請使用輔助意圖。

範例:確認協助結果

確認協助意圖可讓您要求使用者確認是/否,並取得最終答案。下列程式碼片段說明您的 Webhook 如何根據確認輔助程式意圖傳回的結果自訂回應。如需更完整的範例,請參閱 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.`);
  }
});

下列程式碼片段展示了您的執行要求 Webhook 如何依據使用者針對輪轉介面輸入自訂回應。您的輪轉介面元件 可讓動作為使用者提供一系列選項如需更完整的範例,請參閱 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!`);
  }
});

設定對話回應物件

用戶端程式庫提供對話回應類別,代表動作可傳送的豐富回應或多媒體元素。一般而言,如果使用者不需要輸入任何資訊來繼續進行對話,您通常會傳送這些回應或元素。

範例:圖片

下列程式碼片段展示了您的出貨 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 用戶端程式庫專為非同步程式設計所設計。您的意圖處理常式可以傳回一個 promise,它可以在執行 Webhook 完成回應之後解決。

下列程式碼片段展示如何發出非同步函式呼叫以傳回 promise 物件,然後在出貨 Webhook 收到「問候」意圖時,以訊息回應。在這個程式碼片段中,承諾可確保只有在外部 API 呼叫的承諾已解決後,您的 Webhook 才會傳回對話回應。

在這個範例中,我們使用假 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}.`);
  });
});

下列簡化的程式碼片段效果相同,但使用了 ECMA 2017 (Node.js 版本 8) 中引入的 async await 功能。如要將這個程式碼與 Cloud Functions for Firebase 搭配使用,請確認您使用的是正確的 Firebase 工具版本並採用正確的設定。

app.intent('Default Welcome Intent', async (conv) => {
  const weather = await forecast();
  conv.ask('How are you?');
  conv.ask(`Today's weather is ${weather}.`);
});

儲存對話資料

用戶端程式庫可讓您的出貨 Webhook 將資料儲存在對話中,以供日後使用。可用於資料儲存的關鍵物件包括:

下列程式碼片段說明您的出貨 Webhook 如何將資料儲存在您定義的任意屬性 (someProperty) 中,並附加至 Conversation#user.storage 物件。如需更完整的範例,請參閱 Conversation#user.storage 類別參考說明文件。

app.intent('Default Welcome Intent', (conv) => {
  conv.user.storage.someProperty = 'someValue';
  conv.ask('...');
});

您可以使用 Conversation#user 物件來取得使用者的相關資訊,包括字串 ID 和個人資訊。某些欄位 (例如 conv.user.name.displayconv.user.email) 分別要求 conv.ask(new Permission) 要求 NAME 和 conv.ask(new SignIn) 要求 Google 登入。

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!`);
  }
});

使用中介軟體進行資源調度

您可以透過中介軟體擴充用戶端程式庫。

中介軟體層包含您定義的一或多個函式,用戶端程式庫會在呼叫意圖處理常式之前自動執行。使用中介軟體層可讓您修改 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();
});

匯出應用程式

如要公開網路架構或無伺服器運算平台的執行要求 Webhook,您必須將 app 物件匯出為可公開存取的 Webhook。用戶端程式庫支援立即可用的功能,以部署至多個環境。

下列程式碼片段展示如何在不同執行階段中匯出 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;