📖

re:Invent 2024: AWSがMemoryDBで生成AIアプリを最適化

2024/01/01に公開

はじめに

海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!

📖 AWS re:Invent 2024 - Optimize gen AI apps with durable semantic caching in Amazon MemoryDB (DAT329)

この動画では、AWS上でGenerative AIアプリケーションを構築する際のスケーリング、パフォーマンス向上、コスト最適化について解説しています。Amazon MemoryDBを使用したDurable Semantic Cachingの実装方法を中心に、Vector Similarity SearchやHNSWなどの技術的な詳細、そしてCache比率が75%の場合に約75%のコスト削減が可能といった具体的な効果が示されています。また、Iterate.aiの事例では、月間57,000件の質問を処理するChatbotアプリケーションでコストを70%削減し、レイテンシーを秒単位からミリ秒単位に改善できたことが紹介されています。さらに、MemoryDBの重複排除技術によるメモリ消費量の52-56%削減など、実装に役立つベストプラクティスも詳しく解説されています。
https://www.youtube.com/watch?v=2mNXSv7cTLI
※ 動画から自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますので、正確な情報は動画本編をご覧ください。
※ 画像をクリックすると、動画中の該当シーンに遷移します。

re:Invent 2024関連の書き起こし記事については、こちらのSpreadsheet に情報をまとめています。合わせてご確認ください!

本編

Generative AIアプリケーションの課題とDurable Semantic Cachingの導入

Thumbnail 0

みなさん、ご参加ありがとうございます。私たちは皆、Generative AIで何ができるかということに魅了されてきました。もし皆さんがAWS上でGenerative AIアプリケーションを構築していて、アプリケーションのスケーリング、パフォーマンスの向上、コストの最適化のための適切なソリューションをお探しでしたら、まさに適切な場所にいらっしゃいます。このセッションでは、Amazon MemoryDBを使用してDurable Semantic Cachingを実装することで、それらをどのように実現できるかをご紹介します。私はIn-Memory Databasesのゼネラルマネージャーを務めるItay Maozです。一緒にいるのは、MemoryDBのVector Similarity Search機能のローンチを主導したプロダクトマネージャーのSanjit Misraです。始める前に、すでにGenerative AIアプリケーションの構築を始められている方は手を挙げていただけますか?素晴らしいですね。多くの方が手を挙げてくださって嬉しく思います。

Thumbnail 70

Generative AIは世界中の何百万人もの人々の想像力を掻き立てています。企業はGenerative AIモデルの活用を始めたばかりですが、その威力がどれほどのものかが見え始めています。Generative AIは、会話、物語、画像、音楽など、新しいコンテンツやアイデアを生み出すことができるAIの一種で、すべてのAIと同様に、機械学習モデルによって支えられています。これらは非常に大規模なモデルで、一般的にFoundation Modelsと呼ばれています。

Thumbnail 100

Thumbnail 110

Gartnerは、2026年までに80%の企業が本番環境でGenerative AIを使用するようになると予測しています。 Generative AIは、膨大な量の非構造化データで事前学習されたFoundation Modelsによって支えられています。これらのモデルは、多くの異なるアプリケーションに適用できる複雑な概念を学習することができます。TitanやClaudeなどのLarge Language Models(LLMs)についてお聞きになったことがあると思いますが、これらはFoundation Modelsの一種です。

Durable Semantic Cachingの仕組みと利点

Thumbnail 110

Thumbnail 160

Thumbnail 180

LLMsやFoundation Modelsの課題の1つは、使用量が増えるにつれてコストが高くなることです。 こちらは、Amazon BedrockでTitan Text Premierを使用したチャットボットの実装例です。黄色い線で示されているように、ユーザー数が増えるとコストも同様に増加していきます。 実際に私たちが目指しているのは、緑の線のように、サブリニアにスケールする状態です。今日は、Durable Semantic Cachingを実装することで、この線形的な増加を避け、この緑の線を実現する方法についてお話しします。

Thumbnail 180

Thumbnail 200

Thumbnail 210

Durable Semantic Cachingの考え方は、皆さんがよくご存じの他のキャッシングシステムと似ています。パフォーマンス、スケーラビリティ、コストを改善するために、コストのかかる繰り返しのクエリの結果をキャッシュします。 では、 Durable Semantic Cachingの特徴は何でしょうか?まずはSemantic(意味的)な側面について理解しましょう。Semantic Cachingを理解するには、まずVector Embeddingsについて理解する必要があります。

非構造化データ(ドキュメント、ビデオ、オーディオなど)を、そのデータの意味的・文脈的な意味を含む数値表現に変換することを考えてみましょう。Vector Embeddingは、異なる意味要素間の意味的な関係を捉えることができます。例えば、テキストの場合、意味的な認識により、「book」という単語が文脈に応じて、読む「本」を指すのか、フライトの「予約」を指すのかを区別することができます。これらのVector Embeddingを作成するプロセスには、ソースからのデータの取り込み、チャンクへの分割、ベクトルへの変換が含まれます。これらのベクトルは、通常数百から数千の次元を持つ多次元のものです。

Thumbnail 270

Thumbnail 280

Thumbnail 300

そして、意味的な意味を正確に表現することが重要です。これを視覚化するために、3次元を使用してみましょう。 ここでの重要なポイントは、意味的に似ているベクトルは、ベクトル空間内で互いに近い位置に配置されるということです。 Vector Embeddingについて理解できたところで、Semantic Cachingについて見ていきましょう。

Thumbnail 330

チャットボットやその他のアプリケーションで、ユーザーからのプロンプトクエリがある場合を考えてみましょう。本、家具、金融の例を使って、3次元で視覚化しながら説明させていただきます。簡単にするために、これらのクエリをDurable Semantic Cacheに保存します。例えば、以前のクエリが「冒険小説のおすすめを教えて」で、新しいクエリが「どんな冒険小説がおすすめ?」だとします。これら2つの文字列は完全に一致していないため、完全一致や文字列のハッシュを使用する従来のキャッシング技術では機能しません。しかし、人間であれば、これら2つの文字列が意味的に似ていることがわかります。

Thumbnail 360

Thumbnail 390

Thumbnail 400

これこそが、新しいクエリに対してベクトルで実現しようとしていることです。意味的に類似したベクトルを探し始め、徐々に検索範囲を広げていきます。十分に近いものが見つかれば(「十分に近い」とは具体的に何を意味するのかは、後ほど説明します)、そのクエリに対するキャッシュとデータを返します。では、Durable Semantic Cachingがアプリケーションのどこに適合するのか見てみましょう。エンドユーザーがGenerative AIアプリケーションにプロンプトリクエストを送信します。ここでも同じ例「冒険小説のおすすめを教えて」を使用します。そして、Generative AIアプリケーションは同じプロンプトをFoundation Modelに送り、レスポンスを受け取ってエンドユーザーに返します。

Thumbnail 420

Thumbnail 430

Thumbnail 440

Thumbnail 450

Thumbnail 460

ここでキャッシングを追加してみましょう。プロンプトで始まるのは同じですが、Foundation Modelに行く代わりに、まずEmbeddingを作成します。これにより約100ミリ秒のレイテンシーとわずかなコストが追加されます。Embeddingを作成し、ベクトルを取得し、Durable Semantic Cacheで検索を行います。このようなベクトルを初めて見る場合は、キャッシュミスとなります。キャッシュミスが発生すると、2つのことを行います。まず、Foundation Modelからデータを取得します。このFoundation Modelの呼び出しはかなりコストがかかり、通常数秒の時間がかかります。レスポンスを受け取ったら、並行して2つのことを行います:まず、エンドユーザーにレスポンスを返し、次に、このベクトルデータでキャッシュを更新します。

Thumbnail 500

Thumbnail 510

これがCache Missの場合です。Embeddingの作成とCacheの操作に少し多くの作業が必要になりますが、非常に低コストで低レイテンシーです。では、なぜこれが価値があるのか見てみましょう。Cache Hitの場合どうなるか見てみましょう。まず同じクエリ「Tell me some adventure books to read」から始めます。Embeddingを作成し、ベクトルを取得し、このベクトルを使って私たちのDurable Semantic Cacheを検索します。 今回はCache Hitとなり、Cache Hitにより、Foundation Modelへの高コストな呼び出しを避けて、非常に低レイテンシーでユーザーにレスポンスを返すことができます。

Thumbnail 570

「これは一般的なCachingシステムと何が違うの?」と思われるかもしれません。そこで、Semantic Cachingの真の力を示しましょう。同じクエリではなく、似たような意味を持つ別のクエリを送信してみましょう。「tell me some adventure books to read」の代わりに「what adventure books do you recommend?」というクエリです。これは同じクエリではありませんが、同様にEmbeddingを作成し、ベクトルを取得して、Durable Semantic Cacheで検索します。今回も非常に似ている - 十分に近い - ため、Cache Hitとなります。ベクトル検索を行うと、十分に似ているためCache Hitとなり、ユーザーにレスポンスを返し、再びFoundation Modelへの高コストな呼び出しを避けることができます。

Thumbnail 580

Thumbnail 600

数字を見てみましょう。これはAmazon Bedrockを使用するアプリケーションの例で、コストと関連性のバランスを取った設定で1日10万件の質問を処理しています。MemoryDBとDurable Semantic Cachingを使用した場合の月額コストは28,000ドルです。ここで分かるのは、大幅なコスト削減が可能だということです。

Semantic Cachingを見てみましょう。実際、コスト削減はCache比率と直接相関しています。25%のCache比率であれば約25%のコスト削減が得られ、75%のCache比率であれば約75%のコスト削減が得られます。これは、コストの大部分がFoundation Modelから来ており、Durable Semantic Cachingを追加するオーバーヘッドが非常に低いことを示しています。

Thumbnail 640

Thumbnail 660

Thumbnail 680

Thumbnail 690

実際のケーススタディを見てみましょう。Iterate.aiは、顧客がGenerative AIアプリケーションを構築するのを支援するAI企業です。彼らは顧客の1社がAmazon Bedrockを使用して月間57,000件の質問を処理するChatbotアプリケーションを構築するのを支援しました。LLMのコストが懸念事項となっていることに気付き、クエリの80%が意味的に重複していることを発見しました。そこでMemoryDB Durable Semantic Cachingを使用することで、コストを70%削減することができました。さらに、レイテンシーを秒単位からミリ秒単位に低減し、顧客体験を大幅に改善することができました。

Amazon MemoryDBの特徴とVector Similarity Search機能

Thumbnail 700

Thumbnail 710

Durable Semantic Cachingについて説明しましたが、この目的にはどのデータベースを使用すべきでしょうか? まずはSemanticの観点から見ていきましょう。先ほどSemantic機能について少し触れましたが、データベースにはSemantic SearchやVector Similarity Searchをサポートしている必要があります。Vector Similarity Searchの高度な機能や、様々な距離メトリクスもサポートしている必要があります。これらについては後ほど詳しく説明します。ハイレベルな要件としては、SemanticとVector Similarity Searchをサポートしているデータベースが必要だということです。

Thumbnail 740

二つ目の観点はパフォーマンスです。 読み取りと書き込みの両方で高速なパフォーマンスを持つデータベースが必要です。Cache Missが発生した際にデータベースを更新する必要があるため、書き込みの速さも重要です。主要な目的の一つがコスト削減であるため、クエリあたりのコストが低いこと、あるいはノードあたりの処理能力が高いことが求められます。そして、これらは後ほど定義する関連性を犠牲にすることなく実現する必要があります。

Thumbnail 780

最後の観点は、少し直感的ではありませんが、耐久性です。 検索を行う際、データベース内のすべてのベクトルを線形探索で比較することも可能です。いわゆるテーブルスキャンのようなものですが、これでは望むパフォーマンスは得られません。そのため、高性能なVector Similarity Searchを実現するには何らかのインデックスが必要になります。このインデックスの再構築にはコストがかかります。キャッシュが完全に失われた場合、インデックスの再構築も必要になるため、キャッシュの再構築はより大きな影響を及ぼします。そのため、他のデータベースのユースケースと同様に、セキュリティ、高可用性、AWSによる完全マネージド運用の優位性など、当社が提供する他のデータベース機能と同様の耐久性を推奨しています。

Thumbnail 860

AWSは、最新のアプリケーションの要件に応えるため、様々な目的特化型データベースを提供しています。異なるアクセスパターン、データモデル、パフォーマンス、スケールを必要とするクラウドネイティブアプリケーションの急増に対応して、アプリケーションのニーズに合わせて選択できる充実した目的特化型データベースのポートフォリオを用意しています。MemoryDBは、 先ほど説明したパフォーマンス、検索機能、耐久性の要件を満たしており、これから詳しく見ていきます。

Thumbnail 870

Amazon MemoryDBは、現在AWSが提供する中で最も高速な耐久性のあるデータベースで、マイクロ秒単位の読み取りレイテンシーと、1桁ミリ秒台の書き込みレイテンシーを実現しています。Vector Searchのパフォーマンスについて説明する際に、このパフォーマンスの側面についてさらに詳しく説明します。MemoryDBはValkeyおよびRedis Open Source互換です。MemoryDBの説明に進む前に、Valkeyをご存知の方は手を挙げてください。次に、Redisをご存知の方は手を挙げてください。

もっと多くの手が挙がりましたね。このような反応を予想していましたので、MemoryDBの話を進める前に、少し寄り道をして、Valkeyについて説明させていただきます。これから先の話の文脈を理解していただくためです。

Thumbnail 930

今年3月、Redisは将来のバージョンをオープンソースライセンスから変更すると発表しました。これを受けて、開発者コミュニティはすぐにプロジェクトをフォークし、Valkeyを立ち上げました。Valkeyは、ライセンス変更前にRedisを開発していた方々の一部や、以前のRedisのメンテナーの何人かがメンテナーとなり、さらに多くのコミュニティの開発者が参加して開発されています。大規模なクラウドプロバイダーを含む40以上の組織がサポートしており、Linux Foundationが運営することで、ベンダーニュートラルであり続け、常にオープンソースであることを保証しています。Valkeyの最初のバージョンは、Redisの最後のオープンソースバージョンである7.2と完全な互換性があります。

Thumbnail 1000

これは、私たちのマネージドサービスであるElastiCacheとMemoryDBでリリースした最初のバージョンでもあります。両サービスでValkeyを大幅に低価格でリリースし、わずか数クリックでオンラインアップグレードが可能なドロップイン置き換えを提供しています。特にMemoryDBに関して、MemoryDB for RedisからMemoryDB for Valkeyに移行する場合、インスタンスで30%、書き込みデータで80%の価格削減を実現しました。これは、Durable Semantic Cachingを実装する理由の一つであるコスト削減において、さらなるメリットをもたらします。

Thumbnail 1030

それでは、MemoryDBに話を戻しましょう。MemoryDBはValkeyおよびRedisのオープンソースと互換性があります。リスト、セット、ハッシュ、ソート済みセットなどの豊富な機能とデータ構造を利用でき、50以上のプログラミング言語のクライアントライブラリを持つ人気のValkeyエコシステムの恩恵を受けることができます。MemoryDBは、Valkeyの豊富な機能に耐久性を加えた設計になっています。データ損失ゼロを目指して設計されており、MemoryDBに組み込んだ主要なイノベーションの一つがマルチAZトランザクションログです。すべての書き込みは、少なくとも2つの異なるアベイラビリティーゾーンにある3つ以上のコピーに書き込まれた後に確認され、S3やAmazon.comがデータ保存に使用しているのと同じ基盤技術を活用しています。他のAWSデータベースと同様に、99.99%の高可用性と、セキュリティ、スケーラビリティ、パフォーマンスにわたる重要な特性を備えた完全マネージド型サービスです。

Thumbnail 1120

Thumbnail 1130

Thumbnail 1150

では、MemoryDBがどのように耐久性と高可用性を実現しているのか、内部の仕組みを見てみましょう。こちらは1つのシャードを持つMemoryDBクラスターで、1つのプライマリノードと1つ以上のレプリカがあります。先ほどお話したマルチAZトランザクションログも備えています。 クライアントがプライマリノードに書き込みリクエストを送信します。 プライマリノードはそのリクエストをトランザクションログに書き込み、データはトランザクションログ全体にレプリケーションされます。少なくとも2つの異なるアベイラビリティーゾーンに3つのコピーが作成されると、プライマリノードに確認応答が送られ、プライマリノードがクライアントに確認応答を送信します。

Thumbnail 1160

Thumbnail 1170

Thumbnail 1180

Thumbnail 1190

Thumbnail 1200

この時点で、クライアントはデータがトランザクションログ内で永続化されていることを認識します。レプリカへの非同期レプリケーションが行われていることが分かりますが、これは高可用性のために重要です。 では、障害が発生した場合どうなるのか見てみましょう。 まず、クライアントがプライマリノードに書き込みリクエストを送信し、 マルチAZトランザクションログに送信され、確認応答を受け取り、その後クライアントも確認応答を受け取ります。ここで、プライマリノードが故障したとします。 この時点で、即座にフェイルオーバーは行いません。可用性よりもデータの永続性を重視し、すべてのデータがレプリカに再生されることを確実にします。レプリカをプライマリに昇格させる前に、そのレプリカがすべてのデータを持っていることを確認します。レプリカをプライマリに昇格させるこのプロセスは比較的高速で、通常1秒未満で完了します。

Thumbnail 1230

これが、高可用性と永続性を提供する方法です。レプリカをプライマリに昇格させると、クライアントは新しいプライマリノードにリダイレクトされ、 非同期でデータの送信を継続します。追加の障害に備えて高可用性を維持するため、データは引き続きレプリカに複製されます。

Vector Searchの基本概念とHNSWアルゴリズム

Thumbnail 1250

Amazon MemoryDBは、様々な業界で多様なワークロードに活用されています。一般的なユースケースには、マイクロサービスのデータストア、セッションストア、リーダーボードなどがあります。お客様は、MemoryDBのデータ構造、低レイテンシー、スケーラビリティの恩恵を受けています。今回、Vector Similarity Searchの導入により、本日お話しする永続的なSemantic Cachingなど、新しいユースケースが可能になりました。ここからは、これらのユースケースとDurable Semantic Cachingについて、Sanjitにバトンを渡したいと思います。

Thumbnail 1300

Thumbnail 1320

Thumbnail 1340

Thumbnail 1350

本日のメインテーマであり、プレゼンテーションの焦点となっているのがDurable Semantic Cachingです。これは、LLMの推論結果を保存し、意味的に類似した質問に対してLLMではなくVector Storeから応答を提供することで、パフォーマンスを向上させコストを削減することができます。 さらに、高速なSemantic Searchにより、例えば靴のような商品を検索し、カタログ内の意味的に類似した全商品を一桁ミリ秒のレイテンシーで返すことができるカタログ検索が可能になります。 多くの方がご存じのRetrieval Augmented Generation(RAG)は、 お客様独自のデータをLLMのコンテキストとして活用し、ユーザーにより正確な回答を提供します。また、異常検知は金融サービス業のお客様が損失を減らすため、一桁ミリ秒のレイテンシーで不正を検出するのに役立ちます。

Thumbnail 1370

Thumbnail 1380

Thumbnail 1390

Thumbnail 1400

Durable Semantic Cachingの詳細に入る前に、 いくつかの重要な用語について確認しておく必要があります。Vector Searchにおける完全一致は、基本的に 入力ベクトルからベクトルデータセット内のすべてのベクトルまでの距離を検索することです。ここで赤い円で示された入力ベクトルを例に見てみましょう。 完全一致では、基本的にすべてのベクトルとの距離計算を行い、この場合、紫色でハイライトされた最も近い上位3つのベクトルを返します。これは 非常に計算負荷が高く、時間のかかるプロセスです。

Thumbnail 1420

Thumbnail 1430

Thumbnail 1440

Thumbnail 1450

Thumbnail 1470

理解しておくべきもう1つの重要な概念は、Approximate Nearest Neighbor検索(ANN)です。ANNは、Vector データセット内のすべてのVectorを検索することなく、類似したVectorを検索する方法です。実際には上位3つに近いVectorを見つけるために、ほんの一部のVectorだけを検索するため、完全一致検索よりもはるかに高速です。クラスターベースのアプローチを例に見てみましょう。A、B、Cという3つの異なる領域があり、これらの3つの異なるクラスターの中心までの距離を計算します。クラスターAが最も近いと特定されたら、そのクラスター内のすべてのVectorに対して直接距離計算を行い、ここでハイライトされている上位3つの最近接Vectorを特定します。ただし、薄いピンク色の円は、実際には赤で表されているこのVectorよりも遠いことに注目してください。名前が示すように、Approximate Nearest Neighbor検索では、ほとんどのVectorは見つかりますが、このようなケースを見逃す可能性があります。

Thumbnail 1490

Thumbnail 1500

Thumbnail 1510

ANN検索に関連して考慮し理解すべきもう1つの用語は、Recallです。これは検索結果の品質を測る指標です。右の例を見てみましょう。緑の丸はすべて、ANN検索で返されることが期待されるVectorを表しています。しかし、10個中8個しか得られなかった場合、これは本質的にRecallが80%であることを意味します。これがANN検索の結果の品質を測る方法です。

Thumbnail 1520

Thumbnail 1530

Thumbnail 1550

Thumbnail 1560

このANN検索を実現するための基本的なANNインデックスアルゴリズムをいくつか見ていきましょう。Hash-basedアプローチとTree-basedアプローチがその代表例です。これらは低次元のVectorでは良好な性能を発揮します。しかし、高次元のVectorでは苦戦し、計算負荷が高く、かなりのメモリを消費します。次に、先ほど説明したCluster-basedインデックスアルゴリズムがあります。これらはインデックスの構築が非常に速い簡単なアプローチですが、非常に高いRecallレベルでは苦戦します。最後に、Graph-basedインデックスアルゴリズムがあります。これらは非常に相互接続性が高く、高次元かつ高いRecallレベルで非常に優れた性能を発揮します。

Thumbnail 1570

このGraph-basedインデックスアルゴリズムの1つがHNSW(Hierarchical Navigable Small World)です。HNSWは性能とRecallのバランスを最適化し、MemoryDBで高いスループットと低レイテンシーの高いQPSを実現します。HNSWを考える際には、インデックスパラメータとして3つの変数を考慮する必要があります。1つ目はMで、インデックス内のすべてのVectorが作る双方向接続を表します。Mを非常に高く設定すると、非常に高いRecallレベルが得られますが、インデックスが消費するメモリに影響します。2つ目はefConstructionで、高品質なグラフを作成するためにどれだけの時間を費やすかを表します。そして3つ目は、実際に検索を行う際のefRuntimeです。efRuntimeが高いと、Vector検索やクエリの実行に大幅に時間がかかります。efConstructionが高いとインデックス作成時間が長くなるのと同様です。収穫逓減の法則により、これらの値を全て大幅に増やすことはできないため、これら3つの変数はVector検索を実行する際に慎重に検討する必要があります。アプリケーションのユースケースをよく理解して、これらの設定を決定する必要があります。

MemoryDBを用いたSemantic Cachingの実装と性能

Thumbnail 1670

MemoryDBがどのようにしてこれを実現するのか考えてみましょう。FT.CREATEコマンドでは、ベクトルをJSONフォーマットで保存するか、Hashフォーマットで保存するかを指定できます。インデックスアルゴリズムとしてHNSWを選択するか、あるいは完全一致を指定することもできます。また、テキストから生成するベクトルの埋め込みモデルに合わせて次元数を指定し、距離メトリクスとしてCosine類似度、ユークリッド距離、内積のいずれかを選択できます。

Thumbnail 1710

Thumbnail 1730

Thumbnail 1740

実際にKNN検索をFT.SEARCHで実行する方法を見ていきましょう。MemoryDB APIのこのFT.SEARCHコマンドでは、KNN 10は入力ベクトルに最も近い上位10個のベクトルを返すことを意味します。 先ほど説明したように、Semanticキャッシュを考える際、これはFT.SEARCHコマンドによる従来のKNN検索を少しアレンジしたVector 検索です。Semanticキャッシュでは、Vector Rangeと呼ばれる機能を提供しています。これにより、入力ベクトルに対して意味的に十分に類似したベクトルを返すための類似度しきい値を設定できます。0個か10個のどちらかが返されますが、これは設定したRadiusに大きく依存します。Radiusは0から1の間で設定でき、デフォルトは0.2です。この値を小さくすると、意味的な類似性の観点から、入力ベクトルと返されるベクトルの近さに対する要件がより厳しくなります。

Thumbnail 1790

FT.SEARCHコマンドの具体例を見ていきましょう。先ほど説明したように、Vector Range機能はRadiusを指定することで動作します。 さらに、Vector Range検索から返されるベクトルの種類をカスタマイズできる追加機能もあります。MemoryDBでは、数値やタグベースのフィルターを有効にしています。この例では、国に関するメタデータタグを使用しているのがわかります。

Thumbnail 1830

これらのメタデータタグは、Vector Database内の各ベクトルに関連付けられています。つまり、このクエリではベクトルデータセットをフィルタリングしてから検索を実行しているということです。実際の例を見て、どのように機能するか考えてみましょう。 アメリカ、カナダ、メキシコのユーザーがそれぞれ色分けされており、彼らが尋ねた質問の種類を示しています。これらはすべて、回答に関連付けられてSemanticキャッシュに保存されているデータです。

Thumbnail 1850

メキシコのユーザーが「今年のベストロマンス小説は何ですか?」という質問をしたとします。Radiusを大きくして意味的な類似性を高めていくと、 アメリカのユーザーが尋ねた「今年のトップロマンス小説を教えて」という質問にたどり着きます。これは意味的には似ていますが、国が異なるため、このメキシコのユーザーには関連性の低い回答かもしれません。先ほど説明した国のタグを使ってメタデータフィルターを適用すれば、アメリカのユーザーのデータを除外するようにベクトルデータセットを事前にフィルタリングできます。Radiusのしきい値を上げていくと、最終的にメキシコの別のユーザーが尋ねた「今年のロマンスに関するトップ評価の小説は何ですか?」という意味的に類似した質問にたどり着くことができます。

Thumbnail 1920

Thumbnail 1940

これらのVectorはかなりのメモリを消費します。Vectorが生成されると、Key-ValueとVector Indexの両方に格納されることになります。ご覧のように、各Vectorがメモリ上で重複して保存されているわけです。しかし、MemoryDBがメモリ重複排除をどのように処理しているか考えてみましょう。アメリカとメキシコのユーザーからの質問というこの同じユースケースで、Vectorは生成されますが、MemoryDBが行っているのは、実際にはKey-Value内の実際のVectorへの参照ポインタをVector Index内に保存することで、メモリを約50%節約しているのです。

Thumbnail 1950

Thumbnail 1980

これをさらに実証するために、いくつかのベンチマークとテストを実施しました。Y軸はメモリ消費量を示しています。この2つのグループは、1536次元のVector 500万個と768次元のVector 1000万個についてのものです。重複排除なしの場合、どちらも約70ギガバイトのメモリを占有していることがわかります。しかし、この重複排除技術により、メモリ消費量は両方のケースで52〜56%削減されていることがわかります。Vector処理のためのインスタンスタイプを過剰にも過少にもプロビジョニングしないよう支援するため、MemoryDBコンソール内にVector Calculatorをリリースしました。これを使用すると、Vectorの数、次元数、M値、およびインスタンスに保存する可能性のあるメタデータを指定できます。

Thumbnail 2000

Thumbnail 2020

実践的な例として、ここでJupyter Notebookを使って順を追って説明していきます。これは、Semantic Cache MissとSemantic Cache Hitを通じて、実際にどれだけのパフォーマンス改善が見られるかを示すものです。まず始めに、MemoryDBがVector Indexをどのように設定しているかを示します。先ほど説明したように、これによってHNSWなどの使用したいIndexアルゴリズム、データの保存方法、ここでは1536次元の次元数、そして使用したい距離メトリックを指定することができます。

Thumbnail 2040

Thumbnail 2060

UIに移動して質問してみましょう。これは今作成したばかりのキャッシュなので、まだ何も入っていません。新しい質問をしてみましょう:「Tom Clancyの本をすべて教えて」。これは実際にLLMのClaude 3 Sonnetにアクセスしています。かなり時間がかかっていることがわかります。キャッシュミスが発生したため、LLMにリダイレクトされてこの質問に答えているのです。回答が表示されました。上にスクロールすると、この処理に約7秒かかったことがわかります。

Thumbnail 2080

Thumbnail 2100

コードに戻ってみましょう。ここでは、まずキャッシュから検索を行います。先ほど説明したように、Vector Range Queryを実行します。ここではRadiusを0.2に設定していますが、もちろんニーズに応じて設定を変更することができます。実行時間を出力する行も用意してあり、後ほどご紹介します。

Thumbnail 2110

Thumbnail 2130

Thumbnail 2140

そして、キャッシュミスの場合、LLMでユーザーに応答した後にこれをキャッシュに追加する必要があります。 ここでは、add_to_cache関数を使用しており、基本的に質問、回答、そして使用された実際のEmbeddingモデルを入力するだけです。そして最後に、キャッシュミスが発生した際に質問に回答するために選んだモデルは、Claude 3 Sonnetモデルでした。では実際にコードに戻って、UIで意味的に似た質問をして、パフォーマンスを確認してみましょう。例えば、シンプルに「Tom Hanksの本は全部何ですか?」というような質問をしてみましょう。この質問をして、どのくらいの速さで返ってくるか見てみましょう。約111-112ミリ秒で回答が返ってきましたね。ただし、先ほど述べたように、この時間の大部分は実際にはEmbeddingモデルから来ています。

Thumbnail 2160

Thumbnail 2170

Thumbnail 2180

Thumbnail 2190

では、一番下に戻って、MemoryDBがどれくらい速く応答したか見てみましょう。ここで分かるように、MemoryDBは約1.4ミリ秒でその応答を返しました。これは、以前にMemoryDBに保存された質問と意味的に似た質問に対する応答です。ここで重要なポイントは、MemoryDBが最高レベルのリコールで最適なパフォーマンスを提供するということです。私たちAWSでは、MemoryDBのパフォーマンスを評価するために、かなり詳細なベンチマークを実施しました。このグラフでは、Y軸がミリ秒単位のレイテンシー(P99レイテンシー)を示しています。そして、Cohereの1,000万データセットとOpenAIの500万データという2つのクラスターが見られます。これらは両方とも、ベンチマークによく使用されるベクターデータセットです。両方のケースで、MemoryDBは他のベクターデータベースよりもかなり優れたパフォーマンスを示しています。

Semantic Cachingの運用とベストプラクティス

Thumbnail 2210

Thumbnail 2220

Thumbnail 2230

Thumbnail 2240

Thumbnail 2250

Thumbnail 2260

そしてQPSに関しては、Y軸が明らかにQPSを示しており、同じ2つのベクターデータセットについて見ています。この場合も、MemoryDBは各ベクターワークロードに対して約10,000 QPSを提供するという、非常に優れたパフォーマンスを示しています。ただし、ここで考慮すべきベストプラクティスがあります。データの鮮度管理については、他のキャッシュの運用と非常によく似ています。他のキャッシュのユースケースと同様に、データの鮮度とキャッシュヒットの間には本質的なトレードオフが存在します。キーに対してTime to Live(TTL)を使用することを検討できます。ここで重要な考慮事項は、TTLが低いと、キャッシュヒット率は低くなりますが、鮮度は保たれます。逆にTTLが高いと、キャッシュヒット率は高くなりますが、データの鮮度は低下します。そのため、実際にどのようにバランスを取るか、そしてビジネスユースケースは何かを十分に検討する必要があります。ユースケースによっては、非常に高い鮮度が必要な場合もあれば、ある程度の古さを許容できる場合もあります。これは本当に、お客様とアプリケーションのユースケースに大きく依存します。

Thumbnail 2280

Thumbnail 2300

Thumbnail 2310

Thumbnail 2330

ベクター範囲とセマンティックキャッシングに特有の事項として、先ほど述べたように、類似度のしきい値とパーソナライゼーションの最適化に関する事項があります。具体的には、半径や類似度のしきい値を最適化し、フィルターを活用することです。つまり、MemoryDBが提供するタグベースや数値ベースのフィルターを使用します。先ほどのスライドと同様に、半径が小さいほど、入力クエリと保存されているベクターデータベースの意味的な類似性の制約が厳しくなります。また、フィルターが多いほど、実際に検索するベクターの量が制限され、これによりキャッシュヒット率は低下しますが、ユーザーにとってより関連性の高い結果が得られます。逆に、半径が大きく、フィルターが少ない場合は、キャッシュヒット率は高くなりますが、ユーザーにとっての関連性は低下します。そのため、顧客にどのように応答したいかに基づいて、類似度のしきい値をどのように調整するかを十分に検討する必要があります。

Thumbnail 2360

Thumbnail 2380

MemoryDBでは、メモリと容量の消費も監視することができます。FT.INFOコマンドを使用することで、ベクター空間の使用量、インデックス化されたドキュメント数、ベクターの数を確認できます。これにより、アプリケーションに必要なTTLの設定や、フィルター、半径のしきい値を適切に調整することができます。最後に、まとめとして、耐久性のあるセマンティックキャッシングの素晴らしい利点は、コスト削減です。LLMへの高価な呼び出しを減らすことで、かなりの節約につながります。そして、他のキャッシングのユースケースと同様にスケーラビリティも向上します。コストを比例的に増やすことなく、より多くのユーザーを処理できます。そして最後に、速度の向上です。先ほど強調したように、1桁ミリ秒のレイテンシーでユーザーに応答することができます。

Thumbnail 2410

Thumbnail 2440

最後に、2つの便利なQRリンクをご紹介します。1つ目は、MemoryDBのGitHubで、Semantic Cachingのユースケースや、Vector Searchを始めるための基本的なコードサンプルが豊富に用意されています。そして2つ目は、Semantic Cachingに関するブログで、Terraformスクリプトを使って独自の環境を立ち上げて実際に始められるようになっています。以上で本日のセッションを終了させていただきます。ご参加いただき、ありがとうございました。アンケートへのご協力をお願いいたします。皆様からのフィードバックを心よりお待ちしております。


※ こちらの記事は Amazon Bedrock を利用することで全て自動で作成しています。
※ 生成AI記事によるインターネット汚染の懸念を踏まえ、本記事ではセッション動画を情報量をほぼ変化させずに文字と画像に変換することで、できるだけオリジナルコンテンツそのものの価値を維持しつつ、多言語でのAccessibilityやGooglabilityを高められればと考えています。

Discussion