チャットボットを作成したい。そんな時ありますよね。
今回、趣味でLINE MessgingAPI + AWSを利用してチャットボットを作成してみました。
約3~5ヶ月前の話ですが、復習も兼ねて思い出しながら記事にまとめたいと思います。
Messaging APIでできること
ボットのアプリサーバーとLINEサーバー間でデータ通信ができ、Webhookをトリガーにリクエストを送信することができます。
具体的には、応答メッセージやプッシュメッセージにはじまり、画像・音声・動画やスタンプを送信することができたりします。また、ユーザーのプロフィール取得など、基本的に普段利用しているLINEの機能ならある程度使えます。
詳しくはこちらを参照すると良いと思います!
システム設計
大枠としては以下の流れになります。
1) LINEで送信した情報をAPI Gatewayを通じてLambda(Receiver)が受信
2) 受信した情報をDynamoに格納
3) Dynamoは更新を検知し、トリガーとして別のLambda(Sender)を呼び出す
4) Senderで情報を更新し、NATを通しLINEサーバーに送信
5) Botからレスポンスが返る
今回作成するBOTでは、一度に大人数に利用してもらうことを想定しており、かつレスポンス処理に様々なロジックを組み込むことを想定していました。
そのため、単純に一つのサーバー内で完結するような構成にはせず、サーバー負荷やパフォーマンスを考慮した構成になっています。
結論から言うと、以下の戦略をとり「メッセージの受信」と「メッセージの送信」との役割を非同期にすることで、これを解決します。
BOT Serverは、ユーザからのメッセージをLINE Serverに「できるだけ貯めさせない」ようにする。つまり、とにかくLINE ServerからBOT Serverにメッセージを迅速に移動させる。
ユーザは数秒であれば、返事を待ってくれる。返信処理を焦って行わない。
上記システムの具体的な説明については、以下の記事にまとまっており、そちらを参考にさせて頂きました。
大量メッセージが来ても安心なLINE BOTサーバのアーキテクチャ
LINE Bot を AWSを使ってシステム構築してみた。
注意したいポイント
具体的な作成手順は上記の記事にまとまっていますので、
ここでは、ネットワーク構築や開発の際に気をつけたいポイントを実際にハマってしまった実例を元に紹介します。
ルートの定義忘れ
実際に構築を行えばわかりますが、DynamoDBでは異なるAvailability ZoneのSubnetを2セット利用します。
これにより、ルートテーブルも追加で作成する必要があるのですが、あろうことか後で作成したAZ-CのPrivateRouteTableのTargetにNAT Gatewayの設定をし忘れ、一定頻度で接続ができない状態が続きました。
AZ-Aの方はしっかり定義されているため、Lambdaの中身を変えたり等、環境を更新するたびにいずれかのアベラリティーゾーンのルートで通り一定確率で疎通する、しないが起こり原因特定に時間がかかってしまった背景もあり、
特に設定をドキュメントに起こさず構築してしまったが故に、このミスに気づくのに実に1ヶ月ほどかかりました😂
この間、LambdaやDynamoの設定が悪いんじゃないか?、もしかしてメモリやタイムアウトの設定?、Lambdaでの組み合わせによってそういうこともあるらしい?、そもそも方法が違うのではないか等々、ひたすら調べては実行してみて解決できなかったので、最終的にはHerokuにNode.jsのソースを移植して開発していました(笑)
原因がまさかのルートの定義忘れだとは。。灯台下暗しでした。
恐怖!deadbeafメッセージ
LINE上でメッセージを送り、それをDynamoDBに格納していくテストを行なっていた時です・・・
idはユニーク, fromには送信されたグループIDまたはユーザーIDが, textには送信内容が入るようになっています。
そうです。

明らかに、自分たちがデバッグで送信したもの以外のメッセージが飛んできていたのです。
この時深夜3時ぐらいに2人で開発をしていたのですが、「自分たちがデバッグしているLINEグループに知らない人が入っている?」「DBを直接いじられているのかも!」「AWSに入られている可能性があるかも、今すぐ止めよう!」とかなり焦った記憶を鮮明に覚えています。
「タチの悪いハッカーが侵入してきた、やばい、終わった。」当時はそんな気持ちでした。
ひとまず稼働しているものを全て止めて動かない状態にして、変なインスタンスが立っていないか?高額請求されていないか?を一通り確認しましたが、結論何も問題がありませんでした。
落ち着いて朝方5時ぐらいに調査をしていた結果、衝撃の事実が。実はこれ、LINEの仕様だったのです。
「deadbeefdeadbeefdeadbeefdeadbeef・・・」というのは、 16進数で作れるおもしろ単語ということで、一部の界隈では好まれているらしいです。
不吉すぎて何も面白くなかったです。。。心臓に悪い。。
はじめてのNode.js+LINE APIでのサーバーサイド開発
今回はじめてAPIを調べながら考え、一から叩くような開発を行いました。
そして普段開発で利用しないNode.jsを利用することもあり、LINEのAPIリファレンスや参考記事をみながら開発にかなりの時間がかかりました。
APIを叩いて、結果を受け取ってというのは割とスムーズにできたのですが、Node.jsのサーバーサイド開発が一番苦労しました。
コールバック地獄
はい、コールバック地獄にどハマりしました。
単体の非同期処理は何度か書いたことがあるのですが、今回の開発のように複数の非同期処理と同期処理が混ざるような開発は初めてでして、とても苦戦しました。
苦戦した原因としては以下の2つです。
1) 完全に趣味の開発だったので、ろくに設計をせず実装をしながら方針を決めて開発していた
2) async/awaitを知らなかった
1つ目に関しては、設計の手間を省いたために大変なことになりました。最初のうちはよかったのですが、機能を追加するたびにコードが肥大化していってしまっため、かなり可読性が悪いコードとなってしまいました。反省。
2つめに関しては、完全に知識不足でした。非同期=Promiseという固定観念が自分の中であり、ひたすらPromiseしていました。同期処理を行うためにひたすらthenで苦しみながら連結していたのですが、それってasync/awaitで簡単にできるよと言われ衝撃を受け、のちに書き換え可能な箇所は全て書き換えました。。
また、LINE BOTの開発ということで当然テスト環境のようなものはなく、毎回「修正→(herokuの場合)デプロイ→LINEで動作確認→ログやDBを確認」ということを行なっていたため、ここにも時間を費やしてしまいました。
その他
他にもLINEの認証設定や、LambdaやDynamoの設定、JSONの利用等、色々なところで詰まりましたが、ここでは割愛します。
まとめ
LambdaやDynamoDB等はじめての技術を多く使い、LINE Botを作成することができました。
開発期間としては、込み込みで3ヶ月ぐらいでしたが、UXを考え、ここで処理を失敗した時はこうしようとか、初めてBotを入れる人の立場に立ってシナリオを考えようとか、色々な経験ができてとても楽しかったです。
作成背景やサービスについてはここでは語れないですが、ただのBotではなく、AIを利用した感情分析を入れてみたり、対話AIを追加してみたりをしていました。
**対話AIについてはこちらの記事**にまとめていますので参考にして見てください。
また、今回は紹介しませんでしたが**LIFF(LINE Front-end Framework)**というプラットーフォームを機能に
組み込んだりもしました。
LINE上でwebアプリを開けるので、Formをコーディングをするのも地味に楽しかったです。
普段頻繁に利用しているLINEだからこそ、こんなUXだったら良いよねというのが思いつき、それをすぐに近くの人に利用してもらうことでフィードバックを貰うことができたのがとても良かったです。
実は、AWSで開発する前はしっかりDB設計をしてPosgre+Node+herokuで開発をしており、そこでも山あり谷ありだったのですが、それは別の機会に。
参考文献等(メモしている限り)
LINE Bot を AWSを使ってシステム構築してみた。
LINE Messaging API
LINE Front-end Framework
DynamoDB の基礎知識とまとめ
AWS Lambda超入門
parse・stringifyメソッドの使い方
LINEのMessaging APIを使って投稿(push)と返信(reply)を使ってみる。
LINE Messaging API と AWS Lambda で LINE BOT を作ってみた
AWS LambdaとLINE BOT APIで友達になったユーザーをDynamoDBで管理する
aws lambdaとapi gatewayで linebotを作成する
LINE BOTをNode.jsで作る
Talk API
日本語極性判定を作って公開した