14
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Agents for Amazon Bedrockでホテル予約エージェントを作ってみる過程

Posted at

こんなの作ってみました。

エージェント開発の試行錯誤っぷりをお楽しみください。

Agents for Amazon Bedrockの構築方法

前回の構成をもとにしました。

Agents for Amazon Bedrockの構築方法は他の方の投稿などを参照ください。
(皆さん、検証が早い!w)

概要

  • 概要図:

    ホテルの予約はGoogleカレンダーに登録するようにしました。APIが用意されていて簡単に使用できました。

    参考:Google Calendar API の概要

    image.png

  • API:

    はじめは予約を行うAPIと客室が空いているかをチェックするAPIの2つを用意しました。
    お試しなので、誰かが予約済みの場合は予約できないような感じで作りました。

    パス Description リクエストボディ(例)
    /reserve 予約を行うAPI {
    "reservation_holder": "string",
    "checkin": "2023-12-28",
    "checkout": "2023-12-28"
    }
    /is_vacancy 予約可能かどうかを判定するAPI {
    "checkin": "2023-12-28",
    "checkout": "2023-12-28"
    }
  • Model:

    ケチなのでanthropic.claude-instant-v1を選択しました。

  • Instructions for the Agent:

    あなたはホテルの予約管理を行うAIアシスタントです。 
    高級ホテルのフロントマンのように振る舞ってください。
    

Lambdaのソースコードはこちら。

試行錯誤

パターン①:ユーザー側が気を使って丁寧に入力する

まずは手始めに、ユーザーがAPI側に合わせた入力をしてくれるパターンです。
APIに必要なパラメーターは以下の3つです。

  • 予約者名
  • チェックイン日
  • チェックアウト日

一つの入力中にわかりやすく入れてみました。

期待通り動作しました。Googleカレンダーにも上手に登録されています。

パターン②:情報を小出しにしてみる

チャットでのやり取りっぽく、情報を小出しにしてみました。
情報が不足していると何が知りたいかを聞いてくれました。

ただ、予約に不要な連絡先をしつこく聞いてくる。。

こちらのパターンも、ちゃんと予約されました。

パターン③:もっと雑に依頼する

日付だけを雑に入力してみました。フォーマットが違うよと怒られます。

諦めずに挑戦してみますが、頑なに断ってきます。

実装を確認します。

APIの入力フォーマット
class is_vacancy_req(BaseModel):
    checkin: datetime.date = Field(description="チェックイン日")
    checkout: datetime.date = Field(description="チェックアウト日")

FastAPIのドキュメント(Extra Data Types)で確認したところ、datetime.dateで定義した値はISO 8601フォーマットである必要があるようです。

datetime.date
In requests and responses will be represented as a str in ISO 8601 format, like: 2008-09-15.

入力チェックが厳しく、API内でエラーになってました。

  • 解決方法

    1. 型定義をdatetime.date | strに変更

      class is_vacancy_req(BaseModel):
        checkin: datetime.date | str = Field(description="チェックイン日")
        checkout: datetime.date | str = Field(description="チェックアウト日")
      
    2. 受け取ったcheckincheckoutを関数内で文字列型変換する。
      dateutil.parserparseを使うことで、ある程度表記ゆれにも対応できるようです。(ドキュメント

        now = datetime.datetime.now(timezone)
        checkin = parse(request.checkin)
        checkout = parse(request.checkout)
      
        # 2023/12/28に1/1をパースすると、2023/1/1になるので、2024/1/1になるように調整
        if checkin.astimezone(timezone) < now:
          checkin = checkin + relativedelta.relativedelta(years=1)
        if checkout.astimezone(timezone) < now:
          checkout = checkout + relativedelta.relativedelta(years=1)
      

こうすることで、日付が適当なフォーマットでも予約できました。

しかーし!

John Doeって誰やねん。。

出典:Wikipedia

英語で「名無しの権兵衛」に相当するのは、ジョン・ドウ (John Doe) である。Doe 自体に架空の姓の意味がある。ジョンは、ありふれた男性の名前であり、女性が対象となる場合は同様の理由でジェーンが用いられ、ジェーン・ドウ (Jane Doe) となる。複数の「名無しの権兵衛たち」を表す場合はそれぞれジョン・ドウズ (John Does)、ジェーン・ドウズ (Jane Does) となる。

予約名は必ずユーザーに問い合わせるようにしたいです。
Instructions for the Agentに一行追加してみます。

  あなたはホテルの予約管理を行うAIアシスタントです。 
  高級ホテルのフロントマンのように振る舞ってください。
+ お客様名を間違えることは許されません。まずはお客様名を訪ねてください。

これで再挑戦したけど、改善しない。。。

さて、どうしたものか。。もうプロンプトで改善するアイディアは限界です。

モデルをClaude V2.1(anthropic.claude-v2:1)にしてみると、、、

お!改善!!

さすがClaude V2.1!!!

東京リージョンに来てくれてありがとうございます!!!
(当分、来ないんじゃないっすかぁ。。とか言いふらしてごめんなさい!!!)

パターン④:「来週末」みたいな言い方で予約したい

どんどん欲が出てきます。「来週の土日」で挑戦します。

わかってたことですが、日付が違います。(来週末は1/6です)

Claudeが日付を知ってる訳はないので、日付情報を取得できるよう、APIを追加しました。

パス Description リクエストボディ(例)
/get_today 処理当日の日付が取得できます

リクエストボディはありません。レスポンスは"2023/12/28"のように日付情報だけを返却します。

このAPIを足して再度挑戦です。

今週末を聞いてみると、、

いいね!

どことなくClaude 2.1にしたことでやり取りも丁寧になった気がします。
今週末がだめなので来週末で予約しました。

ホテルっぽいね!

パターン⑤:空いてる日を雑に聞く

どんどんイジワル質問がしたくなりますね。来週の月曜から水曜日で空いてるところありますか?と聞いてみました。

予約状況としては、火曜日から水曜日は予約が入ってますが、月曜日から火曜日は予約が入ってない状態でした。

一泊ではなく月曜日から水曜日の2泊の間が確保できるかチェックして、空いてないという判断になりました。

他の聞き方として、「1/8の週の水曜日」はどうでしょうか

.png

残念ながら1/3になりました。水曜日はあってるのですごいですね。

日付の計算は間違うこともまだありますね。

パターン⑥:予約の変更がしたい

予約の変更機能を追加します。

3つのAPIを足すイメージです。

  • 予約取得API
  • 予約変更API
  • 予約削除API

ですが、Agents for Amazon Bedrockのクオータ制限で、1つのAgentに5つのAPIまでしか含めることができません。
すでに3つAPIを使っているので、予約変更と予約削除を一つのAPIにして、フラグ制御をするようにしました。

パス Description リクエストボディ(例)
/get_my_reservation 自分の予約を取得するAPI {
"reservation_holder": "string"
}
/update_reservation 予約を更新するAPI {
"update_type": "update",
"reserve_id": "string",
"reserve_info": {
"reservation_holder": "string",
"checkin": "2023-12-28",
"checkout": "2023-12-28"
}
}

フラグでの制御とか、上手にできるか心配。。

予約の日付変更を実験

試行錯誤の結果、なんとか動きました!

色々やってる途中で、予約をキャンセルして別の日で取りますか?と、親切に言ってくれたので従ってみました。

いいですね!
ちゃんと1/6の予約が消えて、1/10に予約が入ってました。

つまずいたところ

  • リクエストパラメーターは必須だけで構成する

    API定義で必須でなくしたり、条件付きで必須にすると、自動生成されるプロンプトには含まれないことがわかった。

  • リクエストに深いネストはやめた方がいい

    パラメーターはフラットな形式にしないと正しく受け取れないように思う(FastAPIとの組み合わせのせいかもしれない)

まとめ

  • デバッグがつらい。どこまでうまく動いているのか、何がだめなのかが、生成されたプロンプトを追わないといけない
  • まだ上手く使いこなせていないのか、思ったように振る舞わせるのはまだまだ調整が必要
  • 1つのエージェントでAPIが5個までなので、それほど複雑なことはできなさそう
  • このままだと人の予約も見れちゃったりするので、プロダクションにはまだ遠い印象
14
7
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
14
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?