建構執行要求 (Dialogflow)

執行要求會定義動作的對話介面,以取得使用者輸入內容和處理輸入內容的邏輯,藉此完成動作。

定義對話

現在您已定義動作,可以為這些動作建構對應的對話。要達到這個目的,您可以建立 Dialogflow 意圖來定義文法或使用者需要說的內容,藉此觸發意圖,並在觸發意圖時處理相應的執行要求。

您可以建立任意數量的意圖,用來定義整個對話的文法。

建立意圖

在 Dialogflow 左側導覽面板中,按一下「Intents」(意圖)+ 選單項目旁的「+」+符號。畫面上會顯示意圖編輯器,您可以在其中輸入下列資訊:

  • 「意圖名稱」是意圖在 IDE 中顯示的名稱。
  • 「情境」可讓您將意圖觸發範圍的範圍縮小至特定情況。詳情請參閱有關背景資訊的 Dialogflow 說明文件。
  • 「事件」會觸發意圖,而使用者無需採取任何動作。其中一個範例事件是 GOOGLE_ASSISTANT_WELCOME 事件,可讓 Google 助理叫用您的動作。這個事件會用於動作的預設動作。如要進一步瞭解內建輔助意圖,請參閱說明文件。
  • 訓練詞組會定義使用者需要說的內容 (文法) 才能觸發意圖。請在這裡輸入幾個詞組 (5 至 10),說明使用者可說哪些內容來觸發意圖。Dialogflow 會自動處理您提供的範例詞組的自然變化形式。
  • 如果這個意圖啟用了執行要求,「動作和參數」會定義要傳送至執行要求的資料。包括剖析使用者輸入內容中的資料,以及在執行要求中使用的名稱,以偵測觸發的意圖。您稍後會使用這個名稱,將意圖對應到對應的執行要求邏輯。如要進一步瞭解如何定義動作,請參閱 Dialogflow 說明文件中的動作和參數

  • 回應是 Dialogflow 回應建構工具,您可以在 Dialogflow 中直接定義這個意圖的回應,而不必呼叫執行要求。此功能對於不需要執行要求的靜態回應非常實用。這可以提供簡單的歡迎訊息或道別訊息。然而,您可能會使用執行要求來回應使用者大多數的意圖。

  • 「Fulfillment」(執行要求) 可讓您指定是否在觸發此意圖時呼叫執行要求。您很可能會針對 Dialogflow 代理程式中的大多數意圖啟用這項功能。如要在意圖中查看這個項目,您必須先在「Fulfillment」選單中為代理程式啟用執行要求。

在 Dialogflow 中建構回覆

在某些意圖中,您可能不需要讓執行要求傳回回應。在這種情況下,您可以在 Dialogflow 中使用回應建構工具來建立回應。

在「Responses」區域中,提供您要傳回給使用者的文字回應。預設文字回應是簡單的 TTS 文字回應,可用於多項 Dialogflow 整合。請參閱「回應」頁面,瞭解 Google 助理的回應。

建築物執行要求回應

您的執行要求程式碼會託管於該動作的 Webhook 執行要求邏輯。例如,在 Silly Name Maker 範例中,您可以在 Cloud Function for Firebase 的 index.js 中找到這個邏輯。

使用執行要求觸發的意圖時,您會收到來自 Dialogflow 的要求,當中包含意圖相關資訊。接著,您可以處理意圖並傳回回應,藉此回應要求。這項要求和回應是由 Dialogflow Webhook 定義,

強烈建議您使用 Node.js 用戶端程式庫來處理要求及傳回回應。以下為使用用戶端程式庫的一般程序:

  1. 初始化 Dialogflow 物件。這個物件會自動處理並剖析要求,方便您在執行要求中處理。
  2. 建立函式來處理要求。 這些函式會處理使用者輸入內容和其他意圖元件,並建立回應以傳回 Dialogflow。

初始化 Dialogflow 物件

以下程式碼會執行個體化 Dialogflow,並對 Google Cloud Functions 執行部分樣板 Node.js 設定:

Node.js
'use strict';

const {dialogflow} = require('actions-on-google');
const functions = require('firebase-functions');

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

app.intent('Default Welcome Intent', (conv) => {
  // Do things
});
exports.yourAction = functions.https.onRequest(app);
Java
public class DfFulfillment extends DialogflowApp {
  private static final Logger LOGGER = LoggerFactory.getLogger(DfFulfillment.class);

  @ForIntent("Default Welcome Intent")
  public ActionResponse welcome(ActionRequest request) {
    // Do things
    // ...
  }

建立函式來處理要求

當使用者說出會觸發意圖的詞組時,您就會收到 Dialogflow 發出的要求,這類要求會使用執行要求中的函式處理。在這個函式中,您通常會執行以下操作:

  1. 執行任何處理使用者輸入內容所需的邏輯。
  2. 建構回應來回應觸發的意圖。請將使用者用來建構適當回應的介面納入考量。如要進一步瞭解如何為不同介面提供回應,請參閱「介面功能」。
  3. 使用回應呼叫 ask() 函式。

以下程式碼示範如何建構兩個用於處理叫用意圖 (input.welcome) 的 TTS 回應,以及歡迎使用者執行動作的對話方塊意圖 (input.number),並回響使用者對 Dialogflow 意圖說出的一個數字:

Node.js
const app = dialogflow();
app.intent('Default Welcome Intent', (conv) => {
conv.ask('Welcome to number echo! Say a number.');
});
app.intent('Input Number', (conv, {num}) => {
// extract the num parameter as a local string variable
conv.close(`You said ${num}`);
});
Java
@ForIntent("Default Welcome Intent")
public ActionResponse defaultWelcome(ActionRequest request) {
  ResponseBuilder rb = getResponseBuilder(request);
  rb.add("Welcome to number echo! Say a number.");
  return rb.build();
}

@ForIntent("Input Number")
public ActionResponse inputNumber(ActionRequest request) {
  ResponseBuilder rb = getResponseBuilder(request);
  Integer number = (Integer) request.getParameter("num");
  rb.add("You said " + number.toString());
  return rb.endConversation().build();
}

與上述程式碼一同的自訂意圖 Input Number 會使用 @sys.number 實體,從使用者話語中擷取數字。接著,意圖會將 num 參數 (內含使用者提供的數字) 傳送至執行要求中的函式。

您也可以新增備用函式,而非為每個意圖設定個別處理常式。在備用函式中,檢查哪個意圖觸發了此函式,並據此採取適當行動。

Node.js
const WELCOME_INTENT = 'Default Welcome Intent';
const NUMBER_INTENT = 'Input Number';
const NUMBER_PARAMETER = 'num';
// you can add a fallback function instead of a function for individual intents
app.fallback((conv) => {
 // intent contains the name of the intent
 // you defined in the Intents area of Dialogflow
 const intent = conv.intent;
 switch (intent) {
   case WELCOME_INTENT:
     conv.ask('Welcome! Say a number.');
     break;
   case NUMBER_INTENT:
     const num = conv.parameters[NUMBER_PARAMETER];
     conv.close(`You said ${num}`);
     break;
 }
});
Java
// you can add a fallback function instead of a function for individual intents
@ForIntent("Default Fallback Intent")
public ActionResponse fallback(ActionRequest request) {
  final String WELCOME_INTENT = "Default Welcome Intent";
  final String NUMBER_INTENT = "Input Number";
  final String NUMBER_ARGUMENT = "num";
  // intent contains the name of the intent
  // you defined in the Intents area of Dialogflow
  ResponseBuilder rb = getResponseBuilder(request);
  String intent = request.getIntent();
  switch (intent) {
    case WELCOME_INTENT:
      rb.add("Welcome! Say a number.");
      break;
    case NUMBER_INTENT:
      Integer num = (Integer) request.getParameter(NUMBER_ARGUMENT);
      rb.add("You said " + num).endConversation();
      break;
  }
  return rb.build();
}

未比對重複的提示

如果 Dialogflow 無法比對意圖訓練詞組中定義的任何輸入文法,就會觸發備用意圖。備用意圖通常會再次提示使用者為動作提供必要的輸入內容。如要提供自動提示詞組,請在備用意圖的「Response」區域中指定這些詞組,也可以使用 Webhook 提供回應。

如果使用者的回應與動作的訓練詞組不符,Google 助理會嘗試處理輸入內容。這個行為可協助使用者在對話中變更動作。例如,有位使用者詢問「本週上映哪些電影?」,然後在對話期間變更情境:「明天天氣如何?」在這個例子中,由於「明天天氣如何?」對於初始提示觸發的對話並非有效的回應,因此 Google 助理會自動嘗試處理相符項目,並將使用者移至適當的對話。

如果 Google 助理找不到與使用者輸入內容相符的適當動作,使用者就會返回動作的情境。

由於 Google 助理可能會中斷您的動作以回應有效的不相符情境,因此請勿使用備用意圖來完成使用者查詢。您應只使用備用意圖,重新提示使用者輸入有效的輸入內容。

如要建立備用意圖,請按照下列指示操作:

  1. 在 Dialogflow 的導覽選單中按一下「Intents」
  2. 按一下「Create Intent」(建立意圖) 旁的 ⋮,然後選取「Create Fallback Intent」(建立備用意圖)。(您也可以按一下 [Default Fallback Intent] (預設備用意圖) 來編輯)。
  3. 指定要提示的詞組,回覆使用者。這些詞組應為對話式,並盡可能對使用者目前背景資訊有用。

    如要在沒有執行要求的情況下執行這項操作:請在意圖的「Response」區域中指定詞組。Dialogflow 會隨機從這份清單中選擇詞組來向使用者說話,直到觸發更具體的意圖為止。

    如何透過執行要求執行這項操作

    1. 在意圖的「Fulfillment」區段,切換「Enable Webhookcall for this intent」(針對這個意圖啟用 Webhook 呼叫)。
    2. 請在執行要求邏輯中,按照「建立處理要求的函式」一節所述的方式處理備用意圖。

    舉例來說,下列函式會使用 Node.js 用戶端程式庫conv.data 物件 (可用來維護狀態的任意資料酬載),儲存計數器,追蹤備用意圖的觸發次數。如果動作多次觸發,動作就會退出。儘管程式碼並未顯示,但應在觸發非備用意圖時,讓其他意圖將此計數器重設為 0。(如要進一步瞭解如何實作此範例,請參閱「數字 Genie 範例」)。

    Node.js
    app.intent('Default Fallback Intent', (conv) => {
     conv.data.fallbackCount++;
     // Provide two prompts before ending game
     if (conv.data.fallbackCount === 1) {
       conv.contexts.set(DONE_YES_NO_CONTEXT, 5);
       conv.ask('Are you done playing Number Genie?');
     } else {
       conv.close(`Since I'm still having trouble, so I'll stop here. ` +
         `Let's play again soon.`);
     }
    });
    Java
    @ForIntent("Default Fallback Intent")
    public ActionResponse defaultFallback(ActionRequest request) {
      final String DONE_YES_NO_CONTEXT = "done_yes_no_context";
      ResponseBuilder rb = getResponseBuilder(request);
    
      int fallbackCount =
          request.getConversationData().get("fallbackCount") == null
              ? 0
              : (Integer) request.getConversationData().get("fallbackCount");
      fallbackCount++;
      request.getConversationData().put("fallbackCount", fallbackCount);
    
      if (fallbackCount == 1) {
        rb.add(new ActionContext(DONE_YES_NO_CONTEXT, 5));
        rb.add("Are you done playing Number Genie?");
      } else {
        rb.add("Since I'm still having trouble, so I'll stop here. Let's play again soon")
            .endConversation();
      }
      return rb.build();
    }

使用背景資訊

如果您想讓 Dialogflow 只在特定情況下觸發備用意圖,請使用結構定義。如果您想為不同的不相符情境設定不同的備用意圖,這個方法就十分實用。

  • 如果您未針對備用意圖設定背景資訊,系統會將此動作視為全域備用意圖,在沒有相符的其他意圖時觸發。如果你選擇使用其中一個變數,只能擇一使用。
  • 如果您為備用意圖設定輸入背景資訊,Dialogflow 會在以下情況觸發這個備用意圖:

    • 使用者的目前背景資訊是意圖中定義的背景資訊超集。
    • 沒有其他相符的意圖。

    如此一來,您就能使用不同輸入情境的多個備用意圖,自訂要與特定情境不相符的重新比對。

  • 如果您對備用意圖設定輸出背景資訊,系統在觸發及處理備用意圖後,就能將使用者留在相同的情境中。

詳情請參閱「Dialogflow 情境」一文。

無輸入重新提示

如要進一步瞭解當使用者未在 Google Home 等需要持續互動的語音裝置上提供進一步輸入內容時,應如何處理。請參閱拒絕提示頁面。