TechBlog一覧へ
AWS 2026年4月27日

AWS Bedrockで最初にLLMを呼び出すまでに詰まったところ全部書く

XECIN BedrockClaudePythonAI

「LLMを社内のサービスに組み込んでみたい」と話が出たとき、正直なところ最初は何から始めればいいか全然分かりませんでした。

OpenAI APIは名前くらい知っていたんですが、社内では「AWSで完結させたい」という方向になって、調べ始めたのが今年の初め。Bedrockという名前は聞いたことがあったけど、実際に触ったことはなかった。今回はその時にやらかしたことや、ドキュメントだけでは分からなかった詰まりポイントをまとめておきます。

まず「Model Access」の申請が必要だと知らなかった

AWSコンソールでBedrockを開いて、早速コードを書いてみたんですが、最初は普通にエラーが出ました。

import boto3
import json

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

response = client.invoke_model(
    modelId="anthropic.claude-3-sonnet-20240229-v1:0",
    body=json.dumps({
        "anthropic_version": "bedrock-2023-05-31",
        "max_tokens": 1024,
        "messages": [{"role": "user", "content": "こんにちは"}]
    }),
    contentType="application/json",
    accept="application/json"
)

「AccessDeniedException」というエラーが返ってきて、最初はIAMのせいだと思い込んで、ポリシーをひたすらいじり始めてしまいました。

恥ずかしながら30分以上そこで悩んだあとに、先輩から「Model Accessの申請した?」と言われて初めて知りました。

AWSコンソールのBedrockページには「Model access」という項目があって、そこで使いたいモデルを事前に申請しないとそもそも呼び出せない仕組みになっているんですよね。Claudeは申請後すぐ承認されたんですが、この仕組み自体をまったく知らなかった。ドキュメントにはちゃんと書いてあったみたいなんですが、読み飛ばしていたようです。今思えばまずページを端から端まで読めって話なんですが。

IAMポリシーにも地味な罠があった

Model Accessが通ったあと、今度はIAMの設定でもう一回ハマりました。

ネットで調べると「bedrock:InvokeModelをアタッチすればいい」という情報が山ほど出てきて、最初はこんなポリシーを書きました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "bedrock:InvokeModel",
      "Resource": "*"
    }
  ]
}

これで動いたんですが、先輩に「本番でResourceに * は絶対ダメ」と言われて修正することになりました。正しくは使うモデルのARNを明示するべきで、Claude 3 Sonnetなら以下のように書くほうがいいそうです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "bedrock:InvokeModel",
      "Resource": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0"
    }
  ]
}

あと、リージョンも注意が必要でした。Claude 3 Sonnetは東京リージョン(ap-northeast-1)では使えないモデルで、バージニア北部(us-east-1)やオレゴン(us-west-2)を指定する必要があります。最初に東京リージョンで叩こうとして「このリージョンではご利用いただけません」みたいなエラーが出て焦りました。ドキュメントにはこう書いてあるけど、実際に失敗してみないと身に染みないですね。

動いた瞬間と、まだできていないこと

ここまでの壁をなんとか乗り越えてようやく動いたとき、ターミナルに日本語の返答が出てきたのはちょっと感動しました。

# 動いたコード(※エラーハンドリングが不十分。改善の余地あり)
response_body = json.loads(response["body"].read())
message = response_body["content"][0]["text"]
print(message)

ここ、ぶっちゃけエラー処理が全然入っていなくて、ネットワークエラーやAPIのスロットリングが発生した場合に何もできない状態です。本番で使うならリトライ処理や例外ハンドリングをちゃんと入れないといけないんですが、まず動かすことを優先してしまいました。

学んだことをまとめると:

  • Model Accessの申請は使い始める前の最初のステップ(知らなかっただけで当然の手順らしい)
  • IAMのResourceには * ではなくモデルのARNを指定する
  • Claude 3系はus-east-1かus-west-2を使う(東京リージョン非対応のモデルがある)
  • boto3のレスポンスは response["body"].read() で読み出してからパースする必要がある

今後はここをベースにして、社内ドキュメントを活用したRAGシステムに挑戦してみたいです。Amazon OpenSearch Serverlessをベクトルストアにして、質問に対して関連ドキュメントを引っ張ってから回答させる構成を試してみるつもりです。ベクトルDBのところが完全に未着手なので、うまくいったらまた書きます。

もっと良いやり方があったら教えてください!