11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LambdaでBedrockのClaude 3を呼び出してみた

Posted at

Supershipの名畑です。プリティーリズム・レインボーライブ10周年展おめでとうございます。とても楽しい展示でした。

はじめに

AnthropicがリリースしたClaude 3が話題です。

ということで今回はタイトルの通り、AWS(Amazon Web Services)上においてLambdaからBedrockClaude 3を呼び出してみます。

前に書いた記事「AWS Lambda(Python)からOpenAIのGPT4のAPIを呼び出してみた」の「Claude-3版、しかもAWS上で完結」といったところです。
また、前の記事と違って、今回はひとまず動作を試すことを最優先とし、ブラウザ上のコンソールのみで進めます。

Bedrockとは

Amazon Bedrock は、AI21 Labs、Anthropic、Cohere、Meta、Stability AI、Amazon などの大手 AI 企業が提供する高性能な基盤モデル (FM) を単一の API で選択できるフルマネージド型サービスです。

参考:Amazon Bedrock

モデルのアクセスリクエスト

現在、Bedrock上でAnthropicのモデルを使用するにはユースケースを送信して許可をもらう必要があります。その手順を進めます。

Amazon Bedrock の Anthropic の Claude 3 Sonnet は、米国東部 (バージニア北部) および米国西部 (オレゴン) の各 AWS リージョンでご利用いただけます。

参考:Anthropic の Claude 3 Sonnet モデルが Amazon Bedrock で利用可能に

とのことですので、まずリージョンua-east-1 米国東部 (バージニア北部) としました。

その上でBedrockのサイドメニューからモデルアクセスのページを開きます。

clause-3-1.png

右上の「モデルアクセスを管理」を押します。

clause-3-2.png

Claude 3には3種類のモデルがあるのですが、今回はSonnetを使うことにします。ですので、Claude 3 Sonnetを選んで「ユースケースの詳細を送信」を押します。

遷移先の画面で会社名などの項目を入力して送信します。

clause-3-3.png

するとリクエスト可能という状態になりますので、希望するモデルを選択して画面下部の「モデルアクセスをリクエスト」を押します。

clause-3-4.png

ステイタスが進行中に変わります。

モデルにアクセスするには数分かかる場合があります。その間、Bedrock コンソールの他のページを使用できます。アクセスが付与されると、Bedrock でモデルを使用できるようになります。ベースモデルテーブルを更新すると、更新されたステータスが表示されます。

とのことなので、少し待ってからリロードします。

clause-3-5.png

アクセスが付与されました」となりました。これで使用可能です。

余談ですが「ユースケースの送信」はAnthropic共通で1度だけで良いですが、「モデルアクセスをリクエスト」はモデル毎に必要です。

IAMでロールの作成

LambdaからBedrockを呼び出せるようにするためにIAMでロールを作成します。

AWS Identity and Access Management (IAM) は、AWS リソースへのアクセスを安全に管理するためのウェブサービスです。IAM を使用すると、ユーザーがアクセスできる AWS のリソースを制御するアクセス許可を集中管理できます。IAM を使用して、誰を認証 (サインイン) し、誰にリソースの使用を認可する (アクセス許可を付与する) かを制御します。

参考:IAM とは - AWS Identity and Access Management

まず「ロールを作成」のページに行きます。

clause-3-6.png

信頼されたエンティティタイプ」として「AWSのサービス」を、ユースケースとしてLambdaを選択して次へを押します。

clause-3-7.png

許可ポリシーとしてAmazonBedrockFullAccessを選択して次へを押します。AmazonBedrockReadOnlyだとこの後の処理実行時にAccessDeniedExceptionが起きます。

clause-3-8.png

ロール名をつけます。私はわかりやすくLambdaToBedrockAccessRoleとしました。

これで「ロールを作成」を押して作成完了です。

Lambda関数の作成

次にLambdaの設定に移ります。
Labmdaは他のリージョン(たとえばアジアパシフィック (東京) ap-northeast-1)でも動きます。

Lambda関数の作成のページを開きます。

今回は下記の設定としました。

  • 関数名:LambdaToBedrockAccess
  • ランタイム:Python3.12
  • アーキテクチャ:arm64
  • デフォルトの実行ロールの変更
    • 「既存のロールを使用する」を選択して先ほど作成したLambdaToBedrockAccessRoleを選択

アーキテクチャについて詳しくは「Lambda 命令セットアーキテクチャ (ARM/x86) - AWS Lambda」をご覧ください。

ランタイムの注意点としては、PythonのバージョンによってBoto3(AWSのサービスを扱うライブラリ)のバージョンも変わります。Boto3のバージョンによってはBedrockへのアクセスに対応していないため、ご注意ください。仮に古いバージョンのPythonが必須の場合は、過去記事OpenAIのライブラリをアップロードしたのと同じように、Boto3をアップロードする必要があります。

バージョンについて詳しくは「Lambda ランタイム - AWS Lambda」を、Boto3からBedrockへのアクセスについて詳しくは「BedrockRuntime - Boto3」をご覧ください。

Lambda関数の設定

clause-3-9.png

基本的にはほぼデフォルト設定で動くのですが、タイムアウトだけはデフォルトの3秒のままだとレスポンスが間に合わないので30秒に伸ばしました。

コード

Anthropic Claude Messages APICode examplesを参考にして書きました。
Lambdaに渡されてきたjsonmessageを参照して、それをclaude 3に投げるように実装しています。必要最低限のコードだとかなりシンプルです。

import json
import boto3

def lambda_handler(event, context):
    bedrock_runtime = boto3.client(service_name='bedrock-runtime', region_name='us-east-1')

    model_id = 'anthropic.claude-3-sonnet-20240229-v1:0'
    system_prompt = "必ず日本語で答えてください"
    max_tokens = 1000

    user_message = {"role": "user", "content": event.get("message")}
    messages = [user_message]
    
    body = json.dumps(
        {
            "anthropic_version": "bedrock-2023-05-31",
            "max_tokens": max_tokens,
            "system": system_prompt,
            "messages": messages
        }  
    )  

    response = bedrock_runtime.invoke_model(body=body, modelId=model_id)
    response_body = json.loads(response.get('body').read())

    return {
        'statusCode': 200,
        'body': response_body
    }

テスト

clause-3-10.png

テストのページに移動して、以下のjsonを記述してみます。

{
  "message": "東京都23区を教えてください"
}

そしてテストを押すと、数秒で以下のようなレスポンスが返ってきました。

{
  "statusCode": 200,
  "body": {
    "id": "msg_hogehoge",
    "type": "message",
    "role": "assistant",
    "content": [
      {
        "type": "text",
        "text": "東京都23区は以下の通りです。\n\n千代田区\n中央区\n港区\n新宿区\n文京区\n台東区\n墨田区\n江東区\n品川区\n目黒区\n大田区\n世田谷区\n渋谷区\n中野区\n杉並区\n豊島区\n北区\n荒川区\n板橋区\n練馬区\n足立区\n葛飾区\n江戸川区\n\n1947年に東京都内の旧区が統合されて誕生した23の特別区で、人口が密集し、商業や業務が集中する都心部を形成しています。"
      }
    ],
    "model": "claude-3-sonnet-28k-20240229",
    "stop_reason": "end_turn",
    "stop_sequence": null,
    "usage": {
      "input_tokens": 29,
      "output_tokens": 178
    }
  }
}

東京都23区は以下の通りです。\n\n千代田区\n中央区\n港区\n新宿区\n文京区\n台東区\n墨田区\n江東区\n品川区\n目黒区\n大田区\n世田谷区\n渋谷区\n中野区\n杉並区\n豊島区\n北区\n荒川区\n板橋区\n練馬区\n足立区\n葛飾区\n江戸川区\n\n1947年に東京都内の旧区が統合されて誕生した23の特別区で、人口が密集し、商業や業務が集中する都心部を形成しています。

バッチリな回答に思えます。

画像の解析

せっかくなので画像の解析もしてみましょう。画像url指示を渡すこととします。いわゆるマルチモーダルです。

用語「マルチモーダルAI」について説明。テキスト/画像/音声/数値など複数の種類のモダリティー(データ種別)を一度に処理できる統合されたAIモデルを指す。

参考:マルチモーダルAI(Multimodal AI)とは?:AI・機械学習の用語辞典 - @IT

Lambdaに渡されてきたjsonmessage指示image画像urlとして扱うコードとします。

import json
import boto3
import urllib
import base64

def lambda_handler(event, context):
    bedrock_runtime = boto3.client(service_name='bedrock-runtime', region_name='us-east-1')

    model_id = 'anthropic.claude-3-sonnet-20240229-v1:0'
    system_prompt = "必ず日本語で答えてください"
    max_tokens = 1000
    
    with urllib.request.urlopen(event.get("image")) as image_file:
        content_image = base64.b64encode(image_file.read()).decode('utf8')

    user_message = {
        "role": "user",
        "content": [
            {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": content_image}},
            {"type": "text", "text": event.get("message")}
        ]
    }
            
    messages = [user_message]
    
    body = json.dumps(
        {
            "anthropic_version": "bedrock-2023-05-31",
            "max_tokens": max_tokens,
            "system": system_prompt,
            "messages": messages
        }  
    )  

    response = bedrock_runtime.invoke_model(body=body, modelId=model_id)
    response_body = json.loads(response.get('body').read())

    return {
        'statusCode': 200,
        'body': response_body
    }

先ほどのコードと多くは同じですが、画像の読み込みと、モデルに渡すmessagesの生成が異なっています。

テストで渡すjsonは以下としました。

{
  "image": "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/467c6358-084c-6ce1-d684-cad6dbfe501a.png",
  "message": "これはどんな絵ですか"
}

ちなみにurlの示す画像は過去記事で生成したこちらです。

gen-2-6.png

テストしたところ、レスポンスは以下のようなものでした。

{
  "statusCode": 200,
  "body": {
    "id": "msg_hogehoge",
    "type": "message",
    "role": "assistant",
    "content": [
      {
        "type": "text",
        "text": "この画像は東京の繁華街、渋谷のスクランブル交差点を捉えたものです。大きな電光掲示板や高層ビルが映っており、にぎやかな雰囲気が伝わってきます。そして、前景には個性的なアニメキャラクターのバッグを持った明るい笑顔の若い女性が写っています。都会的で活気に満ちた渋谷の風景と、それを楽しむような女性の様子が見事に描かれた1枚の写真です。個人の特定は避けましたが、都会的で賑やかな雰囲気が伝わる魅力的な写真だと思います。"
      }
    ],
    "model": "claude-3-sonnet-28k-20240229",
    "stop_reason": "end_turn",
    "stop_sequence": null,
    "usage": {
      "input_tokens": 423,
      "output_tokens": 208
    }
  }
}

この画像は東京の繁華街、渋谷のスクランブル交差点を捉えたものです。大きな電光掲示板や高層ビルが映っており、にぎやかな雰囲気が伝わってきます。そして、前景には個性的なアニメキャラクターのバッグを持った明るい笑顔の若い女性が写っています。都会的で活気に満ちた渋谷の風景と、それを楽しむような女性の様子が見事に描かれた1枚の写真です。個人の特定は避けましたが、都会的で賑やかな雰囲気が伝わる魅力的な写真だと思います。

正確にはスクランブル交差点ではないですが、かなり高精度な分析だと感じます。

最後に

Claude 3は評判通り、かなり優秀と感じます。
そしてなにより、AWSのみで完結するのが本当に魅力ですね。

ナレッジベースを使ったRAG(検索拡張生成)も試したので記事にする予定です。まだ現時点ではClaude 3は対応はしていないようですが。

宣伝

SupershipのQiita Organizationを合わせてご覧いただけますと嬉しいです。他のメンバーの記事も多数あります。

Supershipではプロダクト開発やサービス開発に関わる方を絶賛募集しております。
興味がある方はSupership株式会社 採用サイトよりご確認ください。

11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?