👨‍🎤

【AWS】 Amazon API GatewayとLambdaでBedrockを使ってみる。(初心者)

2024/03/07に公開

はじめに

AWSはほんのちょっと触ったことがあるくらいで、ベストプラクティス等は全然わかっていません。
ご了承ください🙇
今回はBedrockのClaudeモデルをAPI経由で利用できるようにしてみました。

APIを作る

まずは、APIを作ってみようということで、下記の記事を参考にAPI GatewayとLambdaでHello World取得してみました。
https://zenn.dev/kouichirou/articles/a70a9e514a757b

モデルへのアクセスを管理する

公式ドキュメントに沿って、ポチポチしながらモデルへのアクセスを有効にします。
https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/model-access.html

LambdaからBedrockを利用する

APIを試せたら、あとはLambdaでBedrockを呼び出すだけです。
Hello World関数をそのまま使用し、必要な権限等を割り当てます。

今回は、LambdaからBedrockにアクセスしたいので、Lambdaの実行ロールにBedrockへのアクセス追加します。

設定 > アクセス権限 > 実行ロールをクリック

ロール > 許可を追加 > インラインポリシーを作成

JSONを選択し以下のように作成

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": "bedrock:*",
			"Resource": "*"
		}
	]
}

Lambda > コード
今回はNode.jsで書いてみました。

import { BedrockRuntimeClient, InvokeModelCommand } from "@aws-sdk/client-bedrock-runtime";

const client = new BedrockRuntimeClient({ region: "ap-northeast-1" });

  export async function handler(event) {
    console.log('Received event:', event);
  
  // event.bodyが存在するか確認し、JSONとしてパースする
  const body = event.body ? JSON.parse(event.body) : {};
  const userPrompt = body.prompt;
  console.log(userPrompt)
  
  // userPromptが未定義の場合の処理
  if (!userPrompt) {
    console.error('No user prompt provided');
    return {
      statusCode: 400,
      body: JSON.stringify({ message: "No user prompt provided" }),
    };
  }
  
  const dynamicPrompt = `\n\nHuman:${userPrompt} について100文字程度でわかりやすく教えてください。文章の末尾に「にゃん」をつけてください。\n\nAssistant: `;
  
  const input = {
    "modelId": "anthropic.claude-v2:1",
    "contentType": "application/json",
    "accept": "*/*",
    "body": JSON.stringify({
      "prompt": dynamicPrompt,
      "max_tokens_to_sample": 200,
      "temperature": 0.7
    })
  };

  try {
    const data = await client.send(new InvokeModelCommand(input));
    const jsonString = Buffer.from(data.body).toString('utf8');
    const parsedData = JSON.parse(jsonString);
  
    // APIレスポンスの構造をログに出力
    console.log('API Response:', parsedData);
  
    // completionが存在するかをチェック
    if (parsedData.completion) {
      const text = parsedData.completion;
      console.log('Generated text:', text);
      return {
        statusCode: 200,
        body: JSON.stringify({ text }),
      };
    } else {
      // completionが期待したデータを含んでいない場合のエラーハンドリング
      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" }),
    };
  }
}

結果

今回は、質問に対して100文字程度で語尾に「にゃん」と付けて回答するようにプロンプトを作ってみました。
ターミナルからAPIを叩いて試しました。

>curl -X POST -H "Content-Type: application/json" -d '{"prompt": "東京都はどこに国にありますか。について100文字程度でわかりやすく教えてください。文章の末尾に「にゃん」をつけてください。"}' <API endpoint>
{"text":" 東京都は日本国のほぼ中央に位置する首都圏にある都市ですにゃん。東京は政治・経済・文化の中心地で、日本で一番大きな都市ですにゃん。東京都には23区という特別区があり、そこに900万人以上が住んでいますにゃん。東京は技術革新の先進地で、ファッション、アニメ、ゲームなどの文化的影響力も大きいですにゃん。東京湾に面し、富士山が遠くに見える美しい都市ですにゃん。"}

感想

ChatGPTのAPIを利用したことがありますが、Amazon Bedrockもお手軽にAPIを利用できることがわかりました。モデルのパラメータをチューニングするなど、色々試してアプリなどに搭載していきたいです。

Discussion