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

建議您使用 Actions on Google Node.js 用戶端程式庫,還是能存取及 與 Actions on Google 平台互動 執行 Webhook

簡介

Node.js 用戶端程式庫是 Actions on Google 提供以下功能:

  • 支援所有 Actions on Google 功能,包括文字和互動式多媒體回應 登入帳戶、儲存資料、交易等。
  • 提供 JavaScript 中慣用的抽象層, 對話 HTTP/JSON Webhook API
  • 處理執行要求與執行要求之間的低層級通訊細節 Actions on Google 平台
  • 可透過熟悉的套件管理工具安裝,例如 npmyarn
  • 讓您在無伺服器運算平台上輕鬆部署執行要求 Webhook 例如 Cloud Functions for FirebaseAWS Lambda。您也可以代管執行要求 Webhook 或自行託管及自行管理的環境
  • Node.js 6.0.0 以上版本相容。

您可以將用戶端程式庫與 適用於 Actions on Google 的 Dialogflow 整合功能 或使用 Actions 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 平台將 HTTP 要求傳送至執行要求 Webhook;要求 包含 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. 對話處理:用戶端程式庫代表 以 Conversation 物件的形式提供個別對話資訊,這個物件會附加到 app 執行個體。執行要求 Webhook 可以使用 Conversation 物件: 擷取跨對話已儲存資料或狀態資訊、傳送回應 或關閉麥克風
  5. 中介軟體處理:用戶端程式庫可讓您建立 自己的對話服務中介軟體,內含一或多個功能 您定義在呼叫之前,用戶端程式庫會自動執行 意圖處理常式執行要求 Webhook 可以使用中介軟體新增屬性 或是 Conversation 物件的輔助類別。
  6. 意圖處理常式處理:用戶端程式庫可讓您 執行要求 Webhook 能理解的意圖處理常式。以 Dialogflow 來說, 用戶端程式庫會藉由 對應於 Dialogflow 主控台。至於 Actions SDK 的轉送方式是根據已傳送的 intent 屬性轉送 透過 Actions on Google 收集資訊
  7. 將回應傳送給使用者:如要建構回應,您的執行要求 Webhook 會呼叫 Conversation#ask() 函式。ask() 函式可以是 以便逐步建構回應。 用戶端程式庫會將回應序列化為 HTTP 要求, JSON 酬載並傳送至 Actions on Google。close() 函式有一個 這個行為與 ask() 相似,但會關閉對話。
,瞭解如何調查及移除這項存取權。

設定本機開發環境

實作執行要求 Webhook 之前,請務必先安裝 用戶端程式庫

安裝用戶端程式庫

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

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

  • 如果使用 npmnpm install actions-on-google
  • 如果使用紗線yarn add actions-on-google

設定專案資料夾

視您打算部署執行要求 Webhook 而定 (Google 的 Cloud Functions) 或自行託管的 Express 服務),您可能需要建立 的特定專案資料夾結構,才能儲存檔案。

舉例來說,如果您使用的是 Cloud Functions for Firebase 所需專案資料夾的 設定 Node.js 和 Firebase CLI ,並 初始化 Cloud Functions 的 Firebase。以 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 } 標記,藉此取得使用者要求或回應:

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

設定事件的處理常式

為了處理用戶端程式庫於 您需要使用 用戶端程式庫,建構處理常式來處理使用者要求 回應。

您可以建立函式做為這些主要事件類型的處理常式 用戶端程式庫可辨識的字元:

  • 意圖事件:意圖是 Actions on Google 傳送的專屬 ID 加進執行要求。如果 您正在使用 Dialogflow,這相當於 Dialogflow 比對使用者查詢 附加至 Dialogflow 代理程式中的意圖
  • 錯誤事件:發生 JavaScript 或用戶端程式庫錯誤時, 您可以使用 app 執行個體的 catch 函式來處理錯誤例外狀況 才是正確的做法您應實作單一 catch 函式來處理所有 執行要求所關注的錯誤
  • 備用事件:當使用者 Actions on Google 無法辨識任何查詢。您可以使用 app 執行個體的 fallback 函式,用於註冊一般備用處理常式 如果輸入的 filment 沒有符合任何意圖處理常式,就會觸發 請求。您應實作單一 fallback 函式來處理所有 備用事件。如果您使用的是 Dialogflow,Dialogflow 可以觸發特定的 沒有其他相符意圖時的備用意圖您應建立 該備用意圖的對應意圖處理常式。

每當使用者傳送要求至您的動作時,app 例項就會建立 Conversation 。這個物件是透過以下方式存取: 在意圖處理常式函式中傳遞的 conv 變數名稱,做為 第一個函式引數您通常會使用 conv 物件,傳送回應給使用者。

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

  • 如果您使用的是 Actions SDK,請在動作套件中定義參數。 如要瞭解如何從意圖中擷取參數,請參閱 Eliza 程式碼範例
  • 如果您使用的是 Dialogflow,可以透過 params 變數。如要查看在 Google Play 遊戲中 請參閱這篇文章,瞭解如何存取參數和背景資訊。

設定意圖的處理常式

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

如果您使用的是 Dialogflow,則無需為以下項目設定處理常式: 代理程式您可以改用 Dialogflow 的內建回應 處理常式可自動處理意圖,無需實作自己的處理常式 函式。舉例來說, 預設歡迎意圖可以是 則是透過這種方式委派給 Dialogflow。

以下範例顯示「greeting」的意圖處理常式和「再見」 意圖。其匿名處理常式函式會使用 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() 類似,差別在於其關閉 麥克風和對話結束了

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

設定錯誤事件的處理常式

如要為錯誤設定處理常式,請呼叫 appcatch() 函式 執行個體。(舉例來說,如果使用 Dialogflow,這裡的就是 DialogflowApp#catch()敬上 function.)

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

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

設定備用事件的處理常式

如要設定一般備用處理常式,但該處理常式與 傳入執行要求,請呼叫 fallback() 函式 您的 app 執行個體。(舉例來說,如果使用 Dialogflow,這裡的就是 DialogflowApp#fallback()敬上 function.)

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

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

建構意圖處理常式

本節說明實作意圖處理常式的幾個常見用途 用戶端程式庫如要瞭解用戶端程式庫的比對結果 意圖,請參閱「意圖處理常式處理」區段,位於 瞭解運作方式

存取參數和結構定義

如果您使用的是 Dialogflow,您可以定義 參數和 在您的 Dialogflow 代理程式中進行結構定義,以便進行維護 並控制對話流程。

參數適合用來擷取使用者中的重要字詞、詞組或值 舉個簡單的例子,您可以定義情境 並指示 AI 如何回應服務中心查詢Dialogflow 會從使用者的查詢內容中擷取對應的參數 並在執行要求 Webhook 中處理這些參數值, 判斷回應使用者的方式

每當使用者傳送要求至您的動作時,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('...');
});

存取輔助意圖結果

為了方便起見,用戶端程式庫 輔助意圖類別 納入「動作」經常要求的常見使用者資料類型。這些 包含類別來代表各種 Actions on 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 用戶端程式庫專為非同步設計 程式設計意圖處理常式可傳回 執行要求 Webhook 生成回應。

下列程式碼片段說明如何進行非同步函式呼叫, 傳回承諾物件,並在執行要求 Webhook 時回應訊息 收到「希臘」時意圖。在這個程式碼片段中,保證可確保 執行要求 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 await 功能在 ECMA 2017 (Node.js 版本 8) 中推出。使用條件 透過 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}.`);
});
敬上

儲存對話式資料

用戶端程式庫可讓您的執行要求 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;