1 はじめに
CX事業本部製造ビジネステクノロジー部の平内(SIN)です。
Agents for Amazon Bedrockでアクションの定義を行う場合、次の2種類の方法があります。
- Set up an OpenAPI schema
- Set up function details
https://docs.aws.amazon.com/bedrock/latest/userguide/action-define.html
1.は、従来のOpenAPI標準のスキーマを準備する方法で、2.は、先月、新しく追加された簡素化された設定です。
Apr 23, 2024 - Amazon Bedrock のエージェントでエージェント作成が簡素化され、Return of Control 機能をリリース
今回は、最初にOpenAPIのスキーマを使用した従来の定義方法でエージェントを作成し、これを簡素化された定義に変更することで、その移行方法を確認してみました。
最初に、サンプルで作成したエージェントが動作している様子です。
このエージェントは、天気情報を取得して、服装をアドバイスするものです。 参照する地域が変わると、天気情報が変化するため、レコメンドも変化していることが分かると思います。
2 OpenAPIスキーマーによる設定
Action group typeでは、Define with API schemasを選択し、Action group schemaで、S3に配置されたOpenAPIスキーマーを指定しています。
Lambdaは、天気情報を取得するために使われています。
天気情報については、OpenWeatherMapから3時間毎の天気情報を取得し、9時間分を整形して配列で返しています。
[
{"日時": "2024-05-24 09:00:00+09:00", "天気": "厚い雲", "気温(℃)": 21.58, "気圧": 1007, ・・・・},
{"日時": "2024-05-24 12:00:00+09:00", "天気": "晴れ", "気温(℃)": 27.18, "気圧": 1007, ・・・},
{"日時": "2024-05-24 15:00:00+09:00", "天気": "雨", "気温(℃)": 25.71, "気圧": 1006, "湿度": 33・・・}
]
なお、都市については環境変数で指定されており、使用場所に応じて変化させる想定です。
Lambda
import datetime
import json
import os
import requests
import pytz
def create_forecast_item(item):
date_str = str(
datetime.datetime.fromtimestamp(item["dt"], pytz.timezone("Asia/Tokyo"))
) # 日時
weather = item["weather"][0]["description"] # 天気
feels_like = item["main"]["feels_like"] # 体感温度
pressure = item["main"]["pressure"] # 気圧
humidity = item["main"]["humidity"] # 湿度
wind = item["wind"]["speed"] # 風速
clouds = item["clouds"]["all"] # 曇り率(%)
rainfall = item.get("rain", {}).get("3h", 0) # 雨量(mm)
return {
"日時": date_str,
"天気": weather,
"気温(℃)": feels_like,
"気圧": pressure,
"湿度": humidity,
"風速": wind,
"曇り率(%)": clouds,
"雨量(mm)": rainfall,
}
def get_weather_forecast(city, api_key):
url = "http://api.openweathermap.org/data/2.5/forecast?q={}&appid={}&lang=ja&units=metric".format(
city, api_key
)
forecast_data = requests.get(url).json()
if "list" in forecast_data:
list = forecast_data["list"]
return [create_forecast_item(item) for i, item in enumerate(list) if i < 3]
return []
def lambda_handler(event, context):
city = os.getenv("CITY")
api_key = os.getenv("API_KEY")
forecast = get_weather_forecast(city, api_key)
response = {
"actionGroup": event["actionGroup"],
"apiPath": event["apiPath"],
"httpMethod": event["httpMethod"],
"httpStatusCode": 200,
"responseBody": {
"application/json": {
"body": json.dumps({"forecast": forecast}, ensure_ascii=False)
}
},
}
api_response = {"messageVersion": "1.0", "response": response}
return api_response
OpenAPIのスキーマは、以下のとおりです。
openapi.yaml
openapi: 3.0.0
info:
title: 天気取得API
version: 1.0.0
description: 3時間毎の天気情報を取得するAPI
paths:
/get_weather:
post:
summary: 3時間毎の天気情報を取得するAPI
description: 3時間毎の天気情報が配列で返されます
operationId: get_weather
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
"200":
description: articless response
content:
application/json:
schema:
type: object
properties:
article:
type: string
description: 天気情報の配列
エージェント向けの指示
あなたは、外出の服装を、{天気}に合わせてアドバイスするファッションのプロです。
{天気}は{天気取得API}から取得できます。
ファッション・服装に関する事項は、エージェント自身で考えてください
アドバイスには、女性向けに具体的な服装を教えて下さい
アドバイスには、天気の情報や、注意事項を含めてください
アドバイスには、ちょっとした励ましの言葉を追加してください
### 会話の例
ユーザー:何を着て行けばいいでしょう?
エージェント:日中は穏やかですが、朝夕、気温が下がるので、少し上から羽織るものも用意したほうが良いでしょう。良い日になりますように!
ユーザー:今日、着ていく服のアドバイスを下さい
エージェント:今日は一日雨の予報です。小雨なので濡れる心配は少ないですが、長靴やレインコートを持っていくことをおすすめします。気温は朝が13度くらいで、日中は12度くらいに下がる見込みです。湿度も高いので、少し厚手の上着を羽織ることをおすすめします。楽しんで来てください!
ユーザー:どんな服装で出かければいいでしょう?
エージェント:朝は晴れですが、気温が低めですので、長袖の上着を羽織ることをおすすめします。 日中は高温多湿なので、半袖で過ごしやすいでしょう。日傘があると良いでしょう。 雨も少し降る可能性があるので、折り畳み傘を持参することをおすすめします。 楽しい1日になりますように!
3 簡素化された設定
続いて、簡素化された設定に変更してみます。
Action group typeでは、Define with function detailsの選択となり、Action group functionで、Lambdaの機能の説明や、パラメータ設定を行っています。(※今回は、Lambdaのパラメータは使用されていません)
実は、設定だけを変更してエージェントを使用すると、下記のようにLambdaの呼び出しが失敗します。
この原因は、簡素化された設定を使用する場合、Lmabdaのリクエスト及び、レスポンスの形式が変わるためです。
Lambdaのレスポンスを下記のように変更することで、エラー無く利用できるようになります。
def lambda_handler(event, context):
city = os.getenv("CITY")
api_key = os.getenv("API_KEY")
forecast = get_weather_forecast(city, api_key)
# 簡素化された設定の場合
response = {
"actionGroup": event["actionGroup"],
"function": event["function"],
"functionResponse": {
"responseBody": {
"TEXT": {"body": json.dumps({"forecast": forecast}, ensure_ascii=False)}
}
},
}
# OpenAPI Schemaの場合
# response = {
# "actionGroup": event["actionGroup"],
# "apiPath": event["apiPath"],
# "httpMethod": event["httpMethod"],
# "httpStatusCode": 200,
# "responseBody": {
# "application/json": {
# "body": json.dumps({"forecast": forecast}, ensure_ascii=False)
# }
# },
# }
api_response = {"messageVersion": "1.0", "response": response}
return api_response
今回は、Lambdaへのパラメータを使用していないので、上記の修正(レスポンス)だけで作業は完了でしたが、パラメータを使用している場合は、そこの修正も必要になります。
それぞれのパラメータ及び、レスポンスの形式については、下記にドキュメントがあります。
Configure Lambda functions to send information an Amazon Bedrock agent elicits from the user to fulfill an action groups in Amazon Bedrock
4 最後に
今回は、エージェントのアクション定義で「簡素化されたもの」を試してみました。 OpenAPIスキーマを準備するより、圧倒的に手軽だし、すべてがコンソール上で定義できるので、手返しも良くなって全然いい感じでした。
Set up function details 一択でいいのでは・・・って思ってしまってます。
5 参考にさせて頂いたリンク
Create an action group for an Amazon Bedrock agent
PDF
【WebAPI】OpenWeatherMapで3時間ごとの天気を取りたい【json】