発展LESSON 07

この教材で学ぶこと Bedrock経由のモデル利用とAWS統合を理解します。

Claude with Amazon Bedrock

参照コース: https://anthropic.skilljar.com/claude-in-amazon-bedrock
前提知識: AWSの主要サービス。本教材ではBedrock経由でClaudeを使う方法と、直接APIとの使い分けを扱います。


1. Bedrock vs Anthropic API 直接 — どちらを使うか

観点 Anthropic API 直接 Amazon Bedrock
課金 Anthropic に直接支払い AWS 請求に統合
IAM 認証 API キーのみ IAM ロール・ポリシーで管理可
VPC 内利用 不可(インターネット経由) VPC エンドポイント経由で可
監査ログ Anthropic コンソールのみ CloudTrail に記録
モデルの種類 Claude のみ Claude + Titan + Llama 等
レイテンシ 低い やや高い(AWS 経由)
エンタープライズ △ ◎(コンプライアンス・ガバナンス対応)

選び方:

  • 個人・スタートアップ → Anthropic API 直接
  • AWS 既存環境・エンタープライズ → Bedrock 推奨
  • コンプライアンス要件(データの AWS 内保持など)→ Bedrock 一択

2. セットアップ

# boto3 で Bedrock を使う(AWS CLI の設定が前提)
pip install boto3

# モデルアクセスの有効化
# AWS コンソール → Amazon Bedrock → モデルアクセス → Claude を有効化

3. 基本的なリクエスト

import boto3
import json

bedrock = boto3.client(
    service_name='bedrock-runtime',
    region_name='us-east-1'  # 利用可能リージョンに注意(東京は一部モデルのみ)
)

# Anthropic Messages API 互換フォーマット
response = bedrock.invoke_model(
    modelId='anthropic.claude-opus-4-5-20251101-v1:0',
    body=json.dumps({
        "anthropic_version": "bedrock-2023-05-31",
        "max_tokens": 1024,
        "messages": [
            {"role": "user", "content": "Terraform でプライベートサブネットを作るコードを書いて"}
        ]
    })
)

result = json.loads(response['body'].read())
print(result['content'][0]['text'])

4. boto3 でのストリーミング

response = bedrock.invoke_model_with_response_stream(
    modelId='anthropic.claude-opus-4-5-20251101-v1:0',
    body=json.dumps({
        "anthropic_version": "bedrock-2023-05-31",
        "max_tokens": 2048,
        "messages": [{"role": "user", "content": "K8s の Deployment マニフェストを詳しく説明して"}]
    })
)

for event in response['body']:
    chunk = json.loads(event['chunk']['bytes'])
    if chunk.get('type') == 'content_block_delta':
        print(chunk['delta'].get('text', ''), end='', flush=True)

5. Bedrock 固有の機能

Guardrails — 入出力フィルタリング

# Guardrail を設定して有害コンテンツをブロック
# コンソールで Guardrail を作成後、ID を指定

response = bedrock.invoke_model(
    modelId='anthropic.claude-opus-4-5-20251101-v1:0',
    guardrailIdentifier='xxxxxxxx',  # Guardrail ID
    guardrailVersion='DRAFT',
    body=json.dumps({
        "anthropic_version": "bedrock-2023-05-31",
        "max_tokens": 1024,
        "messages": [{"role": "user", "content": user_input}]
    })
)

Knowledge Bases — マネージド RAG

# Bedrock Knowledge Base = S3のドキュメントを自動でベクトル化してくれるマネージドRAG

bedrock_agent = boto3.client('bedrock-agent-runtime', region_name='us-east-1')

response = bedrock_agent.retrieve_and_generate(
    input={'text': '障害対応手順を教えてください'},
    retrieveAndGenerateConfiguration={
        'type': 'KNOWLEDGE_BASE',
        'knowledgeBaseConfiguration': {
            'knowledgeBaseId': 'XXXXXXXXXX',
            'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-opus-4-5-20251101-v1:0'
        }
    }
)
print(response['output']['text'])
# 引用元も返ってくる
for citation in response.get('citations', []):
    print(f"参照: {citation['retrievedReferences'][0]['location']}")

6. IAM ポリシー設定

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream"
            ],
            "Resource": [
                "arn:aws:bedrock:*::foundation-model/anthropic.claude-*"
            ]
        }
    ]
}

7. Lambda から Bedrock を呼ぶ(実践パターン)

# Lambda 関数(Lambda の実行ロールに Bedrock 権限を付与)
import json
import boto3

bedrock = boto3.client('bedrock-runtime', region_name='us-east-1')

def lambda_handler(event, context):
    user_message = event.get('message', '')
    
    response = bedrock.invoke_model(
        modelId='anthropic.claude-haiku-4-5-20250307-v1:0',  # 安い・速いモデル
        body=json.dumps({
            "anthropic_version": "bedrock-2023-05-31",
            "max_tokens": 512,
            "messages": [{"role": "user", "content": user_message}]
        })
    )
    
    result = json.loads(response['body'].read())
    return {
        'statusCode': 200,
        'body': json.dumps({
            'response': result['content'][0]['text'],
            'usage': result['usage']
        })
    }

🔗 次のステップ