teratailの最新技術チュートリアル - LINEで感情を読み取る

気になるあの子を確実に落とすためのLINE Botを作ろう!

意中のあの人のハートをゲット!Tone Analyzerで会話の雰囲気を分析して通知してくれるLINE Botを作ろう

みなさんこんにちは。みなさんは不意にデリカシーのないことを言ってしまい誰かを怒らせてしまったりしたことはないでしょうか。親しき仲と言えど、何気なく言ってしまった言葉が相手を不快にさせてしまうことってありますよね。僕は最近デートしてる際に政治と数学の話をするなと怒られました。そんな空気が読めているかどうか心配しているあなたも、人の気持ちが手に取るように分かると思っているあなたも、IBM BluemixのTone AnalyzerとLINE Messaging APIで作成できるBotを使えばたった20分で相手の気持ちを探ることができちゃうんです。このチュートリアルを取り組み終わった頃には、あなたはTone Analyzerを使いこなせるようになり、意中の人からも、そうでない人からも、モテすぎて困ってしまうようになるかも?! では、早速、このチュートリアルに取り組んでみましょう。

注意:

  • 以下の事前準備で必ず、Node-REDのユーザー認証を有効にしてください。有効にせずに進めると、セキュリティリスクが発生します。以下、ダッシュボード > ランタイム > 環境変数 から認証情報を設定した状態の図になります。認証情報設定後、すぐに再デプロイをおこなってください。 Node-REDにセキュリティ認証を行っている図
  • Node-REDは一部ブラウザでエディタのカーソル位置がずれる不具合があります。Node-RED上からテキスト編集を行いたい場合は、Firefoxをご利用いただくことを推奨いたします。

事前準備

このチュートリアルで使用するサービスは、期間内であれば全て無料で使用することができます(2016年11月14日現在)。安心してご利用ください。

  • LINE Business Centerのアカウント作成

    LINE Business CenterにてDeveloper Traialに申し込み、LINE@のアカウントをBot化する作業が必要になります。LINE@のアカウントを作成後、 以下の画像のリンクから飛べるDeveloper Centerのアカウントページに飛び、Webhook URLの取得と、Channel SecretとChannel Access Tokenを発行してください

    今回は自分で作ったBotに愛着を持てるようにライセンスフリーなハリネズミの画像を使ったBot、woktくんを用意しました。

  • IBM Bluemixアカウントの作成

    こちらのBluemixの登録ページからBluemixのアカウントを作成することができます。

  • Node-REDとCloudantとTone Analyzerのアクティベート

    Bluemixにログイン後、以下の画面からNode-RED Starterのボイラープレートを選択しNode-REDアプリケーションを作成してください。

    Node-RED_starterのボイラープレートを作成している図

    Node-REDのインスタンスを作成後、CloudantとTone Analyzerをアクティベートして置いてください。また、Node-REDのインスタンスとそれらの接続をおこなってください。

  • DevOps ServicesとNode-REDアプリの連携

    DevOps ServicesはWEBブラウザ上で使えるIDEです。DevOps Servicesを使うと次のbluemix-setting.jsの編集が楽になります。DevOps Servicesのアクティベートは以下のリンクを開き手順に従っていけばアクティベートされます。

    DevOps Servicesの登録動線を指し示している図
  • bluemix-setting.jsからNode-REDにNode.jsライブラリを追加する

    このチュートリアルでNode.jsの標準ライブラリにあるcryptoを使用します。以下の画像のようにbluemix-setting.jsのfunctionGlobalContextにライブラリを追加する必要があります。以下はDevOps Servicesから編集している例です。errorが出ていますが、後で名前解決されるので気にせず保存しましょう。Node-RED上で標準ライブラリやnode_moduleのライブラリを使いたい場合も、ここに使用するライブラリを追加する必要があります。

    DevOps Servicesでライブラリを設定している図

時間がない方のために

完成品はこちらから

Step1 Node-REDでWebサーバを立ててLINE Botからのメッセージリクエストを受け取る

では実際に開発していきましょう。

LINE Messaging APIでは、2016年11月現在、会話中のグループやユーザーのIDを知る手段は会話中のBotから会話データを送信してもらう以外に術はありません。(今後取得できるようになる可能性はあります。) そのため、まずは以下のようにNodeを配置していき、Botに会話中のグループやユーザのIDを取得させるためのサーバを用意します。

Node-REDでWebサーバを作る方法を説明する図  

httpノードを使うと、簡単にURLのルーティングを行うサーバを作成することができます。

Node-REDでPOSTリクエストに対応するURLを設置する方法を説明する図

httpノードは、POSTリクエストの場合、リクエストヘッダをmsg.req.headersという変数に、ボディをmsg.payloadという変数に受け取ります。デバッグノードを設置するとNode-REDを設置したurlに送られたリクエストの中身を確認することができます。以下にリクエストヘッダを確認する設定例を示します。ボディを確認したい場合は同様にdebugノードのoutputにmsg.payloadを設定します。

Node-REDでPOSTリクエストに対応するURLを設置する方法を説明する図

この例は、今回だけでなくHTTPリクエストの検証に使えるので覚えておくと便利です。

LINE Messaging APIのドキュメントに必ずHTTPコード200でレスポンスを返してくださいと書いてあるので、今回は空のレスポンスを返すノードも設置しています。

ノードを以上の手順で配置した後、LINE Messaging APIのアカウントからNode-REDにリクエストを送れるか試してみましょう。LINE DevelopersアカウントページからVERIFYボタンを押すとリクエストが送信されます。

LINE Messaging API の動作確認方法を説明する図

リクエストが成功していれば、以下の写真のようにdebugタブを開くことでブラウザからURLに送られてくるリクエストを監視することができます。

Node-REDでWebサーバのリクエストを監視する方法を説明する図

リクエストの確認ができたら、BotをフォローしたユーザーやBotが参加しているグループやルームチャットでメッセージを送ると、同様にメッセージが送られるようになっているので、グループ、または、ルームのID、ユーザーのアカウントIDをBotにメッセージを送ることによって知ることができます。試しに自分のLINEアカウントからBotにメッセージを送ってサーバで自分のIDを確認しましょう。この時、受信したuserId、groupId、roomIdなどは、絶対外部に公開しないように注意しましょう。外部のBotから盗聴やなりすましをされたり個人を特定されるリスクを増加させてしまいます。また、このサービスを使用する際は会話情報の利用に対して会話者から同意を得るなどし、個人情報の管理には十分に注意してください。 くれぐれもストーキング等の迷惑行為やその他の違法行為目的で使用しないでください。

Step2 LINE Messaging APIの認証機能を実装する

現在のWebサーバはリクエストを無差別に受け付けてしまうため好ましくありません。LINE Messaging APIでは認証方法として、msg.payloadで受け取ったリクエストボディをChannel Secretを使ったsha256で暗号化し、さらにそれをbase64に変換したものがヘッダのx-line-signatureの値と一致することを確認するという方法で認証を行ないます。まずは、これらの情報を保存しておくノードを作ります。

LINEの認証情報を保存しておく図 これらの認証を行うfunctionノードを以下のように設置しましょう。

Node-REDでLINE Messaging APIの認証を行う方法を説明する図

下図では認証が失敗した場合の原因を特定しやすくするためdebug用にlogノードを作成しています。

認証をした後の動作確認を行う図

Step3 Cloundantを使用して受け取ったメッセージを保存する

CloudantはdocumentDB型のNoSQLデータベースです。Cloudantがアクティベートされた状態であれば以下のようにテーブル名だけを指定するだけで、JavaScriptオブジェクト形式やJSON形式のデータに対して、keyをカラム、valueをカラムの値のように見なしてJSON形式で保存してくれるようになります。今回のサンプルではCloudantでLINE Messaging API のリクエストの中身を保存してもらうために、一つ一つのeventオブジェクトをループで取得してJavaScriptのオブジェクト形式でノードへと送るようにしています。ただし、DocumentDBのハッシュアクセスの利点を生かすために、配列ごとデータベースに保存しても構いません。

Node-REDでCloudantの設定を行なっている図

今回はグループチャットやルームチャットのメッセージのデータのみをTone Analyzerの解析対象としているので、source.typeがgroupまたは、roomのデータかつtype:messageが含まれているevents要素のみを、Cloudantに保存することにします。まずは、送られて来たメッセージのtypeがgroupかroomかuserか、さらにそれ以外の不正なリクエストである可能性も踏まえて条件分岐を以下のように設定します。

条件分岐を設置している図

ここでは、flow全体で共有されるスコープの変数flow.typeを宣言してeventsオブジェクトのtypeを保存することにしました。これらによって送られてきたeventの要素のタイプごとに条件分岐を行うことができるようになります。

Node-REDでevent.typeを調べている図

さらにeventsの要素一つ一つに対してこれらの条件分岐を有効にするために以下のようにevents要素の数だけループを実装します。

Node-REDでCloudantを接続して行なっている図

以上でCloudantに送信メッセージやどのチャットに参加しているかを特定するIDなどの情報が保存できるようになりました。

Step4 Cloundantを使用して受け取ったメッセージを翻訳してTone Analyzerで解析する

Cloudantに保存したデータをroomId、またはgroupIdごとに取得するためには、保存されているドキュメントテーブルに対してSearch Indexを設定する必要があります。Cloudantのダッシュボード画面に飛び、以下のボタンから遷移し、Search Indexを追加します。

CloudantダッシュボードからSearch Indexを設定している図

以下の画像の第一引数が検索に使う際に指定する任意のカラム識別子、第二引数がカラム識別子によって検索対象にしたいColumnになります。{store:true}はデータを取得した際に紐づくレコードにクエリで取得したレコードのカラムを含めるかどうかを表すパラメータになります。よってここでは、trueに設定しておく必要があります。   CloudantダッシュボードからSearch Indexを設定している図 ここで注意しておくべきことは、Search Indexに設定したカラムが全て存在するレコードのみにしか、インデックスは有効にならないということです。groupId、userId、roomIdなどのカラムを抽象化したくなりそうですが、同時に存在しないカラムに対して同時にインデックスを張ることはできないので、もしuserIdやroomIdなどでクエリをかけたい場合は、それぞれ別々のインデックスを張るようにしましょう。

以上のように作成したSearch Indexを覚えておき、以下のようにCloudantノードに対応付けます。これによってSearch Indexに設定されたカラムに対してクエリを実行できるようになります。

CloudantノードにSearch Indexを設定している図

今回は特定のルームチャットの雰囲気を分析することにしますので、分析したいルームチャットのroomIdに条件一致するようにクエリを実行するようにします。ここで注意しなければならないのはNode-REDからCloudantノードを使用する場合、クエリはJavaScriptのオブジェクト形式でmsg.payloadに渡す必要があるため、以下のようにfunctionノードを使ってクエリを設定する必要があります。

Cloudantに対してクエリを設定している図

Cloudantからデータを取得した後はTone Analyzerにメッセージ部のみを送信するためにデータを整形します。今回は以上のように最新100件までのメッセージを連結するようにしました。

データを成形しているfunctionノードの中身

Tone Analyzerには英語のテキストを渡す必要があります。なのでここでは連結した文字列をYandexのTranslate APIを使って英訳したものを使用しています。YandexのAPIは非常にシンプルで、エンドポイントに、上記のようにAPIキー、テキスト、翻訳後の言語を渡すだけでテキストの翻訳ができます。テキストを取り出して英語に訳せるようになったら最終ステップに進みましょう。

Step5 Tone Analyzerの分析結果を自分のLINEアカウントに通知する

最後に分析結果を自分のLINEアカウントに送信する処理を書きます。Tone Analyzerは分析結果を以下のようなパラメータを持つjsonで結果を返してくれます。

Tone Analyzerの分析結果のjson

また、Tone Analyzerは、分析対象としてemotion、language、socialというカテゴリの指定ができます。今回は会話の雰囲気をemotionから分析することにして、最もscoreの高かったemotionを元にメッセージを作成して通知するようにしましょう。httpノードを使ってNode-REDからLINE Messaging APIのpush機能のエンドポイントへメッセージを送信するようにします。ただ送るのも面白くないので、一言多い感じのメッセージを設定しました。push機能を使用するためには、headerに以下のような情報を含めてあげるようにする必要があります。今回toにはuserIdを設定しましたが、メッセージを送るのは、roomIdでもgroupIdでも構いません。

functionノードでheaderを設定する図

その際、以下のようにtemplateノードを挟むことによってリクエストの書式の見通しが良くなります。

Node-REDでPOSTリクエストを行う図

正しく実装できていれば、Botにメッセージを送ると会話の分析結果を自分に通知してくれるようになります。

完成品

実際に今回作成したサンプルアプリケーションは以下のJSONからNode-REDのImportフォームに貼り付けると完成品のFlowを読み込むことができます。

完成済みのJSONファイル

INPORTを実行している図1 INPORTを実行している図2

読み込みが成功すると以下のようなFlowが出来上がります。実際に使用する場合は、以下の図のsecret_key_set、line_authentication、query、sanitize_records、process_resultの設定をご自身のアカウントの設定のものに変更してください。

BluemixのNode-REDとLINE Messaging APIを連携させた図

実際にやってみた

僕が気になっている知人の方と、実際に作成したBotを混ぜてグループ会話をしてみました。(*会話の掲載については了承を得ています。)

INPORTを実行している図2

なぜかすごく警戒されていますが・・・

果たして結果は・・・?

LINEからBotにメッセージを送ると分析結果を教えてくれる図 INPORTを実行している図2

お疲れ様でしたorz

まとめ

今回紹介した使い方以外にもNode-REDやTone AnalyzerとLINE Messaging APIを組み合わせて様々なことができると思います。例えば Weather Company Dataを使って一定時間会話が続かなかったりした時に「今日はいい天気ですね。」などの合いの手を入れて気まずくならないようにするBotなんて面白いのではないでしょうか。また、勤務時間中に外出してから一定時間以上帰社報告がないと「大丈夫?今日は帰宅する?」など心配してくれるBotなんていうのも面白いかもしれません。 様々な実用的な使い方ができそうですね。 みなさんも是非Bluemixを使ってBot開発してみてください。
限定バッジや豪華賞品がもらえる!アドベントカレンダーに参加する
初回、1ヶ月間無料で使い放題!IBM Bluemixに登録する
Bluemixアドベントカレンダー

teratailの最新技術チュートリアル

Bluemixなら、最新技術にチャレンジし放題!

  • 言語翻訳

    Language Translation

  • IoT

    Internet of Things

  • 対話

    Conversation

  • 音声合成

    Speech to Text

  • 音声認識

    Text to Speech

  • API Connect

    API Connect

  • Apache Spark

    Apache Spark

  • 仮想コンテナー

    IBM Containers

  • サーバーレス

    OpenWhisk

\初回、1ヶ月間無料!/

Bluemixアドベントカレンダーに参加すると、特別賞品やバッジがもらえる!

Bluemix優秀賞は青汁1年分!参加賞はteratailバッジとイベント限定の缶バッジ2種!他にもBluemix・teratailのTシャツ・ステッカーがもらえるチャンスも!

せっかくの機会じゃ。Bluemixアドベントカレンダーに参加して、
今年流行った技術で2016年を締めくくるんじゃ!

1
milktea milktea
98
2
ikuwow ikuwow
32
3
FSyuu FSyuu
80
4
tokutoku393 tokutoku393
53
5
n0bisuke n0bisuke
51
6
KazukiHonjo KazukiHonjo
22
7
tkow tkow
52
8
yutori_828 yutori_828
102
9
trashbox trashbox
58
10
SSaka SSaka
35
11
zuhito zuhito
7
12
kousuketanihata kousuketanihata
70
13
sykmhmh sykmhmh
32
14
storywriter storywriter
82
15
h-takeo h-takeo
35
16
_skuwa _skuwa
64
17
miyamiya miyamiya
68
18
o_chicchi o_chicchi
34
19
1ft-seabass 1ft-seabass
50
20
shanonim shanonim
37
21
ShoheiTai ShoheiTai
41
22
Gazelle Gazelle
35
23
wtruby wtruby
29
24
nikosun nikosun
19
25
S346 S346
33
  • タイトル

  • URL

※賞品をお届けする際に、teratailに登録されたメールアドレス宛にご連絡を差し上げますので、予めご登録ください。

※アドベントカレンダーに参加いただいた方へ、teratailに登録されたメールアドレス宛にteratail運営または日本アイ・ビー・エムよりご連絡差し上げる場合があります。予めご了承ください。

※URLについては、ご自身のブログや外部サービスをご利用いただけます。参加日になるとURLが自動的に公開されます。

Niceでバッジゲット!

Bluemix Nice

みんなの投稿に3つ以上のNiceをつけると、限定バッジがもらえます。

イベントの詳細

  • ・アドベントカレンダーの参加には、teratailへの会員登録が必要です
  • ・アドベントカレンダーの参加は、1人1枠までとさせていただきます
  • ・投稿予定日から1日を過ぎても投稿が確認できない場合、投稿予約を削除させていただく恐れがあります
  • ・イベント期間は、2016年11月28日(月)00:00~2017年1月11日(水)10:00です
  • ・本イベントは予告なく終了する場合がありますので、あらかじめご了承ください
  • ・アドベントカレンダーへの投稿内容は、IBM Bluemixをテーマとしたもののみです
  • ・IBM Bluemixに関係ない投稿であると運営チームが判断した場合、投稿を削除することがあります
  • ・投稿内容に不正があった場合、応募資格・当選資格を取り消すなど、イベント参加の対象外となる場合があります
  • ・賞品をお届けする際に、teratailに登録されたメールアドレス宛にご連絡を差し上げますので、あらかじめご登録ください
  • ・ご連絡が取れない場合、賞品送付できないため対象外となります
  • ・参加賞の「Bluemixサンタ」バッジは、2017年1月16日(月)に付与いたします
  • ・Bluemix優秀賞・IBM賞・teratail賞に選ばれた方には、2017年1月16日(月)にteratailに登録されたメールアドレス宛に当選結果のご連絡を致します
  • ・迷惑メール対策で受信設定をご利用の場合、あらかじめ、info@teratail.comからのメールを受信できるよう設定してください
  • ・アドベントカレンダーに参加いただいた方へ、teratailに登録されたメールアドレス宛にteratail運営または日本アイ・ビー・エムよりご連絡差し上げる場合があります
  • ・IBM Bluemixをご利用される際は、Bluemixプライバシー・ポリシーおよびBluemix利用条件をご確認ください。
  • ・IBM Bluemixの登録やご利用に関するお問い合わせは、Bluemixの公式サイトからお願い致します。

アドベントカレンダーに登録された投稿

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る