re:Invent 2025: ElastiCacheとAurora PostgreSQLで構築するサーバーレスチャットボット
はじめに
海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!
re:Invent 2025 の書き起こし記事については、こちらの Spreadsheet に情報をまとめています。合わせてご確認ください
📖re:Invent 2025: AWS re:Invent 2025 - Build serverless chatbots using Amazon ElastiCache & Aurora PostgreSQL (DAT314)
この動画では、架空の旅行プラットフォームFlightlyを題材に、ElastiCacheとAurora PostgreSQLを使ったサーバーレスチャットボットの構築方法が解説されています。応答遅延による年間5,000万ドルの損失という課題に対し、ElastiCacheによるキャッシング層とAurora PostgreSQLのpgvectorを活用したセマンティック検索を組み合わせることで、サブミリ秒のレスポンスを実現します。会話履歴、ユーザープロファイル、セッション状態をElastiCacheに保存し、永続的なセマンティックキャッシングで90%以上のキャッシュヒット率を達成。さらにStrands AgentsとModel Context Protocolを用いてチャットボットからagentic AIへ進化させ、最終的にBedrock AgentCoreで本番環境へのスケーリングを実現する実践的なアーキテクチャパターンが示されています。
※ こちらは既存の講演の内容を最大限維持しつつ自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますのでご留意下さい。
本編
Flightlyの課題:遅いチャットボットがもたらす年間5,000万ドルの損失
皆さん、こんにちは。4日目へようこそ。信じられないですね。皆さん、調子はどうですか、生き延びてますか?はい、良いですね。さて、4日目まで来られましたね。そして、この45分ほど、このセッションに参加することを決めていただき、とても嬉しく思います。こちらはセッション314です。私の名前はShayon Sanyalです。AWSのPrincipal Database Specialistをしています。本日は、ElastiCacheとAurora PostgreSQLを使ってサーバーレスチャットボットを構築する方法について深く掘り下げていきます。
今日、本番環境でAuroraを使っている方は?手を挙げていただけますか。おお、大多数の方ですね、わかりました。では、PostgreSQLをデータベースとして使ってチャットボットを構築している方は?誰もいませんね。わかりました。では、皆さんは正しい部屋にいますよ。それでは始めましょう。
本日のケーススタディはFlightlyです。これは架空の旅行プラットフォームで、顧客がフライトを検索したり、ホテルを予約したり、休暇を計画したりできるものです。本日は、このアーキテクチャを詳しく見ていきます。Flightlyがそれを構築するのをお手伝いします。そして、Flightlyが持つこの基本的なチャットボットを、エージェント型AIシステムへと進化させる方法も見ていきます。その過程で、皆さんが自分のシステムに適用できるような、再利用可能なアーキテクチャパターンをいくつか抽出していきます。それでは始めましょう。
金曜日の午後、私はハワイへの休暇を計画しています。Flightlyにクエリを入力すると、考え始めます。まだ考えています、まだ考えています、まだ続いています。 そこで私は、私たち皆がやることをします。メールをチェックしに行きます。そしてすぐに、この競合のIsland Airがフラッシュセールをしていることに気づきます。ハワイ行きのフライト、皮肉なことに、素晴らしい価格です。 Flightlyに戻ると、まだ考えています。私はIsland Airで予約します。完了です。 Flightlyは私を顧客として失いました。そしておそらく何千人もの他の顧客も失いました。製品が悪かったからではなく、チャットがあまりにも遅すぎたからです。
これがビジネスにどれだけのコストをもたらすかお見せしましょう。1回の予約に対する平均応答時間は30秒です。ユーザーの約半数がこのパフォーマンスの壁にぶつかります。平均予約額は約300ドルです。彼らは1日に100万件のリクエストを処理します。さて、業界データによると、1秒の遅延ごとにコンバージョンが7%失われます。非常に長い応答時間では、ほんのわずかなユーザーが離脱するだけでも、非常に速く積み重なっていきます。 つまり、計算してみると、毎日約1,500ドルの損失となり、これが年間5,000万ドルに膨れ上がります。では、これをどう修正すればよいのでしょうか?
スケールの壁:MVPから数百万ユーザーへの成長がもたらしたボトルネック
ここで重要なのは、Flightlyが始まった当初、彼らはこのような事態を予想していなかったということです。誰もがそうするように、スピードとスケールを目指して構築していたわけですが、チームは私たちの多くがやるであろうことをやりました。MVPを構築したんです。素早くスタートし、プラットフォームをローンチし、ユーザーの採用が加速していきました。 しかし、成功は新たな問題を生み出しました。数千人のユーザーが数百万人になり、突然、このスケールでなければ明らかに現れないような、まったく新しいボトルネックに直面することになったのです。そこで問題が変わってきました。1日あたり数百万のリクエストを処理しているときに、どうやってサブセカンドのレスポンスタイムを維持するのか?
Flightlyが扱っているのはこういうものです:顧客データと会社データです。私たち全員がデータベースに持っているようなデータと似ています。顧客データには、過去の予約、検索履歴、好みなどが含まれます。会社データは、フライトの在庫、ホテルの在庫、プロモーションなどです。このすべてのデータはAurora PostgreSQLに保存されています。何年も何年もの豊富なデータです。チャットボットにとって完璧な基盤ですね。
しかし、ここに問題があります。キャッシュがなければ、すべてのクエリがデータベースにヒットします。すべてのセマンティック検索がベクトル距離を再計算します。1日100万リクエストになると、まさに私たちが見たものが得られます:苦痛なレスポンスタイムです。さて、皆さんの直感では、より高速なデータベースに移行しようと思うかもしれません。しかし、それには新しいインフラ、新しいETLパイプライン、移行リスクが含まれます。そしてAuroraは何年も非常に安定して動作してきました。データベースが問題なのではなく、アクセスパターンが問題なのです。そこで、Auroraを信頼できる情報源として維持し、キャッシング層を追加します。これを覚えておきましょう。
現在のアーキテクチャを理解しましょう。ユーザークエリが入ってきます、「バリでビーチリゾートを見つけて」と。 システムはAuroraをナレッジベースとしてクエリします。関連するコンテキストを取得します、空室状況、季節ごとの価格設定、ユーザーの好みなどです。 これらすべてがコンテキストを考慮したシステムプロンプトに組み立てられます、これはLLMへの指示セットに他なりません。
システムプロンプトは2つのことを行います。 動作を定義します、つまり旅行に関する質問に答える、ナレッジベースを参照する、会話履歴を維持する、そして個性を設定します。温かく、熱心で、親切に。 この充実したプロンプトとユーザーの質問が大規模言語モデルに送られ、そこでカスタマイズされた応答が生成されます。
さて、単一ターンの会話、つまり単一のユーザーがこの質問をする単一のインタラクションに対しては、このアーキテクチャは素晴らしく機能します。完璧です。しかし、これを数千人のユーザーが同時に同じ質問や異なる質問をする規模にスケールさせると何が起こるか見てみましょう。今、複数のユーザーがシステムにアクセスしています。そして旅行業界では、私はこれをポテトルールと呼ぶのが好きなんです。クエリの80%は単に異なる質問なんです。それらは20の質問が異なる服を着ているだけなんです。
さて、レイテンシーが積み重なっていくのを見てください。オレンジの線は警告ゾーンです。赤い線は、今システムの限界に達しているところです。すべてのクエリが全く同じ高コストなパイプラインをトリガーします。クエリがデータベースにヒットし、距離計算があり、コンテキストを取得し、システムプロンプトを組み立て、LLMに送信します。各操作は約100ミリ秒を追加し、それが積み重なっていきます。すぐにお気づきになると思いますが、リクエストあたり0.2秒以上、500ミリ秒以上を費やすようになり、これはどんどん悪化していきます。
レスポンスタイムは500ミリ秒から5秒、30秒へと劣化し始めます。1日あたり100万ユーザーでは、このアーキテクチャは持続不可能です。アプリケーションチームに何が問題か尋ねれば、きっと全員がデータベースを指差すでしょう。しかし、データベースのせいではありません。アクセスパターンの問題なんです。
ElastiCacheによるスピードレイヤー:サブミリ秒のパフォーマンスを実現するキャッシング戦略
さて、少し前にキャッシングについて触れました。なぜそれが大規模な会話型AIにとって不可欠なのか、掘り下げていきましょう。ユーザーが手荷物ポリシーやよくある質問について尋ねたとき、キャッシュはそれを1ミリ秒未満で提供できます。データベースだった場合、それはディスクIO、バッファルックアップ、クエリパース、クエリ実行などです。そしてそれは約50ミリ秒かかります、ソリッドステートドライブ、SSDを使っていてもです。そしてすべてのデータベース接続はTCPハンドシェイク、TLSネゴシエーション、クロスアベイラビリティゾーンのラウンドトリップを意味します。それは各イテレーションあたり約5ミリ秒で、これはクエリがデータベースにヒットする前のプロトコルオーバーヘッドだけです。
APIエコノミクスです。ハワイ行きのフライトを見せてくださいというのは、おそらく毎日何千回も尋ねられます。キャッシュされていない各リクエストは推論コストを消費します。エンベディング生成があり、LLM呼び出しがあります。一度キャッシュすれば、そのコストをフリート全体で償却できます。最後に、定義上、セマンティック検索とセマンティックルックアップは、これらの1024、1536、3072のベクトル次元にわたるコサイン距離計算を意味し、おそらく何百万ものベクトルがあります。ですから、それらのトップK結果をキャッシュすることで、繰り返しクエリに対してこれらの重い浮動小数点コサイン距離演算を完全にスキップできます。これこそが私たちが求めているものです。これが私たちのアーキテクチャに追加しようとしているスピードレイヤーです。
さて、これはキャッシングがなぜ不可欠なのかについての素晴らしい導入となります。少し寄り道して、サービス側の話をしましょう。Amazon ElastiCacheは、私たちのフルマネージドキャッシングサービスです。Redis OSS互換、Memcached互換、そしてValkey互換です。アプリケーションは標準のRedisまたはValkeyプロトコルを使用して、単一のDNSエンドポイントに接続します。その背後には、この分散クラスター全体で接続の多重化を処理するマネージドプロキシフリートがあり、コンシステントハッシング、アベイラビリティゾーン間の非同期レプリケーション、サブミリ秒のフェイルオーバーなど、優れた機能を提供します。もちろん、サービスのメリットとして、スケーリングは自動です。
さて、これがFlightlyのボトルネックを解消するスピードレイヤーです。これがアーキテクチャをどのように変革するか見てみましょう。ElastiCacheの共有クラスターアーキテクチャは、データがどのアベイラビリティゾーンにあるかに関係なく、メモリから直接データを提供します。つまり、秒間100リクエストでも10万リクエストでも、一貫したマイクロ秒のP99レイテンシを保証します。
さて、re:Inventの直前、確かre:Inventの1週間ほど前だったと思いますが、ElastiCache向けのベクトル検索をローンチしました。そしてそれと共に、永続的なセマンティックキャッシングも提供しています。ElastiCache Valkeyの永続的セマンティックキャッシングにより、繰り返しクエリに対して実際に90%以上のキャッシュヒット率を達成しています。
つまり、10件のリクエストのうち9件がメモリから提供されるということです。
3つ目はレジリエンスです。すべてのシャードは、アベイラビリティゾーン間でリードレプリカを維持します。ハードウェアに障害が発生したとき、そして12月のホリデートラフィック中は、ハードウェアが故障する可能性が高いのですが、ElastiCacheは自動的に検出し、リードレプリカを昇格させて新しいライターにします。そしてもちろん、ホリデートラフィックは本質的に予測不可能です。春休みは通常の2月のベースラインの15倍に急増する可能性があります。そのため、ElastiCacheはそれを監視し、その成長に対応するために必要に応じて追加のシャードをプロビジョニングできます。
セマンティック検索とpgvector:Aurora PostgreSQLで実現するインテリジェンスレイヤー
さて、スピードの問題は解決しました。ミリ秒未満のレスポンスが得られています。しかし、これにはもう一つのコンポーネントがあります。今度はインテリジェンスが必要です。ユーザーは、select star from destinations where activities like beachなんて聞いてきません。 彼らは「サーフィンとパーティーができる場所はどこ?」と聞いてくるんです。そして、彼らは正確なクエリを繰り返しません。意図なんです。彼らはそれらのクエリについて意図を表現します。つまり、これらすべてはセマンティック検索と呼ばれるものに関連しています。セマンティック検索が実際にどのように機能するか見てみましょう。
まず、ドメイン知識から始めます。これは旅行ガイド、ホテルの説明、ビザポリシーなどです。Flightlyの場合、すべてがAurora PostgreSQLに入っています。 このコーパスを一口サイズのチャンクに分割します。そして、このデータを埋め込みモデルに通します。それらのドキュメント内のテキストは多次元ベクトルになり、各次元がセマンティックな特徴を捉えます。つまり、ビーチとコーストのような類似した概念は一緒にクラスター化されます。類似していない概念は離れたままになります。
実際には、Miamiの埋め込みはこんな感じになります。pristine beaches plus world-class clubs が、例えば1024次元にわたって表現されます。Baliのエンコーディングは、tropical surf beaches plus wellness spasを表します。どちらもビーチのコンポーネントを含んでいることに注意してください。しかし、Miamiはこのurbanとnightlifeのテーマに傾いているのに対し、Baliはよりspiritualとwellnessのテーマに傾いています。これらの埋め込みはベクトルデータベースに保存されます。Aurora PostgreSQLにはpgvectorがあります。pgvectorを聞いたことがある方、手を挙げてください。
OK、かなり多くの方がご存知ですね、良いですね。pgvectorは、知らない方のために説明すると、PostgreSQLの拡張機能で、ベクトル埋め込みの保存とクエリを行うためのものです。そして、これがセマンティックルックアップ、セマンティック検索を可能にします。一方で、ユーザーがやってきて「サーフィンとパーティーができる場所はどこ?」という質問をすると、 そのクエリは同じ埋め込みモデルを通過し、例えば1024次元のベクトルに変換されます。
そして、pgvectorを使ってAuroraに対してセマンティック検索を実行します。クエリはこんな感じです。皆さんはこれを見ることはありません。モデルが裏側で処理します。 皆さんが見るのは、類似度スコアでランク付けされたトップマッチ、MiamiとBaliです。これがインテリジェンスレイヤーです。スピードがあり、今度はインテリジェンスレイヤーを追加しました。これが、Flightlyが単純なキーワードマッチを超えて、真のユーザーインテントを理解する方法です。
さて、このスライドはベクトル埋め込みを使用したセマンティック検索に純粋に焦点を当てていますが、従来のキーワードベースのフルテキスト検索も見過ごすことはできません。PostgreSQLには完全に機能するフルテキスト検索コンポーネントも備わっています。そして実際には、これらの検索システムの多くは両方を組み合わせており、これをハイブリッド検索と呼んでいます。今回はセマンティック検索を中心にお話ししていますが、もしご興味があれば、明日ハイブリッド検索に関するセッションもあります、409番です。
では、サービス側について少し寄り道しましょう。AWSはネイティブなベクトル検索を備えた複数のマネージドデータベースを提供しており、このエコシステム全体にどんどん多くのデータベースを追加し続けています。RDS for PostgreSQLはベクトル検索をサポートしていますし、Aurora PostgreSQL、DocumentDB、OpenSearchなども同様です。さて、FlightlyはAurora PostgreSQLを選択しました。なぜなら、彼らのデータはすでにそこに存在していたからです。簡単な選択でした。
Aurora serverlessアーキテクチャでは、フライト検索は通常非常にスパイキーで、季節性やフラッシュセールなどに依存します。このアーキテクチャの仕組みは、コンピュートとストレージレイヤーが分離されているということです。そしてAurora capacity unitsを使用することで、スケールアップやスケールダウンに必要なプロビジョニングのレベルを制御できます。Aurora I/O Optimizedは、ストレージ構成の一つですが、このI/O集約的なベクトル検索と、通常のトランザクションワークロード、つまり予約や支払いなどを処理します。
DynamoDB optimized configurationで採用しているより優れた技術により、パフォーマンスの低下はありません。さらに、予測可能なコストという追加のメリットも得られます。データのローカリティは大きな利点です。ベクトル埋め込みはトランザクションデータと同じPostgreSQLテーブルに存在します。これには予約や顧客プロファイルが含まれます。外部データベースは不要で、ETLパイプラインを設定する必要もなく、移行リスクもありません。
最後に、グローバルリーチの観点です。グローバルデータベースは、サブセカンドのレプリケーションラグでリージョン間でレプリケートします。東京のユーザーはAsia Pacificレプリカから提供され、ロンドンのユーザーはEUレプリカから提供されます。グローバルなデータ、ローカルな読み取りパフォーマンスです。さて、これで完全なアーキテクチャが揃いました。ElastiCacheは、キャッシュされたデータに対してサブミリ秒のパフォーマンスを提供します。Auroraは、pgvectorを通じた永続的なセマンティックインテリジェンスレイヤーです。では、この2つがどのように統合されるか見ていきましょう。基礎となるアーキテクチャから始めて、段階的に洗練されたレイヤーを追加していきます。
4つのステップで構築する会話システム:シンプルなQ&AからRAGへの進化
ステップ1はシンプルなQ&Aです。これがベースラインパターンになります。私が「ラスベガスからハワイへのフライトを予約できますか?」と尋ねます。クエリは直接Bedrockにルーティングされます。前処理もなく、コンテキストの組み立てもなく、ただ生のユーザー入力だけです。LLMは事前学習された知識のみを使用して応答を返してきます。これは通常、非常に一般的なものです。ここにはパーソナライゼーションはありません。ユーザーである私に特化したものは何もないんです。
さて、ここでアーキテクチャ上の課題があります。定義上、LLMはステートレスです。何も記憶しません。セッション状態やインタラクション間の連続性を一切維持しないんです。このチャットを閉じた瞬間、会話履歴は消えてしまいます。チャットボットに記憶させる方法が必要です。そこでElastiCacheを使って会話メモリを追加しましょう。
ステップ2は、その会話履歴、つまりチャット履歴を追加することです。ここでElastiCacheが会話履歴を保存するためにレイヤーとして追加されます。このクエリが到着すると、これはフォローアップの質問なんですが、私は前の質問を繰り返していません。「そこのホテルはどうですか?」と聞いています。ElastiCacheが今や以前のコンテキストを持っていることが前提となっていて、そのコンテキストを私のプロンプトに提供できるんです。これによって再びカスタマイズされた応答が得られます。これが変化です。ステートレスなAPI呼び出しからステートフルな会話へと変換されたわけです。ElastiCacheがこの永続的なセッションメモリを提供します。しかし注目してください、ここでの応答はまだかなり一般的です。まだパーソナライゼーションはありません。
ステップ3は、そのパーソナライゼーション層を追加することです。今度は基本的な会話履歴を超えて進化していきます。私が別のフォローアップ質問をします。「家族向けのアクティビティを推薦してください」と。ここでElastiCacheの役割が拡大します。今度はユーザープロファイルデータをキャッシュしています。これは家族構成を含むハッシュになります。私には2人の子供がいて、4歳と8歳です。アクティビティの好みとしてアウトドアアドベンチャー、予算の制約として最大300ドルといった情報です。このクエリが到着すると、ElastiCacheのget allを使用して、完全な設定ハッシュを取得し、それをプロンプトに注入できます。LLMは今度は私のパーソナライズされた情報に基づいて、非常にカスタマイズされた応答を生成します。4歳から8歳に適したアクティビティで、アウトドアアドベンチャーに沿ったものです。
この段階では、単に記憶しているだけでなく、永続的なユーザー属性でコンテキストを充実させています。私について、私の家族についての情報を知っているんです。このユースケースにおけるElastiCacheは、一時的なセッションメモリと永続的な設定ストレージの両方を提供します。これが記憶から理解への変化です。さて、最終段階に入ります。これはコンテキストインテリジェンス、Retrieval-Augmented Generationとも呼ばれるものです。
私が尋ねます、来月の最安フライトオプションを教えてください。 それだけです。ここでAurora PostgreSQLが登場します。アプリケーションはembeddingを生成し、フライトモデルに対してセマンティック検索を実行します。 私が指定した日付範囲でフィルタリングされた最安オプションにマッチしたものをルーティングし、リアルタイムの価格情報と結合することで、非常にカスタマイズされた レスポンスを提供します。これがRAGの実践です。私たちは今、サブミリ秒のセッション状態とプリファレンスルックアップのためにElastiCacheを使用しています。しかし同時に、セマンティック検索を通じてドメイン知識にデータをグラウンディングするためにAuroraも使用しています。これらが一緒になって、高速でパーソナライズされた、正確なカスタマーエクスペリエンスを提供しているのです。
Agentic AIへの転換:Strands AgentsとModel Context Protocolによる実装
ここまで4つのステップで、かなり洗練された会話システムを構築してきました。メモリがあり、チャット履歴があり、パーソナライゼーションがあり、コンテキストインテリジェンスがあります。しかし覚えておいてください、私たちはまだチャットボットの段階にいるのです。もし単純なQ&Aを超えることができたらどうでしょうか?もしホテルの空室状況やフライトの空席状況についての情報を提供するだけでなく、さらに一歩進んで、それらを実際に予約し始めることができたらどうでしょうか? それがagentic AIへのシフトです、質問に答えることからアクションを起こすことへの転換です。
agenticレイヤーとアーキテクチャに入る前に、どのようにしてここに至ったかを見てみましょう。この視点を持ち続けることが重要です。2年前、私たちはgenerative AIチャットボットから始めました。シングルターンで、ルールベースで、常に人間の監視を必要としていました。その後、generative AIエージェントが登場しました。計画し、推論し、ツールを使用する目標駆動型のシステムです。予約エージェントはフライトを検索し、価格を比較し、ワークフローを実行しますが、まだシングルドメインです。 今、私たちはagentic AIの時代に足を踏み入れています。専門化されたエージェントが非常にうまく連携するマルチエージェントシステムです。予約エージェント、カスタマーサービスエージェント、レコメンデーションエージェント、これらすべてが最小限の監視でコミュニケーションし、委任し合います。これが私たちがFlightlyのために構築しているものです。
アーキテクチャを見てみましょう。 先ほどと同じ旅行に関する質問です。エージェントはこの場合Valkeyからキャッシュされたコンテキストを取得します、すべて並列で。覚えておいてください、 ElastiCacheでユーザープロファイル、ElastiCacheで会話履歴、ElastiCacheでセッション状態です。サブミリ秒での取得、超高速で完全なユーザーコンテキストを組み立てます。 同時に、Auroraに対してセマンティック検索を実行しています。クエリのベクトル化、類似性検索です。これは通常2桁のミリ秒で完了します。Valkeyからのユーザーパーソナライゼーション、Auroraからのドメイン知識です。
ここからが面白くなります。Model Context Protocolと呼ばれる別の概念を通じたツールの呼び出しです。MCPはLLMがさまざまなサービス、例えばAPI、データベースなどと通信するための標準化されたインターフェースを提供します。エージェントは外部APIも呼び出すことができます、天気予報、旅行勧告、FAA規制などです。これらすべての結果が、超パーソナライズされた、実行可能なレスポンスになります。エージェントは 予約したいか、他のオプションを探索したいかを尋ねます。
これは有望ですが、実際にどうやって実装するのでしょうか?ここで登場するのがStrands Agentsです。これはAIエージェントを構築するためのオープンソースSDKです。軽量で、モデルに依存せず、Bedrockをネイティブにサポートしていますが、それだけでなく、OpenAI、Anthropic、Ollamaなどとの統合もあります。このマルチエージェントオーケストレーションを処理し、85以上のツールが利用可能なネイティブMCPツールサポートを提供します。そして、既存のAPIをカスタムツールと統合することもできます。後ほどいくつかの例を見ていきます。
コードを見てみましょう。Strandsでエージェントを構築するのは比較的簡単です。特定のプリミティブがあり、それらを実装するだけです。まず、コアプリミティブをインポートして、LLMを設定します。この場合、Bedrock上のClaude Sonnet 4を使用しています。次に、エージェントを作成します。これだけです、たった1行のコードです。それだけです。これで機能するAIエージェントができました。しかし、非常に限定的ですよね?シンプルなQ&Aしかできません。まだ何の機能も持っていません。
では、機能を追加しましょう。ここでシステムプロンプトを定義し始めます。覚えておいてください、これがエージェントのパーソナリティです。Flightlyのパーソナリティ、ドメインの専門知識、行動の制約、これらすべてがシステムプロンプトに入ります。あなたはFlightlyです、フライト予約と旅行日程を専門とする旅行アシスタントです。明確で簡潔、そしてプロフェッショナルな回答を、役立つオプションと価格とともに提供してください。ですので、ベガスからハワイへのフライトのようなクエリが来ると、エージェントはキャラクターに沿って応答します。旅行ドメインに焦点を当て、プロフェッショナルなトーンを使い、価格付きの実行可能なオプションを提供します。
しかし覚えておいてください、エージェントはアクションも実行できます。これはまだシンプルなQ&Aです。では、いくつかのツールを追加しましょう、これが行動する能力です。エージェントにAurora PostgreSQLデータベースへのアクセスを与える最速の方法は、Aurora PostgreSQL MCPサーバーを使うことです、これがエージェントのツールになります。Aurora PostgreSQL MCPサーバーを使えば、標準的な接続パラメータ、つまりすでに慣れ親しんでいるもので直接接続できます。ホスト名、データベースの認証情報です。カスタムツールの実装は必要ありません。手書きのSQLラッパーを書く必要もありません。
メリットは、メンテナンスのオーバーヘッドがないことです。スキーマが進化しても、標準的な認証情報を使って接続するだけです。さて、Strandsはlist tool sync APIを提供しており、16行目に表示されていますが、これがこれらのツールを自動的に検出します。これはMCPサーバー、さらにカスタムツール、API、データベースなどです。
さて、ここでは、Aurora PostgreSQLがMCPサーバーとして、いくつかのツールを公開しています。Get Table SchemaとRun Queryです。Get Table Schemaはスキーマの検出用で、Run QueryはSQLクエリの実行用です。このケースでは、ツールをインポートしてツール呼び出しを行うと、データベースへの呼び出しは2桁のミリ秒程度で、これは通常、直接接続でも同じくらいの時間がかかります。しかし、この行に注目してください。永続的なMCP接続があります。再接続のオーバーヘッドはゼロです。
PostgreSQLでは、接続を再確立しようとするたびに、多くのオーバーヘッドが発生します。TCPハンドシェイク、TLSネゴシエーション、認証などがあります。MCPはこのボトルネック全体を排除し、データベースへの永続的な接続を使用します。もう一つのメリットは、もちろん、自分でSQLクエリを書く必要がないことです。SQLを知らなくても、エージェントがそれを処理してくれます。
さて、MCPサーバーは実際にこれらのデータベースを超えることもできます。天気APIについて話したのを覚えていますか?この例では、天気APIを追加してみましょう。同じパターンで、今度は天気用です。MCPツールデコレーターという特別なシンボルを使用します。これはご覧いただけると思います。これはOpen Weather APIを外部で呼び出す関数を定義しています。そして、このコードスニペットは実際に天気データAPIをMCPツールとしてエージェントに公開します。私たちのStrandsエージェントは、Auroraに接続したのと同じ方法で接続します。同じプロトコルで、異なる機能です。
しかし、ここに本番環境での課題があります。1日100万件のクエリです。多くは意味的に似ています。例えば、ハワイの天気、天気予報、ハワイの予報、ホノルルの気温など、多数の異なるユーザーによって尋ねられます。それぞれがAPI呼び出しをトリガーします。コストがかかり、遅く、不必要です。そのため、標準的なMCPサーバーを超えたインテリジェンスが必要です。ツールレイヤーでのツールキャッシングを備えたインテリジェンスが必要です。
再利用可能な5つのアーキテクチャパターン:コンテキストキャッシュから階層型メモリ管理まで
つまり、標準的なMCPでは不十分なのです。では、少し先に進んで、カスタムツールを追加しましょう。さて、ツールについて何度も言及してきました。ツールとは、単にPythonプログラム、つまりエージェントにビジネスロジックや実行ロジックを与える関数に他なりません。単純にPython関数です。ここでのツールデコレーターは、実行ロジックを完全に制御できるようにします。
では、例を見てみましょう。search flightsは出発地、目的地、そしてオプションで日付を受け取ります。しかし、docstringは引数として、エージェントがいつどのように呼び出すかを理解するためのスキーマ情報を提供します。ここからが強力なところです。ロジックでは、まずValkeyをチェックすることが定義されています。もしキャッシュにそのデータが存在すれば、1ミリ秒以内に結果を返します。もし存在しなければ、Auroraにクエリを投げます。初回はペナルティがあります。データベースにヒットしますが、その後の結果はValkeyレイヤーにキャッシュされます。ここでも予測可能性は維持されます。
ここで注目していただきたい重要なポイントは、MCPはスキーマディスカバリーやクリティカルでないパスに使用し、カスタムツールはMCPが提供する以上の機能が必要な場合やパフォーマンスが重要な場合に使用するということです。これがユーザー出力です。クエリがキャッシュにヒットしない場合は、データベースにヒットします。これも2桁のミリ秒、だいたい85ミリ秒くらいです。しかし2回目がメリットです。Valkeyキャッシングレイヤーによって、すぐにその恩恵を受け始めます。
さて、Flightlyの完全なアーキテクチャを構築しました。では、再利用可能なパターンをいくつか抽出しましょう。これらは基本的に、皆さんが自分のアプリケーションにすぐに適用できる設計図です。パターン1はコンテキストキャッシュです。Johnが「そこのホテルはどう?」と尋ねます。エージェントはValkeyにクエリを投げ、Johnの完全なコンテキストを取得します。覚えていますか、あの並列処理全体、Wi-Fiの議論からのチャット履歴、セッション状態、ユーザー設定などです。同時に、Auroraデータベースでセマンティック検索を実行します。最終的に、これらすべてがコンテキストを考慮した、Johnの好みなどを考慮したレスポンスを生成します。そしてこのパターンは普遍的に適用可能です。
カスタマーサービスエージェントに適用できます。チケットのコンテキストを維持することを想像してください。セッションをまたいで好みを記憶する必要があるバーチャルアシスタント、患者の履歴を追跡するヘルスケアチャットボット。会話の継続性が重要で、迅速なコンテキスト取得が必要なあらゆるシステムに、このパターンは適用できます。
パターン2は埋め込みキャッシュです。これはベクトル埋め込みをキャッシュすることでセマンティック検索を高速化するものです。かなり優れています。ユーザーが新しい場所でやることを検索することを考えてみてください。これらはほとんどの場合、短いキーワードベースの検索です。そして多くの場合、多くのユーザーが同じ質問を繰り返し尋ねています。日本に行くなら、京都の象徴的な寺院、東京の最高の食べ物、といった具合です。最初の問い合わせは、もちろんデータベースに行きます。そして通常200ミリ秒未満で完了する埋め込みパイプライン全体を通過する必要があります。しかしその後の取得はキャッシングレイヤーを通じて行われ、ここで利点が得られます。そしてこれらはサーバーレスサービスなので、両方ともその場でスケールできます。上下に、内外に。
さて、パターン3は興味深いものです。これはElastiCacheによる永続的なセマンティックキャッシングです。データソースが以前と同じように埋め込みモデルへの入力として入ってきます。これがパイプライン全体です。しかし多くの場合、覚えていますか、人々は異なる言い回しをすると言いましたね。同じ質問をするわけではありません。ハワイで最高のビーチの目的地は何ですか?ハワイでビーチリゾートをおすすめしてもらえますか?などなど。さて、セマンティックキャッシングがない場合、これは応答を得るためにこのパイプライン全体を通過します。もちろん、LLMの呼び出しがあり、埋め込みの生成があり、多くのことが行われています。そしてレイテンシーとコストがかかります。
セマンティックキャッシングでは、類似性の閾値を定義し、その閾値を超えると、その閾値に達したときはいつでも、類似しているすべての質問がグループにまとめられ、応答がキャッシュから返されます。つまり、Valkeyレイヤーに類似性とLLM応答の両方をキャッシュしているのです。そして何が起こるかというと、パイプライン生成プロセス全体をスキップできます。そしてキャッシュに行って結果を取得するだけです。LLMコストはゼロ、レイテンシーなし、そしてサブミリ秒のパフォーマンスです。実はセマンティックキャッシングに関する詳細なセッションがありました。月曜日に行われました。ですので、YouTubeの録画、セッション451を見ることを強くお勧めします。これはセマンティックキャッシングについてもっと深く掘り下げています。
実際の動作はこのように見えます。緑は良好、赤は悪いです。左側のセマンティックキャッシングありでは、質問1から4まで、Valkeyから即座に応答が得られます。これが私たちが望むもので、スムーズで、素晴らしいパフォーマンスで、ユーザーのエンゲージメントを維持します。さらに重要なのは、予約が時間通りに完了することです。なしの場合、同じ質問が毎回完全なLLM推論をトリガーします。さらに悪いことに、ユーザーがこれらの遅延に気づき、予約の途中で会話を放棄し始めます。
パターン4は興味深いものです。ここでは本番アーキテクチャに少し踏み込みます。階層型メモリ管理です。ユーザーが「そこへの家族のフライトを予約して、あの航空会社は避けて」と言います。おそらく以前のコンテキスト、以前のセッションなどを参照しています。エージェントはこの場合、短期記憶のためにValkeyにメッセージを渡します。それが通過するのを見ていきます。そして、Valkeyは、この場合、チャットメッセージ、つまり会話履歴、セッション状態、チェックポイントなどを保存していることに気づくでしょう。これらは通常、エージェントが特定のワークフロー、パイプライン、ジョブ、または基本的な会話を通過している場合のワークフローチェックポイントです。チェックポイントを定義することで、データベースのチェックポイントと同様に、中断したところから再開できます。これらすべてをValkeyにキャッシュして保存できます。
さて、素晴らしいのは、実際に舞台裏でこのインテリジェンスを持つことができることです。Lambdaが非同期で短期記憶の重要な部分を抽出します。つまり、すべての会話履歴、セッション状態、チェックポイントなどです。そしてそれを長期ストレージとしてAuroraにプッシュします。Aurora内で、pgvectorを使用すると、得られる利点は、エピソード記憶の想起のようなことができることです。pgvectorは、セッションID、メモリID、全体のインタラクションとともに、すべての過去の履歴を長期記憶として保存しています。
できることは、その長期的な階層型ストレージを見ることで、会話全体を再構築することです。このユースケースでは、例えばこのユーザーは通路側の座席を好むか窓側の座席を好むか、予算があって、おそらく300ドル以下という厳しい予算がある、といったことです。これらは長期ストレージに永続化されるもので、デバイス間、チャネル間で毎回参照することができます。そしてもちろん、Model Context Protocol、つまりMCPも組み込まれています。 MCP内では、これらのメモリモジュールを抽出したり、これらのメモリイベントを順次、連続的にリストアップしたり、これらのメモリレコードを取得して再構築したり、といったことができます。エージェントでできることはたくさんあります。これがホットまたは短期メモリと長期メモリの分離です。
本当に面白くなるのは、マルチエージェントワークフローを使ったこの種の階層型共有メモリアーキテクチャで、これがFlightlyで構築しているものです。 フライトを予約する前に旅行保険を追加して、サポート会話からのメールを使ってください。これはステートフルなマルチエージェントワークフローで、共有メモリの状態がElastiCacheとAurora PostgreSQLの間に保存され、エージェントがシームレスなハンドオフを行います。 オーケストレーターがあります、この場合はFlightlyのオーケストレーターです。3つの専門エージェントがあります:サポートエージェント、予約エージェント、そして決済エージェントです。 これらすべてが両方のレイヤーでメモリを共有します、長期ストレージと短期メモリの両方です。
舞台裏では、同じことをやっています。ElastiCacheから短期メモリを抽出し、Auroraに永続化しています。そしてこの方法で、基本的に状態を共有していて、ワークフローは次のようになります。まず、サポートエージェントがAuroraにセマンティックにクエリします。先週のサポート会話を見つけて、メールを抽出します。予約エージェントがフライトを検索して予約し、この確認済み予約状態をValkeyに書き込みます、これがチェックポイントです。決済エージェントがこの確認済み予約状態を読み取り、保険を追加してから決済を処理します。これらすべてが共通のメモリレイヤーを通じてオーケストレーションされています。コンテキストの欠落はなく、エージェントのハンドオフ間で連続性が失われることもなく、状態は両者の間でリアルタイムに同期されています。
本番環境へのスケール:Bedrock AgentCoreによるエンタープライズ対応と成果
さて、5つの異なるパターンを見てきました。この会話型AIシステムを構築するさまざまなステップを見てきました。では重要な質問です:これを本番環境にスケールするにはどうすればいいでしょうか?1日100万クエリ、高可用性、コスト最適化、セキュリティ。これまで、エージェントはローカルのノートパソコン上で動いていました。MCPサーバー、Aurora PostgreSQLのMCPサーバーは、ノートパソコン上でSTDIOローカルPythonサブプロセスとして動いています。もしノートパソコンがクラッシュしたら?トランザクションの途中で何が起こるでしょうか?トランザクションを失います、当然ですが、それは論外です。どうやってこれをスケールするのでしょうか?
ここでBedrock AgentCoreの出番です。ちょっと確認させてください、AgentCoreを聞いたことがない人は?誰かいますか?みんな聞いたことがありますね、一人だけAgentCoreを聞いたことがない方がいますね、はい。AgentCoreは、エージェントを安全に大規模に構築、実行、デプロイするためのエージェンティックプラットフォームです。自己管理サーバー上でPostgreSQLを実行するのと、フルマネージドサーバーとしてのAurora PostgreSQLを比較してみてください。AgentCoreは、エージェントを実行するためのフルマネージド機能です。
これには多くのコンポーネントが含まれていますが、あまり深くは立ち入りません。AgentCoreに関するセッションはたくさんありますが、非常に高いレベルで言うと、runtimeはローカルエージェントと環境を提供し、クラウド上で大規模に実行できるようにします。もうローカルでエージェントを実行する必要はありません。このフレームワークの素晴らしいところは、Bedrockモデルだけに制限されないということです。OpenAIも使えますし、Anthropicも使えますし、Geminiも使えます、何でも構いません。さらに、Crew AI、Autogen、LangChain、LangGraphなど、独自のagenticフレームワークを持ち込むこともできます。AgentCore Identityは、エージェントに安全なアイデンティティとアクセス管理を提供します。これは本番環境では非常に重要です。AgentCore Gatewayは、MCPサーバー、カスタムツール、Lambda関数、OpenAPIスキーマへのゲートウェイを提供します。既存のツールやビジネスロジックがAgentCore Gatewayによってフロントされ、既存のアプリケーションにとってよりシームレスなルーティングレイヤーを提供します。
BrowserやCode Interpreterなど、他にもいくつかのツールがあります。Browserは、Claudeのcomputer useに馴染みがある方ならご存知かと思いますが、エージェントにあなたのコンピューターへのアクセスを与えるものです。これは本来すべきではないのですが、物事を実行するためのものです。Browserはそのために使用されます。Code Interpreterは、よりサンドボックス化されたコード実行環境です。 しかし、AgentCore Memoryのような他の優れた機能もあります。これは、すぐに使える短期記憶と長期記憶のモジュールも提供しています。 そして、これらすべてを適切なガードレールとエージェントアクションのトレーシングで包み込むために、AgentCore Observabilityレイヤーもあります。
では、私の金曜日のフラストレーションを覚えていますか? 同じジャーニーを、完全に再構築しました。このケースでは、Valkeyがよくある質問、手荷物ポリシー、予約テンプレート、メールテンプレートをキャッシュし、これらの結果をマイクロ秒で返します。pgvectorを搭載したAuroraがルート情報を処理し、座席の好み、長期記憶、セマンティック検索を、すべて2桁のミリ秒で検索します。10人中9人の顧客が留まり、60%のコスト削減、真にスケールするパフォーマンスです。そして、Flightlyはハワイの準備が整い、皆さんもそうです。それでは、お時間をいただきありがとうございました、Mahalo。
共有したいリソースがいくつかあります。もし質問があれば、外で受け付けましょう。ただし、セッションサーベイの記入をお忘れなく。そして、ご参加いただきありがとうございました。re:Inventの残りの時間をお楽しみください。
※ こちらの記事は Amazon Bedrock を利用し、元動画の情報をできる限り維持しつつ自動で作成しています。












































































































Discussion