怒りを検知すると逆ギレしてくるチャットボット作ってみた

#はじめに
チャットボット、作ってますか？
人間のように会話できるチャットボットを作るというのはチャットボット開発における永遠のテーマですよね。
今回は、「人間のように」すなわち、感情を吹き込んだチャットボットを作ってみました。
吹き込む感情は **「怒り」**です。

#イメージ図
イメージはこんな感じです。
あえてボットにはユーザーを煽るような返事をさせます。
![スクリーンショット 2018-01-31 10.53.53.png](https://qiita-image-store.s3.amazonaws.com/0/143517/a59ff17d-27c2-32f0-c3bf-d2c477bc43cb.png)

するとユーザーは当然怒ります。しかしこのボットは怒りを検知すると逆ギレします。
![スクリーンショット 2018-01-31 10.59.22.png](https://qiita-image-store.s3.amazonaws.com/0/143517/008f7a6c-57e9-4e30-96da-4dbdbcbed013.png)

#構成図
![プレゼンテーション2.png](https://qiita-image-store.s3.amazonaws.com/0/143517/2972f84a-c301-551b-c852-04c4acf218c7.png)
- ユーザーからの入力を常に[Watson ToneAnalyzer](https://www.ibm.com/watson/jp-ja/developercloud/tone-analyzer.html)で感情分析する。
- 怒りを表す"anger"値がxx以上だった場合、逆ギレする。
- [こちらの記事](https://qiita.com/utti0331/items/7980bee5ca5f6481ee8e)を参考にSlackと[Watson Conversation](https://www.ibm.com/watson/jp-ja/developercloud/conversation.html)を繋いだボットを作る。
- [Watson ToneAnalyzer](https://www.ibm.com/watson/jp-ja/developercloud/tone-analyzer.html)は日本語対応してないので、英訳に[Watson Language Translator](https://www.ibm.com/watson/jp-ja/developercloud/language-translator.html)を使用する。

という構成にします。

#手順
##Watson Conversationの準備
今回は簡単な挨拶をするだけの構成にしました。
・`#挨拶`というインテントを作成
![スクリーンショット 2018-01-31 13.18.26.png](https://qiita-image-store.s3.amazonaws.com/0/143517/28bbbd17-17fe-7881-ca92-e8bbb8051e15.png)

・Dialogノードはこんな感じ。"anger"が0.3以上のときには他ノードに飛ばないように怒り検知ノードを最上部へ配置しました。
![スクリーンショット 2018-01-31 13.18.36.png](https://qiita-image-store.s3.amazonaws.com/0/143517/a9416d77-ab42-076f-6df5-115445748dd4.png)

・`#挨拶`を認識したら相手を煽る挨拶を返すノード
![スクリーンショット 2018-01-31 13.18.50.png](https://qiita-image-store.s3.amazonaws.com/0/143517/bd07dd08-2fc6-0086-4b06-f4c3490b4c0a.png)

・Contextの"anger"値が0.3以上のときに相手を煽る挨拶を返すノード
![スクリーンショット 2018-01-31 13.18.44.png](https://qiita-image-store.s3.amazonaws.com/0/143517/396550d0-050c-378c-fc8a-64cf569a7fec.png)

このワークスペースのJSONです。Import Workspaceでそのまま取り込めます。

```json
{"name":"逆ギレ","created":"2018-01-31T02:54:48.056Z","intents":[{"intent":"挨拶","created":"2018-01-31T02:55:25.287Z","updated":"2018-01-31T02:56:04.803Z","examples":[{"text":"こんにちは。","created":"2018-01-31T02:55:53.711Z","updated":"2018-01-31T02:55:53.711Z"},{"text":"おはよう。","created":"2018-01-31T02:55:56.600Z","updated":"2018-01-31T02:55:56.600Z"},{"text":"やあ。","created":"2018-01-31T02:55:58.478Z","updated":"2018-01-31T02:55:58.478Z"},{"text":"おはようございます。","created":"2018-01-31T02:56:01.612Z","updated":"2018-01-31T02:56:01.612Z"},{"text":"こんばんは。","created":"2018-01-31T02:56:04.803Z","updated":"2018-01-31T02:56:04.803Z"}],"description":""}],"updated":"2018-01-31T04:18:01.610Z","entities":[],"language":"ja","metadata":{"api_version":{"major_version":"v1","minor_version":"2017-05-26"}},"description":"","dialog_nodes":[{"type":"standard","title":"その他","output":{"text":{"values":["解釈できませんでした。申し訳ありませんが違う表現を試していただけますか。","恐れ入りますが表現を変えていただけますか。解釈できませんでした。"],"selection_policy":"sequential"}},"parent":null,"context":null,"created":"2018-01-31T02:56:22.997Z","updated":"2018-01-31T02:56:22.997Z","metadata":{},"next_step":null,"conditions":"anything_else","description":null,"dialog_node":"その他","previous_sibling":"ようこそ"},{"type":"standard","title":"挨拶","output":{"text":{"values":["こんにちは。チャットボットです。お前のかーちゃんでべそ！"],"selection_policy":"sequential"}},"parent":null,"context":null,"created":"2018-01-31T02:56:22.997Z","updated":"2018-01-31T02:58:42.630Z","metadata":{},"next_step":null,"conditions":"#挨拶","description":null,"dialog_node":"ようこそ","previous_sibling":"node_1_1517367701357"},{"type":"standard","title":"怒り検知","output":{"text":{"values":["は？キレてんじゃねぇよ！"],"selection_policy":"sequential"}},"parent":null,"context":null,"created":"2018-01-31T03:01:43.315Z","updated":"2018-01-31T04:18:01.610Z","metadata":{},"next_step":null,"conditions":"$anger >= 0.3","digress_in":"does_not_return","description":null,"dialog_node":"node_1_1517367701357","previous_sibling":null}],"workspace_id":"44d94825-1b6f-4438-8fd8-f2550c81e460","counterexamples":[],"learning_opt_out":false}
```

##NodeREDでロジック作成
![スクリーンショット 2018-01-31 14.04.11.png](https://qiita-image-store.s3.amazonaws.com/0/143517/b109483b-f0a7-68d1-d028-988849f74920.png)
こんな感じになりました。
ポイントは、Conversationで使うContextに`"anger"`値を追加(msg.additional_context)したことです。
Tone Analyzerからはanger値が入ってきますので、これをContextに入れてConversationに渡すことでDialogノードの怒り検知ノードでanger値を評価してくれるようになります。
こちらのフローは以下です。

```json
[{"id":"2f2a5edd.cd51b2","type":"watson-conversation-v1","z":"4db2b831.2986b8","name":"","workspaceid":"","multiuser":false,"context":true,"empty-payload":false,"default-endpoint":true,"service-endpoint":"https://gateway.watsonplatform.net/conversation/api","x":490,"y":180,"wires":[["4606b527.f783cc"]]},{"id":"4606b527.f783cc","type":"function","z":"4db2b831.2986b8","name":"","func":"msg.payload = msg.payload.output.text[0];\nreturn msg;","outputs":1,"noerr":0,"x":590,"y":260,"wires":[["ffac6b3c.3031a"]]},{"id":"a6d8fcdd.0bd44","type":"watson-translator","z":"4db2b831.2986b8","name":"","action":"translate","basemodel":"es-en","domain":"news","srclang":"ja","destlang":"en","password":"","custom":"","domainhidden":"news","srclanghidden":"ja","destlanghidden":"en","basemodelhidden":"es-en","customhidden":"","filetype":"forcedglossary","trainid":"","lgparams2":true,"neural":true,"default-endpoint":true,"service-endpoint":"https://gateway.watsonplatform.net/language-translator/api","x":170,"y":260,"wires":[["d4744fb3.2eda5"]]},{"id":"d4744fb3.2eda5","type":"watson-tone-analyzer-v3","z":"4db2b831.2986b8","name":"","tones":"emotion","sentences":"true","contentType":"false","tone-method":"generalTone","interface-version":"2016-05-19","inputlang":"en","default-endpoint":true,"service-endpoint":"https://gateway.watsonplatform.net/tone-analyzer/api","x":280,"y":180,"wires":[["a0273ad9.ceb64"]]},{"id":"a0273ad9.ceb64","type":"function","z":"4db2b831.2986b8","name":"","func":"msg.additional_context = {\n    \n        \"anger\":msg.response.document_tone.tone_categories[0].tones[0].score\n    \n};\nmsg.payload = msg.slackObj.text;\n\nreturn msg;","outputs":1,"noerr":0,"x":390,"y":260,"wires":[["2f2a5edd.cd51b2"]]},{"id":"313e7515.d76c62","type":"Slack Bot In","z":"4db2b831.2986b8","name":"Slack Bot In","apiToken":"","channel":"","x":70,"y":180,"wires":[["a6d8fcdd.0bd44"]]},{"id":"ffac6b3c.3031a","type":"Slack Bot Out","z":"4db2b831.2986b8","name":"Slack Bot Out","apiToken":"","channel":"","x":700,"y":180,"wires":[]}]
```
※Credential情報などは適宜IBM Cloudのサービスからコピペしてください。
※SlackノードにはHuebotのAPIトークンと、channel名を入力してください。
※そのchannelにHuebotを招待することでチャットボットとして稼働できます。

#動作の様子
![スクリーンショット 2018-01-31 14.10.31.png](https://qiita-image-store.s3.amazonaws.com/0/143517/f96272c8-0151-3b15-609f-8332dac650f2.png)

ちなみに、Debugノードを1つめのfunctionノードに繋いで`msg`の中身を確認したところ、
`いきなり悪口言うなよ！失礼だろ馬鹿野郎！`
の英訳結果は
`Don't speak ill of me!You're rude, you idiot!`
anger値は
`0.895779`
となっていました。(母親のでべそを指摘されたらこのくらい怒るのは当然ですね。)


#終わりに
いかがでしたか？
今回は超絶簡単な作りですが、常にユーザーの感情を取得することでチャットボットが人間のように反応を変えるようにすることができます。
何かの参考になれば嬉しいです。