
【開発記録 #3】BedrockでWell-Architectedレビューを生成する——システムプロンプト設計
インフラができたら次はLambdaの中身。Claude Codeにどう依頼すれば、AIが使えるシステムプロンプトを設計してくれるのか。モデル選定の判断基準も含めて記録する。
まず使うクライアントを決める
BedrockをPythonから呼ぶとき、boto3のクライアントが2つある。
| クライアント | 用途 |
|---|---|
bedrock-runtime |
モデルを直接呼び出す |
bedrock-agent-runtime |
Knowledge BaseやAgentを使う |
今回はモデルに直接プロンプトを投げてレビューを生成するだけなので bedrock-runtime を選ぶ。
RAGを追加するPhase 5で bedrock-agent-runtime に移行する予定だが、今は最小構成で動かすことを優先する。後から変えられる部分は後回しにする判断が、開発を止めないコツ。
モデル選定の判断基準
Claude Codeに「どのモデルを使うべきか」を相談する前に、自分で判断軸を持っておく。
| モデル | 入力 (1Mトークン) | 出力 (1Mトークン) |
|---|---|---|
| Claude Haiku 4.5 | $0.80 | $4.00 |
| Claude Sonnet 4.5 | $3.00 | $15.00 |
Well-Architectedレビューの用途なら、Haikuで十分な品質が出ると判断した。理由は2つ。
- レビューの精度は「モデルの賢さ」より「システムプロンプトの設計」に依存する部分が大きい
- SaaSとして提供する場合、コストがそのまま収益性に直結する
Sonnetは3〜4倍のコストがかかる。精度が同程度ならHaikuを選ぶ。本当に精度が足りないと分かってから乗り換えれば十分。
Lambdaの生成依頼——出力形式まで指定する
Claude Codeへの依頼:
lambda/review.pyを作ってください。
- boto3でBedrock(Claude Haiku)を呼び出す
- 入力:アーキテクチャの説明文(JSON)
- 出力:Well-Architectedの5本柱に沿ったレビュー結果(JSON)
- システムプロンプト:AWSのSolutions Architectとして振る舞う
「出力:JSON」と明示したのが重要なポイント。
出力形式を指定しないと、Claude Codeは自由なフォーマットでレビューを返す実装を作る。フロントエンドで扱うためにはJSON形式である必要があるため、最初から仕様に含めた。
生成されたシステムプロンプトの骨格:
SYSTEM_PROMPT = """
あなたはAWSの認定ソリューションアーキテクトです。
AWS Well-Architectedフレームワークの5つの柱(運用上の優秀性・セキュリティ・信頼性・パフォーマンス効率・コスト最適化)に基づいて、
提供されたAWSアーキテクチャを評価してください。
以下のJSON形式で回答してください:
{
"operational_excellence": {"score": 1-5, "issues": [], "recommendations": []},
"security": {"score": 1-5, "issues": [], "recommendations": []},
"reliability": {"score": 1-5, "issues": [], "recommendations": []},
"performance_efficiency": {"score": 1-5, "issues": [], "recommendations": []},
"cost_optimization": {"score": 1-5, "issues": [], "recommendations": []}
}
"""
5本柱それぞれにスコア(1〜5)・問題点・推奨事項を返す構造。Claude Codeはプロンプトの依頼に「JSON形式で」と書いていたのを受けて、具体的なJSONスキーマまで自動で設計してきた。このスキーマはほぼそのまま採用した。
東京リージョンのモデルIDは別物
ローカルテストを実行したら最初のエラー:
ValidationException: The provided model identifier is invalid
生成されたコードに含まれていたモデルIDは anthropic.claude-haiku-4-5-20251001。これは東京リージョンでは使えない。
東京リージョンでClaude Haikuを使う場合、クロスリージョン推論プロファイルのIDを使う必要がある。正しいIDの確認方法:
aws bedrock list-inference-profiles --region ap-northeast-1
正しいIDは:
jp.anthropic.claude-haiku-4-5-20251001-v1:0
jp. プレフィックスと末尾の -v1:0 が東京リージョンでは必要。Claude Codeはリージョン固有の仕様を必ずしも知っているわけではない。AWSのリージョン特有の制約は自分で確認する必要がある。
このエラーはClaude Codeにそのまま貼り付けると解決策を提案してくれるが、最終的に正しいモデルIDを特定するのはAWSコンソールかCLIで確認するしかない。
JSONが返ってこない——Claudeの出力の癖
モデルIDを修正して再実行したら次のエラー:
Bedrockの応答をパースできませんでした
原因はClaudeの出力の癖。「JSON形式で返して」と指示しているのに、実際の出力はこうなっていた:
```json
{
"operational_excellence": ...
}
```
コードブロック(```json ```)で囲まれて返ってくる。json.loads() にそのまま渡せないのでパースエラーになる。
Claude Codeに「コードブロックを除去する処理を追加して」と依頼したら、strip処理を追加してきた:
def extract_json(text):
text = re.sub(r'```json\s*', '', text)
text = re.sub(r'```\s*', '', text)
return json.loads(text.strip())
システムプロンプトに「JSONのみを返してください、コードブロックは不要です」と書いても、モデルによってはコードブロックを付けて返すことがある。strip処理は保険として必ず入れておくのが安全。
実際のレビュー結果
「EC2インスタンス1台にすべてを詰め込んだ構成」を入力して動作確認:
{
"operational_excellence": {
"score": 2,
"issues": ["デプロイの自動化がない", "ログ収集の仕組みがない"],
"recommendations": ["CodeDeployでデプロイ自動化", "CloudWatch Logsへのログ転送設定"]
},
"security": {
"score": 2,
"issues": ["すべてのポートが0.0.0.0/0で開放されている", "IAMロールが未設定"],
"recommendations": ["セキュリティグループで必要なポートのみ開放", "EC2インスタンスにIAMロールを付与"]
},
"reliability": {
"score": 1,
"issues": ["単一障害点(SPOF)", "オートスケーリングなし"],
"recommendations": ["マルチAZ構成への変更", "Auto Scalingグループの設定"]
}
}
「単一障害点」「セキュリティグループの過剰な開放」など、実際のレビューで指摘されるような内容が出た。Haikuでも十分な品質と判断した。
システムプロンプト設計でつかんだ感覚
出力形式は最初の依頼に含める
JSONが必要なら「出力:JSON形式で」と明示。後から変えると生成コードの修正範囲が広くなる。
リージョン固有の仕様はClaude Codeに頼らない
東京リージョンのモデルIDのように、AWSのリージョン特有の制約は自分でドキュメントを確認する。
Claudeの出力の癖を知っておく
JSON指定でもコードブロックで返ってくることがある。strip処理は標準で入れる。
Phase 1完了。APIエンドポイントにアーキテクチャの説明を投げればWell-Architectedレビューが返ってくる状態になった。次回からはPhase 2——Cognito認証を追加していく。
← 前回:第2回——CDK × Claude CodeでLambda + API Gatewayを最速で作る | 次回:第4回——Amazon CognitoでユーザーIDと認証を実装する →