※本記事は、AWS re:Invent 2024のセッション「Build serverless chatbots using Amazon ElastiCache & Aurora PostgreSQL (DAT326)」の内容を基に作成されています。セッションの詳細情報はAWS re:Inventのウェブサイト(https://go.aws/reinvent )でご覧いただけます。
本記事では、セッションの内容を要約・構造化しております。なお、本記事の内容は原著作者の見解を正確に反映するよう努めていますが、要約や解釈による誤りがある可能性もありますので、正確な情報や文脈については、オリジナルのセッション動画をご視聴いただくことをお勧めいたします。
AWSでは、オンラインおよび対面でのイベントを通じて、クラウドコンピューティングコミュニティが集まり、AWSの専門家と交流し、学ぶ機会を提供しています。より多くのAWSコンテンツについては、AWSのYouTubeチャンネル(http://bit.ly/2O3zS75 )やAWSイベント動画(http://bit.ly/316g9t4 )をご参照ください。
本セッションの講演者であるShayon Sanyal氏の見解や説明は、AWSの公式見解を代表するものではありません。また、本記事に含まれる情報は、セッション時点のものであり、その後のアップデートや変更は反映されていない可能性があることをご了承ください。
1. イントロダクション
1.1. 講演者の紹介
本セッションの講演者であるShayon Sanyalは、AWSのプリンシパルワールドワイドPostgresスペシャリストソリューションアーキテクトとして活躍しています。特に近年は、Aurora PostgreSQLの専門家として、生成AIの領域に注力しています。
このre:Invent 2024のセッションでは、多くの参加者が初めての参加であることを確認した上で、通常の講演とは異なるサイレントセッション形式で進行することを説明しています。このアプローチにより、技術的な内容を効率的に伝達しつつ、質問については講演後に詳しく対応する形式を採用しています。
Sanyalは、AWSの中でもデータベース、特にPostgreSQLとの生成AI統合という最先端の領域で専門性を発揮しています。この専門性は、本セッションのテーマである「Amazon ElastiCacheとAurora PostgreSQLを使用したサーバーレスチャットボットの構築」において、実践的な知見を提供する基盤となっています。
Sanyalは、理論的な知識だけでなく、実際の顧客事例や実装経験に基づいた知見を共有できる立場にあり、このセッションを通じて、チャットボットアプリケーションの構築における具体的な課題解決方法を提示することを目指しています。
このセッションにおけるSanyalの役割は、単なる技術解説にとどまらず、実践的なアーキテクチャパターンや実装戦略、そして実世界のユースケースを通じて、参加者が実際のビジネス課題に適用できる知識を提供することです。
1.2. セッションの概要と課題提起
Shayon Sanyal:このセッションでは、Amazon ElastiCacheとAurora PostgreSQLを使用したサーバーレスチャットボットの構築について説明します。まず、典型的なブレイクアウトセッションとは異なり、これはサイレントセッションという形式で行われます。質問がある場合は、セッション終了後に詳しく議論できる形式を採用しています。
具体的な課題として、次のような実際のシナリオを考えてみましょう。あなたが次週にハワイへの休暇を計画していて、フレンドリーなチャットボットにチケットの予約を依頼したとします。しかし、チャットボットは「待機中」の無限ループに陥ってしまいます。これは非常にフラストレーションがたまる経験です。
この待ち時間の間に、あなたはメールアプリに切り替えて確認すると、皮肉にも競合他社が同じチケットについて良い取引を提供していることを発見します。チャットボットに戻ってみると、まだ待機中です。これはわずか30秒以内で起こる出来事です。この短い時間で、ユーザーは競合他社のウェブサイトに移動し、そこでディスカウントを見つけ、チケットを予約してしまいます。
旅行業界において、このような顧客のコンテキストスイッチや離脱は、即座に顧客の損失、収益の損失、販売機会の損失につながります。顧客の維持率を最高レベルに保つことが非常に重要です。
本日のセッションでは、この問題をより最適化する方法について、高レベルな概要を説明します。チャットボットの進化について簡単に触れた後、実際の顧客が本番環境でこれをどのように実装しているかについて、アーキテクチャパターンやアーキテクチャの概要に多くの時間を割きます。Amazon ElastiCacheとAurora PostgreSQLといった特定のサービスを使用した実装方法を見ていきます。また、大規模言語モデルプロバイダーとしてBedrockの活用、そしてRAG(Retrieval-Augmented Generation)にも重点を置きます。さらに、RAGの先にあるBedrock Agentsについても説明します。
このセッションを通じて、皆さんの思考が正しい方向に導かれ、セッション終了時には目指すべき場所に到達できることを期待しています。
1.3. チャットボットの進化 (2023年から2024年への変遷)
Shayon Sanyal:2023年は間違いなくPOC(Proof of Concept)の年でした。生成AIやチャットボットの大きな波が押し寄せ、企業からは様々な質問が寄せられました。例えば、「モデルを構築すべきか、購入すべきか?」「データセキュリティをどのように確保するか?」といった質問です。
その時点では、RAG(Retrieval-Augmented Generation)は表面的なレベルにとどまっていました。これは1年前、2、3年前ではなく、たった1年前の状況です。また、「モデルが幻覚を起こしたらどうするか?」「望ましくない応答が返ってきた場合どうするか?」という懸念もありました。
既存システムとの統合に関する質問も多く寄せられました。「既に構築済みのものとどのように連携させるか?」「リレーショナルデータストアやノンリレーショナルデータストアとどのように統合するか?」「既存のインフラストラクチャにチャットボットアーキテクチャをどのように組み込むか?」これらが2023年に顧客から多く聞かれた質問でした。
わずか1年後の現在、チャットボットはファーストクラスの市民となっています。企業にとって、自社の製品やサービスに関する一般的な質問に答えるための基本的なチャットボットを持つことは、最低限の要件となっています。
企業におけるRAGの概念もより一般的になってきています。組織内の分断されたサイロ化されたデータ、例えば医療データ、財務データ、マーケティングデータ、CRMデータなどを統合し、単一のチャットボットですべての問題を解決するという統合的なアプローチが見られます。
さらに重要なのは、エージェントの台頭です。これは業界が向かっている方向であり、トレンドとなっています。エージェントは自律的な意思決定を行うボットと考えることができます。これらは単なるチャットボットですが、独自の思考プロセスを通じて意思決定を行います。業界では、思考の連鎖や段階的な実行、マルチステップの実行オーケストレーションなどの用語が使用されていますが、これらについては後ほど詳しく説明します。エージェントは急速に普及し、標準となりつつあります。
2. ユースケース分析: AZFlights社の事例
2.1. 主要な課題
Shayon Sanyal:今日は皆さんに、AZFlights社の一員として考えていただきたいと思います。私たちは、先ほどのデモで見たような終わりのない待機ループの問題に直面している会社の一員として、この課題に取り組んでいきます。
AZFlightsには、2つの明確な目標があります。第一に、フライト予約体験の最適化です。先ほど見たような、待機と待機の無限ループは、顧客にとって決して快適な体験ではありません。この問題を解決することが私たちの最初の目標です。
第二の目標は、ビジネスの多様化です。私たちの基幹事業はフライトチケットの予約ですが、次の休暇を探している顧客に対して、パーソナライズされた推薦やパーソナライズされた旅程を提案することで、ビジネスを多様化したいと考えています。
これらの課題は、旅行業界特有の重要性を持っています。なぜなら、この業界では顧客が他のアプリケーションに切り替えたり、離脱したりすることが、即座に顧客の損失、収益の損失、販売機会の損失につながるからです。私たちの課題は、これらの損失を最小限に抑えながら、顧客体験を向上させることです。
この2つの課題に対して、私たちは既存の豊富な情報とデータを活用しながら、最新のテクノロジーを組み合わせて解決策を見出していく必要があります。これは単なる技術的な改善だけでなく、ビジネス価値の創出にも直結する重要な取り組みとなります。
2.2. 既存データの状況
Shayon Sanyal:これらの会社と話をすると、多くの場合、既存のリレーショナルデータストアやノンリレーショナルデータストアに、すでに豊富な情報が蓄積されています。私たちAZFlightsにおいても、顧客360度データと呼ばれる包括的な情報を保有しています。
このデータには、過去の旅行情報、Webの閲覧履歴、顧客の好み、顧客プロファイルなどが含まれています。これに加えて、企業データも豊富に存在します。フライト情報、ホテル情報、進行中のプロモーション、類似した旅行者のプロファイルなど、多くの切り離された情報源からのデータがあります。
このユースケースでは、これらすべての既存の豊富な情報がAurora PostgreSQLに格納されていることを想定しています。この状況は、多くの企業で見られる一般的なケースです。データは存在していますが、それらを効果的に活用し、顧客体験を向上させるためには、適切なアーキテクチャとテクノロジーの組み合わせが必要となります。
つまり、私たちの課題は、すでに持っている豊富なデータを活用して、どのように顧客体験を向上させるかということです。このデータを活用することで、より個人化された、より効率的なサービスを提供することが可能となります。
2.3. 目標設定と要件定義
Shayon Sanyal:私たちのアーキテクチャを構築するにあたり、まず開発者やアーキテクトとして、基本的な構想から始めましょう。第一歩として、主要なパフォーマンス要件を設定します。
ユーザーが質問を入力した際、例えば「バリのビーチリゾートを探して」といった質問に対して、トラベルアシスタントはナレッジベースやベクトルストアと呼ばれるところから関連情報を迅速に取得する必要があります。ここでは、顧客データやドキュメントソース全体から情報を引き出すことが求められます。
ビジネス目標との整合性を考慮すると、私たちは拡張されたプロンプト、つまりコンテキストを認識したプロンプトを形成する必要があります。これはユーザーからの質問とナレッジベースからのコンテキストを組み合わせ、大規模言語モデル(LLM)に送信します。このLLMは、インターネットスケールのデータで訓練された巨大な機械学習モデルです。
技術的な制約条件として、LLMは、コンテキストを理解した上で、ビーチフロントリゾートの好みやユーザーの予算などを考慮しながら、個別にカスタマイズされた応答を提供する必要があります。これは、単なる情報の検索ではなく、ユーザーの具体的なニーズと状況に応じた適切な提案を行うことを意味します。
この高レベルのアーキテクチャを基に、以降で具体的な実装方法について説明していきますが、常にこれらの要件とゴールを念頭に置きながら構築を進めていく必要があります。
3. アーキテクチャの基本構成要素
3.1. プロンプトエンジニアリングの重要性
Shayon Sanyal:プロンプトは、アーキテクチャの中心的な要素として非常に重要です。簡単な復習として、プロンプトの本質について説明させていただきます。プロンプトとは、大規模言語モデルに特定の方法で応答するよう導くための一連の入力指示です。それだけです。ユーザーの質問に対して特定の方法で応答するよう大規模言語モデルを導くための一連の入力を指します。
私たちAZFlightsの観点から、プロンプトエンジニアリングの構築者としての視点を見てみましょう。基本的なプロンプト構造は次のようになります:
「あなたはAZFlightsのヘルプフルなトラベルアシスタントです。常にフレンドリーで会話的、かつプロフェッショナルなトーンを維持してください。私が指定するデータソースから関連データを取得してください。この場合、Aurora PostgreSQLは私の顧客360度データです。Amazon ElastiCacheに保存されているユーザー設定を考慮してください。また、ユーザーが圧倒されないように、応答は簡潔にしつつ、十分な詳細さを保ってください。」
プロンプトが有用な理由は、まず創造性を可能にすることです。プロンプトを調整することで、フレンドリーな調子や、プロフェッショナルな調子など、特定の方法で応答するように調整できます。また、プロンプトエンジニアリングの分野は実際にはかなり過小評価されています。問題の多くを解決するための開始点として、とても簡単で経済的、コスト効率的な方法なのです。
このように、プロンプトエンジニアリングは、単なる技術的な実装以上の重要性を持っています。これは、ユーザー体験の質を決定する重要な要素であり、システム全体の効果的な動作を支える基盤となるものなのです。
3.2. キャッシュの必要性と役割
Shayon Sanyal:チャットボットを構築する際に、なぜキャッシュが必要なのかについて考えてみましょう。実は、これには2つの重要な理由があります。
第一の理由は速度です。キャッシングサービスは、従来のデータベースアーキテクチャ(リレーショナルやノンリレーショナルを問わず)では実現できないマイクロ秒レベルのレイテンシを提供します。現代のチャットボットを構築する際、ユーザー体験を考慮すると、長い待ち時間は許容されません。先ほど見たように、チャットボットから他のアプリやメール、競合他社のサイトへのコンテキストスイッチが簡単に発生してしまいます。
このキャッシングソリューションを活用することで、常にサブミリ秒の応答時間を一貫して提供できるようにチャットボットを設計できます。また、データベースへのラウンドトリップを排除できます。チャットボットはI/O集約型で、常に多くの読み取りと書き込み、多くのルックアップが発生します。キャッシュを使用することで、より高コストなデータベースへのルックアップを防ぐことができます。これにより、一貫したパフォーマンスが実現できます。
第二の重要な理由は運用コストの削減です。顧客が同じ質問を繰り返し行い、同じ回答を何度も求める場合を想像してください。典型的なRAGベースのアーキテクチャでは、検索距離の再計算、埋め込みの再生成、ユーザークエリの埋め込みへの変換、データベースからの類似した応答の取得、プロンプトとの組み合わせによる返答など、多くの処理が必要です。
データベースへの1回のラウンドトリップでこれらの処理を行うには多くの時間がかかります。しかし、キャッシュを使用して、顧客からよく尋ねられる質問と回答のペアをキャッシュすることで、総運用コストを大幅に削減することができます。これらの理由から、キャッシュの導入を強く推奨します。
3.3. Amazon ElastiCacheの特徴と利点
Shayon Sanyal:AWSスタックでキャッシングサービスを考える際、Amazon ElastiCacheがありますが、ここでServerlessという要素が加わります。例えば、私がニューヨーク出身なので想像しやすいのですが、JFK空港で夜11時に足止めされる状況を考えてみてください。フライトがキャンセルされた場合、次のフライトを探すのは大変です。もし朝の便に乗る必要がある場合は、近くのホテルに宿泊する必要があります。
このとき、同じフライトの200人の乗客全員が同時に同じホテルや別のホテルを必死に探すことになります。このような場合、プロビジョニングされたインスタンスやキャッシングサービス、プロビジョニングされたクラスターを使用していると、需要の急増に対応するためのキャパシティを計画する時間も余裕もありません。夜11時にそのような大規模なスパイクが発生し、通常時間帯にはまた需要が下がるような状況で、動的にスケールアップとスケールダウンができるソリューションが必要です。
そこでServerlessが非常に適しているのです。Amazon ElastiCache Serverlessは、業界で一般的な3つのエンジン(Redis、Memcached、最近ではElastiCacheのオープンソース提供であるValkey)と互換性のある、完全マネージド型のキャッシングソリューションです。
クライアントアプリケーションは単一のエンドポイントに接続するだけでよく、そのエンドポイントの背後では、プロキシノードのセットに接続されます。これはアプリケーションからは完全に透過的で、顧客は接続先を意識する必要はありません。これはロードバランスされたネットワークロードバランサーのような仕組みです。
このプロキシレイヤーはクラスター全体を抽象化しています。需要のスパイクに対応するためにシャードを追加したり、リソースを追加したりする必要がある場合、このアーキテクチャによって自動的に追加・削除が行われます。
このアーキテクチャはAZFlightsのようなユースケースに非常に適しています。高いキャッシュヒット率により、常にサブミリ秒の応答時間を保証し、データベースへの負荷を軽減します。また、4つ9(99.99%)の可用性とアップタイムを維持します。これはサービス保証の一環として、RDSやキャッシングスタックのすべてのマネージドサービスで提供している機能です。
さらに、静かな期間やホリデーシーズンのピーク時、緊急事態、予期せぬ状況など、フライトのキャンセルによるスパイクが発生した場合でも、自動的にスケーリングが可能です。これにより、そのような需要の急増も簡単に処理できるようになります。
4. ベクトルストアの実装
4.1. ベクトルストアの必要性
Shayon Sanyal:高速なデータアクセスについて説明しましたが、次はそのデータに意味を持たせる方法について考えていきましょう。キャッシングソリューションは、投入されたすべてのデータを単純にキャッシュするだけで、そのデータに対する知的な処理や意味付けは行いません。しかし、私たちは、ユーザーの好みやプロファイルに合わせてデータを調整する必要があり、そのためには検索時にデータに意味を持たせ、インテリジェンスを加える必要があります。
これは重要な疑問を提起します。なぜデータを永続的に保存する必要があるのでしょうか?単にキャッシングソリューションで一時的に保存し、失われても構わないのではないでしょうか?その理由を説明させてください。
質問と回答のペアを追加するたびに、以前の質問に対するフォローアップがある場合、チャットボットには記憶力がありません。保持する能力がないのです。文脈を失い、会話の履歴もなくなってしまいます。そのため、チャットボットが応答する際の狂気に、何らかの方法を加える必要があります。
私たちのシナリオでは、CSVやPDFファイルなどのドキュメントソースに基づいた知識ソースを入力します。これらのソースには、ホテル、フライト、人気の休暇先などに関する情報が含まれています。重要な点として、このソースは必ずしもテキストである必要はありません。画像や動画でも構いません。マルチモーダルモデルが最近のトレンドとなっています。例えば、バリのビーチの写真を見せて、「このビーチに似たリゾートを探して」といったクエリも可能です。これも有効なユースケースとなりえます。
このプロセスは、ドキュメントソースをベクトルストアに取り込む際に行われます。埋め込みモデルを通じて、自然言語で読める形式(テキスト、画像、動画)から、いわゆるベクトルに変換されます。このベクトルは、単なる一連の数字です。n次元の浮動小数点数です。整数やバイナリ、浮動小数点といった典型的なデータ型ではなく、この新しいベクトルデータ型は非常に大規模です。三次元配列の1000倍、さらにその1000倍というような巨大な次元の浮動小数点数の配列です。これが、私たちのソースに意味を付与する情報であり、ベクトルデータベースにベクトルの形で格納されます。
4.2. Aurora PostgreSQLの活用
Shayon Sanyal:ベクトル検索機能を提供するAWSのデータベースは、現在多くあります。実際、私たちの完全マネージド型データベースのほとんどが今日このベクトル検索機能を提供しています。そして、時間の経過とともに、データベースとアナリティクスサービスの両方がベクトル検索機能を提供するようになるでしょう。
その中で、Aurora PostgreSQLデータベースはpgvector拡張機能を備えています。pgvector拡張機能は、単なるもう一つのデータ型だと考えてください。複雑に考える必要はありません。これは、先ほど説明したn次元の浮動小数点数を格納する方法に過ぎません。
しかし、このデータ型を導入することで、多くの機能と利点が得られます。なぜなら、このデータ型により、インデックスが導入され、類似性検索などを実行するための特定の関数が導入されるからです。
実際のデータを見てみましょう。私のテーブル「travel_knowledge_base」には、コンテキスト情報が格納されています。例えば、「シドニーの歴史は温泉で豊かです」といったサンプルレコードがあります。このようなレコードは何百万もありますが、これがベクトルの次元がどのように見えるかの実例です。これらは1024次元の巨大な数値の配列です。
このようなベクトルデータを効率的に検索・管理するために、私たちは適切なインデックスを作成します。このインデックスにより、大規模なベクトルデータセットに対しても高速な類似性検索が可能になります。これは、チャットボットの応答性能に直接影響を与える重要な要素となります。
4.3. Serverless v2の特徴と利点
Shayon Sanyal:Aurora ServerlessはPostgresとMySQL両方のAuroraエンジンで提供されていますが、今回はpgvector拡張機能を持つPostgresエンジン用のServerless v2バージョンに焦点を当てています。
Aurora Serverless v2は、Amazon Auroraのオンデマンドオートスケーリング構成です。先ほど説明したElastiCacheと同じように、アプリケーションに影響を与えることなく、スケールアップ、スケールダウンが可能です。コンピュートノードは自動的に垂直に成長・縮小します。つまり、容量を自動的に追加・削減しているのです。
なぜこれがAZFlightsに適しているのでしょうか?第一に、需要に基づいて自動的にスケーリングできるため、検索のスパイクや急な乗客の予約などを最小限の労力で簡単に処理できます。
最近のアップデートとして、Serverless v2で完全なゼロへのスケーリングが可能になりました。これは直接的なコスト削減につながります。もはや、ワークロードがない時でも最小0.5 ACU(Aurora容量ユニット)の容量を支払う必要がなくなったのです。
さらに、追加のコスト削減が、昨年のre:Invent時期に発表された新しいストレージタイプでも可能になりました。IO最適化ストレージ構成です。これにより、IOコストを文字通りゼロにすることができます。チャットボットやジェネレーティブAIソリューションを構築する際、距離計算やセマンティック検索は非常にIO集約的です。このストレージ設定により、IOコストが完全に無効化されるのです。
その結果、チャットボットの運用コストをより予測可能な形で事前に見積もることができます。実際に、IO最適化により最大40%のコスト削減を達成した顧客も見てきました。
第三の利点として、Bedrock知識ベースとAurora Postgresをベクトルストアとして直接統合できます。これにより、カスタマーサポートエージェントは、複雑なインフラストラクチャを管理したり、適切なパイプラインを構築したりすることなく、カスタマーサービスボット機能を何千もの地域や場所に大規模に展開できます。
最後に、最大の利点は、ベクトルデータをトランザクションデータ、顧客360度データと共に配置できることです。これにより、アーキテクチャ全体が簡素化されます。新しい専用のベクトルデータベースとの間でデータをやり取りする必要もなく、クライアントドライバーの接続性を心配する必要もありません。既存のJDBC、ODBCなどのクライアントドライバーがこのアーキテクチャでシームレスに動作します。さらに、高速クローン、グローバルデータベース、ゼロRTOなど、従来のAuroraの利点もすべて享受できます。
5. RAG (Retrieval-Augmented Generation)の実装
5.1. RAGの基本概念と重要性
Shayon Sanyal:RAGを実例を使って説明させてください。「エッフェル塔に入るのに最適な時間は?」という質問を考えてみましょう。私たちのLLMが、リレーショナルデータストアからリアルタイムのエレベーター待ち時間情報にアクセスできる場合、これが状況に応じたコンテキストとなります。
RAGには2つの重要な要素があります。一つは知識ベースからの情報で、これを私たちは静的コンテキストと呼んでいます。リアルタイムの待ち時間が動的コンテキストであるのに対し、開館時間やチケット料金、頻繁には変更されないFAQなどが静的コンテキストです。
つまり、これは意味的なコンテキストです。FAQや開館時間、チケット料金に対する厳密なマッピングはありません。エッフェル塔を訪れる時間帯の範囲や、チケットの価格帯など、常に一定の幅を持った情報となります。
これらすべてを単純な質問と組み合わせることで、RAGが定義されます。動的コンテキスト(状況に応じたコンテキスト、リアルタイムのエレベーター待ち時間)と静的情報(開館時間、チケット料金)に基づいて、「午前9時から10時の間に行くことをお勧めします。この時間帯が最も待ち時間が短いです」といった具体的な回答が生成されます。
さらに、プロンプトで指示したように、ボットは「チケットの予約をお手伝いしましょうか?」といった親切なフォローアップも提供します。これが基本的なアーキテクチャであり、今後構築していく中核となる技術です。RAGとは、このように私のデータ、つまり私の独自のデータを使って、チャットボットの応答を外部のインテリジェンスで補強することを可能にする技術なのです。
5.2. 知識ベースの統合
Shayon Sanyal:知識ベースについて説明する際に、私はよく車のアナロジーを使用します。知識ベースはハイブリッドのようなものです。ちょうど中間に位置し、乗り込んで動かすだけで機能します。ある程度のコントロールはありますが、柔軟性はそれほどありません。
Amazon Bedrock知識ベースを使用すると、RAGパイプラインが完全マネージド型で提供され、より簡単になります。同じ質問「エッフェル塔を訪れるのに最適な時間は?」を考えてみましょう。知識ベースはデータソース(フラットファイル、CSVファイルなど)と、Aurora Postgresなどのベクトルストアにアクセスできます。
Amazon Bedrock知識ベースに任意のデータソースを供給すると、自動的にソースファイルのチャンク分割、埋め込みモデルを使用したベクトル化、そしてベクトル埋め込みのベクトルデータストアへの格納を行います。ユーザーとして必要な高レベルの決定事項は、チャンク分割戦略、埋め込みモデル、ベクトルストアの選択だけです。チャンク分割、使用、格納の背後にあるプロセス全体は自動的に処理されます。
実際、今朝発表したばかりですが、Aurora Postgres用の新しいクイッククリエイト機能を導入しました。これにより、Bedrock知識ベースとAurora Postgresのベクトルストアとしての統合がさらに簡単になります。これはシンガポールとUS West-2リージョンで最初に展開され、その後、異なるリージョンに段階的に展開される予定です。
以前は、ベクトルストアの選択が大きな決定でした。Pinecone、OpenSearch、MemoryDB、Postgres、MySQLなど、多くの選択肢があり、それぞれに考慮すべき点がありました。私たちは、このワンクリック統合でそれを少し簡単にしようとしています。必要なのは2つのことだけです:知識ベースを作成する際にベクトルストアを選択する時に、推奨オプションであるクイッククリエイトベクトルストアを選択し、Aurora Postgres ServerlessをAzureエンジンベクトルストアエンジンとして選択するだけです。
これにより、最小および最大ACUを持つこれらのリソースをプロビジョニングするCloudFormationテンプレートが背後で展開されます。必要に応じて設定をカスタマイズすることもできますが、このRAGパイプライン構築の全体的な決定プロセスをできるだけ簡単にしようとしています。以前は数日かかっていた作業が、今では数分で設定できるようになりました。
5.3. Amazon Bedrockとの連携
Shayon Sanyal:知識ベースについて説明した際に使用した車のアナロジーを続けると、完全自動運転車が必要な場合は、Amazon Qを選択することになります。シートに座って運転するだけで、サービスのプロビジョニングやキャパシティの心配をする必要はありません。必要なのは、ドキュメントをアップロードして質問を始めるだけです。これがQの簡単さです。
一方で、LangChainのような第三者統合は、マニュアル・トランスミッションの車のようなものです。より大きな柔軟性が得られます。Hugging Face、OpenAPI、OpenAIなどのオープンソース統合と接続するためのAPIが利用可能です。しかし、それと同時により多くの運用オーバーヘッドも伴います。マニュアルシフトと同様に、より多くの労力が必要です。
選択は本当にリソース、コストによって決まります。これが全てです。Amazon Qについてより詳しく説明すると、これはAmazonの完全マネージド型のノーコード、ローコードソリューションです。ドキュメントをアップロードするだけで、AZFlightsのFAQドキュメントのような場合、すぐに質問を始めることができます。
Qは設定不要で、統合や接続を構築する必要もありません。RAGの精度を持ちながら、100%ソースから情報を取得します。クイックルックアップ用の組み込みベクトルインデックス機能を備えており、Aurora Postgresを含む40以上の一般的なデータソースに接続できます。
つまり、Bedrockとの統合を考える際には、必要な柔軟性のレベルと運用オーバーヘッドの許容度に基づいて、適切なアプローチを選択することが重要です。これは、プロジェクトの要件と利用可能なリソースに応じて、最適な選択を行うことを意味します。
6. アーキテクチャパターン
6.1. コンテキストキャッシング
Shayon Sanyal:スケールでLLMを扱う際に、リアルタイムのコンテキスト取得を効率的に管理することが重要な課題となります。これに対処するため、私たちはコンテキストキャッシングのパターンを採用しています。この解決策は、ElastiCacheをコンテキストキャッシュソリューションとして導入することで実現します。
このアプローチには、二つの主要な利点があります。まず、高速なデータ取得が可能になります。ElastiCache Serverlessを利用し、これをAurora PostgresやI/O最適化、Serverlessと組み合わせることで、予測可能なパフォーマンスを実現できます。また、需要のスパイクにも対応できます。読み取り負荷の高いワークロードに対しても、コスト面での利点があります。
このパターンが実際にどのように機能するか、具体例で説明します。例えば「イタリアの理想的な7日間の旅程は?」という質問があった場合、ElastiCacheは状況に応じたコンテキスト、つまりリアルタイムデータをリレーショナルデータストアから取得します。これにはRDSやAuroraなどが含まれます。
同時に、静的コンテキスト、つまり意味的なコンテキストも取得します。これらの情報をLLMに提供し、そのLLMはユーザーに対して詳細にカスタマイズされた応答を生成します。このアプローチにより、パフォーマンスの向上とコストの最適化を同時に実現できます。
私たちの実装では、キャッシュヒット時のレスポンスタイムが200%高速化され、サブミリ秒レベルの応答時間を達成しています。また、ElastiCacheとAurora PostgreSQLの組み合わせにより、最大40%のコスト削減も実現しています。このパターンは特に、頻繁なコンテキスト検索が必要なチャットボットアプリケーションで効果を発揮します。
6.2. ベクトル埋め込みのキャッシング
Shayon Sanyal:ベクトル埋め込みは非常に強力ですが、いくつかの課題も伴います。セマンティック検索のパフォーマンスを低下させる可能性があります。なぜなら、生成、取得、変換、そして距離計算など、多くの処理が必要だからです。さらに、コストの側面も重要な考慮点となります。
この問題に対して、異なるアプローチを考えてみましょう。ElastiCacheは基本的にすべてをキャッシュしますが、ElastiCacheを使って埋め込み自体もキャッシュすることはできないでしょうか?これらの埋め込みは非常に計算負荷の高い操作です。「一度生成してキャッシュし、その後は繰り返し使用する」というアプローチを取ることができます。「バリでの休暇」や「ベルリンのナイトライフ」といった頻繁に検索される用語について、埋め込みを一度生成し、それをElastiCacheでキャッシュすることで、パフォーマンスとコストの両面でメリットを得ることができます。
パフォーマンス面では、ElastiCacheで埋め込みをキャッシュすることで、セマンティック検索のスピードを大幅に向上させることができます。コスト面では、埋め込みの生成は入力トークンと出力トークンに基づいて課金されます。トークンは単語に基づいています。これらの単語をキャッシュすることで、実質的にプロンプトを最小化し、支払うコストを削減できます。
このように、埋め込みのキャッシングは、パフォーマンスの向上とコストの最適化の両方に直接的な効果をもたらす戦略となります。特に大規模なシステムや高頻度のクエリが発生する環境では、この戦略の効果が顕著に現れます。
6.3. サーバーレスアーキテクチャの活用
Shayon Sanyal:このアーキテクチャが実際にどのように動作するかを説明しましょう。「アムステルダムのベストバー」、「ロンドンのアートギャラリー」、「パリのベストフード」、「タイの市場」といった大量のクエリが入ってくる状況を想定してください。
このようなクエリは、まずAPI Gatewayを通過し、そこから2つのパスのいずれかにリダイレクトされます。ベストケースのシナリオは、検索語がすでにキャッシュされている場合です。この場合、ElastiCacheに到達し、サブミリ秒での取得が可能となります。
一方、質問がキャッシュされていない場合は、より深い検索が必要になります。その場合、完全にサーバーレスなスタックを活用し、Lambdaを経由してAurora Postgresに到達します。ただし、同じ質問に対する後続の取得はキャッシュされることになります。
このグローバルな急増するワークロードがある場合、世界中のどこからでも顧客がログインして質問を投げかけることができます。サーバーレススタックの中核であるElastiCacheとServerless Aurora Postgresが、その負荷を動的に非常に簡単に処理できます。
このフルスタックサーバーレスアーキテクチャは、このようなユースケースに非常にうまく適合します。特に、地理的に分散したユーザーからの予測不可能な負荷パターンに対して、効率的なスケーリングと一貫したパフォーマンスを提供できます。
7. 実装デモンストレーション
7.1. システム構成の概要
Shayon Sanyal:それでは、実際の動作を見ていきましょう。理論の話は十分にしましたので、実践的な部分に移りましょう。私たちはValkey cacheをElastiCacheで設定し、またAurora Postgres Serverless v2を最小ACUと最大ACUを設定して構築しています。このアーキテクチャ全体がどのように機能するか、順を追って説明していきます。
私たちはAurora Postgresを知識ベースとして使用しており、これは同時にベクトルストアとしても機能します。pgvector拡張機能により、ベクトルという特定のデータ型が利用可能になり、これによって巨大な次元のベクトルを格納することができます。
実際のデータを見てみましょう。私の「travel_knowledge_base」というテーブルには、コンテキスト情報が格納されています。例えば「シドニーの歴史は温泉で豊か」といったサンプルレコードがあります。これは数百万件あるレコードの一例ですが、このようなデータに対してベクトルの次元がどのように見えるかを示しています。これらは1024次元の巨大な数値の配列です。
デモンストレーションのインターフェースとして、私はStreamlitを使用しています。これはPythonベースのオープンソースツールで、アプリケーションを素早く構築するために広く使用されています。このデモユーザーインターフェースを通じて、実際のシステムの動作とパフォーマンスを確認していきます。
このアーキテクチャでは、クエリのパフォーマンス、キャッシュの効果、そしてシステム全体の応答性を測定するために、いくつかの重要なメトリクスをサイドバーで追跡しています。これにより、システムの動作を実時間で確認し、各コンポーネントがどのように連携しているかを示すことができます。
7.2. パフォーマンス測定結果
Shayon Sanyal:私たちのデモを使用して、具体的なパフォーマンス指標を確認していきましょう。最初に「京都の文化的な場所について教えて、日本を訪れる予定です」という質問をしてみました。この最初のクエリは、Aurora Postgresに向かいます。なぜなら、まだキャッシュされていないからです。これはキャッシュミスとして記録され、サイドバーのメトリクスに表示されています。キャッシュミスのカウンターが1になり、データベースクエリは40~200ミリ秒の範囲内に収まっています。
次に、同じ質問を再度実行してみました。これは全く同じ検索語であり、すでにキャッシュされているはずです。実際、キャッシュヒットが発生し、キャッシュカウンターが更新されました。より重要なのは、キャッシュからの取得時間がデータベース時間と比較して200%高速化され、0.45ミリ秒というサブミリ秒レベルの応答時間を達成したことです。
次に、チャット履歴のパフォーマンスを実証するため、「これらの場所を訪れるのに最適な時期は?」という質問をしました。この質問では京都への言及はありませんが、システムはElastiCacheからチャット履歴を取得し、京都に関する適切な応答を非常に迅速に提供しました。重要な指標は履歴取得時間で、これもサブミリ秒を達成しています。
さらなるフォローアップ質問として、「参加すべき文化的なイベントはありますか?」を試してみました。ここでも京都への言及はありませんが、前の会話の文脈を維持したまま、チャット履歴の取得時間はサブミリ秒を維持しています。これは、キャッシングと履歴管理が効果的に機能していることを示しています。
システム全体の性能評価としては、一貫してサブミリ秒レベルのレスポンスタイムを維持し、特にキャッシュヒット時には著しいパフォーマンス向上を示しています。また、暖機運転後のデータベースクエリも許容範囲内のレスポンスタイムを維持しており、システム全体として安定した性能を発揮しています。
7.3. キャッシュヒット率の分析
Shayon Sanyal:次に、ユーザーの好みに基づく推薦機能のパフォーマンスを検証してみましょう。「バリでのビーチと予算内での訪問に興味があります」という設定で、ElastiCacheに設定が即座に保存されます。その後、「バリで訪れるべきおすすめの場所を教えてください」という質問をしました。
この質問は、初回はデータベースから取得されたため、キャッシュミスとなりましたが、それでも44ミリ秒という良好なレイテンシを示しました。重要なのは、ElastiCacheからのユーザー設定の統合がサブミリ秒で実行されたことです。
続いて、バリに関する文脈を明示せずにフォローアップ質問をしましたが、システムはチャット履歴からその文脈を取得し、バリに関する詳細な応答を提供しました。チャット履歴の取得はElastiCacheから行われ、再びサブミリ秒のレイテンシを達成しています。ユーザー設定の統合も同様にElastiCacheからサブミリ秒で実行されました。
さらに、バリに関する別のフォローアップ質問では、設定、コンテキスト、チャット履歴、そして予算フィルターを含む統合的な応答を生成しました。履歴取得はサブミリ秒、設定の統合もサブミリ秒を維持し、予算範囲のフィルターも指定通りに機能しました。
これらの結果は、キャッシュの多層的な活用が、単なる応答時間の改善だけでなく、文脈の維持やパーソナライゼーションの品質向上にも貢献していることを示しています。特に、チャット履歴とユーザー設定の組み合わせによる相乗効果が、システム全体のパフォーマンスを最適化する重要なポイントとなっています。
8. Bedrock Agentsの活用
8.1. エージェントの基本構造
Shayon Sanyal:これまでのRAGベースのアーキテクチャの次の進化として、Bedrock Agentsについて説明したいと思います。私たちのトラベルアシスタントは、これまで質問に答えることには優れていました。これらは検索ベースの質問で、検索、生成というプロセスで対応していました。
しかし、「マウイで3,000ドルの予算で5日間のフードツアーを計画できますか?」といったタスクベースの質問はどうでしょうか?これは一見単純に見えるかもしれませんが、実はボットにとって複雑なタスクです。エージェントは以下のステップを実行する必要があります:
- フライトと料金の空き状況を確認
- 予算内のホテルを探す
- ユーザーの好みに合うレストランを見つける
- 日程ごとの予算に配慮した旅程を要約する
このような一連のステップを含むマルチステップのタスク実行が必要な場合、Bedrock Agentsのワークフローが非常に有効になります。Bedrock Agentsはオーケストレーターとして機能し、ユーザーリクエストが入ってくると、一連のステップを生成します。
次に、必要な情報が何か、外部ソースは何か、内部ソースは何かを判断します。例えば、トラベルのコンテキストをリレーショナルデータベースやノンリレーショナルデータベースから取得する必要があるかもしれません。また、Lambda関数やOpenAPIスキーマへのアクセスも可能で、これらは特定のステップを実行するための機能を提供します。
エージェントはこのプロセスを繰り返し実行し、ユーザーリクエストを満たすまでプランを実行します。そして最終的にタスクを完了します。同時に、高度な機密性を持つデータに対してもセキュリティを確保します。これはすべて、企業の独自のデータを使用して応答を生成するプロセスの一部となります。
8.2. アクショングループの実装
Shayon Sanyal:エージェントの構造は3つの重要な要素から構成されています。まず「インストラクション」があり、これはエージェントに役割を割り当てます。例えば、「あなたは親切なカスタマーサービスボットです」「あなたはトラベルエージェントです」「フレンドリーで会話的なトーンで応答してください」といった指示を与えます。
次に、エージェントにはナレッジベースとアクショングループへのアクセス権が与えられます。これらは、エージェントが実行する具体的なタスクを定義します。そして最後に、LLMモデルへのアクセスが提供されます。
オーケストレーションの基本的なフローは以下のようになります:まずタスクを複数のステップに分解します。そして、特定のアクションを実行するか、ナレッジベースから情報を取得します。エージェントは、思考、観察、アクションというプロセスを反復的に実行し、満足のいく結果が得られるまでこれを繰り返します。最後に最終的な応答を生成します。
実際のアクショングループの実装では、APIの仕様とLambda関数を紐付けます。これは重要なポイントで、アクショングループ(エージェントが実行するアクション)とエンドポイント(呼び出すAPI)、そしてそのアクションを実行するLambda関数との間に1対1対1の対応関係があります。この全体的なアーキテクチャが、エージェントワークフローの本質です。
この方式により、エージェントは複雑なタスクを管理可能な単位に分解し、各ステップを適切なコンポーネントと連携しながら実行することができます。これは、単なる質問応答を超えて、実際のタスクを完遂できる強力なシステムとなります。
8.3. APIとLambda関数の統合
Shayon Sanyal:「フライトを確認する」といったAPIのサンプルについて、OpenAPI仕様はどのように見えるか説明しましょう。これは業界標準のAPI仕様で、とても一般的なJSON形式を使用します。必要なパラメータ(目的地、日付、予算など)を指定し、それを実装するLambda関数を定義します。
私たちのAPIの実装例を見てみましょう。Lambda関数は、まず質問と回答がElastiCacheに保存されているかどうかを確認します。もし存在すればそれを取得し、存在しない場合はAurora Postgresで検索を行います。そして、ベクターデータベースを通じて検索を実行した後、後続の性能向上のためにキャッシュに保存します。
このアーキテクチャを全て組み合わせると、以下のような流れになります。例えば、「マウイで3,000ドルの5日間のフードツアーを計画できますか?」という質問に対して、エージェントはこの複雑な質問を複数のアクションに分解します。これらのアクションは、先ほど説明したナレッジベースやアクショングループ(OpenAPIとLambdaの組み合わせ)のツールを使用して実行されます。
同時に、ElastiCacheから設定を取得し、キャッシュされた埋め込みを取得し、チャット履歴も取得して、そのプロンプトを補強します。このユーザーに質問している文脈を考慮しながら、この反復的なループを通じて、エージェントは思考、行動、観察を行い、最終的に詳細な旅程で応答します。
このように、Bedrockエージェントは、私たちが構築したAPIコールとLambda関数を、シームレスで高速な予約体験へと変換します。最後のデモでは、このエージェントが実際にクレジットカードの詳細、名前、情報、旅行プロファイルを取得し、簡単な質問に答えるだけで予約を完了する様子を確認できました。
9. まとめと今後の展望
9.1. 主要な成果
Shayon Sanyal:私たちはこのセッションを通じて、パズルの重要な部分を解決することができました。最初の課題であった、より個人化された旅行itineraryの提供という目標の50%を達成しました。
大きな成果として、まずパフォーマンスの面で、ElastiCacheとAurora PostgreSQLの組み合わせにより、200%の応答時間の改善を達成しました。特に、キャッシュヒット時にはサブミリ秒レベルのレスポンスタイムを実現することができました。
また、IO最適化ストレージの活用により、最大40%のコスト削減も実現しています。これは特に、チャットボットのような高いI/O負荷がかかるワークロードで顕著な効果を示しました。
Bedrock Agentsの導入により、単なる質問応答を超えて、実際の予約フローの自動化まで実現できました。デモで示したように、クレジットカードの詳細や顧客プロファイルの取得から、実際の予約完了まで、シームレスな体験を提供することができます。
このアーキテクチャの主要な利点は、スケーラビリティとコスト効率の両立です。サーバーレスコンポーネントの採用により、需要の変動に応じて自動的にスケールアップ・ダウンが可能になり、同時に予測可能なコスト構造を維持することができます。
これらの成果は、当初の課題であった顧客離脱の防止と、より効率的な予約プロセスの実現という目標に直接的に貢献しています。
9.2. 推奨リソースと関連セッション
Shayon Sanyal:今日のデモで使用したコードは公開されています。また、この技術をより深く学ぶためのリソースも用意しています。特に、ワークショップやGitHubのサンプルなど、様々な学習リソースを活用していただけます。
また、このトピックに関連する他の興味深いセッションも多数開催されています。これらのセッションは、今日カバーしたトピックと密接に関連しており、ぜひ参加をお勧めします。
このセッションは終了となりますが、マハロ(ハワイ語で「ありがとう」)、そして残りのre:Inventをお楽しみください。また、来年のセッションをさらに良いものにするために、セッションのサーベイにもぜひご協力ください。
私たちはここで、チャットボットの応答時間の最適化から始まり、RAGの実装、そしてBedrock Agentsの活用まで、幅広いトピックをカバーしました。これらの技術を組み合わせることで、より良い顧客体験を提供することが可能になります。ぜひ、これらのリソースを活用して、皆さんの組織でも同様の改善を実現していただければと思います。