22
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【コード38行】初心者向き超シンプルなLambdaを用いた生成AIアプリ開発のやり方

Last updated at Posted at 2025-06-16

はじめに

現在新卒研修中であり,チームメンバーから「Bedrockの使い方を教えて欲しい」という声がありました.
今回は,簡単に生成AIを用いたアプリケーションを開発することのできる「Bedrock」を用いた簡単なテキストチャットアプリを作成します.
エラーハンドリング等の処理をすべて省き,Bedrockでclaude4-sonnetに質問をしてその返答をreturnするだけのシンプルなLambda関数を作成しました.
はじめてLambdakを触るような人にもわかるように解説していきます.
その関数のコードをもとに,使い方を解説していきます.
また,Bedrockの使用にはAIがよく出力するInvokeModelではなくconverseを使用します.

使用するAWSリソース

  • Lambda: Bedrockにプロンプトを入力し,推論結果を返す関数を作成する
  • IAM: LambdaにBedrockへのアクセスを許可する
  • Bedrock: 使用可能な生成AIのモデルアクセスを選択する

Lambda関数の準備

AWS マネージメントコンソールから,Lambda関数を作成する

  1. マネージメントコンソール上から,Lambdaを検索し,クリックする.
    スクリーンショット 2025-06-10 17.32.06.png

  2. 添付画像右上の[関数の作成]をクリックする.
    スクリーンショット 2025-06-10 17.30.55.png

  3. Lambda関数を作成する
    添付画像と同じように設定する
    スクリーンショット 2025-06-10 17.37.02.png

関数名:simple-bedrock
ランライム:python3.13
アーキテクチャ:x86_64

その他は何もいじらなくて大丈夫です.
また,ランタイムはPython3.9以上であればどのバージョンを使用しても問題ありません.

以下のUIになれば大丈夫です.これでLambda関数の準備は終わりました.
スクリーンショット 2025-06-10 17.40.26.png

Bedrockの有効化

  1. リージョンを「バージニア北部(us-east-1)」に変更する
    Bedrockで使用する生成AIのモデルは,このリージョンで最も安定して動きます.
    そのため,東京(ap-northeast-1)リージョンのLambda関数で,
    バージニア北部(us-east-1)リージョンにあるBedrockの生成AIモデルを使用します.
    スクリーンショット 2025-06-10 17.45.16.png

  2. 左のバーの下部にあるモデルアクセスをクリックする.
    Bedrock configurationsの中にあるはずです.
    スクリーンショット 2025-06-10 17.47.29.png

  3. モデルアクセスを変更をクリックする.
    使用したい生成AIのモデルにチェクマークを入れ,[次へ]から[送信]してください.
    今回は全て選択してもらっても大丈夫です.

数分待てば,今申請したモデルが使用可能になり,Bedrockの有効化が完了したことになります.

LambdaからBedrockにアクセス可能にする

LambdaのIAMロールにBedrockへのアクセスを許可しないと,
Bedrockを呼び出す権限がない.というエラーになります.

  1. Lambda関数を開き,[設定]タブから[アクセス権限]に行きます.
    スクリーンショット 2025-06-10 18.03.07.png

  2. [ロール名]の下にリンクがあると思うので,そこからIAMロールというものを設定していきます.
    [許可]タブから[許可ポリシー]の[許可を追加]→[インラインポリシーを作成]
    JSONを選択し,以下のjsonを貼り付けて,[次へ].

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"bedrock:InvokeModel",
				"bedrock:InvokeModelWithResponseStream"
			],
			"Resource": [
				"arn:aws:bedrock:*:*:foundation-model/anthropic.*",
				"arn:aws:bedrock:*:*:inference-profile/us.anthropic.*",
				"arn:aws:bedrock:*:*:inference-profile/eu.anthropic.*"
			]
		}
	]
}

スクリーンショット 2025-06-16 22.41.36.png

3.ポリシー名を決め,[ポリシーの作成]をクリックします.
今回はsimple-bedrock-policyとしましょう.
これでLambdaからBedrockを使用することができるようになります.

Lambda関数を書く

今回はライブラリにboto3とjsonしか用いないため,コンテナイメージやLambdaレイヤーなどの準備をする必要はないです.このコードを貼り付けて,イベントJSONを入力すれば動きます.

完成コード

lambda_function.py
import json
import boto3


def lambda_handler(event, context):
    # プロンプトを取得
    prompt = event.get("prompt")
    
    # Bedrockクライアントを作成
    bedrock_client = boto3.client('bedrock-runtime', region_name='us-east-1')
    
    # Converseを呼び出し
    response = bedrock_client.converse(
        modelId="us.anthropic.claude-sonnet-4-20250514-v1:0",
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "text": prompt
                    }
                ]
            }
        ],
        inferenceConfig={
            "maxTokens": 1000
        }
    )
    
    # レスポンスから結果を取得
    result = response['output']['message']['content'][0]['text']
    
    # 結果を返す
    return {
        "prompt": prompt,
        "result": result
    }

イベントJSON

{
  "prompt": "日本の三大武将を教えて"
}

一度実行してみましょう.

  1. [コード]タブの中の[コードソース]のlambda_function.pyに完成コードを貼り付けます.
  2. [Deploy]をクリック,もしくはShift + Cmd + Uでデプロイします.
  3. [設定]タブの[一般設定]の[編集]をクリックし,[タイムアウト]をデフォルトの3秒から30秒に変更し,保存します.
  4. [テスト]タブの[イベントJSON]に上記のjsonを貼り付け,オレンジ色のテストボタンをクリックし,[テスト]を行います.
    スクリーンショット 2025-06-10 21.35.17.png

テストで成功するとこのようなUIになります.
スクリーンショット 2025-06-10 21.45.57.png
詳細を確認すると,以下のようになっています.
スクリーンショット 2025-06-10 21.46.48.png

{
  "prompt": "日本の三大武将を教えて",
  "result": "日本の三大武将としてよく挙げられるのは、以下の3人です。\n\n1. 源頼朝(1147年-1199年)\n鎌倉幕府を開いた初代将軍。平氏一門を討伐し、武家政権の基礎を築きました。\n\n2. 織田信長(1534年-1582年) \n天下布武を目指した戦国大名。本能寺の変で暗殺されましたが、東西の統一に大きく貢献しました。\n\n3. toyotomi 秀吉(1537年-1598年)\n甲斐武田家の家臣から出世し、関ヶ原の戦いで徳川家康に勝利しました。全国統一を達成した太閤です。\n\nこの3人の武将は、日本の歴史に大きな足跡を残し、時代を画する活躍をしたことから、三大武将と呼ばれています。頼朝は武家政権の祖、信長は統一への布石、秀吉は実際の統一を成し遂げた、という位置付けです。"
}

今回は日本の三大武将を教えてという内容のプロンプトを推論させました.
イベントJSONのpromptに与える文字列を好きに変えてみると,その文字列の回答がresultとして返されます.

コードの解説

ライブラリのインポート

import json
import boto3

pythonでjsonの操作を行うため,jsonライブラリをインポートしてます.
boto3はpythonでAWSリソースを扱うためのライブラリです.今回の場合,このboto3でbedrockを使用しています.

lambda_handler関数の宣言

def lambda_handler(event, context):

C言語のmain関数と同じです.APIの呼び出しなどによってLambda関数が実行された場合,このlambda_handlerの中の処理が行われます.
また,2つの引数event,contextがあります.
イベントJSONに入っているjsonはこのeventに渡されます.
contextは,Lambda関数の関数名やランタイムなどの情報が入っています.

プロンプトを取得

    prompt = event.get("prompt")

生成AIに推論させる内容であるpromptに,イベントJSONのpromptを渡しています.
つまり,今回の場合,prompt = "日本の三大武将を教えて"と同義です.

Bedrockクライアントを作成

    bedrock_client = boto3.client('bedrock-runtime', region_name='us-east-1')

クライアントとは,この場合接続窓口を表します.
bedrockを使用するため,窓口を作成する必要があります.boto3を使用し,バージニア北部(us-east-1)にあるbedrockのbedrock-runtimeを使用する宣言をします.bedrock-runtimeは,AWSが提供するAI推論サービス,つまりBedrockのことです.

Bedrock呼び出し

    response = bedrock_client.converse(
        modelId="us.anthropic.claude-sonnet-4-20250514-v1:0",
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "text": prompt
                    }
                ]
            }
        ],
        inferenceConfig={
            "maxTokens": 1000
        }
    )

少し前に定義したbedrock_clientを使用し,Bedrockを呼び出します.
modelIdで使用するモデルを指定します.今回はanthropic社のclaude4-sonnetを使用します.
modelIdはマネジメントコンソール上のBedrockのModel catalogから確認できます.
messagesの中のtextにAIに推論してほしい内容を入れます.
推論結果を含めて様々な情報がこの変数responseに代入されます.

レスポンスの解析

    result = response_body['output']['message']['content'][0]['text']

responseには,欲しい情報以外にも様々な情報が含まれます.具体的には以下の感じです.

{'ResponseMetadata': {'RequestId': '1234567890',
'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Mon, 16 Jun 2025 13:49:27 GMT', 
'content-type': 'application/json', 'content-length': '1197', 
'connection': 'keep-alive', 'x-amzn-requestid': '1234567890'}, 'RetryAttempts': 0}, 
'output': {'message': {'role': 'assistant', 
'content': [{'text': '日本の三大武将として一般的に挙げられるのは以下の3人です:
\n\n## **織田信長(1534-1582)**\n- 戦国時代の革新的な武将
\n- 楽市楽座や兵農分離など革新的な政策を実施\n- 天下統一の基盤を築いた
\n\n## **豊臣秀吉(1537-1598)**\n- 信長の後継者として天下統一を達成
\n- 農民出身から関白まで上り詰めた立身出世の代表例\n- 刀狩りや太閤検地などの政策を実施
\n\n## **徳川家康(1543-1616)**\n- 江戸幕府の初代将軍
\n- 関ヶ原の戦いで勝利し、約260年続く江戸時代の基礎を築いた
\n- 忍耐強い性格で「鳴くまで待とう時鳥」の句で知られる
\n\nこの3人は「戦国三英傑」とも呼ばれ、それぞれが天下統一に向けて重要な役割を果たし、
日本史上最も有名な武将として親しまれています。'}]}},
'stopReason': 'end_turn', 'usage': {'inputTokens': 19, 
'outputTokens': 348, 'totalTokens': 367}, 'metrics': {'latencyMs': 12345}}

今回の場合,欲しいのはこの中のoutputの中のmessageの中のcontentの最初の要素のtext要素だけです.
なのでresult = response_body['output']['message']['content'][0]['text']responseの中を読み込み,必要な部分だけをresultに代入しています.

結果を返す

    return {
        "prompt": prompt,# 元の質問
        "result": result # AIのかいとう
    }

これが最終的なLambda関数の出力になります.
コードの解説は以上です.

発展

発展1:クエリパラメータでpromptを受け取る

完成コード

lambda_function.py
import json
import boto3


def lambda_handler(event, context):
    # クエリパラメータからプロンプトを取得
    prompt = event.get("queryStringParameters", {}).get("prompt")
    
    # Bedrockクライアントを作成
    bedrock_client = boto3.client('bedrock-runtime', region_name='us-east-1')
    
    # Converseを呼び出し
    response = bedrock_client.converse(
        modelId="us.anthropic.claude-sonnet-4-20250514-v1:0",
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "text": prompt
                    }
                ]
            }
        ],
        inferenceConfig={
            "maxTokens": 1000
        }
    )
    
    # レスポンスを解析して結果を取得
    result = response['output']['message']['content'][0]['text']
    
    # 結果を返す
    return {
        "prompt": prompt,
        "result": result
    }

API Gatewayの設定をする

このセクションでは,API Gatewayで,このLambda関数をGETメソッドで呼び出して使用できるようにする.
そのため,まずはAPI GatewayでAPIエンドポイントを発行する.

  1. マネージメントコンソールで[API Gateway]を検索し,クリックします.

  2. [APIを作成]をクリックします.

  3. APIタイプを選択で[HTTP API]を選択します.
    スクリーンショット 2025-06-16 21.02.21.png

  4. API名を決めて,[確認して作成]をクリックし,作成する.
    今回は[simple-bedrock-api]としましょう.
    スクリーンショット 2025-06-16 21.03.55.png

  5. [Routes]から[作成]をクリックする.
    スクリーンショット 2025-06-16 21.06.47.png

  6. メソッドは[GET]を選択し,[作成]する.
    スクリーンショット 2025-06-16 21.07.54.png

  7. [統合をアタッチする]→[統合を作成してアタッチ]で呼び出すLambda関数を選択する.
    スクリーンショット 2025-06-16 21.09.29.png

  8. [統合タイプ]にLambda関数を指定し,作成したLambda関数simple-bedrockを指定し,[作成]をクリックする.
    スクリーンショット 2025-06-16 21.13.35.png

  9. Lambda関数に戻り,[設定]の[トリガー]を確認すると,APIエンドポイントが発行されている.
    このURLを呼び出すと,Lambda関数が実行されるようになった.
    スクリーンショット 2025-06-16 21.14.20.png

  10. ブラウザを開いて,APIを呼び出してみる.
    エンドポイントのURLを貼り付けて,https://xxxxxx.amazonaws.com/?prompt=日本の有名な武将を教えて
    とし,Enterキーをクリックすると,しばらくして下記画像のように推論結果が返ってくる.
    ?prompt=xxxxxをクエリパラメータという.エンドポイント?クエリパラメータとすることによってそのクエリパラメータの部分がAIに渡すテキストとなり,そのテキストの内容を推論してくれる.クエリパラメータの部分に何も入力しないとエラーになる.
    スクリーンショット 2025-06-16 21.18.01.png

コードの変更点

before

# プロンプトを取得
    prompt = event.get("prompt")

after

# クエリパラメータからプロンプトを取得
    prompt = event.get("queryStringParameters", {}).get("prompt")

変更点はこの行だけであり,イベントJSONからpromptを受け取っていたのを,クエリパラメータから受け取るように変更しただけである.

発展2:POSTメソッドでJSONを受け取り,JSONの中にpromptを格納しておく

完成コード

こちらのコードも発展1と同様に,変更したのはprompt=json.loadsの部分1行だけです.

import json
import boto3


def lambda_handler(event, context):
    # POSTのJSONボディからプロンプトを取得
    prompt = json.loads(event.get("body", "{}")).get("prompt")
    
    # Bedrockクライアントを作成
    bedrock_client = boto3.client('bedrock-runtime', region_name='us-east-1')
    
    # Converseを呼び出し
    response = bedrock_client.converse(
        modelId="us.anthropic.claude-sonnet-4-20250514-v1:0",
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "text": prompt
                    }
                ]
            }
        ],
        inferenceConfig={
            "maxTokens": 1000
        }
    )
    
    # レスポンスを解析して結果を取得
    result = response['output']['message']['content'][0]['text']
    
    # 結果を返す
    return {
        "prompt": prompt,
        "result": result
    }

API Gatewayの設定をする

POSTメソッドを使用することにより,クエリパラメータを使用せず,イベントJSONを用いた時と同じようにしてpromptを渡すことができます.
発展1で使用したものと同じAPI Gatewayに設定を追加し,POSTで通信できるようにしましょう.

  1. 発展1で作成したAPI Gateway「simple-bedrock-api」を開く

  2. [Routes]から[作成]をクリックする.
    スクリーンショット 2025-06-16 21.33.20.png

  3. メソッドに[POST]を指定し,発展1で作成したAPIをエンドポイントが被らないように/postを指定し,作成します.
    スクリーンショット 2025-06-16 21.34.25.png

  4. 発展1と同様に,[統合をアタッチ]でsimple-bedrockLambda関数を統合する.
    スクリーンショット 2025-06-16 21.35.53.png

  5. Lambda関数に戻り,[設定]の[トリガー]を確認すると,新しく/postで終わるAPIエンドポイントが増えている.これを呼び出し,jsonでイベントJSONと同様のものを渡すとプロンプトが返ってくる.
    スクリーンショット 2025-06-16 21.37.20.png

  6. curlコマンドでAPI呼び出しテストを行う
    https:/xxxxxxx/postで終わるAPIエンドポイントに変えてください.

curl -X POST https://xxxxxxxx/post \
  -H "Content-Type: application/json" \
  -d '{"prompt": "日本の有名な武将を教えてください"}'

しばらくすると,推論結果が返ってくると思います.
自分はcurlコマンドの形式を覚えていないのでいつもPostmanを使って呼び出しテストを行なっています.

Postmanを使用してAPI呼び出しテストを行う.

  1. vscodeに拡張機能「Postman」をインストールする.
    スクリーンショット 2025-06-16 21.47.29.png

  2. インストールが完了すると,画像のように,拡張機能マークの下にPostmanマークが現れると思います.
    そのアイコンをクリックし,[New HTTP Request]からAPI呼び出しテストを行うことができます.
    スクリーンショット 2025-06-16 21.49.41.png

  3. 各種設定をする.
    ①POSTメソッドを選択し,APIエンドポイントを貼り付ける.
    ②[Body]→③[raw]→④[Text]を[JSON]に変更する.
    スクリーンショット 2025-06-16 21.51.55.png
    ⑤イベントJSONと同じようにjsonでpromptを指定する.

  4. [Send]をクリックする.
    しばらく経過すると,下記画像のように推論結果が出力される.
    スクリーンショット 2025-06-16 21.59.28.png

おわりに

今回はLambda+Bedrockで簡単なチャットが可能なLambda関数を作成しました.
これらのAPIをWebサイトに埋め込み,fetchaxiosで呼び出すことで簡単にチャットアプリを作成することができます.
しかし,今のままではAIと会話を続けていくことはできません.1つ前にどんな会話をしていたかを考慮していないからです.
そのため,次回ではDynamoDBを使用して会話を続けることのできるチャット機能の実装をします.

22
16
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
22
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?