🔰

【ハンズオン】 LINE Bot つくってみた!

2024/09/16に公開

はじめに

Udemyで以下の講座を購入しやってみました。

Python と AWS で始める!! 感情分析 AI を使った実践的 LINE Bot 開発入門

わたしについて

  • AWSの認定資格は所持しているものの、業務経験なし
  • 現在は主にヘルプデスク業務に従事している。

開発するLINE Bot

  • オウム返し Line Bot
  • 感情分析AI Line Bot(送った画像に写っている人の顔を分析してくれる。)

使用したAWSサービス

  • SAM
  • Lambda
  • API Gateway
  • Rekognition (DetectFaces)

やってみた感想

  • 開発環境の準備からSAMのデプロイまで一通り学べる初心者におすすめのコースでした!
  • ステップアップのヒントとして、AWS、LINE Messaging APIのドキュメントの見方を紹介されていたのがとても参考になりました。

"感情分析AI Line Bot"を少しカスタムしてみた

講座では、"感情分析AI Line Bot"を最後まで作ると感情分析結果によって、”いい笑顔ですね”・”ぼちぼちですね”と返信するようになります。
カスタム前

複数人に対応させてもっと詳しい感情とその信頼度、さらに分析した方の推定年齢も返答するようにカスタムしてみました。
(ChatGPTをフル活用しました。ただコピペするだけではなく各コードの理解もしっかり行なっております!)

Rekognition DetectFacesが返答してくれる感情
"HAPPY・SAD・ANGRY・CONFUSED・DISGUSTED・SURPRISED・CALM・FEAR"
参考:イメージ内の顔の検出
カスタム後

import os
import boto3
import math

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage, ImageMessage
)

# LINE Bot API の認証情報を取得して、ハンドラーを作成
handler = WebhookHandler(os.getenv('LINE_CHANNEL_SECRET'))
line_bot_api = LineBotApi(os.getenv('LINE_CHANNEL_ACCESS_TOKEN'))

# AWS Rekognition クライアントを作成
client = boto3.client('rekognition') 

# 感情タイプの英語から日本語への翻訳マッピング
emotion_translation = {
    "HAPPY": "幸せ",
    "SAD": "悲しい",
    "ANGRY": "怒っている",
    "CONFUSED": "混乱している",
    "DISGUSTED": "嫌悪",
    "SURPRISED": "驚いている",
    "CALM": "落ち着いている",
    "FEAR": "恐れている"
}

def lambda_handler(event, context):
    # Lambda ハンドラー関数。LINE の Webhook イベントを処理します。
    headers = event["headers"]
    body = event["body"]

    # X-Line-Signature ヘッダー値を取得
    signature = headers['x-line-signature']

    # Webhook 本文を処理する
    handler.handle(body, signature)

    return {"statusCode": 200, "body": "OK"}

@handler.add(MessageEvent, message=ImageMessage)
def handle_content_message(event):
    # ユーザーから送られてきた画像を一時ファイルとして保存
    message_content = line_bot_api.get_message_content(event.message.id)
    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"])

    # 各顔の感情から最も信頼度が高い感情を選ぶ関数
    def most_confident_emotion(emotions):
        max_conf = 0
        result = ""
        for e in emotions:
            if max_conf < e["Confidence"]:
                max_conf = e["Confidence"]
                result = e["Type"]
        return result, max_conf

    # 顔の詳細情報を取得
    face_details = response.get('FaceDetails', [])
    if not face_details:
        # 顔が検出されない場合、エラーメッセージを送信
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text="画像内に顔が検出されませんでした。")
        )
        # 一時ファイルを削除
        os.remove(file_path)
        return

    # 各顔の分析結果を1つのメッセージにまとめる
    messages_text = "感情分析結果:\n"
    for i, face in enumerate(face_details):
        emotions = face.get('Emotions', [])
        most_confident_emotion_type, most_confident_confidence = most_confident_emotion(emotions)
        age_range = face.get('AgeRange', {})

        # 感情タイプを日本語に翻訳
        most_confident_emotion_type_japanese = emotion_translation.get(most_confident_emotion_type, "不明")
        
        # 信頼度を小数点1桁で切り上げ
        most_confident_confidence = math.ceil(most_confident_confidence * 10) / 10.0

        # 年齢範囲を取得
        age_range_low = age_range.get('Low', '不明')
        age_range_high = age_range.get('High', '不明')

        # 分析結果をメッセージに追加
        messages_text += (
            f"顔{i+1}:\n"
            f"  感情分析結果:{most_confident_emotion_type_japanese}\n"
            f"  結果の信頼度:{most_confident_confidence}%\n"
            f"  推定年齢:{age_range_low}歳~{age_range_high}歳\n\n"
        )

    # 1つのメッセージとして返信
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=messages_text.strip())
    )

    # 一時ファイルを削除
    os.remove(file_path)

おわりに

AWS,Pythonを使用しての構築が初めてでしたので学びの多いハンズオンでした。
次回はCI/CDについて学んでみようと思います。

Discussion