記事を書こうと思ったきっかけ
勉強会のネタとしてBedrockを使ったAPIを作ることを実施しようと考えている。実施するために事前にやってみようと思った次第。
システムの全体像
かなりシンプルな構成。1時間半いかないくらいでのボリュームで勉強会を実施したいので、なるべくシンプルに。
準備
今回はBedrockが東京リージョンでしか使えないので、API GatewayやLambdaも東京リージョンに作成。
Bedrockのモデルは「Claude 3.5 Sonnet v1」を利用
Lambdaの設定
「Lambda」>「関数の作成」を選択。
Pythonを指定し、IAMロールは名前を付けて新規作成。
まずは、基本設定などを編集。おそらくタイムアウトは3秒だと短いので30秒に設定。また、作成したIAMロールにBedrockを利用するためのIAMポリシー(AmazonBedrockFullAccess)を付与。
一旦動作確認のために以下のページを参考にコードを作成し、適当なプロンプトに対して正しく応答が得られるかを試してみた。
import json
import boto3
bedrock_runtime = boto3.client('bedrock-runtime')
model_id = 'anthropic.claude-3-5-sonnet-20240620-v1:0'
request_body = json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1000,
"messages":[
{
"role":"user",
"content":"Amazon Bedrockについて日本語で教えて。"
}
]
})
def lambda_handler(event, context):
# TODO implement
response = bedrock_runtime.invoke_model(
body = request_body,
modelId = model_id,
contentType = 'application/json'
)
parsed_response = json.loads(response.get('body').read())
output_text = parsed_response['content'][0]['text']
return {
'statusCode': 200,
'body': output_text
}
以下のようなリターンが返ってきた。いけてそう。
Response:
{
"statusCode": 200,
"body": "Amazon Bedrockは、AWSが提供する完全マネージド型のサービスで、大規模言語モデル(LLM)や生成AI用のAPIを簡単に利用できるプラットフォームです。以下にBedrockの主な特徴を挙げます:\n\n1. 多様なAIモデル:\n Anthropic、AI21 Labs、Stability AI、Amazon等の様々なプロバイダーのAIモデルにアクセスできます。\n\n2. サーバーレス:\n インフラストラクチャの管理が不要で、使用した分だけ料金を支払う方式です。\n\n3. プライバシーとセキュリティ:\n データはAWS内で暗号化され、プライベートエンドポイントの使用も可能です。\n\n4. カスタマイズ機能:\n ファインチューニングやプロンプトエンジニアリングにより、モデルをカスタマイズできます。\n\n5. 統合性:\n 他のAWSサービスとシームレスに統合できます。\n\n6. スケーラビリティ:\n 需要に応じて自動的にスケールします。\n\n7. コスト効率:\n 必要な時に必要なだけリソースを使用できます。\n\nBedrockを使用することで、企業は複雑なAI技術を簡単に自社のアプリケーションやサービスに組み込むことができます。これにより、チャットボット、コンテンツ生成、データ分析など、様々な用途にAIを活用することが可能になります。"
}
Bedrockでモデルを呼び出し実行したい場合はboto3.client
にはbedrock-runtime
を指定する必要がある。また、bedrock-runtime
でモデルを呼び出し実行したい場合、modelId
とモデルごとに決められたbody
を指定する必要がある。
今回ClaudeのMessages APIで必要なbody
において、必須のパラメータは以下の通り。
{
"anthropic_version": "bedrock-2023-05-31" //anthoropicのバージョン
"max_tokens": 1000, //生成するトークンの最大数
"messages":[ //プロンプトに入力するメッセージ
{
"role":"user", // 会話の順番の役割でuserもしくはassistantを指定
"content":"Amazon Bedrockについて日本語で教えて。" // 会話内容。画像の指定も可能らしい。
}
]
}
他にもオプションで回答のランダム性など指定可能。Anthoropic Claudeのバージョン2.1以降であれば、あらかじめsystem
パラメータで特定の目標や役割をインプットできる。例えば「あなたは優秀な校閲者です」的な。
次にAPI Gatewayから受け取ったデータをBedrockに投げる形に変更。
system
パラメータで事前に役割を指定し、クエリパラメータで受け取った単語に対して応答を返すような形にしてみる。
import json
import boto3
import logging
logger = logging.getLogger()
logger.setLevel("INFO")
bedrock_runtime = boto3.client('bedrock-runtime')
model_id = 'anthropic.claude-3-5-sonnet-20240620-v1:0'
def lambda_handler(event, context):
# TODO implement
logger.info(event)
input_text = event['queryStringParameters']['input_text']
request_body = json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 100,
"messages":[
{
"role":"user",
"content":input_text
}
],
"system":"あなたは有名でとても面白い芸人です。以下の単語に基づいてギャグを生成し、ギャグのみを出力してください。"
})
response = bedrock_runtime.invoke_model(
body = request_body,
modelId = model_id,
contentType = 'application/json'
)
parsed_response = json.loads(response.get('body').read())
output_text = parsed_response['content'][0]['text']
return {
'statusCode': 200,
'body': json.dumps({
'output_text': output_text
}, ensure_ascii=False),
'isBase64Encoded':False,
'headers':{}
}
API Gatewayの設定
AWSコンソールより「API Gateway」>「API」>「APIを作成」をクリックし、「REST API」で構築を選択。
API名は適当につけてAPIエンドポイントタイプは「リージョン」を選択。これでリソースが作成されるので、「メソッドを作成」をクリックし、メソッドの作成を進める。
メソッドタイプをPOSTとしLambda関数との統合を設定。Lambdaプロキシ統合もONにした。そして、作成したLambdaを指定し、URLクエリ文字列パラメータでAPI呼び出し時に必要な情報を設定した。
いざテスト・・・!
「飴があめぇ」くらいな感じで返すのかと思いきや、意外と一捻りしてきた回答。。。
今回詰まったところ
Boto3のBedrockの使い方
Boto3にはBedrock ClientとBedrockRuntime Clientがあり、最初はBedrock Clientの方を参考にしていた。このBedrock ClientはFine-tuningなどモデルを調整したり評価したりするために使われる様子。
json.dumpsの扱い
ensure_ascii=False
を指定しておらず、文字化けしてしまっていた。デフォルトがTrueであるため、ASCII文字を含む場合は自動的にエスケープしないようにFalseの設定が必要とのこと。
解決していない部分
連続でリクエストすると、Internal server errorが返ってくる。
ログを見てみると「ThrottlingException」というのが出ている。何度もリクエスト送っているため制限がかかっている模様。これの対処については追々考えようと思う。
まとめ
とりあえず勉強会用の簡単な構成は作れたので、これをもとに資料を作っていこうと思う。
逆に短すぎるような気もしてきた。。。