Webhook

為了讓您更靈活地建構動作,您可以將邏輯委派給 HTTPS 網路服務 (執行要求)。您的動作可觸發向 HTTPS 端點發出要求的 Webhook。執行要求時可執行的操作範例包括:

  • 根據使用者提供的資訊產生動態提示。
  • 下單給外部系統並確認成功。
  • 使用後端資料驗證運算單元。
圖 1. 叫用意圖和場景可以觸發 Webhook。

Webhook 觸發條件和處理常式

動作可以在叫用意圖或場景中觸發 Webhook,進而傳送要求至執行要求端點。執行要求包含 Webhook 處理常式,會在要求中處理 JSON 酬載。您可以在下列情況觸發 Webhook:

  • 叫用意圖相符之後
  • 場景處於進入階段時
  • 場景條件階段中的條件評估結果為 True
  • 場景的運算單元填充階段
  • 在場景的輸入階段中比對意圖後

當您在動作中觸發 Webhook 時,Google 助理會將含有 JSON 酬載的要求傳送至執行要求,該執行要求含有用於處理該事件的處理常式名稱。執行要求端點可將事件轉送至適當的處理常式,以便執行邏輯並傳回含有 JSON 酬載的回應

酬載

以下程式碼片段顯示動作傳送至執行要求的範例,以及執行要求傳回的回應。詳情請參閱參考說明文件

要求範例

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "example_session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

回應範例

{
  "session": {
    "id": "example_session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Hello World.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {},
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  }
}

執行階段互動

以下各節說明您可以在 Webhook 處理常式中執行的一般工作。

傳送提示

您可以利用互動式畫布,以簡單的文字、RTF 格式、資訊卡,甚至是網頁應用程式支援的完整 HTML 提示來建立提示。提示說明文件提供如何在處理 Webhook 事件時建立提示的完整資訊。下列程式碼片段會顯示資訊卡提示:

Node.js

app.handle('rich_response', conv => {
  conv.add('This is a card rich response.');
  conv.add(new Card({
    title: 'Card Title',
    subtitle: 'Card Subtitle',
    text: 'Card Content',
    image: new Image({
      url: 'https://developers.google.com/assistant/assistant_96.png',
      alt: 'Google Assistant logo'
    })
  }));
});

回應 JSON

{
  "session": {
    "id": "example_session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "content": {
      "card": {
        "title": "Card Title",
        "subtitle": "Card Subtitle",
        "text": "Card Content",
        "image": {
          "alt": "Google Assistant logo",
          "height": 0,
          "url": "https://developers.google.com/assistant/assistant_96.png",
          "width": 0
        }
      }
    },
    "firstSimple": {
      "speech": "This is a card rich response.",
      "text": ""
    }
  }
}

讀取意圖參數

當 Google 助理執行階段比對意圖時,會擷取任何已定義的參數。原始屬性是使用者提供做為輸入內容,而解析屬性則是 NLU 根據類型規格解析輸入。

Node.js

conv.intent.params['param_name'].original
conv.intent.params['param_name'].resolved

要求 JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "intent_name",
    "params": {
      "slot_name": {
        "original": "1",
        "resolved": 1
      }
    },
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {},
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

讀取使用者語言代碼

這個值反映使用者的 Google 助理語言代碼設定。

Node.js

conv.user.locale

JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

讀取及寫入儲存空間

如需使用各種儲存空間功能的完整資訊,請參閱儲存空間說明文件。

Node.js

//read
conv.session.params.key
conv.user.params.key
conv.home.params.key

// write
conv.session.params.key = value
conv.user.params.key = value
conv.home.params.key = value 

要求 JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {
      "key": "value"
    },
    "typeOverrides": [],
    "languageCode": ""
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED",
      "key": "value"
    }
  },
  "home": {
    "params": {
      "key": "value"
    }
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

回應 JSON

{
  "session": {
    "id": "session_id",
    "params": {
      "key": "value"
    }
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Hello world.",
      "text": ""
    }
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED",
      "key": "value"
    }
  },
  "home": {
    "params": {
      "key": "value"
    }
  }
}

檢查裝置功能

您可以檢查裝置的功能,提供不同的體驗或對話流程。

Node.js

const supportsRichResponse = conv.device.capabilities.includes("RICH_RESPONSE");
const supportsLongFormAudio = conv.device.capabilities.includes("LONG_FORM_AUDIO");
const supportsSpeech = conv.device.capabilities.includes("SPEECH");
const supportsInteractiveCanvas = conv.device.capabilities.includes("INTERACTIVE_CANVAS");

要求 JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": [],
    "languageCode": ""
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO",
      "INTERACTIVE_CANVAS"
    ]
  }
}

如需表面功能的完整清單,請參閱 Capability 參考資料。

執行階段類型覆寫

執行階段類型可讓您在執行階段修改類型規格。您可以使用這項功能從其他來源載入資料,填入該類型的有效值。舉例來說,您可以使用執行階段類型覆寫,在問卷調查問題中加入動態選項,或是在選單中新增每日項目。

如要使用執行階段類型,請從動作觸發 Webhook,以便呼叫執行要求中的處理常式。接著,您可以在回應動作的回應中填入 session.typeOverrides 參數。可用模式包括 TYPE_MERGE 以保留現有類型項目,或加入 TYPE_REPLACE 以覆寫現有項目。

Node.js

conv.session.typeOverrides = [{
    name: type_name,
    mode: 'TYPE_REPLACE',
    synonym: {
      entries: [
        {
          name: 'ITEM_1',
          synonyms: ['Item 1', 'First item']
        },
        {
          name: 'ITEM_2',
          synonyms: ['Item 2', 'Second item']
       },
       {
          name: 'ITEM_3',
          synonyms: ['Item 3', 'Third item']
        },
        {
          name: 'ITEM_4',
          synonyms: ['Item 4', 'Fourth item']
        },
    ]
  }
}];

回應 JSON

{
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": [
      {
        "name": "type_name",
        "synonym": {
          "entries": [
            {
              "name": "ITEM_1",
              "synonyms": [
                "Item 1",
                "First item"
              ]
            },
            {
              "name": "ITEM_2",
              "synonyms": [
                "Item 2",
                "Second item"
              ]
            },
            {
              "name": "ITEM_3",
              "synonyms": [
                "Item 3",
                "Third item"
              ]
            },
            {
              "name": "ITEM_4",
              "synonyms": [
                "Item 4",
                "Fourth item"
              ]
            }
          ]
        },
        "typeOverrideMode": "TYPE_REPLACE"
      }
    ]
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": "This is an example prompt."
    }
  }
}

提供語音自訂調整功能

語音自訂調整功能可讓您為 NLU 指定提示,以改善意圖比對作業。您最多可以指定 1,000 個項目。

Node.js

conv.expected.speech = ['value_1', 'value_2']
conv.expected.language = 'locale_string'

回應 JSON

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": "This is an example prompt."
    }
  },
  "expected": {
    "speech": "['value_1', 'value_2']",
    "language": "locale_string"
  }
}

轉場場景

除了在 Actions 專案中定義靜態轉場之外,也可能導致場景轉換在執行階段發生。

Node.js

app.handle('transition_to_hidden_scene', conv => {
  // Dynamic transition
  conv.scene.next.name = "HiddenScene";
});

回應 JSON

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {},
    "next": {
      "name": "HiddenScene"
    }
  }
}

讀取場景版位

在運算單元填充期間,您可以使用執行要求來驗證運算單元,或檢查運算單元填充狀態 (SlotFillingStatus)。

Node.js

conv.scene.slotFillingStatus  // FINAL means all slots are filled
conv.scene.slots  // Object that contains all the slots
conv.scene.slots['slot_name'].<property_name> // Accessing a specific slot's properties

例如,假設您想要從回應中擷取時區。在這個範例中,運算單元名稱為 datetime1。如要取得時區,您應使用:

conv.scene.slots['datetime1'].value.time_zone.id

要求 JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "",
    "params": {
      "slot_name": {
        "original": "1",
        "resolved": 1
      }
    },
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "FINAL",
    "slots": {
      "slot_name": {
        "mode": "REQUIRED",
        "status": "SLOT_UNSPECIFIED",
        "updated": true,
        "value": 1
      }
    },
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  },
  "session": {
    "id": "session_id",
    "params": {
      "slot_name": 1
    },
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

撤銷場景版位

您可以撤銷運算單元,並讓使用者提供新的值。

Node.js

conv.scene.slots['slot_name'].status = 'INVALID'

回應 JSON

{
  "session": {
    "id": "session_id",
    "params": {
      "slot_name": 1
    }
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {
      "slot_name": {
        "mode": "REQUIRED",
        "status": "INVALID",
        "updated": true,
        "value": 1
      }
    },
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  }
}

開發選項

Actions Builder 提供名為 Cloud Functions 編輯器的內嵌編輯器,可讓您直接在控制台中建構及部署 Cloud Function for Firebase。您也可以在選擇的託管中建構及部署執行要求,並將 HTTPS 執行要求端點註冊為 Webhook 處理常式。

內嵌編輯器

如要使用 Cloud Functions 編輯器進行開發:

  1. 開啟動作專案,然後依序前往「Develop」(開發分頁) >「Webhook」>「變更執行要求方法」。系統會隨即顯示「Fulfillment methods」(執行方法) 視窗。
  2. 選取「Inline Cloud Functions」,然後按一下「確認」

外部 HTTPS 端點

本節說明如何將 Cloud Functions for Firebase 設為對話動作的執行要求服務。不過,您可以將執行要求部署至所選的託管服務。

設定環境

如要設定環境,請按照下列步驟操作:

  1. 下載並安裝 Node.js
  2. 設定並初始化 Firebase CLI。如果下列指令失敗並顯示 EACCES 錯誤,您可能需要變更 npm 權限

    npm install -g firebase-tools
    
  3. 使用 Google 帳戶驗證 Firebase 工具:

    firebase login
    
  4. 啟動您儲存動作專案的專案目錄。系統會要求您選取要為 Actions 專案設定哪些 Firebase CLI 功能。選擇 Functions 和其他您可能會想使用的功能 (例如 Firestore),然後按下 Enter 鍵確認並繼續操作:

    $ cd <ACTIONS_PROJECT_DIRECTORY>
    $ firebase init
    
  5. 如要將 Firebase 工具與您的 Actions 專案建立關聯,請使用方向鍵選取專案清單:

  6. 選取專案後,Firebase 工具會啟動函式設定,並詢問您要使用的語言。使用方向鍵選取,然後按下 Enter 鍵繼續。

    === Functions Setup
    A functions directory will be created in your project with a Node.js
    package pre-configured. Functions can be deployed with firebase deploy.
    
    ? What language would you like to use to write Cloud Functions? (Use arrow keys)
    > JavaScript
    TypeScript
    
  7. 選擇是否要使用 ESLint 偵測可能發生的錯誤,並強制執行樣式,方法是輸入「Y」或「N」

    ? Do you want to use ESLint to catch probable bugs and enforce style? (Y/n)
  8. 在提示中輸入 Y,取得專案依附元件:

    ? Do you want to install dependencies with npm now? (Y/n)

    設定完成後,畫面會顯示類似以下的輸出內容:

    ✔  Firebase initialization complete!
    
  9. 安裝 @assistant/conversation 依附元件:

    $ cd <ACTIONS_PROJECT_DIRECTORY>/functions
    $ npm install @assistant/conversation --save
    
  10. 取得執行要求依附元件,並部署執行要求函式:

    $ npm install
    $ firebase deploy --only functions
    

    部署作業需要幾分鐘時間。完成後,畫面會顯示類似以下的輸出內容。在 Dialogflow 中,您需要輸入函式網址

    ✔  Deploy complete!
    Project Console: https://console.firebase.google.com/project/<PROJECT_ID>/overview Function URL (<FUNCTION_NAME>): https://us-central1-<PROJECT_ID>.cloudfunctions.net/<FUNCTION_NAME>
  11. 請複製執行要求網址,以便在下一個部分使用。

註冊 Webhook 處理常式

如要將 Cloud 函式端點註冊為 Webhook 處理常式,請按照下列指示操作:

  1. 在 Actions 控制台中,依序按一下「Develop」(開發) >「Webhook」
  2. 按一下「變更執行要求方法」。系統隨即會顯示「Fulfillment methods」視窗。
  3. 選取「Webhook」並按一下「確認」
  4. 將網路服務網址貼到「Webhook」欄位中。
  5. 點按「儲存」