AWSを活用してLINEチャットボットを作ってみた!③
こんにちは、宮内です。
前回はAmazon Lexを使用して、到着通知サービスの利用者を登録するチャットボットを作成しました。
最終回となる今回は、Lambdaとチャットボットを連携させ、LINEからサービスを動かしてみたいと思います。
今回は、第1回目と第2回目の記事で作成したリソースを使用します。
それぞれの記事は、以下のリンクから是非ご覧ください。
今回の目標
サービス構成図
今回のサービス構成図ですが、利用者の登録機能については以下の通りです。
これまでの記事で作成したリソースも修正して使用します。

また、到着通知の機能については以下の通りです。
ラズパイに接続したカメラで画像を撮影し、IoT Coreを経由してLambda処理を実行します。
撮影した画像に対してRekognitionで画像分析を行い、分析結果に紐づく利用者の情報をDynamoDBから取得し、LINEで到着通知を行います。

既存リソースの変更点について
第1回目の記事で作成したLINEボットとLambdaについて、以下の変更を行います。
●LINEボット : リッチメニューを追加し、サービスを利用しやすくする
●Lambda : LINEで受信したメッセージをチャットボットへ連携し、対話ができるように修正する
新規リソースの実装について
新規で作成するリソースとしては、以下2つのLambdaとなります。
●サービス利用者を登録するLambda : フルフィルメント処理(ボットとの対話完了後)で使用する
●到着通知の機能を実行するLambda : Eメール通知からLINE通知に変更する
※利用者情報の登録先として使用するS3、DynamoDB、Rekognitionのリソース作成の手順については割愛します。
既存リソースの変更
まずは第1回の記事で作成したLINEボットと、Lambda処理の修正をしましょう。
LINEボットの修正(リッチメニューを追加)
リッチメニューとは、LINEの公式アカウントのトーク画面に訪れた際に、画面の下に表示するメニューのことをいいます。
↓LINEでよくある、トーク画面に固定表示されるメニューのことです。

テキストを送信する以外にも、Webページへのリンクを設定したりできるので、提供するサービスへ簡単に誘導することができ、公式アカウントを活用する上では必須となる機能です。
リッチメニューの詳細については、以下のLINE Developersのページを参照ください。
developers.line.biz
リッチメニューの編集は、LINE Official Account Managerというサイトで行います。
まずは、LINE Developersのチャネル基本設定タブにある、LINE Official Account Managerのリンクをクリックします。

新しいタブでLINE Official Account Managerのページが開くので、左上のホームをクリックします。

左側のメニューバーにあるリッチメニューをクリックします。

画面下部にある作成ボタンをクリックします。

作成するリッチメニューの設定を行います。
まずは、表示設定のタイトルと表示期間を入力しましょう(両方ともに必須入力です)。
メニューバーのテキスト、メニューのデフォルト表示は初期値をそのまま設定します。

次に、リッチメニューのボタン配置と画像を設定します。
まずはボタンの配置を決めるために、テンプレートを選択をクリックします。

メニューは大小2つのサイズが用意されていて、設定するコンテンツの数に応じて決定します。
今回は、利用者の登録機能と、照会機能の2つを設定するため、ボタンを2つ持っているテンプレートにします。
設定するテンプレートをクリックしたら、選択ボタンをクリックします。

次はメニューで表示する画像をアップロード、または作成します。
今回はあらかじめ用意しておいた画像を使用するため、画像をアップロードをクリックします。
※画像を作成する際は、右上のデザインガイドをクリックして、テンプレートファイルをダウンロードするとスムーズに作業ができます。

メニューに設定する画像を選択、またはドラッグ&ドロップします。
画像を選択すると自動的にアップロードが始まりますが、画面下の記載の通り、画像のサイズや容量には制限があります。
制限を超えた場合はエラーとなるので注意しましょう。

画像がアップロードできたら、次は各ボタンのアクションを設定します。

今回は、テキストメッセージをLambdaへ送信するため、タイプはテキストを設定します。
送信するテキストについては、Amazon Lexのチャットボットを起動するためのキーワードや、Lambda処理で使用するキーワードを設定します。
登録機能を実行するボタンには「createUser」、照会機能を実行するボタンには「confirmUser」をそれぞれ設定します。
設定が完了したら、保存ボタンをクリックします。

以上でリッチメニューの編集は完了です。

変更は即時反映されるので、LINEのトーク画面にリッチメニューが表示されていることが確認できます。

更にボタンをタップすると、設定したテキストが送信できていることを確認できます。
Lambda側はオウム返しをするだけの処理となっているので、次はLambda処理を修正します。

Lambda処理の修正(チャットボットとの連携)
Lambda処理について、既にテキストを受信することができる状態なので、受け取ったメッセージに応じた条件分岐と処理を次のように実装します。

コードを全て記載すると非常に長くなってしまうため、Amazon Lexとの連携方法について、コードを抜粋して説明を行います。
Amazon Lexとの対話処理
まずは、LambdaとLexを連携するAPI(recognize_text)について解説します。
# Lexクライアントを作成
lex_client = boto3.client('lexv2-runtime')
# Amazon Lexのボットにメッセージ送信
lex_response = lex_client.recognize_text(
botId = CREATE_USER_BOT_ID,
botAliasId = CREATE_USER_BOT_ALIAS,
localeId = CREATE_USER_BOT_LOCALE,
sessionId = /* LINEのユーザID */,
text = /* LINEから受信したメッセージ */
)
# ボットの返答をLINEにリプライ
for message in lex_response['messages']:
LINE_BOT_API.reply_message(
replyToken,
TextSendMessage(text=message['content'])
)
Amazon Lexと連携するために、Amazon Lex Runtime V2を使用してクライアントを作成します。
これにより、ボットへのメッセージ送信やセッション管理のAPIが実行可能となります。
Amazon Lexのボットへメッセージを送信するには、recognize_textというAPIを実行します。
このAPIの実行パラメータは以下の通りです。
- botId : 呼び出すボットを特定するID。
- botAliasId : 呼び出すボットのバージョンを特定するID。
- localeId : 呼び出すボットで使用する言語を指定するID。日本語の場合は「ja_JP」を設定する。
- sessionId : チャットのセッションを管理するID。今回は、LINEのユーザIDを設定する。
- text : ボットに送信するテキスト。今回は、LINEから受信したメッセージを設定する。
botIdとbotAliasIdについては、Lexのコンソール画面から確認して設定しましょう。

また、APIを実行した際にAmazon Lexのボットに対してセッションが自動的に生成、更新されます。
セッション情報には、各スロットにユーザが入力した値のほか、対話の進捗状況などが含まれています。
ユーザの入力に対するボットの応答は、レスポンスデータのmessagesの中に設定されているので、そのメッセージをLINEのリプライメッセージとして使用します。
新規リソースの実装
今回はLambda処理を新規で2つ作成しますが、コードの全容や詳細は割愛して、実装の要点のみをまとめます。
利用者の登録処理(フルフィルメント処理)用のLambda
フルフィルメント処理のLambdaでは、チャットボットとの対話の結果を受け取って、S3やDynamoDB、Rekognitionへ利用者の情報を登録します。
各AWSリソースへの登録処理は過去のブログ記事でも解説しているので、対話の結果がLexからどのように渡されてくるのかについて説明します。
Amazon Lexから渡される情報としては、セッションIDの他にインテントの入力情報、セッションデータの詳細などが以下のようなJson形式で渡されてきます。
※全て載せると長すぎるので、一部抜粋しています。
Lambdaで使用する値は赤文字にしています。
{
"sessionId": /* LINEのユーザID */,
"interpretations": [
{
"intent": {
"slots": {
"userImageId": {
"value": {
...
"interpretedValue": /* 利用者の画像を送信した時のメッセージID */
}
},
"userName": {
"value": {
...
"interpretedValue": /* 利用者の名前 */
}
}
},
…
},
"nluConfidence": 1
},
...
}
また、登録処理の途中で何らかのエラーが起きた場合、ユーザへの通知はセッションIDに設定したLINEのユーザIDを使用して、プッシュメッセージで通知します。
Amazon Lex側のフルフィルメント対応
フルフィルメント処理用のLambdaを作成したら、チャットボットと連携させます。
Amazon Lexのコンソール画面から、
ボット >(連携対象のボット)> エイリアス >(連携対象のエイリアス名)
と進み、言語の項目にある Japanese(Japan) のリンクをクリックします。

ボットと連携させるLambdaを選択する画面が開くので、フルフィルメント用に作成したLambdaを選択します。
バージョンを「$LATEST」にしておくと、Lambdaを再デプロイした場合でも、修正後のソースで処理をしてくれます。
Lambdaとバージョンを選択したら、保存をクリックします。

次にフルフィルメント処理でLambdaを使用するための設定を行います。
前回作成したインテント「createUserIntent」のコンソール画面に入り、フルフィルメント項目内にある 詳細オプション をクリックします。

「フルフィルメントにLambda関数を使用」にチェックを入れ、更新オプションをクリックします。

最後に、インテントの保存と構築を実行して対応完了です!

到着通知のメッセージについて(Flex Messageの活用)
到着通知では、カメラで撮影した画像の他に、日時などのテキストも一緒に送信します。
画像とテキストを個別に送信しても良いのですが、せっかくLINEを活用しているので、Flex Message(フレックスメッセージ)を使ってみたいと思います。
Flex Messageとは、画像やテキストを自由に配置して送信できるメッセージです。

Flex Messageは、表示するコンテンツやレイアウトの情報をJson形式のデータで保持しているので、メッセージの元となるJsonを事前に作る必要があります。
ちなみに上記の通知メッセージでも、以下のような約80行のコードを書く必要があります。
{
"type": "bubble",
"altText": "Flex Message",
"contents": {{
"type": "bubble",
"hero": {{
"type": "image",
"url": "{filePath}",
"size": "full",
"aspectRatio": "1:1",
"aspectMode": "cover",
"action": {{
…
}}
}},
"body": {{
"type": "box",
"layout": "vertical",
"contents": [
{{
"type": "text",
"text": "{name}さん到着のお知らせ",
"weight": "bold",
"size": "md"
}},
(中略)
]
}}
}}
}
これをゼロから作ったり、手作業で作ったりするのは…さすがにやりたくないですよね。
そこで活用するのが、LINE公式が提供しているFlex Message Simulatorです(2022年7月現在)。
Flex Message SimulatorのURLはこちらです → https://developers.line.biz/flex-simulator/

Flex Message SimulatorはLINE Developersが提供するサービスの1つで、ブラウザ上でFlex Messageを作ることができるだけではなく、Jsonのコード作成まで行ってくれる非常に便利なサービスです。
今回は、Jsonデータ中の画像ファイルのパス、人物名、到着日時などの利用者に関わる情報を置換フィールドに変更し、画像の分析結果に応じて各フィールドを置換する作りにしました。

それでは、実際に作成したサービスをLINEから実行してみましょう!
サービスの検証
まずは利用者の照会を行ってみます。
「登録内容を確認」をタップしてみると、まだ利用者登録を行っていないので、登録情報がありませんと返ってきました。

それでは利用者の登録を行ってみましょう。
リッチメニューの「利用者を登録」をタップすると、利用者の画像送信が求められます。
Lambda側で、受信した画像に顔が写っているか判定するロジックを入れておいたので、顔が写っていない画像を送ってみると再送信を求められます。

ちなみに、顔が写っているかどうかの判定はRekognitionの顔検出用のAPI(detectFaces)で行っています。
顔が検出できなかった場合は、Amazon Lex側にデータを連携しないので、対話が進むことはありません。
顔が検出できた場合は利用者の名前を入力し、登録確認の後に登録処理を行います。
登録確認で「いいえ」と入力した場合は、登録処理が行なわれず、セッション情報もそのまま削除されます。

利用者を登録した後に照会機能を実行すると、登録したユーザの情報が表示されました。
ユーザの照会機能でもFlex Messageを使用しています。

最後に到着通知の検証です。
ラズパイに接続したカメラで撮影を行うと…無事、到着のお知らせが送られてきました!

さいごに
今回は、Amazon Lexを活用したチャットボットをLINEと連携させ、到着通知サービスをLINEから利用できるように対応しました。
Amazon Lex V2は昨年にリリースされたばかりのサービスでドキュメントが少なく、V1とは仕様が大きく異なっていたので、使い始めの頃は思った通りに進まないことが多かったですが、何とか形にすることができました。
Amazon Lexは音声チャットにも対応しているとのことなので、こちらも是非試してみたいところです。