😈

「最新のAIトレンド教えて」とLINEで聞くだけ!専属AIトレンドBotをAWSサーバレスで作った話

に公開

はじめに

「最近のAIの進化、早すぎて追いきれない...」「海外の主要な技術ブログを毎日チェックするのは大変...」

AI開発に携わる多くの人が、そんな悩みを抱えているのではないでしょうか。私もその一人でした。そこで、「LINEで質問するだけで、海外の最新AIトレンドを調べて要約してくれる、自分だけの専属リサーチャーがいたら最高なのでは?」と思い立ち、AIエージェントBotの開発を始めました。

この記事では、そのBot「Line AI Trend Bot」を、AWSのサーバレス技術とTerraformを使って構築した際の技術的な道のり、直面した課題、そしてその解決策を共有します。

会話イメージ

システム構成:なぜSQSが必要だったのか?

このBotの心臓部は、LINEの厳しいタイムアウト要件と、時間のかかるAI処理をどう両立させるか、という点にありました。

LINEのWebhookは、リクエストを送信してから数秒以内に応答がないとタイムアウトエラーになってしまいます。一方、Web検索とAIによる要約は、数十秒かかることも珍しくありません。

この課題を解決するために採用したのが、SQS (Simple Queue Service) を使った非同期処理アーキテクチャです。

    A[LINEユーザー] --> B[LINE Platform];
    B --> C[API Gateway];
    C --> D[APIハンドラLambda];
    D -- 1. 即座にタスクを投入 -- E[SQSキュー];
    D -- 2. すぐに200 OKを返す --> C;
    E -- 3. キューをトリガーに起動 --> F[ワーカーLambda<br>(AIエージェント)];
    F -- 4. 時間のかかる処理<br>(Web検索 & AI要約) --> F;
    F -- 5. Push APIで結果を送信 --> B;
  1. APIハンドラLambda (line_bot_api_handler.py):

    • LINEからのリクエストを受け取ると、処理内容をSQSキューに投げるだけですぐに200 OKを返します。これにより、LINEのタイムアウトを確実に回避します。
  2. ワーカーLambda (worker.py):

    • SQSキューにタスクが入ると起動し、Web検索、記事のスクレイピング、AIによる要約といった時間のかかる処理をじっくり行います。
    • 処理が完了したら、LINEのPush APIを使って、好きなタイミングでユーザーに結果を返信します。

この構成により、ユーザー体験と重いバックエンド処理を完全に分離することができました。

実装のキーポイント

1. AIエージェントの思考プロセス

ワーカーLambdaは、単なるプログラムではなく、目的を達成するために複数のツールを使いこなす「AIエージェント」として設計しました。

src/agent/search.py
def search_and_summarize(user_query):
    # Step 1: ユーザーの日本語の質問から、英語の検索キーワードを生成
    search_keywords = generate_keywords_with_gpt(user_query)

    # Step 2: 質の高い情報源に絞ってWeb検索
    # (Hugging Face Blog, OpenAI Blog, Google AI Blogなど)
    links = search_priority_sites(search_keywords)

    # Step 3: 記事本文をスクレイピング
    text = scrape_articles(links)

    # Step 4: 専門家として本文を要約
    summary = summarize_with_gpt(text, user_query)

    return summary

「あなたは優秀なAIリサーチャーです」と役割(ペルソナ)を与えることで、生成される要約の質と一貫性を向上させています。

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "あなたは優秀なAIリサーチャーです。以下の英語のテキストを、AIの最新動行として重要なポイントを抽出し、専門家の視点から日本語で簡潔に要約してください。"},
        {"role": "user", "content": f"元の質問: {user_query}\n\nテキスト:\n{chunk}"}
    ]
)

2. IaCによるインフラ管理

AWSリソースはすべてTerraformでコード化しました。これにより、インフラの構成変更や再現が容易になります。

terraform/main.tf
# SQSキューとワーカーLambdaを接続
resource "aws_lambda_event_source_mapping" "sqs_trigger" {
  event_source_arn = aws_sqs_queue.line_bot_queue.arn
  function_name    = aws_lambda_function.line_bot_worker.arn
}

このaws_lambda_event_source_mappingが、SQSとワーカーLambdaを繋ぐ重要な役割を担っています。

開発でハマった3つの落とし穴と解決策

1. Lambdaのメモリ不足による「サイレントクラッシュ」

当初、Lambdaのメモリをデフォルトの128MBで動かしていましたが、llama-indexのようなライブラリを読み込むと、ログに何も出力されずにLambdaがクラッシュする現象に悩まされました。
解決策: メモリを2048MBに増強。Lambdaではメモリサイズに応じてCPU性能も向上するため、これがコールドスタート時間の短縮にも繋がり、一石二鳥でした。

2. Dockerイメージの更新がLambdaに反映されない問題

Pythonコードを修正し、新しいDockerイメージをECRにプッシュしても、terraform applyでは「No changes」と表示され、Lambda関数が更新されませんでした。
原因: Terraformはimage_uri = "...:latest"という文字列しか見ておらず、:latestタグが指すイメージの中身が変わったことを検知できないためです。
解決策: コード更新時はterraform applyを使わず、AWS CLIで直接Lambda関数を更新するコマンドを叩くようにデプロイフローを改善しました。

# Pythonコードを修正した場合、このコマンドでLambdaを強制的に更新
aws lambda update-function-code \
  --function-name line-bot-worker-function \
  --image-uri <ECRのイメージURI>:latest

3. SQSトリガーが動かない「権限の罠」

SQSにメッセージは入るのに、一向にワーカーLambdaが起動しない時期がありました。
原因: ワーカーLambdaのIAMロールに、SQSからメッセージを読み取るための権限が不足していました。
解決策: AWSが用意している管理ポリシーAWSLambdaSQSQueueExecutionRoleをワーカーのIAMロールにアタッチすることで解決しました。

まとめと今後の展望

海外のAIトレンドをLINEで手軽に追える、自分だけのAIリサーチャーBotを構築することができました。SQSを使った非同期アーキテクチャや、IaC、Dockerといったモダンな技術スタックに触れる良い機会にもなりました。

今後は、

  • 検索対象サイトの追加
  • 回答精度の向上
  • 過去の会話履歴を記憶させ、より文脈に沿った回答を生成する機能
  • LangChain Agentsのような、より高度なエージェントフレームワークの導入

などを検討していきたいです。


リポジトリはこちらで公開しています: GitHub - (Line-AI-Trend-Bot)

Discussion