Oracle Digital Assistant に選択肢を提示させて会話セッションを実現する

Oracle Digital Assistant にて、ユーザに選択肢を提示して、簡単な会話セッションを実現する。

目次

事前準備

「Oracle Digital Assistant Designer UI」画面に行き、任意の「Skill」を作成する。

インテント

今回作成するインテントは1つとする。「startIntent」というインテント名で、一番最初に会話セッションの開始を判断するだけとする。「start talking」とか、好きなサンプルフレーズを登録しておこう。

会話セッションの途中でやっぱり会話を止めるとか、前の質問に戻るとかいうハンドリングをしたい場合は、それぞれのインテントを作って制御してやると良いかと思う。

ダイアログ・フロー

今回はダイアログ・フローによるステート制御を主目的としている。選択肢の提示には System.List というビルトイン・コンポーネントを使う。このコンポーネントによるステート遷移の制御方法をよく見ていただきたい。

# metadata
# ==================================================
metadata:
  platformVersion: 1.0
main: true
name: MySkill

# context
# ==================================================
context:
  # 変数宣言
  variables:
    # インテント・エンジンの結果を保持する
    iResult: "nlpresult"

# states
# ==================================================
states:
  # セッション開始
  # --------------------------------------------------
  
  # ユーザ入力の文字列を解析し、合致するインテントに振り分ける
  intentState:
    component: "System.Intent"
    properties:
      variable: "iResult"
    transitions:
      actions:
        startIntent     : "q1State"          # 「会話開始」インテントに合致したら最初の質問をする
        unresolvedIntent: "unresolvedState"  # インテントにも合致しなかった場合は会話セッションを開始しない
  
  # 「会話開始」以外のインテントに合致した場合
  unresolvedState:
    component: "System.Output"
    properties:
      text: "「会話開始」と発言してね"
    transitions:
      return: "done"
  
  # 質問 1
  # --------------------------------------------------
  
  # 質問する
  q1State:
    component: "System.List"
    properties:
      prompt: "あなたの性別は?"
      options:
        - label: "男性"  # ユーザに見えるボタンのラベル
          value: "male"  # transitions.actions でこの value 値に沿って次のステートを特定する
        - label: "女性"
          value: "female"
    transitions:
      actions:
        male  : "q2MaleState"    # 「男性」選択肢 (「male」アクション) が選択されたら「q2MaleState」ステートに移動する
        female: "q2FemaleState"  # 同様に「女性」=「female」アクションが選択されたら「q2FemaleState」ステートに移動する
  
  # 選択肢にない言葉を受け取った場合、再度質問する
  q1RetryState:
    component: "System.Output"
    properties:
      text: "男性か女性か、選択肢の中から答えてね"
      keepTurn: true  # transitions で指定した次のステートを (ユーザの発言を待たずに) 続けて実行する
    transitions:
      next: "q1State"
  
  # 質問 2 (男性向け)
  # --------------------------------------------------
  
  # 男性向けの質問
  q2MaleState:
    component: "System.List"
    properties:
      prompt: "どちらがより好きですか?"
      options:
        - label: "ゲーム"
          value: "games"
        - label: "スポーツ"
          value: "sports"
    transitions:
      actions:
        games : "maleGamesState"
        sports: "maleSportsState"
  
  # 選択肢にない言葉を受け取った場合、再度質問する
  q2MaleRetryState:
    component: "System.Output"
    properties:
      text: "ゲームかスポーツか、選択肢の中から答えてね"
      keepTurn: true
    transitions:
      next: "q2MaleState"
  
  # 質問 2 (女性向け)
  # --------------------------------------------------
  
  # 女性向けの質問
  q2FemaleState:
    component: "System.List"
    properties:
      prompt: "どちらがより好きですか?"
      options:
        - label: "ファッション"
          value: "fashion"
        - label: "スイーツ"
          value: "sweets"
    transitions:
      actions:
        fashion: "femaleFashionState"
        sweets : "femaleSweetsState"
  
  # 選択肢にない言葉を受け取った場合、再度質問する
  q2FemaleRetryState:
    component: "System.Output"
    properties:
      text: "ファッションかスイーツか、選択肢の中から答えてね"
      keepTurn: true
    transitions:
      next: "q2FemaleState"
  
  # 最終回答集
  # --------------------------------------------------
  
  maleGamesAction:
    component: "System.Output"
    properties:
      text: "あなたはゲームが好きな男性なんですね!"
    transitions:
      return: "done"
  
  maleSportsAction:
    component: "System.Output"
    properties:
      text: "あなたはスポーツが好きな男性なんですね!"
    transitions:
      return: "done"
  
  femaleFashionAction:
    component: "System.Output"
    properties:
      text: "あなたはファッションが好きな女性なんですね!"
    transitions:
      return: "done"
  
  femaleSweetsAction:
    component: "System.Output"
    properties:
      text: "あなたはスイーツが好きな女性なんですね!"
    transitions:
      return: "done"

System.List コンポーネントを使う際は、options で選択肢を定義できる。

label が選択肢のボタンラベルとなるが、別にユーザがボタンを押さなくとも、同一の文字列を手入力して返信しても同じ効果が得られる。

value で、label と対応するアクション名を任意で定義する。このアクション名は transitions.actions プロパティで「次に移動するステート」をハンドリングするための文言として使用する。

System.List コンポーネントで提示する選択肢にない言葉が飛んできた場合は、transitions.actions で定義しているどのアクションとも合致しないので、自動的にその下 (直後) に記述されているステートに移動する。

たとえば、q1State ステートで「あなたの性別は?」と尋ねられた時に、「どちらでもない」と回答すると、male アクションとも female アクションとも合致しないので、次に書かれた q1RetryState ステートが実行される。

で、この q1RetryState では「選択肢の中から答えてね」と発話させると同時に、keepTurn: true 指定によって、即座に transitions.next に書かれた次のステート、q1State が実行される。つまりユーザからすると、「選択肢の中から答えてね」「あなたの性別は?」と連続で2通の返信をもらうことになる。

このような選択肢による次ステートのハンドリングを行い、最終的には「あなたは○○が好きな人なんですね!」と発言して、return: "done" 指定によって会話セッションを終了する。

作成できたら、「Testing」ボタン (再生マークのアイコン) から会話してみよう。

以上

今回は System.List ビルトイン・コンポーネントを使って選択肢を提示し、ステート制御をしてみた。ダイアログ・フローが長くなりがちなので、ユーザをどのように誘導したいかと、どのようなコンポーネントで制御できそうかを見極める必要があるだろう。

また、ココまででは Digital Assistant の管理画面上でしか動作を確認できないので、Web ページや Facebook Messenger など、何らかの「フロントエンド」が必要になる。コチラは別途紹介しよう。