【ビール女子麦子さん⑥】Watson AssistantとLINE Messaging APIでビールの雑学クイズ機能を作ってみた

#1．はじめに

「ビール女子🍺麦子さん」シリーズ、６回目の投稿です。今回は、少し前にリリース済みの**「ビールの雑学クイズ」**の実装方法について書こうと思います。

機能としては以下のようなものです。　:grinning:　：わたし　　👧　：麦子

　:grinning:　LINE上で「ビールのクイズを出して！」と麦子さんにお願いする。

　👧　ビールのクイズを出題する。回答の選択肢が記載されたボタンを表示する。

　:grinning:　回答ボタンを押す

　👧　正解か不正解を判定。解説を表示。


ちなみに、ビール女子麦子さんとは、以下のようなWatson AssistantとLINE Messaging APIでつくった、ビールに詳しいチャットボットです。よかったら遊んであげてください♪

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">つくってみたー！！中身はWatson Assistant(Watson Conversation)です。会話のスキル作るの楽しい！！<br>これからビールの知識を増やして立派なビール女子に育てます😃 <a href="https://t.co/nZfuqH4IfC">pic.twitter.com/nZfuqH4IfC</a></p>&mdash; はぁこ🌸ビール女子麦子開発中 (@paco_itengineer) <a href="https://twitter.com/paco_itengineer/status/1119612368240005120?ref_src=twsrc%5Etfw">April 20, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

#２．作り方
使うのはいつもの３つと**LINE Bot Designer**です。
・WatsonAssistant
・Node-RED
・LineMessagingAPI
・**LINE Bot Designer** 　←初利用！

##（１）クイズをランダムに出題する仕組み
クイズをランダムに出題するために、クイズを出題するまでに２回Watsonに問い合わせをする仕組みにしました。

![出題の仕組み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/d5fa8ae8-9e0f-866d-0e0d-66413b25887f.png)
①ラインから「クイズを出して」とメッセージを送る。
②WatosonAssistantはクイズNoリストからランダムにクイズ番号を返す。
③そのクイズ番号でもう一度WatosonAssistantに問い合わせを行い、クイズ内容を取得する。
④クイズ内容をLineMessagingAPIで表示する。


##（２）クイズ用のダイアログを出す仕組み
今回は、[LINE Bot Designer](https://developers.line.biz/en/services/bot-designer/)を使います。

①[LINE Bot Designer](https://developers.line.biz/en/services/bot-designer/)をダウンロードし、インストールする。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/9113f615-50a9-74ef-0f80-8514ae2818f2.png)

②LINE Bot Designerのアイコンをダブルクリックして起動。

②プロジェクト設定で「OK」をクリック。

③メニューで「メッセージ」－「ボタン型テンプレートメッセージ」を選択。

④プロパティに表示したい内容を入力。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/bafd3577-e554-2367-8c47-db6204af1cf7.png)

⑤LINE Bot Designerの右下にJSON形式で設定内容が表示されます。クイズのダイアログを出すためには、以下のように設定すればよいことが分かりました。

```
{
  "type": "template",
  "altText": "this is a buttons template",
  "template": {
    "type": "buttons",
    "actions": [
      {
        "type": "message",
        "label": "酵母",
        "text": "酵母"
      },
      {
        "type": "message",
        "label": "大麦",
        "text": "大麦"
      },
      {
        "type": "message",
        "label": "小麦",
        "text": "小麦"
      }
    ],
    "title": "ビールの雑学クイズ",
    "text": "●●とは、なーに？"
  }
}
```




##（３）回答を判定する仕組み
WatsonAssistantで、クイズの設問を親ノード、回答を子ノードとして設定します。
①親ノードでクイズを出題。
②クイズの回答を受け取ると、子ノードで正解/不正解を判定

#３．実装
それでは実装していきましょう。

##（１）WatsonAssistantの設定
①WatsonAssistantの「Intent」で「#ビールの雑学クイズ」を設定します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/4940b0db-f4d4-b689-18a0-03bb4e6fcc92.png)

②WatsonAssistantの「Entity」で「@ビールの雑学クイズ」を作成し、クイズ番号と回答選択肢を登録します。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/0f848d06-1998-4620-2e78-43a12323dff9.png)


②WatsonAssistantの「Dialog」で「#ビールの雑学クイズ」を受け取った場合に、ランダムにクイズ番号を返すように設定します。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/013a316e-9401-d412-c063-70e1435b1107.png)

③子ノードを作成し、「#ビールの雑学クイズ」の子ノードの反応条件を「#ビールの雑学クイズ」と「@ビールの雑学クイズ：ビールの雑学クイズ001（クイズ番号）」を設定します。反応内容の1行目にはタイトル、2行目にはクイズ内容、3行目～5行目には回答選択肢を設定します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/7d0fed2c-b9ec-f6f7-2715-ab88adb7d066.png)

④さらに子ノード（孫ノード）を作成し、「@ビールの雑学クイズ」を受け取った場合に、回答内容に応じて正解/不正解の回答を返すように設定します。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/11310cf7-4f37-61cb-46b3-c590772a230a.png)

##（２）Node-REDの設定
実際の麦子さんは度重なる機能追加でかなり複雑化していますので、シンプルに説明するために[【ビール女子麦子さん】 IBM WatsonとLINEでbotを作ってみた](https://qiita.com/paco_itengineer/items/5981c22edc60494383e6)の時点のNode-REDへ追加するイメージで書きます。初期状態を以下の状態とします。なお、この初期状態のフローは[LINE x Watson AIボット入門](https://qiita.com/bird_tomita/items/4c307f05b6de384b0170)を参考にして作成しています。

![初期状態.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/aa5e2d7b-3961-a50d-0416-b95a29b1d183.png)

①Assistantノードの出口側に「クイズ判定」のSwitchノードを配置します。WatsonAssistantの`msg.payload.output.text[0]`が「ビールの雑学クイズ」の文字列を含むとき１、それ以外の時に２につながるように設定します。（この時、WatsonAssistantから「ビールの雑学クイズ001」のようなクイズ番号が返ってきていることを想定しています）

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/526b9fd2-7915-57e3-8f78-3f063dc9a2e0.png)

②「ビールの雑学クイズ」の文字列を含む場合は、「Input文設定（クイズ）」のchangeノードに進むように設定。それ以外の場合は、「set payload.messages」に進むように設定。

![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/baeae7cd-5322-ad66-696d-8189f6b832f0.png)

③「Input文設定（クイズ）」のchangeノードでは、`msg.payload`に`msg.payload.output.text[0]`を代入するように入力する。（これで、WatsonAssistantに「ビールの雑学クイズ001」のクイズ内容を問い合わせる）

④「assistant」と「クイズ判定」の間に、「回答の数分析」のSwitchノードを挿入する。ここで、`msg.payload.output.text[1]`が`is null`の時には１（クイズ判定）へ、それ以外の場合は２（クイズ用のOutput文設定）へ進むようにする。

＜補足＞
`msg.payload.output.text[0]`~`msg.payload.output.text[4]`には、WatsonAssistantからの回答が格納されます。１つなら[0]のみ、複数回答なら[1]~[4]に値が入ります。今回、クイズの設問の場合は以下のように複数回答になるように設定しているため`msg.payload.output.text[1]`がnullではない場合にクイズとみなす判定をしています。

| payload       |      格納内容 |
|:-----------------|:------------------|
| msg.payload.output.text[0]   |タイトル | 
| msg.payload.output.text[1]   |クイズ内容|
| msg.payload.output.text[2]   |回答選択肢１|
| msg.payload.output.text[3]   |回答選択肢２ |
| msg.payload.output.text[4]   |回答選択肢３ |


![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/6328c9d6-65ab-623b-7c62-b7bbeb36dbb4.png)

⑤「回答の数分析」の２の出口と「set HTTP Headers」の間に「outputメッセージの設定（クイズ）」のChnageノードを配置する。

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/6a2007b9-447f-9be1-83b1-3cd398fc6493.png)

⑥値の代入に`msg.payload.messages`を入力し、対象の値には以下を設定する。

```
[
   {
       "type":'text',
       "text":'ビールの雑学クイズだよ♪'
   },
   {
       "type": "template",
       "altText": "ビールのクイズだよ", 
       "template": {
           "type": "buttons",
           "actions": [
               {
                   "type": "message",
                   "label": msg.payload.output.text[2],
                   "text": msg.payload.output.text[2]
               },
               {
                   "type": "message",
                   "label": msg.payload.output.text[3],
                   "text": msg.payload.output.text[3]
               },
               {
                   "type": "message",
                   "label": msg.payload.output.text[4],
                   "text": msg.payload.output.text[4]
               }
           ],
           "imageBackgroundColor": "#F0FFF0",
           "text": msg.payload.output.text[1]
       }
   }
]
```
⑦ひ・・・ひどい。並べ方のセンスがなさすぎてすみません。ひとまず、これでデプロイしたら完成です。

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/851aa4f9-1057-44be-f720-36858be9cd4c.png)

#４．できあがり
こんな感じになりました！Node-REDのフローがごちゃごちゃしてしまって気持ち悪いですが、何とか動きました。

じつは、このクイズ、弱点がありまして、２人以上が同時に利用すると正解の判定ができなくなってしまいます。麦子さんは１人分しか会話を覚えていられないのですね・・・:disappointed_relieved:

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ビール女子麦子さんに、ビールのクイズ機能をつけました。まだ2問しか登録してないけど😓これも、随時増やしていこうと思います。誰か問題一緒に考えてくれないかなぁ〜なんて... <a href="https://t.co/n3o6tzU37u">pic.twitter.com/n3o6tzU37u</a></p>&mdash; はぁこ🌸ビール女子麦子開発中 (@paco_itengineer) <a href="https://twitter.com/paco_itengineer/status/1127426232105062400?ref_src=twsrc%5Etfw">May 12, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

よかったら麦子さんと遊んであげてください。

ビール女子🍺麦子さん　
　　↓↓↓↓↓
<a href="http://nav.cx/aLo5a15"><img src="https://scdn.line-apps.com/n/line_add_friends/btn/ja.png" alt="友だち追加" height="36" border="0"></a>
※現在開発中につき、予告なくサービスを停止する可能性がある点をご了承ください。