はじめに:Azure OpenAI から Bedrock へ、想定外の「選択の自由」
個人の趣味開発で Azure から AWS に移行することになり、Azure OpenAI Service と AI Foundry で動いていた生成AI アプリケーションを AWS に移植することになりました。「OpenAI の GPT モデルなら同じ」「REST API でラップすれば移植性が高い」という楽観的な見立てで始めた結果、本番環境で次々と予期しない問題が発生。Azure の「統合プラットフォーム」と AWS の「柔軟なサービス選択」の根本的な違いを痛感しました。
最初のローカル環境でのテストは順調でした。Bedrock の Claude でも推論リクエストは返ってくるし、PartyRock でノーコードアプリも作れます。
# これは普通に動く
import boto3
import json
bedrock = boto3.client('bedrock-runtime', region_name='us-east-1')
response = bedrock.invoke_model(
modelId='anthropic.claude-v2',
body=json.dumps({
"prompt": "\n\nHuman: Hello\n\nAssistant:",
"max_tokens_to_sample": 300
})
)
print(json.loads(response['body'].read()))
しかし実際に障害対応訓練で複雑な RAG パイプラインや高負荷のトラブルシューティングを始めた途端、問題が続出しました。
問題1:Bedrock と SageMaker と PartyRock のどれを選ぶべきか分からない
Azure では「Azure OpenAI Service(統合 API)」か「AI Foundry(開発環境)」の 2 択でシンプルでしたが、AWS は Bedrock(マネージド推論)、SageMaker(カスタムモデル)、PartyRock(ノーコード)と選択肢が多すぎて、初期設計で迷走しました。
問題2:Bedrock のモデル ID が「プロバイダー名.モデル名」形式で Azure と異なる
Azure OpenAI では gpt-4 とデプロイ名だけ指定すれば良かったのに、Bedrock は anthropic.claude-v2 や amazon.titan-text-express-v1 といったプロバイダー名込みの ID で、モデル切り替え時にコード変更が必要でした。
問題3:Bedrock のスロットリングが「モデルごと」で細かい制御が必要
Azure OpenAI では TPM(Tokens Per Minute)をデプロイ単位で設定できたのに、Bedrock はモデルごとにクォータがあり、複数モデルを使う場合の制御が複雑で、予期せぬスロットリングが発生しました。
問題4:PartyRock のログが「どこにあるか分からない」
AI Foundry では Azure Monitor に統合されているのに、PartyRock は「アプリ内の Activity タブ」と「CloudWatch Logs」の両方を確認する必要があり、障害時にログを探すのに 15 分かかりました。
問題5:Bedrock の Knowledge Base(RAG)が「Kendra や OpenSearch と別設定」
Azure OpenAI の「自分のデータで拡張」では Azure Cognitive Search との統合が自動だったのに、Bedrock Knowledge Base は S3 + ベクトルDB(OpenSearch/Kendra/Pinecone)を手動で連携する必要があり、初回構築で 2 時間かかりました。
問題6:Bedrock のモデル応答形式が「プロバイダーごとに異なる」
Azure OpenAI では統一された OpenAI API 形式だったのに、Bedrock は Claude(Anthropic)と Titan(Amazon)でリクエスト/レスポンスの JSON 構造が違い、マルチモデル対応のコードが複雑化しました。
これら全ての問題と向き合う中で、AWS の生成AI サービスは「柔軟だが、明示的な設定と理解が必要」という設計思想だと理解しました(気がします)。
Azure OpenAI / AI Foundry との設計の違い:統合 vs 選択の自由
Azure OpenAI Service / AI Foundry と AWS 生成AI サービスは、どちらも「生成AI の推論基盤」ですが、アーキテクチャと統合度が大きく異なります。
| 項目 | Azure (OpenAI / AI Foundry) | AWS (Bedrock / PartyRock / SageMaker) | 影響(実経験) |
|---|---|---|---|
| 選択肢の数 | 2 つ(OpenAI / AI Foundry) | 3 つ以上(Bedrock / PartyRock / SageMaker) | AWS は「どれを選ぶか」の判断が必要 |
| モデル ID | デプロイ名(gpt-4 など) | プロバイダー名.モデル名(anthropic.claude-v2) | モデル切り替え時にコード変更が必要 |
| API 形式 | 統一(OpenAI API 互換) | プロバイダーごとに異なる(Claude/Titan/Jurassic) | マルチモデル対応が複雑 |
| スロットリング制御 | TPM(Tokens Per Minute)をデプロイ単位で設定 | モデルごとにクォータ(Service Quotas で管理) | 複数モデル使用時の制御が複雑 |
| RAG 統合 | Azure Cognitive Search との自動統合 | S3 + ベクトルDB(OpenSearch/Kendra)を手動連携 | 初回構築に時間がかかる |
| ログ統合 | Azure Monitor 標準統合 | CloudWatch Logs(手動設定) | PartyRock はアプリ内 Activity + CloudWatch の両方を確認 |
| ノーコード開発 | AI Foundry(統合開発環境) | PartyRock(独立アプリビルダー) | PartyRock は Bedrock と独立した UI |
| プロンプト管理 | Prompt Flow(バージョン管理) | 手動管理(または Parameter Store) | プロンプトの履歴管理が手動 |
| 料金 | トークン課金 + デプロイ時間課金 | トークン課金のみ(オンデマンド) | Bedrock はデプロイ維持コストなし |
この表を見ると、Azure は「統合された開発体験」、AWS は「柔軟だが個別設定が必要」です。障害切り分けでは「どのサービスのどの設定が問題か」を理解する必要があります。
実際の障害シナリオ:Azure ユーザーがハマるポイント
シナリオA:Bedrock のスロットリングでリクエストが失敗する
背景
- Bedrock で Claude を使った推論 API を本番デプロイ
- Azure OpenAI では TPM 設定で問題なかったが、AWS では「429 Too Many Requests」が多発
問題検知
# アプリケーションログで 429 エラーを確認
aws logs tail /aws/lambda/genai-proxy --since 10m --filter-pattern "429"
# → "ThrottlingException: Rate exceeded for model anthropic.claude-v2"
# Azure OpenAI では TPM を 120K に設定していたが、Bedrock はどこで設定?
CloudWatch Metrics で確認
# Bedrock のスロットリングメトリクスを確認
aws cloudwatch get-metric-statistics \
--namespace AWS/Bedrock \
--metric-name ModelInvocationThrottles \
--dimensions Name=ModelId,Value=anthropic.claude-v2 \
--start-time $(Get-Date).ToUniversalTime().AddMinutes(-30).ToString("s") \
--end-time $(Get-Date).ToUniversalTime().ToString("s") \
--period 60 --statistics Sum
# → Sum: 45(30 分間で 45 回スロットリング)
# Invocations メトリクスを確認
aws cloudwatch get-metric-statistics \
--namespace AWS/Bedrock \
--metric-name Invocations \
--dimensions Name=ModelId,Value=anthropic.claude-v2 \
--period 60 --statistics Sum
# → Sum: 120(30 分間で 120 リクエスト = 4 リクエスト/分)
# 4 リクエスト/分でスロットリング?Azure では 120K TPM(約 2000 リクエスト/分)だったのに…
Service Quotas の確認
# Bedrock のクォータを確認
aws service-quotas list-service-quotas --service-code bedrock --query 'Quotas[?QuotaName==`Anthropic Claude V2 input tokens per minute`]'
# → {
# "QuotaName": "Anthropic Claude V2 input tokens per minute",
# "Value": 10000.0 ← 10K トークン/分(Azure の 120K TPM の 1/12!)
# }
# 原因判明:
# - Azure OpenAI では「デプロイ作成時に TPM を指定」してスケーリング
# - Bedrock では「リージョン&モデルごとのデフォルトクォータ」があり、明示的に引き上げが必要
クォータ引き上げリクエスト
# Service Quotas でクォータ引き上げをリクエスト
aws service-quotas request-service-quota-increase \
--service-code bedrock \
--quota-code L-xxxxxxxx \
--desired-value 100000
# → リクエスト ID: req-abc123(承認に 1~3 営業日かかる)
# 短期対応:リトライ+指数バックオフを実装
短期対処(コード修正)
# boto3 での指数バックオフ実装
import boto3
from botocore.config import Config
from botocore.exceptions import ClientError
import time
config = Config(
retries={
'max_attempts': 5,
'mode': 'adaptive' # 自動的に指数バックオフ
}
)
bedrock = boto3.client('bedrock-runtime', config=config)
def invoke_with_retry(model_id, body, max_retries=3):
for attempt in range(max_retries):
try:
response = bedrock.invoke_model(modelId=model_id, body=body)
return response
except ClientError as e:
if e.response['Error']['Code'] == 'ThrottlingException':
wait_time = (2 ** attempt) + (random.randint(0, 1000) / 1000)
print(f"Throttled. Retrying in {wait_time}s...")
time.sleep(wait_time)
else:
raise
raise Exception("Max retries exceeded")
学び
- Azure OpenAI では「デプロイ作成時に TPM を指定」してスケーリングするが、Bedrock は「リージョン&モデルごとのクォータ」を事前に引き上げる必要がある
- Bedrock のクォータは Service Quotas で確認・変更(承認に時間がかかる)
- 本番前に負荷テストでクォータを確認し、事前申請が必須
シナリオB:PartyRock のログが見つからない
背景
- PartyRock でノーコード RAG アプリを構築
- AI Foundry では Azure Monitor にログが統合されていたが、PartyRock では「どこにログがあるか分からない」
問題検知
# PartyRock アプリでエラーが発生しているが、ログが見つからない
# Azure AI Foundry では「Monitoring」タブでログが一元表示されていたのに…
# CloudWatch Logs で探してみる
aws logs describe-log-groups --log-group-name-prefix /aws/partyrock
# → [] ← Log Group が存在しない?
PartyRock コンソールで確認
# PartyRock アプリのコンソールを開く(ブラウザ)
# https://partyrock.aws/u/<user-id>/apps/<app-id>
# 「Activity」タブを開く
# → 最近の実行履歴が表示される
# → エラーが出ているセル:「Knowledge Base Search」が空返却
CloudWatch Logs の正しい場所
# PartyRock のログは /aws/partyrock ではなく、
# /aws/bedrock または /aws/lambda にある(アプリの構成による)
# Bedrock Knowledge Base のログを確認
aws logs describe-log-groups --log-group-name-prefix /aws/bedrock
# → /aws/bedrock/knowledge-bases/kb-abc123 が存在
# ログを確認
aws logs tail /aws/bedrock/knowledge-bases/kb-abc123 --since 10m
# → "S3 bucket not found: my-knowledge-base-bucket" ← S3 バケットが見つからない!
S3 バケットの確認
# Knowledge Base で指定した S3 バケットを確認
aws s3 ls s3://my-knowledge-base-bucket/
# → "An error occurred (NoSuchBucket) when calling the ListObjectsV2 operation: The specified bucket does not exist"
# 原因判明:
# - PartyRock で Knowledge Base を作成時、S3 バケット名を手動入力したが、タイポしていた
# - Azure AI Foundry では Azure Cognitive Search が自動作成されるが、
# PartyRock では S3 バケットを事前に作成して指定する必要がある
短期対処
# 正しい S3 バケットを作成
aws s3 mb s3://my-knowledge-base-bucket-correct
# ドキュメントをアップロード
aws s3 cp ./docs/ s3://my-knowledge-base-bucket-correct/ --recursive
# PartyRock の Knowledge Base 設定を更新(コンソールから手動)
# S3 URI: s3://my-knowledge-base-bucket-correct
検証
# PartyRock アプリで再度テスト
# 「Activity」タブで新しい実行を確認
# → Knowledge Base Search が結果を返すようになった
# CloudWatch Logs で確認
aws logs tail /aws/bedrock/knowledge-bases/kb-abc123 --since 5m
# → "Retrieved 5 documents from S3" ← 正常に動作
学び
- Azure AI Foundry では Azure Monitor にログが統合されているが、PartyRock は「アプリ内 Activity タブ」と「CloudWatch Logs」の両方を確認する必要がある
- PartyRock のログは
/aws/partyrockではなく、/aws/bedrockや/aws/lambdaにある - Knowledge Base は S3 バケットを事前に作成して指定する必要がある(Azure Cognitive Search のような自動作成はない)
シナリオC:Bedrock の Knowledge Base(RAG)検索が遅い
背景
- Bedrock Knowledge Base で RAG を構築
- Azure OpenAI の「自分のデータで拡張」では数秒で返ってきたが、Bedrock では 20 秒以上かかる
問題検知
# Lambda でプロキシした RAG API のレスポンスタイムを確認
aws logs tail /aws/lambda/rag-proxy --since 10m | Select-String "Duration"
# → Duration: 23456.78 ms(23 秒!)
# Azure OpenAI + Cognitive Search では 2~5 秒だったのに…
X-Ray でトレース確認
# Lambda の X-Ray トレースを確認
aws xray get-trace-summaries \
--start-time $(Get-Date).ToUniversalTime().AddMinutes(-15).ToString("s") \
--end-time $(Get-Date).ToUniversalTime().ToString("s") \
--filter-expression 'service("rag-proxy")'
# トレース詳細を取得
$traceId = "1-abc-def-ghi"
aws xray batch-get-traces --trace-ids $traceId
# → Lambda → Bedrock Knowledge Base: 18 秒
# → Bedrock Knowledge Base → OpenSearch: 17 秒 ← OpenSearch が遅い!
OpenSearch クラスターの確認
# OpenSearch のクラスター状態を確認
aws opensearch describe-domain --domain-name my-knowledge-base-domain
# → {
# "DomainStatus": {
# "ClusterConfig": {
# "InstanceType": "t3.small.search", ← 小さいインスタンス
# "InstanceCount": 1
# },
# "SearchInstanceCount": 1
# }
# }
# Azure Cognitive Search では「Standard S1」($250/月)を使っていた
# AWS では「t3.small.search」($25/月)を選んでしまった
OpenSearch のメトリクスを確認
# SearchRate(検索リクエスト数)を確認
aws cloudwatch get-metric-statistics \
--namespace AWS/ES \
--metric-name SearchRate \
--dimensions Name=DomainName,Value=my-knowledge-base-domain \
--start-time $(Get-Date).ToUniversalTime().AddMinutes(-30).ToString("s") \
--end-time $(Get-Date).ToUniversalTime().ToString("s") \
--period 60 --statistics Average
# → Average: 5(5 検索/分)
# SearchLatency を確認
aws cloudwatch get-metric-statistics \
--namespace AWS/ES \
--metric-name SearchLatency \
--dimensions Name=DomainName,Value=my-knowledge-base-domain \
--period 60 --statistics Average,Maximum
# → Average: 15000ms, Maximum: 22000ms ← 15~22 秒のレイテンシ!
短期対処(インスタンスタイプ変更)
# OpenSearch のインスタンスタイプを変更
aws opensearch update-domain-config \
--domain-name my-knowledge-base-domain \
--cluster-config InstanceType=r6g.large.search,InstanceCount=2
# → 変更には 15~30 分かかる
# 待機中に、検索クエリの最適化も検討
検証
# インスタンスタイプ変更後、再度テスト
aws logs tail /aws/lambda/rag-proxy --since 5m | Select-String "Duration"
# → Duration: 3456.78 ms(3.5 秒!)
# X-Ray で確認
# → Bedrock Knowledge Base → OpenSearch: 2 秒 ← 改善!
学び
- Azure Cognitive Search は「Standard S1」がデフォルト推奨だが、OpenSearch は「t3.small」でも起動できてしまう
- 本番環境では最低
r6g.large以上を推奨(メモリ最適化インスタンス) - OpenSearch のメトリクス(SearchLatency, CPUUtilization)を事前に監視する必要がある
シナリオD:Bedrock のモデル応答形式が Claude と Titan で異なる
背景
- マルチモデル対応のために Claude(Anthropic)と Titan(Amazon)を両方使う設計
- Azure OpenAI では統一 API だったが、Bedrock ではレスポンス形式が違う
問題検知
# Claude で動いていたコード
response = bedrock.invoke_model(
modelId='anthropic.claude-v2',
body=json.dumps({
"prompt": "\n\nHuman: Hello\n\nAssistant:",
"max_tokens_to_sample": 300
})
)
result = json.loads(response['body'].read())
print(result['completion']) # → 正常に動作
# Titan に切り替えると…
response = bedrock.invoke_model(
modelId='amazon.titan-text-express-v1',
body=json.dumps({
"prompt": "\n\nHuman: Hello\n\nAssistant:",
"max_tokens_to_sample": 300
})
)
result = json.loads(response['body'].read())
print(result['completion']) # → KeyError: 'completion' ← エラー!
レスポンス構造の確認
# Claude のレスポンス
# {
# "completion": " Hello! How can I assist you today?",
# "stop_reason": "stop_sequence"
# }
# Titan のレスポンス
# {
# "results": [
# {
# "outputText": "Hello! How can I assist you today?",
# "completionReason": "FINISH"
# }
# ]
# }
# 原因判明:
# - Claude: `completion` フィールド
# - Titan: `results[0].outputText` フィールド
# - Azure OpenAI では統一された `choices[0].text` だったのに…
抽象化レイヤーの実装
def invoke_bedrock_model(model_id, prompt, max_tokens=300):
"""Bedrock モデルの差異を吸収する抽象化レイヤー"""
# リクエストボディの構築(モデルごとに異なる)
if 'anthropic.claude' in model_id:
body = {
"prompt": f"\n\nHuman: {prompt}\n\nAssistant:",
"max_tokens_to_sample": max_tokens
}
elif 'amazon.titan' in model_id:
body = {
"inputText": prompt,
"textGenerationConfig": {
"maxTokenCount": max_tokens,
"temperature": 0.7
}
}
elif 'ai21.j2' in model_id:
body = {
"prompt": prompt,
"maxTokens": max_tokens
}
else:
raise ValueError(f"Unsupported model: {model_id}")
# 推論実行
response = bedrock.invoke_model(
modelId=model_id,
body=json.dumps(body)
)
result = json.loads(response['body'].read())
# レスポンスの抽出(モデルごとに異なる)
if 'anthropic.claude' in model_id:
return result['completion']
elif 'amazon.titan' in model_id:
return result['results'][0]['outputText']
elif 'ai21.j2' in model_id:
return result['completions'][0]['data']['text']
else:
raise ValueError(f"Unsupported model: {model_id}")
# 使用例
text = invoke_bedrock_model('anthropic.claude-v2', 'Hello')
print(text) # → 正常に動作
text = invoke_bedrock_model('amazon.titan-text-express-v1', 'Hello')
print(text) # → 正常に動作
長期対応(ライブラリ化)
# LangChain や LlamaIndex を使用して抽象化
from langchain.llms import Bedrock
# LangChain が内部でモデル差異を吸収
llm = Bedrock(model_id='anthropic.claude-v2')
response = llm('Hello')
llm = Bedrock(model_id='amazon.titan-text-express-v1')
response = llm('Hello')
# → 同じインターフェースで呼び出し可能
学び
- Azure OpenAI では統一された OpenAI API 形式だが、Bedrock はプロバイダーごとにリクエスト/レスポンス形式が異なる
- マルチモデル対応には抽象化レイヤーが必須(LangChain/LlamaIndex 推奨)
- モデル切り替え時は必ず API ドキュメントで形式を確認
AWS 生成AI サービスの優先順位:障害発生時の実戦順序
最初の 3 分:どこで何が起きているか把握
# 1. CloudWatch Metrics で Bedrock のエラー/スロットリングを確認
# Invocations(成功)
aws cloudwatch get-metric-statistics \
--namespace AWS/Bedrock \
--metric-name Invocations \
--dimensions Name=ModelId,Value=$MODEL_ID \
--start-time $(Get-Date).ToUniversalTime().AddMinutes(-15).ToString("s") \
--end-time $(Get-Date).ToUniversalTime().ToString("s") \
--period 60 --statistics Sum
# InvocationErrors(エラー)
aws cloudwatch get-metric-statistics \
--namespace AWS/Bedrock \
--metric-name InvocationErrors \
--dimensions Name=ModelId,Value=$MODEL_ID \
--period 60 --statistics Sum
# ModelInvocationThrottles(スロットリング)
aws cloudwatch get-metric-statistics \
--namespace AWS/Bedrock \
--metric-name ModelInvocationThrottles \
--dimensions Name=ModelId,Value=$MODEL_ID \
--period 60 --statistics Sum
# 2. CloudWatch Logs でエラーメッセージを確認
aws logs tail /aws/lambda/$FUNCTION_NAME --since 10m --filter-pattern "ERROR"
# 3. PartyRock の場合は Activity タブを確認
# ブラウザで https://partyrock.aws/u/<user-id>/apps/<app-id> を開く
次の 10 分:原因カテゴリ別切り分け
1) スロットリング → Service Quotas の確認
Bedrock はモデルごとにクォータがある。
# Service Quotas を確認
aws service-quotas list-service-quotas --service-code bedrock \
--query 'Quotas[?contains(QuotaName, `Claude`)]'
# クォータ引き上げリクエスト
aws service-quotas request-service-quota-increase \
--service-code bedrock \
--quota-code L-xxxxxxxx \
--desired-value 100000
対応案
- リトライ+指数バックオフを実装(boto3 の Config で設定可能)
- 複数リージョンに分散
- クォータ引き上げを事前申請
2) Knowledge Base 検索が遅い → OpenSearch/Kendra のパフォーマンス
ベクトルDB のインスタンスタイプやインデックスサイズを確認。
# OpenSearch のメトリクスを確認
aws cloudwatch get-metric-statistics \
--namespace AWS/ES \
--metric-name SearchLatency \
--dimensions Name=DomainName,Value=$DOMAIN_NAME \
--period 60 --statistics Average,Maximum
# CPUUtilization を確認
aws cloudwatch get-metric-statistics \
--namespace AWS/ES \
--metric-name CPUUtilization \
--dimensions Name=DomainName,Value=$DOMAIN_NAME \
--period 60 --statistics Average
対応案
- インスタンスタイプを変更(r6g.large 以上推奨)
- インデックスの最適化(不要なフィールドを削除)
- 検索クエリの Top-K を減らす
3) PartyRock のログが見つからない → CloudWatch Logs の場所
PartyRock のログは /aws/partyrock ではない。
# Bedrock Knowledge Base のログ
aws logs describe-log-groups --log-group-name-prefix /aws/bedrock/knowledge-bases
# Lambda のログ(PartyRock が内部で使用)
aws logs describe-log-groups --log-group-name-prefix /aws/lambda
対応案
- PartyRock の「Activity」タブでセル単位のエラーを確認
- CloudWatch Logs で
/aws/bedrockや/aws/lambdaを確認 - S3 バケット名やデータソースの設定ミスを疑う
4) モデル応答形式の違い → 抽象化レイヤー
Claude と Titan でレスポンス形式が異なる。
# Claude: result['completion']
# Titan: result['results'][0]['outputText']
# AI21 Jurassic: result['completions'][0]['data']['text']
対応案
- LangChain や LlamaIndex で抽象化
- 自前の抽象化関数を実装(上記シナリオ参照)
- モデル切り替え時は必ずテスト
5) IAM 権限不足 → Bedrock の実行ロール
Lambda や EC2 から Bedrock を呼び出す際の権限。
# IAM ロールのポリシーを確認
aws iam list-attached-role-policies --role-name bedrock-execution-role
# 必要な権限:
# - bedrock:InvokeModel
# - bedrock:InvokeModelWithResponseStream(ストリーミング使用時)
# - s3:GetObject(Knowledge Base 使用時)
対応案
- マネージドポリシー
AmazonBedrockFullAccessをアタッチ(開発環境) - 本番環境では最小権限の原則に従う
よくある落とし穴と対策
| 落とし穴 | 理由 | AWS での対策 |
|---|---|---|
| スロットリングが頻発 | モデルごとにクォータがあり、デフォルト値が低い | Service Quotas で事前にクォータ引き上げ |
| Knowledge Base 検索が遅い | OpenSearch/Kendra のインスタンスタイプが小さい | r6g.large 以上を使用、メトリクス監視 |
| PartyRock のログが見つからない |
/aws/partyrock ではなく /aws/bedrock や /aws/lambda
|
Activity タブ + CloudWatch Logs 両方確認 |
| モデル応答形式が異なる | プロバイダーごとに JSON 構造が違う | LangChain/LlamaIndex で抽象化 |
| IAM 権限不足 | Bedrock の実行ロールに権限がない | AmazonBedrockFullAccess または最小権限ポリシー |
| Azure OpenAI との API 互換性なし | Bedrock は OpenAI API 互換ではない | コード移行時にリクエスト/レスポンス形式を変更 |
| プロンプト管理が手動 | Azure Prompt Flow のようなバージョン管理がない | Parameter Store や S3 でプロンプトを管理 |
移行実装時のチェックリスト
□ Bedrock:Service Quotas でクォータを確認し、必要なら事前申請
□ Bedrock:リトライ+指数バックオフを実装(boto3 Config)
□ Bedrock:モデル ID を環境変数化(プロバイダー名.モデル名)
□ Bedrock:抽象化レイヤーを実装(LangChain/LlamaIndex 推奨)
□ Knowledge Base:S3 バケットを事前作成、ドキュメントをアップロード
□ Knowledge Base:OpenSearch/Kendra のインスタンスタイプを適切に設定(r6g.large 以上)
□ PartyRock:Activity タブと CloudWatch Logs の両方で監視
□ CloudWatch Logs:主要なログの保存期間を設定(コスト最適化)
□ CloudWatch Metrics:Invocations, InvocationErrors, ModelInvocationThrottles のアラート設定
□ IAM:Bedrock 実行ロールに必要な権限を付与(bedrock:InvokeModel など)
さいごに
AWS の生成AI サービスは Azure OpenAI Service のような「統合プラットフォーム」ではなく、「柔軟な選択肢と明示的な設定」が特徴です。Bedrock、PartyRock、SageMaker それぞれに特性があり、適材適所での使い分けが求められます。
Azure では「Azure OpenAI Service を使えば大体 OK」という快適さがありましたが、AWS では「どのサービスをどう組み合わせるか」を理解する必要があります。しかし、柔軟性が高い分、細かい制御やコスト最適化は AWS の方が有利な場面もあります。
本記事の優先度順に切り分ければ、落ち着いて障害対応できるのかなー、と思いました。
補足:AWS マネジメントコンソールでの基本操作
CLI に慣れていない場合、AWS マネジメントコンソール(ポータル)での操作が便利です。以下は障害対応で頻繁に使う画面の場所と確認方法です。
Bedrock の基本操作
1. モデルの確認とテスト実行
1. AWS マネジメントコンソールにログイン
2. 検索バーで「Bedrock」と入力 → Amazon Bedrock を選択
3. 左メニューから「Base models」をクリック
4. 利用したいモデル(例:Claude)の「Request model access」をクリック
→ 初回はモデルへのアクセス申請が必要(数分~数時間で承認)
5. 承認後、左メニューから「Playgrounds」→「Chat」を選択
6. モデルを選択(例:Anthropic Claude 3 Sonnet)
7. プロンプトを入力してテスト実行
→ レスポンスが返ってくることを確認
2. モデルのクォータ確認
1. AWS マネジメントコンソール右上のアカウント名をクリック
2. 「Service Quotas」を選択
3. 左メニューから「AWS services」をクリック
4. 検索バーで「Bedrock」と入力
5. 「Amazon Bedrock」を選択
6. クォータ一覧から確認したいモデルを選択
例:「Anthropic Claude V2 input tokens per minute」
7. 「Request quota increase」をクリックして引き上げ申請
3. CloudWatch でメトリクス確認
1. AWS マネジメントコンソールで「CloudWatch」を検索
2. 左メニューから「Metrics」→「All metrics」を選択
3. 「Bedrock」を選択
4. 「By Model ID」を選択
5. 確認したいモデルの以下のメトリクスをチェック:
- Invocations(成功したリクエスト数)
- InvocationErrors(エラー数)
- ModelInvocationThrottles(スロットリング数)
6. 「Graphed metrics」タブで時系列グラフを確認
7. 右上の期間を「Last 1 hour」などに変更して直近の状況を確認
PartyRock の基本操作
1. アプリの作成と実行
1. ブラウザで https://partyrock.aws にアクセス
2. 「Sign in」→ AWS アカウントでログイン
3. 「Build your own app」をクリック
4. アプリ名とプロンプトを入力(例:「Document QA Bot」)
5. 「Generate」をクリック → 自動的にセルが生成される
6. 各セルの設定を調整:
- Input セル:ユーザー入力を受け取る
- LLM セル:Bedrock モデルで推論
- Output セル:結果を表示
7. 右上の「Publish」をクリックして公開
2. Knowledge Base(RAG)の設定
1. PartyRock アプリの編集画面で、セルを追加
2. 「Knowledge Base」セルを選択
3. 「Create new Knowledge Base」をクリック
4. Knowledge Base 名を入力(例:「my-docs-kb」)
5. Data source として「S3」を選択
6. S3 バケット名を入力(事前に作成が必要)
→ S3 コンソールで「Create bucket」して作成
7. ドキュメント(PDF, TXT, HTML など)を S3 にアップロード
8. 「Sync data source」をクリックしてインデックス作成
→ 数分~数十分かかる
9. PartyRock のセルで Knowledge Base を選択して使用
3. Activity(実行履歴)の確認
1. PartyRock アプリの画面で、下部の「Activity」タブをクリック
2. 最近の実行履歴が時系列で表示される
3. 各実行をクリックすると、セルごとの入出力が確認できる
4. エラーが発生しているセルは赤色で表示される
5. セルをクリックして詳細なエラーメッセージを確認
4. CloudWatch Logs での確認(より詳細なログ)
1. AWS マネジメントコンソールで「CloudWatch」を検索
2. 左メニューから「Logs」→「Log groups」を選択
3. 以下の Log Group を探す:
- /aws/bedrock/knowledge-bases/kb-xxxxx
- /aws/lambda/partyrock-xxxxx(内部で使われる Lambda)
4. Log stream を選択して最新のログを確認
5. フィルターバーで「ERROR」や「Exception」で検索
Bedrock Knowledge Base の構築(ポータル操作)
1. S3 バケットの作成とドキュメントアップロード
1. AWS マネジメントコンソールで「S3」を検索
2. 「Create bucket」をクリック
3. Bucket name を入力(例:my-knowledge-base-docs)
4. Region を選択(Bedrock と同じリージョン推奨)
5. デフォルト設定のまま「Create bucket」をクリック
6. 作成したバケットをクリック
7. 「Upload」をクリックしてドキュメント(PDF, TXT など)をアップロード
2. OpenSearch Serverless の作成(ベクトルDB)
1. AWS マネジメントコンソールで「OpenSearch Service」を検索
2. 左メニューから「Serverless」→「Collections」を選択
3. 「Create collection」をクリック
4. Collection name を入力(例:kb-vector-store)
5. Collection type で「Vector search」を選択
6. Network access で「Public」を選択(開発環境の場合)
7. Encryption は AWS managed key を選択
8. 「Create」をクリック → 作成に 5~10 分かかる
3. Bedrock Knowledge Base の作成
1. AWS マネジメントコンソールで「Bedrock」を検索
2. 左メニューから「Knowledge bases」を選択
3. 「Create knowledge base」をクリック
4. Knowledge base details:
- Name: my-docs-kb
- Description: ドキュメント検索用 KB
5. 「Next」をクリック
6. Data source configuration:
- Data source name: s3-docs
- S3 URI: s3://my-knowledge-base-docs/
7. 「Next」をクリック
8. Embeddings model:
- Amazon Titan Embeddings G1 - Text を選択
9. Vector database:
- 先ほど作成した OpenSearch Serverless collection を選択
10. 「Next」→「Create」をクリック
11. 作成後、「Sync」をクリックしてインデックス作成
→ ドキュメント数に応じて数分~数十分
4. Knowledge Base のテスト
1. 作成した Knowledge Base の詳細画面を開く
2. 右上の「Test」ボタンをクリック
3. クエリを入力(例:「製品の価格は?」)
4. 「Run」をクリック
5. 検索結果が表示されることを確認
→ 結果が空の場合は、ドキュメントの Sync 状態を確認
CloudWatch でのログ確認(障害時の定番操作)
1. Lambda のログ確認
1. AWS マネジメントコンソールで「CloudWatch」を検索
2. 左メニューから「Logs」→「Log groups」を選択
3. 検索バーで「/aws/lambda/」と入力
4. 対象の Lambda 関数の Log group をクリック
5. Log streams を時系列で確認(最新が上)
6. 最新の Log stream をクリック
7. エラーメッセージを検索(Ctrl+F で「ERROR」や「Exception」)
2. Logs Insights でクエリ検索
1. CloudWatch の左メニューから「Logs Insights」を選択
2. 「Select log group(s)」で対象の Log group を選択
3. クエリエディタに以下を入力:
fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 20
4. 右上の期間を選択(例:Last 1 hour)
5. 「Run query」をクリック
6. 結果が表形式で表示される
3. メトリクスアラームの設定
1. CloudWatch の左メニューから「Alarms」→「All alarms」を選択
2. 「Create alarm」をクリック
3. 「Select metric」をクリック
4. 「Bedrock」→「By Model ID」を選択
5. 「InvocationErrors」をチェック
6. 「Select metric」をクリック
7. Conditions で Threshold type を「Static」、条件を「Greater」、値を「5」に設定
8. 「Next」をクリック
9. SNS topic を作成または選択(メール通知用)
10. 「Next」→ Alarm name を入力 → 「Create alarm」
X-Ray でのトレース確認
1. X-Ray トレースマップの確認
1. AWS マネジメントコンソールで「X-Ray」を検索
2. 左メニューから「Service map」を選択
3. サービス間の依存関係がグラフ表示される
例:API Gateway → Lambda → Bedrock
4. 各ノードをクリックすると、レスポンスタイムやエラー率が表示される
5. 遅延やエラーが発生しているノードを特定
2. トレースの詳細確認
1. X-Ray の左メニューから「Traces」を選択
2. フィルターで期間を設定(例:Last 1 hour)
3. レスポンスタイムが長いトレースをクリック
4. タイムラインで各サービスの処理時間を確認
例:Lambda 内部で 15 秒、Bedrock 呼び出しで 12 秒など
5. 「Segments」タブで詳細なログやメタデータを確認
画面操作のチートシート
| 確認したいこと | 開く画面 | 見るべき項目 |
|---|---|---|
| Bedrock のエラー数 | CloudWatch → Metrics → Bedrock | InvocationErrors の Sum |
| Bedrock のスロットリング | CloudWatch → Metrics → Bedrock | ModelInvocationThrottles の Sum |
| Lambda のエラーログ | CloudWatch → Logs → /aws/lambda/xxx | Log stream の最新エントリ |
| PartyRock の実行履歴 | PartyRock アプリ → Activity タブ | 各セルの成功/失敗状態 |
| Knowledge Base の検索結果 | Bedrock → Knowledge bases → Test | クエリを入力して Run |
| API のレスポンスタイム | X-Ray → Traces | Duration の長いトレース |
| クォータの確認 | Service Quotas → AWS services → Bedrock | 各モデルのクォータ値 |
| S3 のドキュメント確認 | S3 → Buckets → バケット名 | Objects タブ |
注釈:本記事で出現する主要な専門用語
Bedrock
- AWS のマネージド生成AI 推論サービス。Anthropic Claude、Amazon Titan、AI21 Jurassic などのモデルを API 経由で利用できる。Azure OpenAI Service に相当するが、プロバイダーごとに API 形式が異なる。
PartyRock
- AWS のノーコード生成AI アプリビルダー。複数の AI セルを組み合わせて RAG パイプラインを構築できる。Azure AI Foundry に近いが、独立したアプリとして動作。
Knowledge Base for Bedrock
- Bedrock の RAG(Retrieval-Augmented Generation)機能。S3 + ベクトルDB(OpenSearch/Kendra/Pinecone)を連携して、独自データで拡張された推論を実行。Azure OpenAI の「自分のデータで拡張」に相当。
Service Quotas
- AWS のリソース制限を管理するサービス。Bedrock はモデルごとにトークン数/分のクォータがあり、Service Quotas で確認・変更する。Azure OpenAI の TPM(Tokens Per Minute)設定に相当。
モデル ID(Model ID)
- Bedrock でモデルを指定する際の識別子。
プロバイダー名.モデル名の形式(例:anthropic.claude-v2,amazon.titan-text-express-v1)。Azure OpenAI のデプロイ名とは異なる。
ThrottlingException
- Bedrock でリクエストがクォータを超えた際に発生するエラー。HTTP 429 に相当。リトライ+指数バックオフで対応する。
OpenSearch Service
- AWS のマネージド検索エンジン。Bedrock Knowledge Base のベクトルDB として使用される。Azure Cognitive Search に相当するが、インスタンスタイプの選択が必要。
Kendra
- AWS のエンタープライズ検索サービス。自然言語クエリに対応。Bedrock Knowledge Base のデータソースとしても使用可能。Azure Cognitive Search に近い。
X-Ray
- AWS の分散トレーシングサービス。Lambda → Bedrock → OpenSearch のレイテンシを可視化できる。Azure Application Insights の依存関係追跡に相当。
LangChain / LlamaIndex
- 生成AI アプリケーションの開発フレームワーク。Bedrock のモデル差異を抽象化し、統一インターフェースで呼び出し可能にする。
Azure OpenAI Service
- Azure のマネージド OpenAI API サービス。統一された OpenAI API 形式で GPT-4, GPT-3.5, DALL-E などを利用できる。Bedrock に相当するが、API 形式が統一されている。
AI Foundry (Azure)
- Azure の統合生成AI 開発環境。Prompt Flow でプロンプトのバージョン管理、Azure Monitor でログ統合が標準。PartyRock に相当するが、統合度が高い。
TPM (Tokens Per Minute)
- Azure OpenAI でデプロイごとに設定するトークン数/分の上限。Bedrock の Service Quotas に相当するが、デプロイ作成時に指定できる。
Prompt Flow (Azure)
- Azure AI Foundry のプロンプト管理機能。プロンプトのバージョン管理、A/B テスト、デプロイができる。Bedrock には同等機能がなく、Parameter Store や S3 で手動管理が必要。
Azure Cognitive Search
- Azure の検索サービス。Azure OpenAI の「自分のデータで拡張」機能で自動統合される。Bedrock Knowledge Base では OpenSearch/Kendra を手動連携する必要がある。
SageMaker
- AWS のマネージド機械学習プラットフォーム。カスタムモデルの学習・デプロイに使用。Bedrock は事前学習済みモデルの推論専用。
boto3
- AWS の Python SDK。Bedrock API を呼び出す際に使用。Config で指数バックオフを設定可能。