Node.js初心者がNode.js + Watson Conversation でチャットボットを実装してみた

# 始めに
既出の記事が多くある感じもありますが、ローカル環境でも動かせるチャットボットを気楽に作ってみました。この記事ではNode.js + Socket.ioを使ったチャットツールにAPIを組み込んでチャット機能を作る方法について記述しています。
※Watson Conversationの開発方法については[こちら](https://www.ibm.com/watson/jp-ja/developercloud/conversation.html)を参照して下さい。
(本当はNode-REDで組んでみたかったのですが、サンプルすら上手く動かせずに断念…こうなったら、一から組もうかなと思ったのが正直なところです。)
# 構成について
今回は下記の構成で作っています。下記は全てインストール済みという前提で進めていきます。
・ npm
・ Node.js
・ Express
・ ejs

# プロジェクトの作成
まず、`express exp01 -e ejs`でプロジェクトを作成します。
次にプロジェクトディレクトリに移動して、`npm install`で必要なモジュールをプロジェクトに追加します。
これだけで下記の構成の基本的なプログラムが作成できました。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/908942de-7eb0-b805-5eb9-f778631e5cb5.png)

早速、`node bin/www`を実行してみましょう。
ポートなどを変更していなければ、[http://localhost:3000](http://localhost:3000)でアクセス出来ちゃいます。
こんな画面が出来たらひとまず、準備作業は完了です。とっても簡単ですね。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/ffa4d707-6c48-ea5b-209c-8ae34a1ad67e.png)

# 必要なモジュールのインストール
次に、`Socket.io`と`watson-developer-cloud`を追加します。`package.json`の`dependencies`に下記の2行を追加しましょう。

```
"socket.io": "2.0.3",
"watson-developer-cloud": "2.39.2"
```
もう一度、`npm install`を実行します。
これで必要なモジュールが全て揃いました。

# API呼び出し処理の組み込み
次に、`bin/www`を編集していきます。

```
/**
 * Create HTTP server.
 */
var server = http.createServer(app);
```
の**後ろ**に下記のソースコードを追加します。
ConversationのAPIの使い方は、[ここ](https://console.bluemix.net/docs/services/conversation/develop-app.html#building-a-client-application)を参考にしました。
また、[Socket.IOのチュートリアル](https://socket.io/get-started/chat/)も元にしています。

```
var io = require('socket.io').listen(server);
io.on('connection', function(socket){
    var ConversationV1 = require('watson-developer-cloud/conversation/v1');

    // Set up Conversation service.
    var conversation = new ConversationV1({
      url: 'https://gateway.watsonplatform.net/conversation/api',
      username: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', // ユーザー名を置き換えてください。
      password: 'xxxxxxxxxxxx', // パスワードを置き換えてください。
      path: { workspace_id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' }, // ワークスペースIDを置き換えてください。
      version_date: 'YYYY-MM-DD'//何でもいいのかも？
    });
    var res = [];
    // このページにアクセスしたときに、空のメッセージをConversationに投げる
    conversation.message({}, processResponse);
    // Conversationのレスポンスを取得する
    function processResponse(err, response) {
        if (err) {
          console.error(err); // something went wrong
          return;
        }
        // intentがマッチしたらコンソールに出力する
        if (response.intents.length > 0) {
            console.log('chat message', 'Detected intent: #' + response.intents[0].intent);
        } 
       // 何らかの返答があれば、それをbotからの返答として全て返す(ループはjump to の時に必要)
        for (var i = 0, len = response.output.text.length; i < len; i++) {
            if(response.output.text[i] !== ''){ 
                io.to(socket.id).emit('bot message', response.output.text[i]);                
            }
        }
        res[socket.id] = response;
    }
    //新しいメッセージを受信したときの動作
    socket.on('chat message', function(msg){
        //受信したメッセージをそのまま、チャット画面に表示
        io.to(socket.id).emit('chat message',msg);
        // 受信したメッセージをAPIに投げる
        conversation.message({
          input: { text: msg },
          context : res[socket.id].context
        }, processResponse);
    });
});
```
ちなみに、ユーザー名とパスワードはダッシュボードのサービス資格情報、ワークスペースIDはConversationのダッシュボードから、自分が作ったアプリの右上にある…をクリック→view detailsから参照可能です。

最後に、`/views/index.ejs`と`/stylesheets/style.css`をそれぞれ書き換えます。
index.ejs

```html
<!doctype html>
<html>
  <head>
    <title>チャットボットテスト</title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
      <div class="chat-box">
        <ul id="messages"></ul>
        <form action="">
          <input id="m" autocomplete="off" /><button>Send</button>
        </form>          
      </div>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
    <script>
        $(function () {
          var socket = io();
          $('form').submit(function(){
            socket.emit('chat message', $('#m').val());
            $('#m').val('');
            return false;
          });
          socket.on('chat message', function(msg){
            $('#messages').append($('<li>').text(msg).addClass('chat-hukidashi someone').wrap('<div />'));
          });
          socket.on('bot message', function(msg){
            $('#messages').append($('<li>').text('ＱＡ botくん：'+msg).addClass('chat-hukidashi').wrap('<div />'));
          });          
        });
    </script>
  </body>
</html>
```
style.css

```css
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin:auto 0; padding: 0; }
#messages li { padding: 5px 10px; display: block }
/* チャットレイアウト */
.chat-box {
    width: 80%;
    height: auto;
    overflow: hidden; /*floatの解除*/
    margin-bottom: 20px;
}
.chat-face {
    float: left;
    margin-right: -120px;
}
.chat-face img{
    border-radius: 30px;
    border: 1px solid #ccc;
    box-shadow: 0 0 4px #ddd;
}
.chat-area {
    width: 100%;
    float: right;
}
.chat-hukidashi {
    display: inline-block; /*コメントの文字数に合わせて可変*/
    padding: 15px 20px;
    margin-left: 120px;
    margin-top: 8px;
    margin-right: 20px;
    border-radius: 10px;
    position: relative; 
    background-color: #D9F0FF; 
}

.chat-hukidashi:after {
    content: "";
    position: absolute;
    top: 50%; left: -10px;
    margin-top: -10px;
    display: block;
    width: 0px;
    height: 0px;
    border-right: 10px solid #D9F0FF;
    border-top: 10px solid transparent;
    border-bottom: 10px solid transparent;}
.someone {
    background-color: #BCF5A9;
}
.someone:after {
    left: auto;
    right: -8px;
    border-right: none;
    border-left: 10px solid #BCF5A9;
    border-top: 10px solid transparent;
    border-bottom: 10px solid transparent;
}
```
これで、改めて`node bin/www`を実行してみましょう。
[http://localhost:3000](http://localhost:3000)にアクセスすると、こんな感じでConversationと会話が出来るようになると思います。
![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/72895423-1c37-db86-f888-8936e2c3bd75.png)

こんな簡単な手順で、チャットボットっぽいものが出来ました。APIの利用のしやすさがbluemixのいいところなんでしょうね。
弄りがいがあってとっても面白いです。皆さんも、ぜひ、トライしてみてくださいね。