|
この記事は、2023 年 9 月 5 日に開催された QCon Global Software Development Conference 2023 北京ステーション - ベクトル データベース サブフォーラムで行われた同名の基調講演「大規模ベクトル データベース シナリオにおける BES の調査と実践」を基に作成されています。 全文は 5989 語から成り、読むのに 15 分かかると推定されます。
ベクターデータベースは、ベクターデータの保存と検索に特化したデータベースシステムです。埋め込み技術を用いることで、画像、音声、テキストなどのデータから特徴を抽出し、ベクトルとして表現することができます。ベクトル間の距離は、元データ間の特徴の類似度を表します。そのため、元データの特徴ベクトルをベクターデータベースに保存しておき、画像検索アプリケーションなどでベクター検索技術を用いて類似の元データを検索することができます。
ベクトル検索技術は、大規模モデルの登場以前から既に十分に発達していました。ディープラーニング技術の発展に伴い、ベクトルデータベースは、画像、音声、動画の検索・推薦、セマンティック検索、テキスト質問応答、顔認識といった分野で広く利用されています。
大規模モデルの出現により、人間とコンピューターの対話方法が変わり、人工知能技術に新たな革命がもたらされ、多数の AI ネイティブ アプリケーションが誕生しました。しかし、まだ開発の初期段階にあり、実用化にはまだ多くの問題が残っています。まず、知識容量が十分ではありません。大規模モデルは一般的な質問に答えることはできますが、垂直的な領域を扱う場合、学習データが限られているため、回答の専門性には依然として改善の余地があります。さらに、大規模モデルは錯覚問題に陥りやすく、回答が事実を歪める可能性があります。さらに、大規模モデルの学習サイクルとコストは非常に高いため、頻繁に学習させることができません。そのため、リアルタイムデータの取得が困難になり、時間的制約がそれほど強くない一般的な質問にしか答えることができません。知識という側面以外にも、大規模モデルは個人データのセキュリティ確保にも苦労しています。例えば、私が大規模なモデルに自分の個人データを提供した場合、モデルが他者にサービスを提供する際に、この個人情報が回答として明らかになる可能性が非常に高くなります。では、プライベート データのセキュリティを保護しながら、大規模モデルの知識機能を強化するにはどうすればよいでしょうか?下の画像の右側に示すように、質問時に気象庁が発令する気象警報を含めることで、大規模モデルが質問に正確に答えられるようになります。外部データやツールを通じて大規模モデルの機能を強化するこの技術システムは、プロンプトワードエンジニアリングと呼ばれます。以上の議論からわかるように、プロンプトワードエンジニアリングは大規模モデル応用において非常に重要です。以下では、プロンプトワードエンジニアリングフレームワークの構築方法を詳しく説明します。大規模なモデル アプリケーションのコア ワークフローを見てみましょう。外部のリアルタイムニュース、専門知識、業界資料などのデータを定期的にベクター形式で埋め込み、ベクターデータベースに保存することで、モデル用の大規模な外部知識ベースを段階的に構築できます。ユーザーが質問すると、まず知識ベースから最も関連性の高いコンテンツを取得し、その後、モデルの回答能力を高めるためのプロンプトを追加できます。 このアプローチにより、大規模モデルを再学習することなく外部のリアルタイムデータと知識を導入できるため、応答性が向上し、実際の結果と乖離するケースが減少します。さらに、ベクターデータベースを用いて外部知識ベースを構築することで、産業データのプライバシーとセキュリティを効果的に保護できます。さらに、ユーザーの会話履歴をベクトル知識ベースに保存することで、後続の対話中に関連性の高い会話履歴を抽出できるため、トークンの数が限られているために大規模な言語モデルに長期記憶が不足するという問題が解決されます。 II. Baidu Smart Cloud BESのエンジニアリングプラクティス Elasticsearchは、Apache Luceneをベースとした分散型検索・分析エンジンです。検索エンジンデータベース分野でトップの座を占め、世界で最も人気のあるオープンソースソリューションです。構造化データと非構造化データを含む様々なデータタイプをサポートし、シンプルで使いやすいインターフェース、包括的なドキュメント、そして業界で数多くの実用的なアプリケーションを備えています。 Baidu AI Cloud Elasticsearch(BES)は、オープンソースのElasticsearchプラットフォーム上に構築された成熟したパブリッククラウド製品であり、堅牢なクラウドリソース保証と運用能力を誇ります。2015年にリリースされたBESは、パブリッククラウドベンダーが提供する最初のマネージドElasticsearchサービスの1つでした。2018年には、Baidu NLP単語セグメンテーションプラグインを導入し、オブジェクトストレージBOSに基づくスナップショットとリカバリをサポートしました。2020年には、オブジェクトストレージBOSに基づくコールド/ホットデータ分離アーキテクチャなどの機能をサポートし、Baidu内で広く使用され、豊富なエンジニアリング経験を蓄積してきたベクトル検索機能を提供しました。2023年には、大規模モデルのニーズを満たすために、特にベクトル検索シナリオ向けにベクトルエンジンやパッケージリソースなど、さまざまな側面を最適化しました。 BESアーキテクチャは、管理・制御プラットフォームとBESクラスタインスタンスの2つの部分で構成されています。管理・制御プラットフォームは、統合的なクラスタ管理、監視、アラート機能に加え、クラスタのスケーリングとホット/コールドデータ分離スケジューリングをグローバルレベルで提供します。BESクラスタインスタンスは、クラウドホストとクラウドディスク上に構築されたElasticsearchクラスタサービスであり、ノードのロードバランシングはレイヤー4プロキシ(BLB)によって処理されます。ディスク上のデータは、ポリシーに基づいて定期的にオブジェクトストレージ(BOS)に移行できるため、ストレージコストを削減できます。 BESのインデックスアーキテクチャは、主にShared Nothing + MPP(マルチプロセッシング)計算アーキテクチャを採用しています。Elasticsearchのデータフローを再利用し、インデックスとシャードに従ってデータを整理します。シャードは複数のレプリカで構成でき、Elasticsearchの標準メソッドを使用して分散およびルーティングされます。これにより、ベクトル検索中に分散データを持つノード上でローカル計算が可能になり、マルチノード並列コンピューティングを通じてクエリ効率が向上します。レプリカ数を増やしてスケールアップすることで、クエリに使用できるノード数とリソース数がさらに増加し、全体的なクエリQPS(1秒あたりのクエリ回数)を向上させることができます。 ベクターデータはElasticsearchの標準的な方法で管理されるため、その使い方はスカラーデータと大きく変わりません。ベクターデータはスカラーデータと並行して書き込むことができ、Elasticsearchのスカラーデータ用の検索・処理機能を再利用できます。ユーザーはElasticsearchのBulkインターフェースを使用して、データを一括で書き込むことができます。データが各シャードに書き込まれた後、ディスク上にフラグメントファイルが作成され、検索機能が提供されます。Elasticsearchは、検索効率を向上させるために、バックグラウンドで定期的にシャードのマージをスケジュールします。クエリ実行中、クエリリクエストは任意のノードに送信され、そのノードはコーディネータノードになります。このノードは、クエリを各シャードに分散して並列計算を行い、結果をマージしてTopKリストを取得して返します。 BESでのベクトルの使用も非常に簡単です。使用例を見てみましょう。まず、インデックスマッピングを定義し、ベクトル関連のパラメータをいくつか指定する必要があります。この手順はテーブルの作成に相当します。次に、ESのBulkインターフェースを介してデータを書き込むことができます。実際には、通常、まず埋め込み機能を使用して生データをベクトル化し、それをバッチで書き込みます。その後、ESスタイルに似た定義済みの構文を使用してベクトルの取得を実行できます。ベクトルインデックスの実装では、自社開発のプラグインを通じてベクトル関連の機能を実装することにしました。コアエンジンはC++で実装されており、ElasticsearchからJNI経由で呼び出されます。独自のプラグインを開発することにした理由は 3 つあります。1 つ目は、C++ で実装することでほぼ最適なパフォーマンスを実現し、SIMD などの最適化を容易にして計算を高速化するためです。2 つ目は、基礎となるストレージ形式の実装を書き換えることで、さらに優れたパフォーマンスを容易に実現できるようにするためです。3 つ目は、取得ロジックをより柔軟に制御し、実行プランを書き換えてより複雑なクエリを実装できるようにするためです。コアとなるベクトル検索エンジンについては、コミュニティの優れたベクトルライブラリ実装をベースに二次開発を行うことにしました。Elasticsearch(8cu仮想マシン、データ書き込みから生成された未結合セグメント、SIFT-1M 128次元データセット)上で、nmslibとfaissの即時パフォーマンスを比較しました。HNSWはリコール率が高いものの、全体的にメモリ消費量が多く、nmslibの実装の方が優れていることがわかります。ベクター検索エンジンの実装を変更することで、HNSWのインデックスタイプのレベル0ベクターデータストレージにカスタムLuceneカラムナストレージを再利用し、mmap経由でロードするようになりました。これにより、データの冗長性とリソースの無駄が削減されます。さらに、mmap経由でデータをロードすることで、メモリ不足時にメモリからスワップアウトし、必要に応じてメモリにロードし直すことができるため、ある程度、メモリとディスクのハイブリッドストレージメディアをサポートします。具体的な最適化について詳しく説明する前に、最も主流のグラフ アルゴリズムの原理を確認しましょう。グラフアルゴリズムは、近似ベクトル検索における比較的新しいアプローチです。ナビゲーブル・スモールワールド理論に基づき、具体的には、全結合グラフでは2点を6ホップで接続できます。ベクトル間の距離関係に基づき、現実世界と同様の「スモールワールド」ネットワークを構築することで、貪欲アルゴリズムを用いて、距離に基づいて接続を確立しながら、ホップバイホップで目標ベクトル点に近づくことができます。前述のように、エッジを構築するために最近傍点を選択するというアプローチに基づいて、小さな世界に点が挿入されるにつれて、新たに挿入された点はより小さな円内に閉じ込められるようになります。この場合、非常に遠い点との接続を確立するには、非常に多くのホップが必要になります。この問題に対処するため、業界ではHNSWアルゴリズムが提案されました。これは、リンクリスト検索アルゴリズムで使用されるスキップリストアプローチを採用しています。異なるレベルでグラフを構築し、頂点数を上に向かって指数関数的に減らして疎なグラフを形成します。当然のことながら、グラフが疎であるほど、遠く離れた点をより適切に接続できます。 HNSWインデックスは高速なクエリ応答と高い再現率を実現しますが、グラフ構築の遅延やCPUおよびメモリのオーバーヘッドの高さといった欠点も抱えています。HNSWグラフ構築プロセスでは、1つのポイントを挿入するだけでも検索と計算が必要となり、多数のポイントを挿入すると膨大な計算コストが発生し、データのインポート速度の低下やフロントエンドのブロックにつながる可能性があります。そのため、ベクターインデックス構築プロセスを非同期のバックグラウンド構築メカニズムへと移行しました。データがディスクに書き込まれると、すぐに結果が返されます。その後、バックグラウンドではElasticsearchのマージ戦略、ユーザータイミングトリガー、またはプロアクティブトリガーを介してHNSWインデックスの構築がトリガーされます。このストリーミング構築手法により、グラフ構築プロセス中のメモリ消費量が削減されます。さらに、フォアグラウンドクエリリクエストへの影響を回避するため、構築には専用のスレッドプールを使用します。同時に、ES のフラグメントマージ戦略も最適化しました。 Elasticsearch のデフォルトのマージ戦略では、1 回のマージに含まれるフラグメントの数や、結果として得られる新しいフラグメントのサイズなどの条件に基づいて、マージするフラグメントのセットが選択されます。その後、さまざまな組み合わせのスコアを計算し、マージに最適なフラグメントの組み合わせを選択します。通常、リソース消費とクエリ効率のバランスをとるために、複数回のマージが行われます。しかし、ベクターインデックスの構築は Elasticsearch のネイティブデータ型よりもコストがかかることが多いため、ベクターインデックスのマージ戦略を調整し、複数回のマージから 1 回のマージに変更することで、フラグメントのマージのオーバーヘッドを削減しました。さらに、データ書き込み前のターゲットインデックスの自動構築をオフにする機能もサポートしています。データをバッチで書き込み、フラグメントをマージした後、APIを介してベクターインデックスを一括構築できるため、バッチデータベースインジェクションのシナリオに適しています。さらに、BESは様々なベクトルインデックスタイプと距離計算アルゴリズムをサポートしています。また、学習を必要とするベクトルインデックスのワークフローサポートも提供しています。例えば、IVFシリーズのインデックスについて、まずはIVFアルゴリズムの原理を確認しましょう。 IVF(転置インデックス)とは、検索エンジンで使用される用語で、ウェブページからキーワードを抽出して転置検索構造を構築し、ユーザーがそれらのキーワードで元の文書を見つけられるようにすることを指します。では、ベクターデータにおけるキーワードとは何でしょうか?現実世界では、ベクターは一般的に空間分布においてクラスタリング特性を示します。下の図をご覧ください。 k-meansアルゴリズムは、ベクトルのクラスター中心を抽出します。これらのクラスター中心は、ベクトルのキーワードとみなされます。これらのクラスター中心を用いて転置インデックスを構築することで、検索エンジンのようなアプローチが可能になります。まず、インデックスがクラスター中心を識別し、次にそれらのクラスター内のベクトルを反復的に検索します。この手法は、グローバル検索と比較して、大量のデータをフィルタリングします。単一のクラスター中心の検出精度が不十分な場合は、複数のクラスター中心を使用できます。クラスター中心が複数検出されるほど、結果の精度は向上します。 IVFのようなベクトルインデックスの場合、BESの構築プロセスは、まずトレーニングデータを書き込み、次にAPIを呼び出してモデルをトレーニングします。このステップでは、トレーニングデータに基づいてクラスタリングを実行し、各クラスターの中心を計算します。モデルのトレーニング後、新しいインデックスが作成され、実際のデータが書き込まれ、トレーニング済みモデルに基づいてベクトルインデックスが構築されます。ベクトルインデックスの構築とマージの具体的なメカニズムは、前述のものと同じです。ベクトルデータにラベルを付けたり、取得したベクトルがラベルと一致することを確認したりなど、ベクトル取得を実行する前にスカラー条件でデータをフィルタリングする必要があるシナリオは数多くあります。この要件を満たすには、ポストフィルタとプレフィルタという2つの方法があります。ポストフィルタでは、まずANN検索を実行し、検索結果に基づいてフィルタリングを行い、最終結果を取得します。ただし、結果セットのサイズがKよりも大幅に小さくなる可能性があります。一方、プレフィルタでは、まずデータをフィルタリングし、フィルタリングされた結果に基づいて最近傍検索を実行します。この方法では、通常、K個の結果が確実に得られます。そこで、元のHNSW実装を修正し、グラフをトラバースして最近傍を選択する際に、フィルタ条件を満たすベクトルのみをアルゴリズムが考慮するようにしました。具体的なプロセスは以下のとおりです。まず、Elasticsearchのスカラーデータインデックスに基づいてフィルタを実行し、呼び出された文書のIDリストを取得します。次に、IDリストに基づいてビットマップを構築し、そのビットマップデータをJNI呼び出しを介してベクトルエンジンに渡します。HNSW検索プロセスでは、ビットマップに基づいて最近傍の頂点をフィルタリングし、フィルタ条件を満たすベクトルのリストを取得します。実際のテストでは、パフォーマンスと再現率は理想的とは言えないことが判明しました。テストデータと調査の結果、フィルタリング率が増加すると、頂点フィルタリングによって接続パス数が減少し、HNSWアルゴリズムの収束速度に直接影響を与え、行き詰まりが発生しやすくなり、結果として再現率が低下することが判明しました。データによると、フィルタリング率が90%を超えると、パフォーマンスと再現率の両方が急激に低下します。そこで、スカラーフィルタリングとブルートフォース探索アルゴリズムを組み合わせて実行プランを書き換えることにしました。フィルタリング率が90%を超えると、フィルタリングされた結果に対してブルートフォース探索を実行し、良好な結果を得ました。同時に、SIMD命令を用いてブルートフォース探索の効率を高めました。 BES の今後の開発計画は、主に以下の点に重点を置いています。何よりもまず、使いやすさが重要です。ベクターデータベースは主に大規模モデルアプリケーションの開発者向けに設計されているため、すぐに使える製品体験を提供し、ユーザーの導入障壁を下げることが目標です。現在、BESが自社開発したベクターエンジンを使用するには、ElasticsearchのDSLを使用してクエリロジックを記述できるなど、Elasticsearchにある程度精通している必要があります。SQLによるk近傍法(KNN)検索のサポートなど、より汎用的でユーザーフレンドリーなアプローチを提供できれば、はるかにユーザーフレンドリーになります。第二に、機能面では、多様なニーズとシナリオに対応するために、DiskAnnやBaiduが独自開発したPuck & Tinkerアルゴリズムなど、より多くのインデックス作成および類似性評価アルゴリズムをサポートする必要があります。また、インデックス構築と検索効率を向上させるために、異種コンピューティング機能のサポートも検討する必要があります。パフォーマンスとコストの観点から、大規模アプリケーションでは、システムのオーバーヘッドを削減し、リソース利用効率を向上させるためのさらなる最適化が必要です。例えば、ElasticsearchはJVM上で動作し、ベクトルエンジンはC++で開発され、JNI呼び出しを介して実行されます。したがって、リソース利用率を最大化しながら、グローバルメモリリソースをより柔軟に管理し、さまざまな顧客のワークロードに適応する方法は、今後の最適化における主要な焦点となります。最後に、BESは現在マネージドクラスタであるため、ユーザーはビジネスボリュームに基づいてクラスタリソースを評価し、適切なパッケージを選択する必要があります。そのため、ユーザーには一定の利用コストが発生します。私たちの最適化の方向性は、リソースをより動的かつ柔軟にすることで、ユーザーの導入障壁を下げ、コストを削減することです。前述のPuck & Tinkerアルゴリズムは、Baiduが100%自社開発し、検索ビジネスで大規模に検証されたベクトル検索アルゴリズムです。第1回BigANN国際ベクトル検索コンペティションにおいて、Puckは参加した4つのデータセット全てで1位を獲得しました。BIGANN-10Mデータセットでは、PuckはHNSWと同等の再現率でありながら、メモリ消費量はわずか約21%で、HNSWの1.7倍の性能を達成しました。Puckはオープンソースです。詳細はhttps://github.com/baidu/puck/tree/main/docsをご覧ください。 まず、動画ウェブサイトにおけるマルチモーダル検索シナリオにおけるベクター機能の応用例を見てみましょう。具体的には、動画をフレームに分割し、各フレームに対して画像特徴処理と時間的モデリングを行います。次に、ニューラルネットワークを用いてフレームシーケンスをベクターに変換し、BES(Browser Estimater System)に書き込んで素材ベクターライブラリを構築します。そして、BESにおいてベクター検索を用いて類似度の高い結果を取得し、上流のビジネスサービスに入力することで、動画のタグ付け、ショートコンテンツからロングコンテンツへのリンク、パーソナライズされたレコメンデーションといったシナリオをサポートします。 Qianfan 大規模モデル プラットフォームの知識ベースは、大規模言語モデルの知識の質問と回答のシナリオ向けに特別に設計された製品であり、顧客がアップロードした知識を管理し、高速なクエリと検索機能を提供することを目的としています。 Baidu AI Cloud BESを基盤とすることで、ユーザーは大量のナレッジベース文書を効率的に保存・検索でき、企業のプライベートドメイン知識の迅速な管理と、ナレッジQ&Aアプリケーションの構築が可能になります。さらに、顧客のデータプライバシーとセキュリティも確保されます。適用方法は2つあります。1つ目は、大規模なモデル知識ベースを独自に展開し、ローカル知識検索アプリケーションを構築する方法です。2つ目は、プラグインアプリケーションをQianfanプラットフォームに直接バインドし、質問応答、生成、タスクの3種類のアプリケーションをサポートする方法です。 |