AWS Lambda と Amazon Rekognitionを利用した写真解析AIのLINE Botを作成してみました。
アプリとしては、AWS Lambdaを使ったサーバーレス構成になっているので、マネしやすいかなと思います。
LINE Developerの設定
LINE Developerのアカウント設定は、先に完了させておいてください。
「https://developers.line.biz/ja/」こちらから登録できます。
まずは、プロバイダーを作成していきます。
画面の「作成」ボタンを選択しましょう。
プロバイダー名は、任意で構いません。今回は、テスト用なので適当に付けました。
下記の画面に遷移できれば、プロバイダー登録は完了です。
このまま、チャネルの登録をしますので、「Messaging API」を選択しましょう。
新規チャネル作成画面が表示されるため、情報を入力していきます。
内容は、下記のような感じです。基本的には、ご自身の内容を入力していただければOKです。
- チャンネルの種類:Messaging API
- プロバイダー:先ほど作成したプロバイダー
- 会社・事業者の所在国・地域:日本
- チャネルアイコン:任意
- チャネル名:任意
- チャネル説明:任意
- 大業種:任意
- 小業種:任意
- メールアドレス:ご自身のメールアドレス
- プライバシーポリシーURL:任意
- サービス利用規約:任意
入力が完了したら、利用規約を読んで同意し、「作成」ボタンを選択します。
下記のようにチャネル設定画面が表示されたら、チャネル作成は完了です。
この画面の下のほうに、「チャネルシークレット」という文字列がありますが、後で利用しますのでメモしておきます。
次に、Message API設定に移動します。
ここのQRコードは、BOTを友達登録する際に利用できます。
この画面の下の方に、「チャネルアクセストークン」がありますので、これもメモしておきます。
応答メッセージも変更しておきます。
下記のように、「Webhook」のみを有効にしておきましょう。
これで、LINE Developerでの設定は、一旦終わりです。
あとで、Webhookの設定だけ別途行います。
AWS CLIの設定
ここは、AWSのユーザーは既に作成済みであることとして、解説しておきます。
aws configure
- AWS Access Key ID:AWSユーザーのアクセスキーID
- AWS Secret Access Key:AWSユーザーのシークレットアクセスキー
- Default region name:ap-northeast-1
- Default output format:json
設定内容はこれだけです。
AWS SAMで利用するソース等を作成
では、AWS SAMを利用してAWS LambdaとAmazon API Gatewayを作成していきます。
AWS SAMに関しては、今回は詳しく説明しません。
まずディレクトリ構成は、このような形でお願いします。
├─ src
│ ├─ mylinebot.py
│ └─ requirements.txt
└─ template.json
まずは、「mylinebot.py」になります。
Lambdaの処理の中身です。言語は、pythonを利用しています。
"""
Line Bot
"""
import os
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage, ImageMessage,
)
import boto3
handler = WebhookHandler(os.getenv('LINE_CHANNEL_SECRET'))
line_bot_api = LineBotApi(os.getenv('LINE_CHANNEL_ACCESS_TOKEN'))
client = boto3.client('rekognition')
def lambda_handler(event, context):
headers = event["headers"]
body = event["body"]
# get X-Line-Signature header value
signature = headers['x-line-signature']
# handle webhook body
handler.handle(body, signature)
return {"statusCode": 200, "body": "OK"}
def all_happy(result):
# 検出した顔がすべてHappyならTrueを返却
for detail in result["FaceDetails"]:
if most_confident_emotion(detail["Emotions"]) != "HAPPY":
return False
return True
def most_confident_emotion(emotions):
"""
複数ある感情のうち、もっとも確度が高い感情を返却する
:param emotions:
:return:
"""
max_conf = 0
result = ""
for e in emotions:
if max_conf < e["Confidence"]:
max_conf = e["Confidence"]
result = e["Type"]
return result
@handler.add(MessageEvent, message=TextMessage)
def handle_text_message(event):
""" TextMessage handler """
input_text = event.message.text
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=input_text))
@handler.add(MessageEvent, message=ImageMessage)
def handle_image_message(event):
# ユーザから送られてきた画像を一時ファイルとして保存
message_content = line_bot_api.get_message_content(event.message.id)
# lambdaで保存できるディレクトリは「/tmp」配下のみ
file_path = "/tmp/sent-image.jpg"
with open(file_path, 'wb') as fd:
for chunk in message_content.iter_content():
fd.write(chunk)
# Rekognition で感情分析
with open(file_path, 'rb') as fd:
sent_image_binary = fd.read()
response = client.detect_faces(Image={"Bytes": sent_image_binary}, Attributes=["ALL"])
print(response)
# 応答するメッセージを決める
if all_happy(response):
message = "みんな楽しそうですね!!"
else:
message = "もう一度写真を取り直してみてはいかがでしょうか。"
# 応答を返す
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=message)
)
# file_pathの画像を削除
os.remove(file_path)
@handler.add(MessageEvent, message=TextMessage)
は、Lineメッセージがテキストだった場合に、ハンドリングされます。@handler.add(MessageEvent, message=ImageMessage)
は、Lineメッセージで画像だった場合に、ハンドリングされます。
画像だった場合は、boto3を利用して、Amazon Rekognitionの「Detect Faces」を呼び出しています。
Detect Facesのレスポンスの「Emotions」が写真に写っている人達の感情情報が含まれる場所です。
この中に含まれる感情の一番確度が高い感情がHappyだった場合に、その人は笑顔だと判定しています。
すべての人がHappyだった場合、「みんな楽しそうですね!!」を返却、だれか一人でも笑顔ではない場合は、「写真を取り直してみてはいかがでしょうか。」と写真の撮り直しを提案しています。
次に「requirements.txt」です。
AWS Lambdaを作成するタイミングで、読み込みたいライブラリを列挙します。
今回は、line-bot-sdkとboto3だけでOKです。
line-bot-sdk
boto3
次に、「template.json」になります
この中身は詳しく説明しませんが、SAMで作成する「Amazon API Gateway」と「AWS Lambda」の情報が記載されています。
注意としては、最初にメモをしたLINEのチャネルアクセストークンとLINEのチャネルシークレットは、パラメータとしてSAMを実行するときに入力するようにしています。
これは、GITなどでソースを管理するときに、トークンが漏れないようにするためです。
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Parameters": {
"LineChannelAccessToken": {"Type": "String", "Description": "LINEのチャネルアクセストークン"},
"LineChannelSecret": {"Type": "String", "Description": "LINEのチャネルシークレット"}
},
"Resources": {
"EndPointFunction": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Runtime": "python3.9",
"CodeUri": "src",
"Handler": "mylinebot.lambda_handler",
"Environment": {"Variables": {
"LINE_CHANNEL_ACCESS_TOKEN": {"Ref": "LineChannelAccessToken"},
"LINE_CHANNEL_SECRET": {"Ref": "LineChannelSecret"}
}},
"Policies": [{"RekognitionDetectOnlyPolicy": {}}],
"Events": {
"API": {
"Type": "Api",
"Properties": {"Path": "/api_endpoint", "Method": "post"}
}
}
}
}
},
"Outputs": {
"ApiEndpointURL": {
"Description": "API Endpoint URL",
"Value": {"Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/${ServerlessRestApi.Stage}/api_endpoint"}
}
}
}
作成したソース等を使って、SAMを実行
sam buildコマンドで、AWS SAM テンプレートファイル、アプリケーションコード、および該当する言語固有のファイルと依存関係を処理させます。
sam build -t template.json
次に、sam buildで処理した結果を、sam deployでデプロイしていきます。
–guidedオプションを付与することで、ガイド付きのインタラクティブモードで実行できます。
また、この際に、LINEのアクセストークンなどParametersで設定した内容が聞かれるので、メモしていたものを記載するようにしてください。
sam deploy --guided
- Stack Name:任意の名前(LineBotの名前になります。)
- AWS Region:ap-northeast-1(ご自身のAWS RegionでOKです。)
- Parameter LineChannelAccessToken:「LINE Developerの設定」で取得したチャネルアクセストークン
- Parameter LineChanelSecret:「LINE Developerの設定」で取得したチャネルシークレット
- Confirm changes before deploy:N(デフォルト)
- Allow SAM CLI IAM creation:Y(デフォルト)
- EndPointFunction may not have authorization defined, Is this okay?:Y(テスト用のため)
- Save arguments to configuration file:Y(デフォルト)
- SAM configuration file:samconfig.toml(デフォルト)
- SAM configuration enviroment:default(デフォルト)
Outputsに下記が出力されているはず。
- Key:ApiEndpointURL
- Description:API Endpoint URL
- Value:https://xxxxx
LINE DeveloperのWebhookを修正
最後に、先ほどのValueをLINE Developersの「Messaging API設定>Webhook URL」に設定します。
Webhookの利用もONにしておきましょう。
動確してみる
では、最初のLINE DeveloperのQRコードからLINE BOTを友達登録して、画像を送信してみましょう。
少し恥ずかしいので、写真は隠しましたが、ちゃんとメッセージの出しわけもうまくいっていそうでした!
まとめ
AWS Lambda と Amazon Rekognitionを利用した写真解析AIのLINE Botを作成してみました。
Amazon Rekognitionはほかにもいろいろできそうなので、機会があればもう少し詳しく触ってみたいなと思います。