0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

とりあえずBedrockを個人利用としてLambdaで実行するまで

Posted at

事前準備

Amazon Bedrockを利用するためには、以下の事前準備が必要です。

  • AWSアカウントの作成されていること
  • マネジメントコンソールまたはAWS CLIが操作可能であること

  • Node.jsがインストールされていること

Amazon Bedrockの有効化

Amazon Bedrockを有効にするための手順を以下に示します。

1. Bedrockサービスの有効化

  1. AWS Management Console にログインします。
  2. 検索バー に Amazon Bedrock と入力し、サービスを選択します。
    001.jpg
  3. 使用開始 をクリックします。
    002.jpg
  4. 左側のメニューから ベースモデル を選択し、 Titan Embeddings G1 - Text を選択します。
    003.jpg
  5. モデルアクセスをリクエスト をクリックします。
    004.jpg
  6. ベースモデルリクエスト可能 から モデルアクセスをリクエスト をクリックします。
    005.jpg
    006.jpg
  7. 使用したいモデル を選択して Next をクリックします。
    007.jpg
  8. Submit をクリックします。
    008.jpg
  9. アクセスが付与されました と表示されれば成功です。
    009.jpg
  10. 最後に ベースモデル から使用したいモデルの Model ID を控えておきます。
    010.jpg

AWS Lambdaの設定

1. Lambda関数の作成

  1. AWS Management ConsoleLambdaサービスに移動します。
  2. 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": "*"
		}
	]
}

011.jpg
012.jpg
013.jpg

開発時の【リージョン】は、東京リージョン( 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 ファイルを作成します:

  • 【リージョン】 は置き換えてください。
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.jsnode_modules フォルダを含むZIPファイルを作成します。

zip -r function.zip .

6. Lambda関数のアップロード

AWS Management Consoleに戻り、作成したLambda関数に function.zip ファイルをアップロードします。

014.jpg
015.jpg

Lambdaテスト

  1. Lambda関数をテストするために、以下のようなテストイベントを使用します:
  • イベント名:bedrock-test-001
イベントJSON
{
  "prompt": "AWS Lambdaとは何ですか?"
}

016.jpg
2. テストを実行して以下のようなレスポンスとなれば成功。

{
  "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秒 に変更すると解決する。

017.jpg

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" }),
    };
  }
}

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を指定しています。

ここで指定する modelId1. 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

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?