Botを作ろうみなさんこんにちは。みなさんは不意にデリカシーのないことを言ってしまい誰かを怒らせてしまったりしたことはないでしょうか。親しき仲と言えど、何気なく言ってしまった言葉が相手を不快にさせてしまうことってありますよね。僕は最近デートしてる際に政治と数学の話をするなと怒られました。APIで作成できるBotを使えばたった20分で相手の気持ちを探ることができちゃうんです。このチュートリアルに取り組んでみましょう。注意:以下の事前準備で必ず、Node-REDのユーザー認証を有効にしてください。有効にせずに進めると、セキュリティリスクが発生します。再デプロイをおこなってください。Node-REDは一部ブラウザでエディタのカーソル位置がずれる不具合があります。Node-RED上からテキスト編集を行いたい場合は、Firefoxをご利用いただくことを推奨いたします。事前準備このチュートリアルで使用するサービスは、期間内であれば全て無料で使用することができます(2016年11月14日現在)。安心してご利用ください。Traialに申し込み、LINE@のアカウントをBot化する作業が必要になります。Tokenを発行してください今回は自分で作ったBotに愛着を持てるようにライセンスフリーなハリネズミの画像を使ったBot、woktくんを用意しました。Bluemixアカウントの作成こちらのBluemixの登録ページからBluemixのアカウントを作成することができます。Starterのボイラープレートを選択しNode-REDアプリケーションを作成してください。Analyzerをアクティベートして置いてください。Node-REDのインスタンスとそれらの接続をおこなってください。ServicesはWEBブラウザ上で使えるIDEです。Servicesを使うと次のbluemix-setting.jsの編集が楽になります。Servicesのアクティベートは以下のリンクを開き手順に従っていけばアクティベートされます。bluemix-setting.jsからNode-REDにNode.jsライブラリを追加するこのチュートリアルでNode.jsの標準ライブラリにあるcryptoを使用します。以下の画像のようにbluemix-setting.jsのfunctionGlobalContextにライブラリを追加する必要があります。Servicesから編集している例です。errorが出ていますが、後で名前解決されるので気にせず保存しましょう。Node-RED上で標準ライブラリやnode_moduleのライブラリを使いたい場合も、ここに使用するライブラリを追加する必要があります。Botからのメッセージリクエストを受け取るでは実際に開発していきましょう。APIでは、2016年11月現在、会話中のグループやユーザーのIDを知る手段は会話中のBotから会話データを送信してもらう以外に術はありません。(今後取得できるようになる可能性はあります。そのため、まずは以下のようにNodeを配置していき、Botに会話中のグループやユーザのIDを取得させるためのサーバを用意します。httpノードを使うと、簡単にURLのルーティングを行うサーバを作成することができます。httpノードは、POSTリクエストの場合、リクエストヘッダをmsg.req.headersという変数に、ボディをmsg.payloadという変数に受け取ります。デバッグノードを設置するとNode-REDを設置したurlに送られたリクエストの中身を確認することができます。以下にリクエストヘッダを確認する設定例を示します。ボディを確認したい場合は同様にdebugノードのoutputにmsg.payloadを設定します。この例は、今回だけでなくHTTPリクエストの検証に使えるので覚えておくと便利です。APIのドキュメントに必ずHTTPコード200でレスポンスを返してくださいと書いてあるので、今回は空のレスポンスを返すノードも設置しています。APIのアカウントからNode-REDにリクエストを送れるか試してみましょう。DevelopersアカウントページからVERIFYボタンを押すとリクエストが送信されます。リクエストが成功していれば、以下の写真のようにdebugタブを開くことでブラウザからURLに送られてくるリクエストを監視することができます。リクエストの確認ができたら、BotをフォローしたユーザーやBotが参加しているグループやルームチャットでメッセージを送ると、同様にメッセージが送られるようになっているので、グループ、または、ルームのID、ユーザーのアカウントIDをBotにメッセージを送ることによって知ることができます。試しに自分のLINEアカウントからBotにメッセージを送ってサーバで自分のIDを確認しましょう。この時、受信したuserId、groupId、roomIdなどは、絶対外部に公開しないように注意しましょう。外部のBotから盗聴やなりすましをされたり個人を特定されるリスクを増加させてしまいます。このサービスを使用する際は会話情報の利用に対して会話者から同意を得るなどし、個人情報の管理には十分に注意してください。ストーキング等の迷惑行為やその他の違法行為目的で使用しないでください。APIの認証機能を実装する現在のWebサーバはリクエストを無差別に受け付けてしまうため好ましくありません。Secretを使ったsha256で暗号化し、さらにそれをbase64に変換したものがヘッダのx-line-signatureの値と一致することを確認するという方法で認証を行ないます。これらの情報を保存しておくノードを作ります。これらの認証を行うfunctionノードを以下のように設置しましょう。下図では認証が失敗した場合の原因を特定しやすくするためdebug用にlogノードを作成しています。Cloundantを使用して受け取ったメッセージを保存するCloudantはdocumentDB型のNoSQLデータベースです。Cloudantがアクティベートされた状態であれば以下のようにテーブル名だけを指定するだけで、JavaScriptオブジェクト形式やJSON形式のデータに対して、keyをカラム、valueをカラムの値のように見なしてJSON形式で保存してくれるようになります。リクエストの中身を保存してもらうために、一つ一つのeventオブジェクトをループで取得してJavaScriptのオブジェクト形式でノードへと送るようにしています。DocumentDBのハッシュアクセスの利点を生かすために、配列ごとデータベースに保存しても構いません。Analyzerの解析対象としているので、source.typeがgroupまたは、roomのデータかつtype:messageが含まれているevents要素のみを、Cloudantに保存することにします。送られて来たメッセージのtypeがgroupかroomかuserか、さらにそれ以外の不正なリクエストである可能性も踏まえて条件分岐を以下のように設定します。ここでは、flow全体で共有されるスコープの変数flow.typeを宣言してeventsオブジェクトのtypeを保存することにしました。これらによって送られてきたeventの要素のタイプごとに条件分岐を行うことができるようになります。eventsの要素一つ一つに対してこれらの条件分岐を有効にするために以下のようにevents要素の数だけループを実装します。以上でCloudantに送信メッセージやどのチャットに参加しているかを特定するIDなどの情報が保存できるようになりました。Indexを設定する必要があります。Indexを追加します。以下の画像の第一引数が検索に使う際に指定する任意のカラム識別子、第二引数がカラム識別子によって検索対象にしたいColumnになります。{store:true}はデータを取得した際に紐づくレコードにクエリで取得したレコードのカラムを含めるかどうかを表すパラメータになります。よってここでは、trueに設定しておく必要があります。Indexに設定したカラムが全て存在するレコードのみにしか、インデックスは有効にならないということです。groupId、userId、roomIdなどのカラムを抽象化したくなりそうですが、同時に存在しないカラムに対して同時にインデックスを張ることはできないので、もしuserIdやroomIdなどでクエリをかけたい場合は、それぞれ別々のインデックスを張るようにしましょう。Indexを覚えておき、以下のようにCloudantノードに対応付けます。Indexに設定されたカラムに対してクエリを実行できるようになります。今回は特定のルームチャットの雰囲気を分析することにしますので、分析したいルームチャットのroomIdに条件一致するようにクエリを実行するようにします。ここで注意しなければならないのはNode-REDからCloudantノードを使用する場合、クエリはJavaScriptのオブジェクト形式でmsg.payloadに渡す必要があるため、以下のようにfunctionノードを使ってクエリを設定する必要があります。Analyzerにメッセージ部のみを送信するためにデータを整形します。今回は以上のように最新100件までのメッセージを連結するようにしました。Analyzerには英語のテキストを渡す必要があります。APIを使って英訳したものを使用しています。YandexのAPIは非常にシンプルで、エンドポイントに、上記のようにAPIキー、テキスト、翻訳後の言語を渡すだけでテキストの翻訳ができます。テキストを取り出して英語に訳せるようになったら最終ステップに進みましょう。Analyzerの分析結果を自分のLINEアカウントに通知する最後に分析結果を自分のLINEアカウントに送信する処理を書きます。Analyzerは分析結果を以下のようなパラメータを持つjsonで結果を返してくれます。Analyzerは、分析対象としてemotion、language、socialというカテゴリの指定ができます。今回は会話の雰囲気をemotionから分析することにして、最もscoreの高かったemotionを元にメッセージを作成して通知するようにしましょう。APIのpush機能のエンドポイントへメッセージを送信するようにします。送るのも面白くないので、一言多い感じのメッセージを設定しました。push機能を使用するためには、headerに以下のような情報を含めてあげるようにする必要があります。今回toにはuserIdを設定しましたが、メッセージを送るのは、roomIdでもgroupIdでも構いません。その際、以下のようにtemplateノードを挟むことによってリクエストの書式の見通しが良くなります。実装できていれば、Botにメッセージを送ると会話の分析結果を自分に通知してくれるようになります。実際に今回作成したサンプルアプリケーションは以下のJSONからNode-REDのImportフォームに貼り付けると完成品のFlowを読み込むことができます。完成済みのJSONファイル読み込みが成功すると以下のようなFlowが出来上がります。実際に使用する場合は、以下の図のsecret_key_set、line_authentication、query、sanitize_records、process_resultの設定をご自身のアカウントの設定のものに変更してください。実際にやってみた僕が気になっている知人の方と、実際に作成したBotを混ぜてグループ会話をしてみました。(*会話の掲載については了承を得ています。APIを組み合わせて様々なことができると思います。Dataを使って一定時間会話が続かなかったりした時に「今日はいい天気ですね。」などの合いの手を入れて気まずくならないようにするBotなんて面白いのではないでしょうか。ないと「大丈夫?今日は帰宅する?」など心配してくれるBotなんていうのも面白いかもしれません。様々な実用的な使い方ができそうですね。みなさんも是非Bluemixを使ってBot開発してみてください。Conversationを触ろうか迷っている人たちのための一歩を踏み出してみた。ContainersサーバーレスOpenWhisk\初回、1ヶ月間無料!/Bluemixを使ってみるBluemixアドベントカレンダーに参加すると、特別賞品やバッジがもらえる!せっかくの機会じゃ。Nice1925S346サービスに対してのユーザーの声をチェックする仕組みをBluemi...Nice33×すでに登録されている方がいます。他の日をお選びください※投稿予定の記事や作品のタイトルを記入してください※投稿予定の記事や作品のURLは正しく記入してください※投稿予定の記事や作品のURLは必須です※賞品をお届けする際に、teratailに登録されたメールアドレス宛にご連絡を差し上げますので、予めご登録ください。※アドベントカレンダーに参加いただいた方へ、teratailに登録されたメールアドレス宛にteratail運営または日本アイ・ビー・エムよりご連絡差し上げる場合があります。※URLについては、ご自身のブログや外部サービスをご利用いただけます。参加日になるとURLが自動的に公開されます。Niceみんなの投稿に3つ以上のNiceをつけると、限定バッジがもらえます。Bluemixをご利用される際は、Bluemixプライバシー・ポリシーおよびBluemix利用条件をご確認ください。Bluemixの登録やご利用に関するお問い合わせは、Bluemixの公式サイトからお願い致します。頂いたご意見への回答は行っておりません。Ltd.teratailアカウントでログインログイン新規会員登録パスワードを忘れた方SNSアカウントでログインFacebookでログインTwitterでログインGoogleでログインGitHubでログインHatenaでログイン思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る閉じる。