こんにちは。SCSK株式会社の佐藤優音です!
この記事は「2025 Japan AWS Jr. Chanpions 夏のQiitaリレー」の記念すべき10日目の記事です!
過去の投稿(リンク集)はこちらからご覧ください!
https://qiita.com/natsumi_a/items/80539843482fed4cd648?utm_campaign=post_article&utm_medium=twitter&utm_source=twitter_share
この記事はこんな方におすすめ!
- 1分でも早くブログを書き終えて寝たい方(私も深夜に執筆しておりますが…)
- AWSの複数サービスを掛け合わせてシステムを作ってみたい初心者の方
- コーディングは最小限で、AIを使った自動化を体験したい方
所要時間: 2〜3時間で完成します!
難易度: AWS初心者〜中級者
前提知識: 基本的なAWSの知識があると良いですが、コピペでもOK
🔥 この記事のGOAL
S3に画像をドラッグ&ドロップするだけで、以下が全自動で完了します!
# 投稿した画像: hachioji-ramen.jpg
# ↓ 1分後、AIが自動生成 ↓
ImageName: hachioji-ramen.jpg
AltText: 熱々のスープに浮かぶ中華麺と、チャーシュー、ネギが盛り付けられた美味しそうな八王子ラーメン
DetectedLabels: Food, Noodle, Ramen, Bowl, Soup, Dish
これを使えば、今までやっていたように画像1枚1枚にキャプションを付ける必要はなくなります!
💡 なぜ作ったのか:3つの理由
1. とにかく面倒だった(切実)
やっぱりブログの価値はコンテンツ!なのに、altタグをつけるような「作業」に時間を奪われるのってストレスですよね…?
1つのブログに対して10枚画像を付けたなら、その分altタグを付けなければいけないなんて面倒ですよね…?
2. SEOとアクセシビリティをサボりたくなかった
せっかく書いたブログを多くの人に見てほしい!でもSEO対策アクセシビリティ対応をする時間がないという方も少なくないのでは…?
3. 初心者の方でも簡単に構築できるシステムを作ってみたかった
AIサービスを触ってみたいという方も多いと思いますが、システムに組み込むのは少々ハードルが高いもの…。
「目で見るAI(画像認識)」と「脳で考えるAI
(文章生成)」の最強コンビを、簡単なセットアップでつくってみたくなりました!
🏗️ システム構成
今回構築するシステムは、面倒なサーバー管理が一切不要なサーバーレス構成です。
ざっくりとした構成図は以下のようになっています。
今回は初心者の方でも短い時間で簡単にサービスどうしの連携を理解してもらいたいという狙いから、データが格納されたDynamoDBを直接参照するような形にしています。
もちろんフロントエンドを開発することでアップロードから結果の取得まで同一画面で行うことができるので利便性は上がりますね!
サービス | 役割 |
---|---|
Amazon S3 | 画像アップロード先 |
AWS Lambda | 処理実行 |
Amazon Rekognition | 画像認識 |
Amazon Bedrock | 文章生成 |
Amazon DynamoDB | データ保存 |
重要: 東京リージョン (ap-northeast-1
) での構築を前提としています
🚀 システムを構築してみよう
Step 1: DynamoDBテーブルの作成
まずは出力結果を格納するDynamoDBをテーブルを作成していきます。
手順は以下の通りですが、CLIからも作成することが可能です!
- DynamoDBコンソールを開く
- 「テーブルを作成」をクリック
- 以下を設定:
- テーブル名:
ImageAltTags
- パーティションキー:
ImageName
(文字列)
- テーブル名:
- 「テーブルを作成」
AWS CLIでの作成例:
aws dynamodb create-table \
--table-name ImageAltTags \
--attribute-definitions AttributeName=ImageName,AttributeType=S \
--key-schema AttributeName=ImageName,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
Step 2: IAMロールの作成
セキュリティ重要: 最小権限の原則に従い、必要な権限のみを付与しましょう!
続いてIAMロールを作成していきます。計5ロール付与できていればOKです。
必要な管理ポリシー:
AWSLambdaBasicExecutionRole(Lambdaを実行を許可するロール)
AmazonRekognitionReadOnlyAccess(Rekognitionの読み取りのみを許可するロール)
AmazonDynamoDBFullAccess_v2(DynamoDBへのアクセスを許可するロール)
AmazonS3ReadOnlyAccess(S3の読み取りのみを許可するロール)
加えて、Bedrock実行用にインラインポリシーも追加しておきましょう。
Bedrock用のインラインポリシー:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "bedrock:InvokeModel",
"Resource": "*"
}
]
}
Step 3: Lambda関数の作成
続いて本システムの司令塔ともいえるLambda関数を作成していきます。
- 関数名:
GenerateAltTagFunction
- ランタイム:
Python 3.13
- 実行ロール: 上記で作成したロール
- タイムアウト: 1分に延長(重要!)
ソースコード:
import json
import boto3
import urllib.parse
# boto3クライアントの初期化
s3_client = boto3.client('s3')
rekognition_client = boto3.client('rekognition')
bedrock_runtime_client = boto3.client('bedrock-runtime', region_name='ap-northeast-1')
dynamodb_resource = boto3.resource('dynamodb')
table = dynamodb_resource.Table('ImageAltTags')
def lambda_handler(event, context):
# S3イベントからバケット名とファイル名を取得
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
try:
# 1. Amazon Rekognitionで画像からラベルを検出
rek_response = rekognition_client.detect_labels(
Image={'S3Object': {'Bucket': bucket, 'Name': key}},
MaxLabels=10,
MinConfidence=80
)
labels = [label['Name'] for label in rek_response['Labels']]
labels_string = ", ".join(labels)
# 2. Amazon Bedrockでaltタグを生成
model_id = 'anthropic.claude-3-5-sonnet-20240620-v1:0'
prompt = f"""
あなたはプロのWebコンテンツライターです。SEOとアクセシビリティの重要性を深く理解しています。
画像の内容を表す以下のキーワード群を元に、その画像に最適なalt属性用の説明文を1つだけ生成してください。
説明文は、具体的で、画像に示されているものが読者にはっきり伝わるように、かつ簡潔に記述してください。
キーワード: {labels_string}
alt説明文:
"""
bedrock_request_body = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 200,
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": prompt}]
}
]
}
bedrock_response = bedrock_runtime_client.invoke_model(
body=json.dumps(bedrock_request_body), modelId=model_id
)
response_body = json.loads(bedrock_response.get('body').read())
alt_text = response_body.get('content')[0].get('text').strip()
# 3. 結果をDynamoDBに保存
table.put_item(
Item={
'ImageName': key,
'AltText': alt_text,
'DetectedLabels': labels_string
}
)
return {'statusCode': 200, 'body': json.dumps('Successfully generated alt tag.')}
except Exception as e:
print(f"Error processing file {key} from bucket {bucket}. Error: {e}")
raise e
プロンプトエンジニアリングのポイント:
あなたはプロのWebコンテンツライターです。
と役割を与えることで、AIの性能が向上します。
ここを書き換えることで、自分だけのAIにカスタマイズ可能!
Step 4: S3バケットとイベント通知の設定
最後に、画像を格納するS3バケットの設定をLambdaへの通知を設定していきましょう。
- S3バケットを作成(例:
my-alt-tag-generator-20250715
) - バケットの「プロパティ」タブを開く
- 「イベント通知」→「イベント通知を作成」
- 以下を設定:
- イベントタイプ: 「すべてのオブジェクト作成イベント」
- 送信先: 「Lambda関数」
- Lambda関数:
GenerateAltTagFunction
🎉 これで完成!早速画像をアップロードして試してみましょう!
🐛 トラブルシューティング:よくあるエラー集
開発時によくあるエラーをおさらいしておきましょう。
迷った時にはとにかくCloudWatchを確認すること!
そこにエラーが吐き出されていなければLambda自体が正しく呼び出されていない可能性が…。
エラーがなかったとしてもトラブルシューティングの対象を絞り込めるという点では、CloudWatchを確認する価値がありそうです。
エラー1: InvalidS3ObjectException
原因: LambdaがS3オブジェクトを読み取る権限がない
解決: IAMロールに AmazonS3ReadOnlyAccess を追加
エラー2: ValidationException
(Bedrock)
原因: 指定したモデルが利用できない、またはリージョンが間違っている
解決: 東京リージョンで利用可能なモデルに変更
エラー3: ResourceNotFoundException
(DynamoDB)
原因: テーブル名が間違っている、またはテーブルが存在しない
解決: DynamoDBコンソールでテーブルの存在を確認
デバッグのコツ: CloudWatch Logsで詳細なエラーログをチェックしよう
今後の展望
このシステムをベースにして、次のような拡張も可能です!
🔄 WordPress連携
- WordPress REST APIを使って記事に自動でaltタグを設定
- 既存記事の画像にも一括でaltタグを適用
🌐 多言語対応
- 英語、中国語、韓国語でのaltタグ生成
- 国際的なWebサイトでの活用
📱 SNS連携
- 生成完了をSlack/Teamsに通知
- 生成されたaltタグをTwitterで共有
🎨 画像解析の高度化
- 感情分析を追加(「楽しそうな」「落ち着いた」など)
- ブランドカラーの検出と説明への反映
コスト試算→月1000枚処理しても激安!
月1000枚の画像処理をするケースで金額を概算してみました。
ブログに写真を多く使用される方にはかなりお勧めできます!
サービス | 使用量 | 単価 | 月額コスト |
---|---|---|---|
S3 | 1GB保存 | $0.025/GB | $0.025 |
Lambda | 1000回実行 | $0.0000002/回 | $0.0002 |
Rekognition | 1000枚解析 | $0.001/枚 | $1.00 |
Bedrock | 1000回呼び出し | $0.003/1K token | $3.00 |
DynamoDB | 1000回書き込み | $0.00000125/回 | $0.00125 |
月額合計: 約$4.03(約600円)
🎯 まとめ:面倒ごとはテクノロジーに任せちゃおう
このシステムにより実現できること:
✅ 生産性向上: altタグ作成時間をゼロに短縮
✅ 品質向上: AIが生成する自然で読みやすい説明文
✅ SEO効果: 検索エンジンが理解しやすい適切なalt属性
✅ アクセシビリティ: 視覚障害者の方への情報提供
✅ 運用コスト: 月数百円程度の低コスト運用
NEXT STEP:
まずは小さな画像から試してみて、徐々に本格運用に移行することをおすすめします!
写真はうまく反応できますが、システム構成図やグラフなどはまだ読み込むことが難しい状態です。
スクリーンショットなどを多く貼るような記事では改善の余地があるかもしれません。
慣れてきたら、上記の発展アイデアにもチャレンジしてみてください!
この記事が、あなたのブログ運営効率化の参考になれば幸いです!
ぜひ皆さんも試してみてください!