Amazon SageMakerで生成AIアプリを作成してみました。
こちらは前回の続きとなりますので、ぜひ前回の記事と合わせてご確認ください!
AWSのSageMakerで推論エンドポイントを設定してみた!
紹介概要
前回はJumpStart基盤モデルをSageMaker推論エンドポイントにデプロイして、動作確認するとこまで紹介しました。
今回はCloudFrontとS3でフロントページを作り、POSTされたリクエストでAPI GatewayからLambdaを呼び出すという一般的な構成で、Lambda関数でSageMakerの推論エンドポイントとやり取りするといった構成を作成します。
前回同様に動作環境は「Cloud Quest」上のテストアカウントにて実行しているため、一部準備されたものがあります。
「Cloud Quest」については下記の記事でご紹介しておりますので、ぜひご覧ください。
AWSのゲーム!?Cloud Questが日本語対応したのでやってみた!
フロント側サービスの作成
今回はSageMakerがメインテーマなのでLambda、API Gateway、その他フロント側サービスの詳細は省略しますが、一部設定を紹介します。
作成したLambda関数の一般設定からタイムアウトの項目を1minにします。タイムアウトを増やすことで、関数がSageMakerエンドポイントから応答を受信して処理するのに十分な時間が確保されます。
環境変数の編集からSageMaker推論エンドポイント名を貼付けます。環境変数を使用することで、コードを更新することなく関数の動作を調整できます。
Lambdaのコードを確認します。
# Import necessary libraries
import json
import boto3
import os
import re
import logging
# Set up logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# Create a SageMaker client
sagemaker_client = boto3.client("sagemaker-runtime")
# Define Lambda function
def lambda_handler(event, context):
# Log the incoming event in JSON format
logger.info('Event: %s', json.dumps(event))
# Clean the body of the event: remove excess spaces and newline characters
cleaned_body = re.sub(r'\s+', ' ', event['body']).replace('\n', '')
# Log the cleaned body
logger.info('Cleaned body: %s', cleaned_body)
# Invoke the SageMaker endpoint with the cleaned body as payload and content type as JSON
response = sagemaker_client.invoke_endpoint(
EndpointName=os.environ["ENDPOINT_NAME"],
ContentType="application/json",
Body=cleaned_body
)
# Load the response body and decode it
result = json.loads(response["Body"].read().decode())
# Return the result with status code 200 and the necessary headers
return {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS,POST'
},
'body': json.dumps(result)
}
# Invoke the SageMaker~のコードブロックでは、ペイロードを使用してSageMakerエンドポイントを呼び出し、応答を保存します。
# Return the resultのコードブロックでは、受信した応答をデコードし、JSON形式で返します。
S3でAPI Gatewayとやり取りするために必要なHTMLとJavaScriptを含むindex.htmlを作成します。処理を含む部分を下記に記載します。
<body>
<div class="container">
<h2>Introduction to Generative AI</h2>
<div id="apiForm">
<label for="apiGatewayUrl">API Gateway URL:</label>
<input type="text" id="apiGatewayUrl">
<label for="content">Prompt:</label>
<textarea id="content" rows="10"></textarea>
<button onclick="callApi()">Generate</button>
</div>
<div id="response">
<label for="output">Output:</label>
<textarea id="output" rows="10" readonly></textarea>
</div>
<h5><i>Please note: As with all AI-powered applications, outputs should be reviewed for accuracy and appropriateness.</i></h5>
</div>
<script>
function callApi() {
var apiGatewayUrl = document.getElementById('apiGatewayUrl').value;
var content = document.getElementById('content').value;
fetch(apiGatewayUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ inputs: content, parameters: { 'max_new_tokens': 400} })
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
if(data && data[0] && data[0].generated_text){
document.getElementById('output').value = data[0].generated_text;
} else {
throw new Error('Response is not in the expected format');
}
})
.catch((error) => {
console.error('Error:', error);
alert('An error occurred: ' + error.message);
});
}
</script>
</body>
CloudFrontでディストリビューション名をコピーし、ブラウザタブに張り付けるとフロントページが確認できます。
動かしてみた
作成したAPI GatewayのURLをコピーし、アプリケーション側に貼付け、プロンプトに質問を入力します。
AIによって質問への回答が出力されたことが確認できました!
上の画像では「AWS SageMakerで推論エンドポイントを立てるにはどのようにすれば良いでしょうか。」という質問に対しての出力が確認できます。
さいごに
SageMakerはデプロイ時に指定したインスタンスタイプに応じた料金が継続的に発生するので、不要になったら停止、削除まで行う必要があります。
普段使っている生成AIがどのような挙動で動いてるか、実際に作成することで理解が深まるのでぜひお試しください!