Oracle Mobile Cloud でチャットボットを作ってみた

こんにちは id:dhigashi です。
忘年会疲れしてませんか。お体をいたわっていきましょう。

それでは Oracle Cloud Advent Calendar 2018 の 18 日目です。

はじめに

今日 @mai_naga17 さんが企画をされている、カスタマーサクセスとチャットボットのイベントが開催されます。

connpass.com

何度も増席を繰り返し100席になっていて、注目度の高さが伺えます。

f:id:dhigashi:20181218110318p:plain

便乗して私も Oracle Cloud の Mobile Cloud でチャットボットを作ってみたいと思います。
今回作成するチャットボットは、ランチのお店を訪ねたらリコメンドしてくれる機能の提供を目指します。

ちなみに、ブログを書き始めてから Oracle Cloud その2 Advent Calendar 2018@chiroito さんが Digital Assistant でチャットボットを作る記事を書かれている事に気づきました。

chiroito.hatenablog.jp

Mobile Cloud と Digital Assistant って何が違うのかと調べると、

Oracle Autonomous Digital Assistant: The new incarnation for conversation interfaces

So what does that mean to the Autonomous Mobile Cloud Enterprise platform that Oracle had earlier? Well technically nothing has changed, we have decoupled the Mobile Platform and the chatbot Platform and now rebranded the SKU as Autonomous Mobile Cloud and Autonomous Digital Assistant.

技術的には一緒みたいです。なので二番煎じの内容もありますが気にせず進めていきます。

↓Digital Assistant のリリース記事
オラクル、企業向け次世代チャットボット構築・運用環境「Digital Assistant Cloud」を提供 | Oracle 日本

Oracle Mobile Cloud スタックの作成

Oracle Cloud のメニューから Mobile に行くと Oracle Cloud スタック の画面になるので、テンプレートに Oracle-Mobile-Cloud-Enterprise-Template を指定してスタックを作成します。
全てのリソースが立ち上がるまで何時間かかかるので気長に待ちます。

全て立ち上がると、24 Resources, 7 OCPUs, 90GB Memory… と何かドキドキしますね。

f:id:dhigashi:20181218131956p:plain

<Stack名>CORE というリソースがあるので、ロードバランサーの URL を取得し OMCe UI にアクセスします。
OMCe UI の URL は <Load Balancer URL>/mobileui/ です。

f:id:dhigashi:20181218131732p:plain

ここからチャットボットを作成していきます。

チャットボットの作成

New Bot から新しいボットを作成します。

f:id:dhigashi:20181218134318p:plain

ボットができると、右上の test ボタンでボットを動かすことができるので試してみると良いと思います。

f:id:dhigashi:20181218134733p:plain

インテントの作成

ボットに与えられる発言が、「ランチのおすすめを聞いている」という意図であるのを理解させる為に、インテント を作成します。

TodaysLunch という インテント を作成し「お昼ごはん」「ランチ」のようなキーワードを登録しました。
また「こんにちは」「やぁ」などを登録した Hello という インテント も作成しておきました。

f:id:dhigashi:20181218142603p:plain

右上の Train でトレーニングを実行し、再度 test で試してみます。
Intent タブで発言を行うと、インテントの推定値がわかります。

f:id:dhigashi:20181218144017p:plain

この発言は、どの インテント にも当てはまりませんでした。適切な インテント を指定して、例文として追加してトレーニングを繰り返していきます。

これらの インテントエンティティ の詳しくについては、自然言語処理で調べてみて下さい。

ダイアログフローの定義

ダイアログフロー で、ボットとユーザーのやりとりの振舞いを定義します。

OBotML 言語で定義していきます。(YAML の独自実装)

metadata:
  platformVersion: 1.0
main: true
name: LunchBot
context:
  variables: {}
states:
  intent:
    component: "System.Intent"
    properties:
      variable: "iResult"
      confidenceThreshold: 0.4
    transitions:
      actions:
        TodaysLunch: "recommendLunch"
        Hello: "hello"
        unresolvedIntent: "unresolved"
  recommendLunch:
    component: "System.Output"
    properties:
      text: "カレーがいいよ"
    transitions:
      return: "recommendLunch"
  hello:
    component: "System.Output"
    properties:
      text: "こんにちは!"
    transitions:
      return: "hello"
  unresolved:
    component: "System.Output"
    properties:
      text: "すみません。わかりません。"
    transitions:
      return: "unresolved"

中程の intent でユーザーの発言によってフローを制御しています。

  • お昼ご飯に関するインテント (TodaysLunch)
    • -> recommendLunch
  • あいさつに関するインテント (Hello)
    • -> hello
  • 推定できなかったもの
    • -> unresolved

f:id:dhigashi:20181218145651p:plain

大丈夫そうです。

ジャンルによってお薦めを変えられたら良さそうなので、選択肢で選択させる事にします。

...
context:
  variables:
    kind: string
states:
  intent:
    component: "System.Intent"
    properties:
      variable: "iResult"
      confidenceThreshold: 0.4
    transitions:
      actions:
        TodaysLunch: "askKind"
        Hello: "hello"
        unresolvedIntent: "unresolved"
  askKind:
    component: "System.List"
    properties:
      prompt: "ジャンルは?"
      options:
        - value: "japanese"
          label: "和食"
          keyword: "1"
        - value: "western"
          label: "洋食"
          keyword: "2"
        - value: "chinese"
          label: "中華"
          keyword: "3"
      variable: "kind"
...

f:id:dhigashi:20181218150902p:plain

カレーは中華?

まだこのボットはカレーしかお薦めしてくれないので、お薦めのお店を出してくれる カスタム・コンポーネント を作成し組み込みたいと思います。

REST API サービスの作成

カスタム・コンポーネント の前に、ジャンルを問い合わせるとお薦めのお店を返してくれる API を提供するサービスを作成します。

今回は同じく Mobile Cloud から作成できる、モバイル・バックエンドAPI を用いてサービスを作成します。

新規で モバイル・バックエンド を作成します。

f:id:dhigashi:20181218154409p:plain

紐付ける API がないので、ここから新規で API を作成します。この時、RAML による API 定義を指定する必要があります。

f:id:dhigashi:20181218154539p:plain

f:id:dhigashi:20181218154832p:plain

今回使用した RAML や API の実装は以下にあります。

github.com

API が作成できたら、今回は検証だけなので セキュリティ からログインの要求を無効にし、実装 から API 実装をアーカイブしたものをアップロードし公開します。

f:id:dhigashi:20181218155838p:plain

f:id:dhigashi:20181218154914p:plain

API の設定の後、モバイル・バックエンド も公開します。

f:id:dhigashi:20181218161115p:plain

この後、ボット側で利用するので以下の値を取得しておいて下さい。

  • 設定 - モバイル・バックエンドID
  • 設定 - 匿名キー
  • API - GET Metadata の URL

f:id:dhigashi:20181218161530p:plain

f:id:dhigashi:20181218161534p:plain

カスタム・コンポーネントの作成

モバイル・バックエンド から ボットの編集画面に戻り、Components から、先程取得した値を指定しService を作成します。

f:id:dhigashi:20181218162410p:plain

f:id:dhigashi:20181218162406p:plain

作成したサービスに Recommend というコンポーネントができました。

f:id:dhigashi:20181218162700p:plain

カレーだけをお薦めしていた recommendLunch のコンポーネントを Recommend に置き換えます。

  recommendLunch:
    component: "Recommend"
    properties:
      kind: "${kind.value}"
    transitions:
      return: "recommendLunch"

問い合わせをしてみると、ジャンルによってお店を選んでくれるようになりました。

f:id:dhigashi:20181218163042p:plain

まとめ

ランチのお店選びを助けてくれるチャットボットを簡単に作ってみました。
今回、お薦めしてくれるお店は入居しているビルの飲食店をジャンルで絞り込みランダムで選んでいるだけですが、カスタム・コンポーネント で利用している API サービスが、食べログなどの外部サービスに接続して検索したり、予約したりできたら楽しそうですね。

参考文献