enebularとSUNABAを使ってローコードでチャットボット開発する

この記事は「[enebular Advent Calendar 2020](https://qiita.com/advent-calendar/2020/enebular)」の7日目です。

また、2020/11/4に行われた「[ゆるふわマシンラーニング vol.5](https://enebular.connpass.com/event/188257/)」にてLTさせていただいた内容を再記事化したものです。
[Speakerdeck](https://speakerdeck.com/kawazu/enebulartosunabawoshi-tuterokododetiyatutobotutokai-fa-suru "Speakerdeck")の方に当時のスライドを載せていますので、合わせて確認いただきながら読んでもらえればなと思います。

## SUNABAとは
Docomoが提供しているチャットボット開発のためのプラットフォームです。

- 対話シナリオをGUIで構築できる
- ユーザーとの会話内容(ステータス)を保持できる
- xAIMLという形式で作成した会話シナリオをエクスポート・インポートできる
- 作成したシナリオをAPI化できる

などの特徴がありまして、楽に会話シナリオ構築ができ、そのまま公開できてしまうのがメリットとしてあります。

会話シナリオはこのような画面で編集することができます。

![スクリーンショット 2020-11-02 14.24.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/28a4c814-6b8b-f652-3b87-476dae0b14f9.png)

また、このようにGUIで作成した会話シナリオを、コード形式でエクスポート・インポートする機能があります。「xAIML」という形式が使われており、これは「[AIML](https://ja.wikipedia.org/wiki/Artificial_Intelligence_Markup_Language)」というXMLベースの言語をDocomo側が独自に改良したものだそうです。

![スクリーンショット 2020-11-30 17.48.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/ea571526-eeab-53e4-dfde-32cee7e62b21.png)

↑雰囲気としてはこんな感じのものになります。

また、作成したシナリオをAPIとして公開できるため、このAPIと通信することでLINE上で会話できるチャットボットを開発することができそうです。
ただ、その場合はSUNABAのAPIと、LINE Messaging APIを呼び出して制御するための中継地点としてバックエンドの機能が必要になり、サーバの構築とAPIプログラムのスクラッチ開発が必要になります。
この中継地点を、今回は「[enebular](https://www.enebular.com/ja/ "enebular")」を用いることでコードをほとんど書くことなく、サーバも立てることなく、チャットボットを開発してみたいと思います。

![スクリーンショット 2020-11-30 18.08.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/44dcb3f6-dde5-8fce-bde0-1f047cd70bd8.png)

## enebularについてのキャッチアップ(おすすめ)
いきなりenebularを使おうといっても、どういった仕様のものでどのように使うべきなのか、初めて触る際にはわからないことが多くなります。**わからないときはとりあえず真似っこをしてみるのが一番理解が早い**かなと思うのですが、がおまるさんという方がハンズオンされていた「[Teachable MachineとenebularとLINE Botで機械学習を体験しよう！](https://atlabo-handson-08.netlify.app)」という資料がめちゃくちゃわかりやすく、とっても入門することができました。まだenebularを触ったことがない方は、こちらを最初から最後までなぞっていくことで、enebularの理解が深まっていくと思います。
(大変ありがとうございました！！！)

このハンズオンでは、enebularを使ってLINEのチャットボットを作っていますが、処理の途中でTeachable Machineとの連携をしています。僕が今回やりたいSUNABAとの連携は、このTeachable Machineとの連携をSUNABAに置き換えることで実現できそうなので、その方向性で実装していきたいと思います。

![スクリーンショット 2020-11-30 18.22.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/ff8f33d6-94ad-bcc6-483e-e005e200faaf.png)

※ちなみにがおまるさんは、今回のenebular Advent Calendar 2020 1日目で[湯婆婆の話](https://qiita.com/h-takauma/items/7a4aabe8af04ecc2c5e8)を投稿されているので、是非ご覧ください。

## LINE Developer Consoleでのセットアップ
LINEでのチャットボット開発を行うためには、LINE Developer Consoleでのプロバイダー作成、チャネル作成を経て、エンドポイント登録やアクセストークン情報などなどを控えておく必要があるのですが、そのあたりの手順は今回は割愛させていただきます。上述のハンズオン資料にそのあたりも大変わかりやすく記載されているため、是非そちらをご覧ください！！
(大変ありがとうございました！！！)

## SUNABAのセットアップ
ここからはSUNABAのセットアップ手順を、画面のキャプチャを交えて解説します。
解説といっても、基本的には「新規登録」 -> 「ボット(会話シナリオ)作成」 -> 「ボット公開&エンドポイント情報取得」の流れです。

### 新規登録
Googleログインですぐできます。ログイン後、固有のIDとなるテナント名を登録します。

![スクリーンショット 2020-11-30 18.31.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/f03e2bfd-af58-aa25-ec32-14392e8e8610.png)

![スクリーンショット 2020-11-30 18.28.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/e1b78028-2f38-e9db-97c4-1409fc920645.png)

### ボット(会話シナリオ)作成
ボット一覧画面から「ボットの追加」を押し、新しく会話シナリオを作成します。このとき、「既存のボットを複製する」という項目を選ぶことができます。SUNABAにはデフォルトでいくつかの会話シナリオパターンがセットされているのですが、自分が作成したい会話シナリオがデフォルトのものに近しい場合、デフォルトのものから複製&編集することで、SUNABAに慣れながらかつ短時間で会話シナリオの作成ができるでしょう。

![スクリーンショット 2020-11-30 18.28.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/6f04a6dd-cc30-4a04-fc0e-eb834eb5c35f.png)

![スクリーンショット 2020-11-30 18.28.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/a1a25d8b-2273-2731-0d45-e3a664989dab.png)

ボットの追加ができたら、「GUIで編集する」というボタンを押下することで、シナリオ編集画面にいくことができ、そこでシナリオの編集が行えます。

![スクリーンショット 2020-11-30 18.29.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/c8dbbaa3-525a-ef33-7902-a4dfc9ef4647.png)

![スクリーンショット 2020-11-30 18.29.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/460eccf2-0d2f-bc20-2cdd-cedf4ebc26ad.png)

### ボット公開&エンドポイント情報取得
ボットの一覧から緑色の「デプロイ」ボタンを押下することで、作成した会話シナリオのボットを公開することができます。
またその状態で、作成したチャットボットと会話が行えるシミュレーターが用意されており、サイドメニューの「APIコンソール」という所から遷移できます。

![スクリーンショット 2020-11-30 18.29.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/0c2e22d4-7159-b159-2f6f-8abb5d7bc940.png)

![スクリーンショット 2020-11-30 18.29.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/71e0a25c-3ef9-1dba-7d62-cbf4ba5123c3.png)

テキストウィンドウに文字を打ち込むことで会話することができるので、自分が組んだ通りに会話が行えるかどうかのテストができます。
また、右側にはその際にやり取りされるHTTPリクエストの内容が表示されます。ここに表示される情報が、enebular側への設定には必要となるため、控えておきましょう。

![スクリーンショット 2020-11-30 18.30.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/a367c7e6-0d9e-a683-fbe7-7139732b6c5a.png)

![スクリーンショット 2020-11-30 18.30.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/21252d86-0437-b109-984b-7b977b9e39a7.png)

念のため、curlなどで叩けるかどうかをこのタイミングでテストしてもいいかもしれません。

## enebularのセットアップ
大まかに下記の順番でセットアップしていきます。

1. LINEのMessaging APIノードを追加する
2. LINEからのWebhook設定
3. LINEへのリクエストパラメータ解析&SUNABAへのリクエストボディ作成
4. SUNABAへのリクエスト処理の作成
5. SUNABAからのレスポンスを解析&LINEリプライの内容を作成
6. LINEへのリプライ処理を作成

### 1. LINEのMessaging APIノードを追加する
enebularのノード編集画面では、左側に様々なノードが用意されており、それをドラッグ&ドロップすることで行いたい処理を構成できます。ただ、デフォルトではLINE Messaging APIと通信してくれるノードはないため、こちらを「右上のハンバーガーメニュー」 -> 「パレットの管理」 -> 「ノードの追加」より、`node-red-contrib-line-messaging-api`を検索して追加します。

![スクリーンショット 2020-11-30 18.56.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/4346c25c-d64b-7b8a-0941-38dbe2803737.png)


### 2. LINEからのWebhook設定
「http in」という名前のノードを使用することで、LINE Developer Consoleに設定するためのエンドポイントを作成します。
ここでは「/sunababot」と記載し、右上の「i」マークにカーソルを合わせることでエンドポイント用のドメインが取得できるため、「https://ドメイン/sunababot」という形でLINE Developer Consoleに設定しましょう。
※このドメインは、enebularノード編集画面を立ち上げるたびに変更されるため注意！(enebularの仕様です。)

![スクリーンショット 2020-11-30 18.56.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/5bbb75e9-c283-0a21-60bf-d934c7b85c4b.png)

### 3. LINEへのリクエストパラメータ解析&SUNABAへのリクエストボディ作成
LINE上で何かメッセージを送信したら、2番で作成したエンドポイントにリクエストデータがくるわけですが、そのデータを解析し、SUNABA APIに送るためのリクエストデータを作成してあげる必要があります。「function」という名前のノードを使用することで、この辺りの処理を少しだけコードを書くことで実装します。

![スクリーンショット 2020-11-30 18.56.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/0332318a-79a8-7724-aad4-e0ff1d270c79.png)

```function-node-1.js
// LINE APPからエンドポイントへのリクエストパラメータから、使用する要素を抽出
const messageID = msg.payload.events[0].message.id;
const replyToken = msg.payload.events[0].replyToken;
const messageText = msg.payload.events[0].message.text;

msg.messageID = messageID;
msg.replyToken = replyToken;

// SUNABAにPOSTするリクエストボディを作成
msg.payload = {
  "appId": "your-app-id",
  "botId": "your-bot-id",
  "voiceText": `${messageText}`, // LINEに入力したメッセージをそのままSUNABAのVoiceTextに渡す
  "initTalkingFlag": false,
  "initTopicId": "enebular-20count", // シナリオを作成した際に作ったID名
  "language": "ja-JP"
}

return msg;
```

### 4. SUNABAへのリクエスト処理の作成
「http request」という名前のノードを使用することで、SUNABA APIへのリクエストを行います。
実際に送られるリクエストボディデータは、「3. LINEへのリクエストパラメータ解析&SUNABAへのリクエストボディ作成」にて記述した通りのJSONデータが送られます。

![スクリーンショット 2020-11-30 18.56.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/95ce2c93-e718-20c3-2fec-967fb284f4bd.png)

### 5. SUNABAからのレスポンスを解析&LINEリプライの内容を作成
SUNABAから返却された返答文をLINEにリプライするために、「3. LINEへのリクエストパラメータ解析&SUNABAへのリクエストボディ作成」でやったようなデータの中継処理を書いていく必要があります。ここでも「function」ノードを使用することで、SUNABAからのレスポンス値解析とLINE Messaging APIへのリクエストを作成してあげます。

![スクリーンショット 2020-11-30 18.57.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/1e882ce5-0a0b-46ca-a8b4-2d16f3ae2ef0.png)

```function-node-2.js
// SUNABAのレスポンスから返答文を抽出
const replyMessage = msg.payload.systemText.expression;
msg.payload = {};

// LINEリプライのためのレスポンスを整形
msg.payload.events = [
    {
        "type": "message",
        "replyToken": msg.replyToken,
        "message": {
            "type": "text",
            "text": `${replyMessage}`
        }
    }
];
return msg;
```

### 6. LINEへのリプライ処理を作成
追加したLINE Messaging APIノードの中から「ReplyMessage」ノードを選択し、LINEへのリプライ処理を作成します。
ここにはLINE Developer Consoleに記載されている、アクセストークンとシークレットトークンを記載します。

![スクリーンショット 2020-11-30 18.57.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/8312f5e8-1ff8-58fe-acc5-3658d7646f06.png)

以上のノードを、下記のような形につなげられれば、チャットボットの完成です！

![スクリーンショット 2020-11-30 19.43.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/8f4952e2-3292-6f82-a912-e06b3508ad9d.png)

### チャットボットを動かしてみる
今回は、「20カウントゲーム」という会話シナリオを作ってみました。ユーザー側とボット側がそれぞれ1〜３の数字を交互に言い合い、20を言ってしまった方が負け、というものです。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/6e4ee3f3-7718-a1c2-9c58-4356406a5396.gif)

このような形で動作させることができました！

SUNABAでは、このシナリオですと合計点管理のために点数を保持しておくことや、点数状態と提示した点数による勝敗確定条件などの、シナリオに関わるバックエンド処理を担うことができます。DBやSession用のストレージみたいなのを用意する必要がないので、この辺りもSUNABAの強みですね。

## まとめ
SUNABAのGUIでの会話シナリオ編集機能を使うことで、ある程度複雑な会話でも作成することができそうです。プログラムで作ろうとするとif文地獄になるようなところを、こう言ったサービスに寄せられるのはいいですね。
ただ、LINEで入力した単語に対してどれくらいの精度で反応してくれるのかというのは今回未検証です。「お腹が空いた」「お腹が空きました」などの言葉のゆらぎをどれだけ吸収してくれるかはもうちょっと検証が必要かと思います。(ただ、触っていた限りはほとんど単語マッチな印象でした)

チャットボットで何かシステムを構築する時は、会話シナリオが体験の肉付けをしてくれるます。通常ならば機械的な操作になるようなものでも、チャットボットに話しかける際には会話する相手を意識した体験になります。だからこそ会話シナリオというのは重要な要素だと思っているので、チャットボットで実現したいシステムにうまく組み込んで行きたいですね。

改めて、こういった外部連携ありのチャットボットをノーコード/ローコードで作れるenebularというサービスはすごいなと感じました。