この記事を読んで何を作れる?
レスポンス帰って来るまでちょっと時間かかります。
Amazon BedrockエージェントとNext.jsアプリを連携し、通常の会話はもちろん、
都市の天気についての質問にも最新の情報を取得して答えできるアプリが作れます。
アーキテクチャ
ローカル開発時のアーキテクチャーは上記の図になります。
もしご好評でしたら、次回の記事でcdk使ってデプロイまでやります
そもそもBedrockって何?
AWSが提供する基盤モデルを使用して生成 AI アプリケーションを構築およびスケーリングする最も簡単な方法らしいです。
詳しく知りたい方はこちらの資料をご覧ください。
事前準備
AWSのアカウント
BedRock モデルの有効化
AWSアカウントが準備できましたら、コンソールからAmazon Bedrockを開いて、
モデルアクセスから今回使用するClaude 3.5 Sonnet
モデルへのアクセス申請を行ってください。
いくつかの質問に回答すると、しばらくしてアクセスが付与されます。
OpenWeather - APIキー
OpenWeatherMapは、Webやモバイルアプリケーションの開発者に、現在の天候や予測履歴を含む各種気象データの無料APIを提供するオンラインサービスである。
アカウントを作ったらメニューバーのMy API Keys
からApiKeyを入手できます。
一点注意すべきなのはApiKey生成後、しばらく待たないと使用できないことです。
エージェント作成
Amazon Bedrockの左にあるメニューバーからエージェントを開いて、エージェントを作成します。
エージェントの名前をweather-agent
にして、説明文を入れて作成します。
作成されたら、あらかじめ有効化にされたモデルを選びます、その他の設定は一旦デフォルトのままにしましょう。
次、アクショングループを作成します。
追加ボタンをクリックすればアクションを追加画面が開きます。
- アクショングループ名を入力します:
action-group-get-weather
- 説明を入力します:
get weather action group
- アクショングループタイプ:
APIスキーマで定義
を選択します - アクショングループの呼び出し:
新しい Lambda 関数をすばやく作成する - 推奨
にチェックを入れます - アクショングループスキーマは:
インラインスキーマエディタで定義
を選びます
インラインオープン API スキーマ
は下記のように定義します。
openapi: 3.0.0
info:
title: GetWeather
version: 1.0.0
paths:
/weather:
get:
summary: Search
description: Retrieve current weather information for a specified city
operationId: searchGetWeatherInfo
parameters:
- name: cityName
in: path
description: Name of the city to get weather information for API
required: true
schema:
type: string
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
body:
type: string
最後作成
をクリックします、しばらくしたらエージェントビルダーのメイン画面に戻されます。
そしたら、アクショングループから先ほど作られたアクションを確認できます。
アクションの名前をクリックして、編集画面に入ります。
その画面のLambda 関数を選択
から表示
ボタンをクリックしてください。
別タグからLambda関数の編集画面が表示されると思います。
エージェントビルダー画面から新しいLambdaを作成する場合、現在Python製になる一択です。
Lambdaコードを下記のように修正して、Deployしてください。
OpenWeatherMapのAPIKeyは一旦ベタ書きします。
import json
import urllib.request
import urllib.parse
from datetime import datetime
def lambda_handler(event, context):
api_key = "" # ご自身のキーを入れてください。
get_parameters = event.get("parameters", [])
city_name = get_parameters[0].get("value", "New York City")
print("city_name:", city_name)
base_url = "http://api.openweathermap.org/data/2.5/weather"
query_params = {
"q": city_name,
"appid": api_key,
"lang": "ja",
"units": "metric"
}
url = f"{base_url}?{urllib.parse.urlencode(query_params)}"
try:
with urllib.request.urlopen(url) as response:
if response.status != 200:
raise Exception(f"HTTP Error: {response.status}")
data = json.loads(response.read().decode("utf-8"))
weather_description = data["weather"][0]["description"]
temperature = data["main"]["temp"]
feels_like = data["main"]["feels_like"]
humidity = data["main"]["humidity"]
wind_speed = data["wind"]["speed"]
sunrise_time = datetime.fromtimestamp(data["sys"]["sunrise"]).strftime('%H:%M')
sunset_time = datetime.fromtimestamp(data["sys"]["sunset"]).strftime('%H:%M')
contents = {
"city": city_name,
"weather": weather_description,
"temperature": temperature,
"feels_like": feels_like,
"humidity": humidity,
"wind_speed": wind_speed,
"sunrise": sunrise_time,
"sunset": sunset_time
}
message = (f"{city_name}の現在の天気は{weather_description}、気温は{temperature:.1f}℃です。"
f"体感温度は{feels_like:.1f}℃、湿度は{humidity}%、風速は{wind_speed}m/sです。"
f"日の出は{sunrise_time}、日の入りは{sunset_time}です。")
contents["message"] = message
except Exception as e:
contents = {"error": f"天気情報の取得中にエラーが発生しました: {str(e)}"}
response_body = {"application/json": {"body": json.dumps(contents)}}
action_response = {
"actionGroup": event.get("actionGroup", ""),
"apiPath": event.get("apiPath", ""),
"httpMethod": event.get("httpMethod", ""),
"httpStatusCode": 200,
"responseBody": response_body,
}
api_response = {"messageVersion": "1.0", "response": action_response}
return api_response
次、Lambda関数の設定から、アクセス権限を選び、リソースベースのポリシーステートメントからagentsInvokeFunction
をチェック入れて編集します。
ポリシーの編集画面でソース ARNにエージェントのARN
を貼り付けて、アクションをlambda:InvokeFunction
を選択します。
エージェント ARNは該当エージェントのメイン画面から入手できます。
設定完了したら、保存してAmazon Bedrockエージェントの画面に戻ります。
次にエージェント向けの指示
を入力します。いわゆるプロンプトです。
今回の目的は、エージェントに天気について質問した際に、アクションを使ってリアルタイムの情報を取得し、それを元に回答してもらうことです。
また、OpenWeatherMap の API は都市名に英語でしか対応していません。そのため、日本語の都市名が入力された場合には、適切に英語に翻訳してから問い合わせてくれると便利です。
あなたはリアルタイムの天気情報を取得してユーザーに回答するエージェントです。以下の条件に従って行動してください:
1.ユーザーからの一般質問に関して、任意に回答してください。
2.ユーザーから天気情報に関する質問はアクション使って回答してください。
3.ユーザーから日本語で都市名を指定された場合、その都市名を英語に翻訳してから使ってください。
ユーザーが指定しない場合、デフォルトの都市名は「Tokyo」としてください。
入力完了しましたら、保存
してから準備
をクリックしてください。
予想通りの結果が返ってきましたね、次はフロントエンドの実装をやっていきます。
チャット画面の実装
最初は Next.js プロジェクトを 0 から構築してすべて解説する予定でしたが、
尺の都合で、こちらのリポジトリをクローンしてご利用ください。
Starいただけると励みになります
クローン後、ルートディレクトリの配下に.env
ファイルを作ってください。
NEXT_PUBLIC_AWS_REGION=
NEXT_PUBLIC_AWS_ACCESS_KEY_ID=
NEXT_PUBLIC_AWS_SECRET_ACCESS_KEY=
NEXT_PUBLIC_AWS_SESSION_TOKEN=
NEXT_PUBLIC_AWS_AGENTID=
NEXT_PUBLIC_AWS_AGENT_ALIASID=
環境変数それぞれの意味を説明します。
- NEXT_PUBLIC_AWS_REGION
先作ったBenrock Agentが存在するリージョン、東京リージョンの場合:ap-northeast-1
- NEXT_PUBLIC_AWS_ACCESS_KEY_ID
- NEXT_PUBLIC_AWS_SECRET_ACCESS_KEY
- NEXT_PUBLIC_AWS_SESSION_TOKEN
AWS Identity Center
を利用している方は、アクセスポータルからアクセスキーなどをコピーしてご使用ください。
利用していない方は、Bedrock 用の IAM ユーザーを作成し、AmazonBedrockFullAccess
ポリシーを付与した上で、アクセスキーとセキュリティキーをコピーしてご使用ください、IAM ユーザー利用される場合、NEXT_PUBLIC_AWS_SESSION_TOKEN
は不要です。
- NEXT_PUBLIC_AWS_AGENTID
- NEXT_PUBLIC_AWS_AGENT_ALIASID
同じくエージェント概要一覧画面の最下部でエイリアス作成できます、作成されたエイリアンID
を利用しましょう
ローカルでの動作確認は下記のコマンドを実行してください。
$ npm i
$ npm run dev
最後に
完成品は下記の図のような感じになります。
デプロイやIaCに興味がある方がいらっしゃれば、今度また別の記事でご紹介します