事前準備
Amazon Bedrockを利用するためには、以下の事前準備が必要です。
- AWSアカウントの作成されていること
- マネジメントコンソールまたはAWS CLIが操作可能であること
- Node.jsがインストールされていること
Amazon Bedrockの有効化
Amazon Bedrockを有効にするための手順を以下に示します。
1. Bedrockサービスの有効化
- AWS Management Console にログインします。
- 検索バー に Amazon Bedrock と入力し、サービスを選択します。
-
使用開始 をクリックします。
- 左側のメニューから ベースモデル を選択し、 Titan Embeddings G1 - Text を選択します。
-
モデルアクセスをリクエスト をクリックします。
-
ベースモデル の リクエスト可能 から モデルアクセスをリクエスト をクリックします。
-
使用したいモデル を選択して Next をクリックします。
-
Submit をクリックします。
-
アクセスが付与されました と表示されれば成功です。
- 最後に ベースモデル から使用したいモデルの Model ID を控えておきます。
AWS Lambdaの設定
1. Lambda関数の作成
- AWS Management ConsoleでLambdaサービスに移動します。
-
Create function(または「関数の作成」) をクリックし、以下の設定で新しい関数を作成します:
-
関数名:
bedrock-titan-function
- ランタイム: Node.js 20.x
- アーキテクチャ: x86_64
-
関数名:
2. IAMロールの設定
Lambda関数がBedrockにアクセスできるように、IAMロールに以下のポリシーを追加します:
-
【リージョン】
と【アカウント ID】
は置き換えてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:【リージョン】:【アカウント ID】:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:【リージョン】:【アカウント ID】:log-group:/aws/lambda/bedrock-titan-function:*"
]
},
{
"Effect": "Allow",
"Action": "bedrock:*",
"Resource": "*"
}
]
}
開発時の【リージョン】は、東京リージョン( ap-northeast-1
)を使用しています。
3. 必要なモジュールのインストール
ローカル環境で @aws-sdk/client-bedrock-runtime
をインストールし、デプロイパッケージを作成します。
mkdir my-lambda-function
cd my-lambda-function
npm init -y
npm install @aws-sdk/client-bedrock-runtime
4. Lambda関数のコード
index.js
ファイルを作成します:
-
【リージョン】
は置き換えてください。
import {
BedrockRuntimeClient,
InvokeModelCommand,
} from "@aws-sdk/client-bedrock-runtime";
const client = new BedrockRuntimeClient({ region: "【リージョン】" });
export async function handler(event) {
const modelId = "amazon.titan-text-express-v1";
console.log("Received event:", event);
const userPrompt = event.prompt;
console.log(userPrompt);
if (!userPrompt) {
console.error("No user prompt provided");
return {
statusCode: 400,
body: JSON.stringify({ message: "No user prompt provided" }),
};
}
const payload = {
inputText: userPrompt,
textGenerationConfig: {
maxTokenCount: 4096,
temperature: 0,
},
};
try {
const command = new InvokeModelCommand({
contentType: "application/json",
body: JSON.stringify(payload),
modelId,
});
const apiResponse = await client.send(command);
const jsonString = Buffer.from(apiResponse.body).toString("utf8");
const parsedData = JSON.parse(jsonString);
console.log("API Response:", parsedData);
if (parsedData.results && parsedData.results[0].outputText) {
const text = parsedData.results[0].outputText;
console.log("Generated text:", text);
return {
statusCode: 200,
body: JSON.stringify({ text }),
};
} else {
console.error("Invalid response structure");
return {
statusCode: 500,
body: JSON.stringify({ message: "Invalid response structure" }),
};
}
} catch (error) {
console.error("Error calling model:", error);
return {
statusCode: 500,
body: JSON.stringify({ message: "An error occurred" }),
};
}
}
開発時の【リージョン】は、東京リージョン( ap-northeast-1
)を使用しています。
5. デプロイパッケージの作成
index.js
と node_modules
フォルダを含むZIPファイルを作成します。
zip -r function.zip .
6. Lambda関数のアップロード
AWS Management Consoleに戻り、作成したLambda関数に function.zip
ファイルをアップロードします。
Lambdaテスト
- Lambda関数をテストするために、以下のようなテストイベントを使用します:
- イベント名:
bedrock-test-001
{
"prompt": "AWS Lambdaとは何ですか?"
}
{
"statusCode": 200,
"body": "{\"text\":\"\\nAWS Lambdaは、サーバーを管理したり、コードをデプロイしたり、スケーリングしたりする必要がない、サーバーレスコンピューティングサービスです。 Lambdaは、イベントやトリガーに応じてコードを実行する、イベント駆動型コンピューティングの方法です。 これにより、開発者はコードを記述するだけで、AWSがサーバーを管理し、スケーリングします。\"}"
}
タイムアウトエラー解決方法
エラー内容
{
"errorType": "Sandbox.Timedout",
"errorMessage": "RequestId: hogehoge-aaaa-bbbb-cccc-fugafuga Error: Task timed out after 3.00 seconds"
}
原因
Lambdaのタイムアウト設定が 3秒
であるため
解決方法
Lambdaの 設定 > 一般設定 > 編集
からタイムアウトの設定を 1分0秒
に変更すると解決する。
Lambdaの処理解説
ソースコード(クリックして展開)
import {
BedrockRuntimeClient,
InvokeModelCommand,
} from "@aws-sdk/client-bedrock-runtime";
const client = new BedrockRuntimeClient({ region: "【リージョン】" });
export async function handler(event) {
const modelId = "amazon.titan-text-express-v1";
console.log("Received event:", event);
const userPrompt = event.prompt;
console.log(userPrompt);
if (!userPrompt) {
console.error("No user prompt provided");
return {
statusCode: 400,
body: JSON.stringify({ message: "No user prompt provided" }),
};
}
const payload = {
inputText: userPrompt,
textGenerationConfig: {
maxTokenCount: 4096,
temperature: 0,
},
};
try {
const command = new InvokeModelCommand({
contentType: "application/json",
body: JSON.stringify(payload),
modelId,
});
const apiResponse = await client.send(command);
const jsonString = Buffer.from(apiResponse.body).toString("utf8");
const parsedData = JSON.parse(jsonString);
console.log("API Response:", parsedData);
if (parsedData.results && parsedData.results[0].outputText) {
const text = parsedData.results[0].outputText;
console.log("Generated text:", text);
return {
statusCode: 200,
body: JSON.stringify({ text }),
};
} else {
console.error("Invalid response structure");
return {
statusCode: 500,
body: JSON.stringify({ message: "Invalid response structure" }),
};
}
} catch (error) {
console.error("Error calling model:", error);
return {
statusCode: 500,
body: JSON.stringify({ message: "An error occurred" }),
};
}
}
1. 必要なモジュールのインポート
import {
BedrockRuntimeClient,
InvokeModelCommand,
} from "@aws-sdk/client-bedrock-runtime";
この部分では、AWS SDKのBedrock RuntimeクライアントとInvokeModelCommandをインポートしています。
これにより、Amazon Bedrockのモデルを呼び出すためのクライアントとコマンドを使用できるようになります。
2. BedrockRuntimeClientの初期化
const client = new BedrockRuntimeClient({ region: "【リージョン】" });
ここでは、BedrockRuntimeClientを初期化しています。
region
には、使用するAWSリージョンを指定します。
:::note info
今回は、東京リージョン( ap-northeast-1
)を使用することを想定しています。
:::
3. Lambdaハンドラー関数の定義
export async function handler(event) {
const modelId = "amazon.titan-text-express-v1";
console.log("Received event:", event);
この部分では、Lambda関数のエントリーポイントである handler
関数を定義しています。
event
オブジェクトには、Lambda関数が呼び出されたときの入力データが含まれます。
modelId
には、使用するモデルのIDを指定しています。
ここで指定する modelId
は 1. bedrockサービスの有効化 で控えた Model ID
です。
4. ユーザー入力の取得と検証
const userPrompt = event.prompt;
console.log(userPrompt);
if (!userPrompt) {
console.error("No user prompt provided");
return {
statusCode: 400,
body: JSON.stringify({ message: "No user prompt provided" }),
};
}
ここでは、event
オブジェクトからユーザーの入力( prompt
)を取得し、ログに出力しています。
もし、 prompt
が提供されていない場合は、エラーメッセージを返します。
5. リクエストペイロードの作成
const payload = {
inputText: userPrompt,
textGenerationConfig: {
maxTokenCount: 4096,
temperature: 0,
},
};
この部分では、モデルに送信するリクエストペイロードを作成しています。
inputText
にはユーザーの入力を設定し、textGenerationConfig
にはテキスト生成の設定を指定しています。
maxTokenCount
は生成するトークンの最大数、temperature
は生成の多様性を制御するパラメータです。
6. モデル呼び出しコマンドの作成と送信
try {
const command = new InvokeModelCommand({
contentType: "application/json",
body: JSON.stringify(payload),
modelId,
});
const apiResponse = await client.send(command);
const jsonString = Buffer.from(apiResponse.body).toString("utf8");
const parsedData = JSON.parse(jsonString);
ここでは、InvokeModelCommand
を使用してモデル呼び出しコマンドを作成し、client.send
メソッドでコマンドを送信しています。
APIのレスポンスを受け取り、レスポンスボディをJSON形式に変換しています。
7. レスポンスの処理
console.log("API Response:", parsedData);
if (parsedData.results && parsedData.results[0].outputText) {
const text = parsedData.results[0].outputText;
console.log("Generated text:", text);
return {
statusCode: 200,
body: JSON.stringify({ text }),
};
} else {
console.error("Invalid response structure");
return {
statusCode: 500,
body: JSON.stringify({ message: "Invalid response structure" }),
};
}
} catch (error) {
console.error("Error calling model:", error);
return {
statusCode: 500,
body: JSON.stringify({ message: "An error occurred" }),
};
}
}
この部分では、APIレスポンスをログに出力し、レスポンスの構造を検証しています。
results
配列に outputText
が含まれている場合は、そのテキストを返します。
そうでない場合は、エラーメッセージを返します。
エラーが発生した場合は、エラーメッセージをログに出力し、500ステータスコードを返します。
GitHub
GitHubにコードを公開しています。
https://github.com/ryomeblog/lambda-bedrock-titan-test