Dialogflowで社員呼び出しアシスタントを作ってみた #dialogflow

SENSY Advent Calendar 2017 １日目は今年９月に入社した私、@flatfisher が担当します。これから趣味で触っているDialogflowについて紹介したいと思います。ちなみに、普段はチャットボット開発をしていますが、Dialogflowは使用していません。

## 社員呼び出しアシスタント
Google homeで社員呼び出しアシスタントを作ってみました。用事のある社員の名前を言うとSlackにメンション付きで通知します。

## 会話フロー
- お客さん「OK Google, Sensyにつないで」
- アシスタント「分かりました、どなたに用事がありますか？」
- お客さん「flatfisherさんに用事があります」
- アシスタント「かしこまりました、flatfisherさんですね。少々お待ち下さい」
この後、Slackに通知が飛びます。通知内容（@flatfisher お客さんが来ています）

<img width="400" alt="Screen Shot 0029-11-29 at 22.34.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/e2de916b-3f50-0b0a-6eb5-d512e93ad06b.png">

Slack に通知
<img width="400" alt="Screen Shot 0029-11-29 at 22.20.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/59a71bc9-2e15-2615-3319-337c32ce2094.png">

## Slack APIの準備
- [こちら](https://api.slack.com/apps)から新しいアプリの作成
- 作成が終わったらIncoming Webhooksをクリック
    - Activate Incoming WebhooksをONにする
   
作成に成功するとサンプルソースが表示されます。ちゃんとSlackに通知されるかテストしてみましょう。

```
$ curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' https://hooks.slack.com/services/
```

- メンションを作成するために、[こちら](https://api.slack.com/methods/users.list/test)からユーザーの id を取得する
- 取得したいSlack名を選択する
- Test Methodをクリック
- botを含めユーザー一覧が表示される
- idを控えておく
    - "id": "U5JD537S9"みたいなやつ

メンション付きメッセージを送ってみる。こんな感じ（<@U5JD537S9> ）に <@id> の形式にするとメンションを付けて通知を出すことが出来ます。

```
$ curl -X POST -H 'Content-type: application/json' --data '{"text":"<@U5JD537S9> Hello, World!"}' https://hooks.slack.com/services/
```

## Dialogflow
Dialogflowでbotを作成します。Dialogflowが初めての方は[こちらの記事](https://qiita.com/flatfisher/items/76bc86b65e5f2150a1a0)を参考にしてください。

### Agentを作成
今回のプロジェクトを作成します。

### Entityを作成
- reference valueを、先ほど取得したslackのuser idにするとメンションが作りやすいです
- シノニムの中に "代表" や "CEO" などのポジションを入れてもいいかも

<img width="400" alt="Screen Shot 0029-11-27 at 20.56.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/166200b5-1423-0b73-1375-619731409cba.png">


- Default Welcome Intentの作成
 - アシスタントを立ち上げた時の挨拶文を入れる

<img width="400" alt="Screen Shot 0029-11-27 at 21.05.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/18397b12-3297-513d-ef1f-3f82f5a62bfc.png">'

- 社員呼び出し用のIntentを作成
    - Name: Call
    - User Says:「フィッシュを呼んで」
    - Action: call
    - Memberには必ずREQUIREDを付ける

<img width="400" alt="Screen Shot 0029-11-27 at 21.10.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/099210dd-a025-4b3e-4225-e0c9cc9c69ef.png">

### バックエンドの準備
Intentsが呼ばれたらSlackに通知を出したいのでバックエンドを用意します。バックエンドはCloud functionsを使用します。[こちらのリポジトリ](https://github.com/actions-on-google/dialogflow-webhook-template-nodejs)を使うと便利です。

- index.js の準備

call intentのイベントを受け取ったら、entityに設定したslack idを取得し、Slackにメンション付きでメッセージを送ります。

```
'use strict';

process.env.DEBUG = 'actions-on-google:*';
const { DialogflowApp } = require('actions-on-google');
const functions = require('firebase-functions');
const slackRequest = require('request');

exports.officeNotify = functions.https.onRequest((request, response) => {
  const app = new DialogflowApp({ request, response });

  function callMember(app) {
    var name = request.body.result.parameters.Member;
    var msg = '<@'+ name + '> ' + 'お客さんが来ています' 
    var options = {
      url: 'https://hooks.slack.com/services/',
      headers: {
        'Content-Type': 'application/json'
      },
      json: {
        'text': msg
      }
    };
    slackRequest.post(options, function (error, response, body) { });
    app.tell('かしこまりました、少々お待ち下さい');
  }

  const actionMap = new Map();
  actionMap.set('call', callMember);

  app.handleRequest(actionMap);
});

```

- Cloud functionsのプロジェクトを配置するGCSのバケットを用意

```
$ gsutil mb -p [PROJECT_ID] gs://[BUCKET_NAME]
```

- デプロイ

```
$ gcloud beta functions deploy officeNotify --stage-bucket [BUCKET_NAME] --trigger-http
```

デプロイが完了するとhttpsTrigger:のURLが取得できるので、そのURLをメモしておきます。

```
httpsTrigger:
  url: https://us-central1-... ←このURLをコピー
```



### Fulfillmentの作成
- WebhookをONにする
    - URLには先ほど取得したURLをいれます
- 入力が完了したらSAVEを押します

<img width="400" alt="Screen Shot 0029-11-28 at 21.16.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/7c3a6f03-24e4-05cd-6bf5-6370f1b9077f.png">

- Call IntentsのFulfillmentにチェックを入れる
    - Callが呼ばれると先ほどのバックエンドにHTTPリクエストを投げてくれます

<img width="400" alt="Screen Shot 0029-11-28 at 21.19.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/5899ec55-949c-756d-7439-a32a404dcaf5.png">

### Integrations
Google Assistantを選択肢シュミレーターを起動します

<img width="400" alt="Screen Shot 0029-11-29 at 22.15.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/3e8d9c54-bc0a-44eb-4394-8bca2ee23143.png">

あとはシュミレータに話かけるだけ
<img width="400" alt="Screen Shot 0029-11-29 at 22.19.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/726732e6-ff74-17d1-84b2-1771ab15b42d.png">

成功するとSlackに通知がいきます

<img width="793" alt="Screen Shot 0029-11-29 at 22.20.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/abb519e7-693a-1f0c-9302-17894a0fcc5c.png">

### Google homeで試す
同一のGoogleアカウントであればGoogle homeでも試せます

<img width="271" alt="Screen Shot 0029-11-29 at 22.36.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/a7e564b1-7415-52e8-0c03-8b2a665d7b1c.png">


## まとめ
- Dialogflowはさくっとアシスタントが作れて便利
- Slackを使っている方はぜひSlack APIを触って欲しい。通知出すだけでも面白い
- オフィスの玄関に置いておけば、来客の方に先進的な印象を与えることができるかも
- 「OK、Google」言うの恥ずかしい
- 小さいオフィスなら**ピンポン押した方が早い**

## バトン
明日は @tsukukobaan によるAIxBlockchain関連のお話です。私も仮想通貨の取引をしているので楽しみです:grin: