Check! Bot Service と Cognitive Services を使って、チャットの発言のキーフレーズを知る

こんばんは、 @dz_ こと大平かづみです。

Prologue - はじめに
====

[Cogbot Advent Calendar 2016](http://qiita.com/advent-calendar/2016/cogbot "Microsoft Cognitive Services & Bot Framework Advent Calendar 2016 - Qiita") 25日目の記事です！トリです！ヽ(☆’v\`)★’v\`)ﾉ

[Microsoft Cognitive Services](https://www.microsoft.com/cognitive-services/en-us/ "Microsoft Cognitive Services") の新しい仲間 [Text Analytics API](https://www.microsoft.com/cognitive-services/en-us/text-analytics-api "Microsoft Cognitive Services - Text Analytics API") (Preview) は、キーとなる言葉や、感情を認識してくれる API です。

これを [Azure Bot Service](https://dev.botframework.com/ "Azure Bot Service - chatbot | Microsoft Azure") でチャットと連携して、発言のキーフレーズを探ってみようと思います。

Cognitive Services とは？
----

昨今では、膨大なデータの蓄積と解析リソースの調達が容易になったことにより、人間が得意とする認知行動を、コンピューターができるようになってきました。Cognitive Services は、視覚、音声、言語、知識、検索などの認知に特化した機能を、専門的な知識がなくても簡単に利用できるよう、 API や SDK として提供してくれるサービスです。

### Text Analytics  API とは？

Text Analytics API は、テキストから、感情、キーフレーズ、トピックや言語を検知してくれる機能を提供してくれます。現時点ではまだ Preview で、日本語で利用できるのはキーフレーズの検知、言語の検知です。

Bot Service とは？
----

チャットボットの仕組みを簡単に実装できる [Microsoft Bot Framework](https://dev.botframework.com/ "Microsoft Bot Framework") に特化した、FaaS (Function as a Service) です。[Azure Functions]() や [Azure Web Apps]() をベースとしたUI・機能ですが、チャットウィンドウや、チャンネル連携のタブがあるのでとても便利です。

準備
====

前提条件
----

- Microsoft アカウントを持っている
    - Cognitive Services のサブスクリプション登録のため
- Azure のアカウントを持っている
    - Azure Bot Service 利用のため


大まかな流れ
----
1. Cognitive Services で Text Analytics のサブスクリプションを登録する
2. Azure で Bot Service を新規作成する
    - Basic テンプレートを選択する
3. Bot Service の環境変数にサブスクリプションキーを設定する
4. Text Analytics API を用いてコーディング

参考資料
----

- [Quick start guide: Machine Learning Text Analytics APIs | Microsoft Docs](https://docs.microsoft.com/en-us/azure/cognitive-services/cognitive-services-text-analytics-quick-start "Quick start guide: Machine Learning Text Analytics APIs | Microsoft Docs")
- [Dialogs | Documentation | Bot Framework](https://docs.botframework.com/en-us/node/builder/chat/dialogs/#navtitle "Dialogs | Documentation | Bot Framework")

Bot Service と Text Analytics を使って発言のキーフレーズを知る
====

1. Cognitive Services で Text Analytics のサブスクリプションを登録する
----

※ 無料枠を利用する前提で進めます。

[Text Analytics API のページ](https://www.microsoft.com/cognitive-services/en-us/text-analytics-api) にアクセスし、「Get started for free」をクリックします。Text Analytics にチェックを付けます。
![20161225_cogbot-advcal_cognitive-services_003.png](https://qiita-image-store.s3.amazonaws.com/0/3812/76efce57-2211-69d6-f4a5-b007d6a9e315.png)

画面下部の利用規約を確認し、チェックを付け、「Subscribe」をクリックすることで、サブスクリプションの登録が完了します。表示されたサブスクリプションキーは、のちに使うのでコピーしておいてください。
![20161225_cogbot-advcal_cognitive-services_004.png](https://qiita-image-store.s3.amazonaws.com/0/3812/c9f9d148-b10c-3506-913e-ceb40d345d9f.png)

2. Azure で Bot Service を新規作成する
----

Azure Bot Service の作成手順については、こちらの 15 ～ 27ページをご参考ください。なお、利用するテンプレートは **Basic** を選択すると扱いやすいです。

<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/oohira-kadumi/8454/luis-and-azure-bot-service" title="LUIS and Azure Bot Service" target="_blank" style="font-family: 'Segoe UI'; font-size: 13px; text-decoration: none; margin-left:18px ">LUIS and Azure Bot Service</a><span style="font-family: 'Segoe UI'; font-size: 13px ">—</span><a href="https://docs.com/oohira-kadumi" target="_blank" style="font-family: 'Segoe UI'; font-size: 13px; text-decoration: none ">Oohira Kadumi</a></div><iframe src="https://docs.com/d/embed/D25192249-1451-4245-2020-001186387225%7eM1af8d7a5-b506-361b-290d-65d4bfcf2516" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="True"></iframe>

3. Bot Service の環境変数にサブスクリプションキーを設定する
---

Bot Service の準備ができたら、 Text Analytics のサブスクリプションキーを環境変数に登録しておきましょう。登録した環境変数は、Node.js であれば `process.env['<キー名>']` で取得できます。

今回は、 `TextAnalyticsSubscriptionKey` というキー名で登録しました。後述のサンプルでも、このキー名でサブスクリプションキーを取得しています。

![20161225_cogbot-advcal_azure-bot-service_004.png](https://qiita-image-store.s3.amazonaws.com/0/3812/92824d5b-f30b-4a2f-efa3-4e78b9ce9276.png)

4. Text Analytics API を用いてコーディング
----
### キーフレーズ検出の API について
コーディングの前に、 [Postman](https://www.getpostman.com/ "Postman | Supercharge your API workflow") などのAPIクライアントなどを利用して、API の使用感を確認しておくと作業を進めやすいです。

| エンドポイント |
|---------------|
| `https://westus.api.cognitive.microsoft.com` |

| リクエストヘッダ | 値 |
|----------------|-----|
| `Ocp-Apim-Subscription-Key` | Text Analytics のサブスクリプションキー（前手順でコピーしたもの） |
| `Content-Type` | `application/json` |
| `Accept` | `application/json` |

```json
{
    "documents": [
        {
            "language": "ja",
            "id": "1",
            "text": "First document"
        },
        ...
        {
            "language": "ja",
            "id": "100",
            "text": "Final document"
        }
    ]
}
```

レスポンスデータやその他詳細については、[こちら](https://docs.microsoft.com/en-us/azure/cognitive-services/cognitive-services-text-analytics-quick-start#task-2---detect-sentiment-key-phrases-and-languages) をご参考ください。

### 

### コーディング

それでは、 Bot Service の `index.js` に Text Analytics API を組み込んでみましょう！

以下は Node.js 版のサンプルコードです。（Node.js は独学なので、あくまで処理の参考としてご了承ください。 (´･ω･`;) ）

#### 概要説明

Bot Framework は、チャットからメッセージを受信すると、 `UniversalBot.dialog()` に登録されたコールバックを呼び出します。そのコールバック先で、 `session.message.text` に格納されたメッセージを、 Text Analytics API に渡してキーフレーズを検出、返信する処理を実装しました。

なお、 Text Analytics API は、一意のIDを付与することで、一度に複数個のテキストを処理にかけることができますので、それを見越した作りにしています。

#### サンプルコード
```js:index.js
"use strict";
var builder = require("botbuilder");
var botbuilder_azure = require("botbuilder-azure");

...<略>...

// --- ★★ ここから ★★ ---
// Load https module
const https = require('https');

/**
 * Text Analytics class
 */
function TextAnalytics() {};

TextAnalytics.prototype.getKeyPhrase = function(messages, callback) {
    // Create send data
    var data = this._createSendData(messages);

    // Request Text Analytics API
    this._requestKeyPhrase(data, callback);

}

TextAnalytics.prototype._createSendData = function(messages) {
    var documents = [];
    var index = 1;
    messages.forEach(function(doc) {
       documents.push({
           "language": "ja",
           "id": index++,
           "text": doc
       }); 
    });
    var data = {
        "documents": documents
    };
    return JSON.stringify(data);
}

TextAnalytics.prototype._requestKeyPhrase = function(data, callback) {
    var that = this;
    // Create options
    var options = {
        hostname: 'westus.api.cognitive.microsoft.com',
        path: '/text/analytics/v2.0/keyPhrases',
        port: 443,
        method: 'POST',
        headers: {
            'Ocp-Apim-Subscription-Key': process.env['TextAnalyticsSubscriptionKey'],
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }
    }

    // Request Text Analytics API
    var req = https.request(options, function(res) {
        res.setEncoding('utf8');
        res.on('data', function(chunk) {
            var responses = that._adjustResponse(JSON.parse(chunk));
            callback(responses);
        });
        res.on('end', function() {
            console.log('No more data in response.');
        });
    });
    req.on('error', function(e) {
        console.log('problem with request: ' + ${e.message});
    });
    req.write(data);
    req.end();
}

TextAnalytics.prototype._adjustResponse = function(response) {
    // Adjust the response
    var res = [];
    response.documents.forEach(function(document) {
        res.push(document.keyPhrases);
    });

    return res;
}
var textAnalytics = new TextAnalytics();
// --- ★★ ここまで追加 ★★ ---

var bot = new builder.UniversalBot(connector);

bot.dialog('/', function (session) {
    // --- ★★ ここから ★★ ---
    // session.send('You said ' + session.message.text);

    // Analytics the message to detected key phrase
    textAnalytics.getKeyPhrase(
        [session.message.text],
        function(keyPhrases) {
           // Return detected key phrase
            session.send('Key phrase: ' + keyPhrases[0]);
        });
    // --- ★★ ここまで変更 ★★ ---

});

...<略>...

```

ここまで反映できたら、右のチャットウィンドウを使って動作確認をしてみましょう！ `Oops. ...` と返信されたり、 Log でエラーの発生がみられたときは、適宜ご調整ください。


できたかなー？ (〃ゝω’)b

そして、Bot Service のチャットウィンドウでしっかり動けば、あとはどのチャットに連携しても動きます！

![20161225_cogbot-advcal_azure-bot-service_007.png](https://qiita-image-store.s3.amazonaws.com/0/3812/69244c49-f323-06d1-0984-bc1ef32c5348.png)

なお、今回は、 Slack 連携を検証していたのですが、Slack 側の UI が変わっていて説明が長くなるので、別途記事にまとめる予定です。


Epilogue - おわりに
====
こんなにあっさり実装できるので、さらに見せ方を工夫すると、ライフログ、作業ログに活かせるかもと思ってます。楽しくなってきましたー！(*ﾉωﾉ)