Facebook bot に wit.ai のボットエンジンを連携させてみる


[API Gateway + Lambda で Facebook bot を作ってみる](http://qiita.com/u-minor/items/685e2cc2554155bf79e7) で作成した bot に、先日 F8 で発表された [wit.ai](https://wit.ai/) の [bot engine](https://wit.ai/blog/2016/04/12/bot-engine) を連携させてそれっぽい感じにしてみました。

API Gateway + Lambda で作成していてステートレスなので、会話のコンテキストを保持するために SimpleDB を用いています。
環境に応じて、ElastiCache や RDS、DynamoDB 等に置き換えることも可能です。

## wit.ai で会話のストーリーを作る

wit.ai に sign up し、新規に app を作成します。

[QuickStart](https://wit.ai/docs/quickstart) にあるように、指定した地域の天気を返す会話を作成していきます。

![Wit_Console.png](https://qiita-image-store.s3.amazonaws.com/0/15611/431eecff-d5b6-c5b4-4cdc-577e382d92da.png "Wit_Console.png")

- User says に「What's the weather?」を入力。
- Bot says に「Where exactly?」を入力。
- User says に「in Tokyo」を入力、「Tokyo」を文字選択して wit/location を選択。
- Bot の merge 部分の Produces context に location を追加。
- Bot executes で fetch-weather を追加。
- fetch-weather の Produces context に location と forecast を追加。
- Bot says に「I see, {location} is {forecast} today!」を入力。

今回は QuickStart に倣って wit/location を選んでいますが、以下のように会話のコンテキストとして判別可能な様々なエンティティが存在しますので、状況に応じていろいろカスタマイズしてみてください。

![Wit_Console.png](https://qiita-image-store.s3.amazonaws.com/0/15611/75f02949-dc85-cb20-7f9a-d8ef0c3f7afa.png "Wit_Console.png")

## wit.ai の API アクセストークンを取得する

右上の Settings をクリックすると、API 利用するためのアクセストークンが取得できます。
今回はクライアント利用ですので、クライアント用のトークンをメモしておきます。

![Wit_Console.png](https://qiita-image-store.s3.amazonaws.com/0/15611/7155b5b0-79f6-bb7f-8717-23e65489a196.png "Wit_Console.png")

## Amazon SimpleDB を作成する

wit.ai の会話のコンテキストを保持するために、SimpleDB でドメインを作成します。

```
aws sdb create-domain --domain-name facebook-testbot
```


## Lambda の IAM Role にポリシーを追加する

Lambda が利用する IAM Role が SimpleDB にアクセスできるように、インラインポリシーを追加します。
以下の様な InlinePolicy.json を作成し、

```InlinePolicy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sdb:*",
      "Resource": "arn:aws:sdb:*"
    }
  ]
}
```

既存の IAM Role に付与します。

```
aws iam put-role-policy \
  --role-name lambda-facebook-testbot \
  --policy-name AsscessSimpleDB \
  --policy-document file://InlinePolicy.json
```

## Facebook bot を wit.ai に対応させる

[前回](http://qiita.com/u-minor/items/685e2cc2554155bf79e7) の延長になります。

```
git clone -b v0.2.0 git@github.com:u-minor/facebook-testbot.git
```

### 設定ファイルの修正

config/development.yml の `wit.token` に先ほどメモした wit.ai のアクセストークンを設定します。

![development_yml_—__Users_minoru_workspace_facebook-testbot.png](https://qiita-image-store.s3.amazonaws.com/0/15611/189453c4-0ed8-1fa6-0fea-4897ba930a7e.png "development_yml_—__Users_minoru_workspace_facebook-testbot.png")

### npm パッケージのインストール

依存パッケージとして新たに [node-wit](https://github.com/wit-ai/node-wit) が追加されていますので、`npm install` します。

### Lambda function の更新

`gulp updateLambda --env=development` で Lambda function を更新します。

## 動作確認

Lambda の更新が完了したら、Messenger で「What's the weather?」と会話してみましょう。
うまく行けば、下の画像のように会話ができるはずです。

![_1__Facebook.png](https://qiita-image-store.s3.amazonaws.com/0/15611/1d1575aa-0f3c-b6ac-9489-6ef6ef2c2231.png "_1__Facebook.png")


## 総括

地域の天気を返す bot 風になっていますが、天気は固定で cloudy と応えるだけで、実際の天気を返す部分は割愛しています。
天気 API はいくつかありますので、適当に連携させてください。

wit.ai は Messenger API に結合されているのかな、と最初は思ったのですが、facebook for developers からは wit.ai へのリンクが張られているだけで、やや拍子抜けでした。疎結合という意味では綺麗ですね。
実装については、Lambda のようなステートレスな環境では会話のコンテキスト維持がやや面倒なだけで、基本はシンプルに連携できるようになっています。
ストーリーという形で会話のシーケンスを定義していき、必要なエンティティをコンテキストに追加していく、という発想は、なるほどな、と関心しました。

今回の wit/location のようなエンティティはある程度自動判別してくれるようになっているようで、ここに機械学習的な要素が含まれていると考えられます。
試しに「in Kyoto」のように未知のエリアを入れてもきちんと判断してくれますし、wit.ai の Inbox に未知のワードの予測結果が表示され、学習させることができるようになっているのが面白いです。

![Wit_Console.png](https://qiita-image-store.s3.amazonaws.com/0/15611/c158a036-bfcb-ddc1-b516-936fd2a19577.png "Wit_Console.png")

単語がスペースで区切られるような欧米圏の言語しかサポートされていないようですが、mecab のような分かち書きができれば日本語等への応用もできるのかもしれません。

完全な機械学習による自動会話とは趣旨が異なりますが、人がある程度会話のパターンを定義してあげることでライトに使えるというアプローチは非常に興味深い手法で、活用範囲を絞ればいろいろ便利な気がします。