Supershipの名畑です。プリティーリズム・レインボーライブ10周年展おめでとうございます。とても楽しい展示でした。
はじめに
AnthropicがリリースしたClaude 3が話題です。
- Anthropic、AIチャット「Claude 3」を3サイズで 日本語力も向上 - ITmedia NEWS
- GPT-4超えをアピールするClaude-3がAIで初めてIQ100超えを達成したという報告 - GIGAZINE
- GPT-4を上回るAIチャット「Claude 3」向けの公式プロンプト集が無料公開 - 窓の杜
ということで今回はタイトルの通り、AWS(Amazon Web Services)上においてLambdaからBedrockのClaude 3を呼び出してみます。
前に書いた記事「AWS Lambda(Python)からOpenAIのGPT4のAPIを呼び出してみた」の「Claude-3版、しかもAWS上で完結」といったところです。
また、前の記事と違って、今回はひとまず動作を試すことを最優先とし、ブラウザ上のコンソールのみで進めます。
Bedrockとは
Amazon Bedrock は、AI21 Labs、Anthropic、Cohere、Meta、Stability AI、Amazon などの大手 AI 企業が提供する高性能な基盤モデル (FM) を単一の API で選択できるフルマネージド型サービスです。
モデルのアクセスリクエスト
現在、Bedrock上でAnthropicのモデルを使用するにはユースケースを送信して許可をもらう必要があります。その手順を進めます。
Amazon Bedrock の Anthropic の Claude 3 Sonnet は、米国東部 (バージニア北部) および米国西部 (オレゴン) の各 AWS リージョンでご利用いただけます。
とのことですので、まずリージョンを ua-east-1 米国東部 (バージニア北部) としました。
その上でBedrockのサイドメニューからモデルアクセスのページを開きます。
右上の「モデルアクセスを管理」を押します。
Claude 3には3種類のモデルがあるのですが、今回はSonnetを使うことにします。ですので、Claude 3 Sonnetを選んで「ユースケースの詳細を送信」を押します。
遷移先の画面で会社名などの項目を入力して送信します。
するとリクエスト可能という状態になりますので、希望するモデルを選択して画面下部の「モデルアクセスをリクエスト」を押します。
ステイタスが進行中に変わります。
モデルにアクセスするには数分かかる場合があります。その間、Bedrock コンソールの他のページを使用できます。アクセスが付与されると、Bedrock でモデルを使用できるようになります。ベースモデルテーブルを更新すると、更新されたステータスが表示されます。
とのことなので、少し待ってからリロードします。
「アクセスが付与されました」となりました。これで使用可能です。
余談ですが「ユースケースの送信」はAnthropic共通で1度だけで良いですが、「モデルアクセスをリクエスト」はモデル毎に必要です。
IAMでロールの作成
LambdaからBedrockを呼び出せるようにするためにIAMでロールを作成します。
AWS Identity and Access Management (IAM) は、AWS リソースへのアクセスを安全に管理するためのウェブサービスです。IAM を使用すると、ユーザーがアクセスできる AWS のリソースを制御するアクセス許可を集中管理できます。IAM を使用して、誰を認証 (サインイン) し、誰にリソースの使用を認可する (アクセス許可を付与する) かを制御します。
まず「ロールを作成」のページに行きます。
「信頼されたエンティティタイプ」として「AWSのサービス」を、ユースケースとしてLambdaを選択して次へを押します。
許可ポリシーとしてAmazonBedrockFullAccessを選択して次へを押します。AmazonBedrockReadOnlyだとこの後の処理実行時にAccessDeniedExceptionが起きます。
ロール名をつけます。私はわかりやすく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関数の設定
基本的にはほぼデフォルト設定で動くのですが、タイムアウトだけはデフォルトの3秒のままだとレスポンスが間に合わないので30秒に伸ばしました。
コード
Anthropic Claude Messages APIのCode examplesを参考にして書きました。
Lambdaに渡されてきたjsonのmessageを参照して、それを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
}
テスト
テストのページに移動して、以下の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モデルを指す。
Lambdaに渡されてきたjsonのmessageを指示、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の示す画像は過去記事で生成したこちらです。
テストしたところ、レスポンスは以下のようなものでした。
{
"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株式会社 採用サイトよりご確認ください。