メインコンテンツまでスキップ

全文検索

全文検索は、テキストデータセット内の特定の用語やフレーズを含むドキュメントを取得し、関連性に基づいて結果をランキングする機能です。この機能は、正確な用語を見落とす可能性があるセマンティック検索の限界を克服し、最も正確で文脈に即した結果を得られるようにします。さらに、生のテキスト入力を受け付けてテキストデータを自動的にスパース埋め込みに変換するため、ベクトル埋め込みを手動で生成することなくベクトル検索を簡素化します。

関連性スコアリングに BM25 アルゴリズムを使用するこの機能は、特定の検索語句に厳密に一致するドキュメントを優先するため、検索拡張生成(RAG)のシナリオで特に役立ちます。

Notes

全文検索をセマンティックベースの高密度ベクトル検索と統合すると、検索結果の精度と関連性を高めることができます。詳細については、ハイブリッド検索 を参照してください。

Zilliz Cloud では、プログラムからでも Web コンソールからでも全文検索を有効にできます。このページでは、プログラムで全文検索を有効にする方法について説明します。Web コンソールでの操作の詳細については、コレクションの管理(コンソール) を参照してください。

BM25 の実装​

Zilliz Cloud は、情報検索システムで広く採用されているスコアリング関数である BM25 関連性アルゴリズムを基盤とした全文検索を提供しており、Zilliz Cloud はこれを検索ワークフローに統合することで、関連性に基づいてランク付けされた正確なテキスト結果を返します。

Zilliz Cloud の全文検索は、以下のワークフローに従います。

  1. 生のテキスト入力: プレーンテキストを使用してテキストドキュメントを挿入するか、クエリを指定します。埋め込みモデルは不要です。

  2. テキスト分析: Zilliz Cloud は アナライザー を使用してテキストを処理し、インデックスを作成して検索できる意味のある用語に変換します。

  3. BM25 関数による処理: 組み込み関数がこれらの用語を、BM25 スコアリングに最適化されたスパースベクトル表現に変換します。

  4. コレクションへの格納: Zilliz Cloud は、高速な取得とランキングのために、生成されたスパース埋め込みをコレクションに格納します。

  5. BM25 関連性スコアリング: 検索時に、Zilliz Cloud は BM25 スコアリング関数を適用してドキュメントの関連性を計算し、クエリの用語に最も適合する結果をランク付けして返します。

DfPMwP6ZahhHlLbIN0gcG9d7nQM

全文検索を使用するには、以下の主要な手順を実行します。

  1. コレクションの作成: 必要なフィールドを設定し、生のテキストをスパース埋め込みに変換する BM25 関数を定義します。

  2. データの挿入: 生のテキストドキュメントをコレクションに取り込みます。

  3. 検索の実行: 自然言語のクエリテキストを使用して、BM25 の関連性に基づいてランク付けされた結果を取得します。

BM25 を活用した全文検索を有効にするには、必要なフィールドを備えたコレクションを準備し、スパースベクトルを生成する BM25 関数を定義し、インデックスを構成してから、コレクションを作成する必要があります。

スキーマフィールドの定義​

コレクションのスキーマには、少なくとも 3つの必須フィールドを含める必要があります。

  • プライマリフィールド: コレクション内の各エンティティを一意に識別します。

  • 文字列フィールド(VARCHAR または TEXT): 生のテキストドキュメントを格納します。Zilliz Cloud が BM25 関連性ランキングのためにテキストを処理できるよう、enable_analyzer=True を設定する必要があります。デフォルトでは、Zilliz Cloud はテキスト分析に standard アナライザー を使用します。別のアナライザーを構成する場合は、アナライザーの概要 を参照してください。このページの例では VARCHAR を使用しています。長いテキストの場合は、入力フィールドを TEXT として定義し、max_length を省略できます。完全な例については、テキストフィールド を参照してください。

  • スパースベクトルフィールド(SPARSE_FLOAT_VECTOR): BM25 関数によって自動生成されたスパース埋め込みを格納します。

python
from pymilvus import MilvusClient, DataType, Function, FunctionType

client = MilvusClient(
uri="YOUR_CLUSTER_ENDPOINT",
token="YOUR_CLUSTER_TOKEN"
)

schema = client.create_schema()

schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True) # Primary field
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1000, enable_analyzer=True) # Text field
schema.add_field(field_name="sparse", datatype=DataType.SPARSE_FLOAT_VECTOR) # Sparse vector field; no dim required for sparse vectors
plaintext
#include "milvus/MilvusClientV2.h"

auto client = milvus::MilvusClientV2::Create();

milvus::ConnectParam connect_param{"YOUR_CLUSTER_ENDPOINT", "YOUR_CLUSTER_TOKEN"};
auto status = client->Connect(connect_param);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}

milvus::CollectionSchemaPtr schema = std::make_shared<milvus::CollectionSchema>();
schema->AddField({"id", milvus::DataType::INT64, "", true, true});
schema->AddField(milvus::FieldSchema("text", milvus::DataType::VARCHAR).WithMaxLength(1000).EnableAnalyzer(true));
schema->AddField(milvus::FieldSchema("sparse", milvus::DataType::SPARSE_FLOAT_VECTOR));
shell
# Zilliz CLI

上記の構成では、

  • id: プライマリキーとして機能し、auto_id=True によって自動的に生成されます。

  • text: 全文検索操作のために生のテキストデータを格納します。データ型は VARCHAR である必要があります。VARCHAR はテキスト格納用の Zilliz Cloud の文字列データ型です。

  • sparse: 全文検索操作のために内部で生成されたスパース埋め込みを格納するために予約されたベクトルフィールドです。データ型は SPARSE_FLOAT_VECTOR である必要があります。

BM25 関数の定義​

BM25 関数は、トークン化されたテキストを、BM25 スコアリングをサポートするスパースベクトルに変換します。

関数を定義し、スキーマに追加します。

python
bm25_function = Function(
name="text_bm25_emb", # Function name
input_field_names=["text"], # Name of the VARCHAR field containing raw text data
output_field_names=["sparse"], # Name of the SPARSE_FLOAT_VECTOR field reserved to store generated embeddings
function_type=FunctionType.BM25, # Set to `BM25`
)

schema.add_function(bm25_function)
パラメーター説明
name関数の名前。この関数は、text フィールドの生のテキストを、sparse フィールドに格納される BM25 互換のスパースベクトルに変換します。
input_field_namesテキストからスパースベクトルへの変換が必要な VARCHAR フィールドの名前。FunctionType.BM25 の場合、このパラメーターは 1つのフィールド名のみを受け付けます。
output_field_names内部で生成されたスパースベクトルが格納されるフィールドの名前。FunctionType.BM25 の場合、このパラメーターは 1つのフィールド名のみを受け付けます。
function_type使用する関数の種類。FunctionType.BM25 である必要があります。
Notes

複数の VARCHAR フィールドに BM25 処理が必要な場合は、フィールドごとに 1つの BM25 関数を定義し、それぞれに一意の名前と出力フィールドを設定してください。

インデックスの構成​

必要なフィールドと組み込み関数を備えたスキーマを定義したら、コレクションのインデックスを設定します。このプロセスを簡素化するには、index_type として AUTOINDEX を使用します。これは、データの構造に基づいて Zilliz Cloud が最適なインデックスタイプを選択して構成できるようにするオプションです。

python
index_params = client.prepare_index_params()

index_params.add_index(
field_name="sparse",
index_type="AUTOINDEX",
metric_type="BM25"
)
plaintext
auto index_params = milvus::IndexDesc("sparse", "", milvus::IndexType::SPARSE_INVERTED_INDEX, milvus::MetricType::BM25);
index_params.AddExtraParam("inverted_index_algo", "DAAT_MAXSCORE");
index_params.AddExtraParam("bm25_k1", "1.2");
index_params.AddExtraParam("bm25_b", "0.75");
shell
# Zilliz CLI

パラメーター

説明

field_name

インデックスを作成するベクトルフィールドの名前。全文検索の場合は、生成されたスパースベクトルを格納するフィールドを指定します。この例では、値を sparse に設定します。

index_type

作成するインデックスの種類。AUTOINDEX を使用すると、Zilliz Cloud がインデックス設定を自動的に最適化します。インデックス設定をより細かく制御する必要がある場合は、Zilliz Cloud でスパースベクトルに利用できるさまざまなインデックスタイプから選択できます。 .

metric_type

全文検索機能では、このパラメーターの値を BM25 に設定する必要があります。

params

インデックスに固有の追加パラメーターのディクショナリ。

params.inverted_index_algo

インデックスの構築とクエリに使用されるアルゴリズム。有効な値:

  • "DAAT_MAXSCORE"(デフォルト): MaxScore アルゴリズムを使用した最適化された Document-at-a-Time(DAAT)クエリ処理。MaxScore は、影響が最小限になる可能性が高い用語とドキュメントをスキップすることで、大きな k 値や用語数の多いクエリに対して優れたパフォーマンスを提供します。これは、最大影響スコアに基づいて用語を必須グループと非必須グループに分割し、top-k の結果に寄与できる用語に焦点を当てることで実現されます。

  • "DAAT_WAND": WAND アルゴリズムを使用した最適化された DAAT クエリ処理。WAND は、最大影響スコアを活用して競合しないドキュメントをスキップすることで、評価するヒットドキュメントを減らしますが、ヒットごとのオーバーヘッドは大きくなります。そのため WAND は、小さな k 値のクエリや短いクエリなど、スキップがより現実的な場合に効率的です。

  • "TAAT_NAIVE": 基本的な Term-at-a-Time(TAAT)クエリ処理。DAAT_MAXSCORE や DAAT_WAND と比較すると低速ですが、TAAT_NAIVE には独自の利点があります。グローバルなコレクションパラメーター(avgdl)の変更に関係なく静的なままであるキャッシュされた最大影響スコアを使用する DAAT アルゴリズムとは異なり、TAAT_NAIVE はそのような変更に動的に適応します。

params.bm25_k1

用語頻度の飽和を制御します。値が大きいほど、ドキュメントのランキングにおける用語頻度の重要度が高くなります。値の範囲: [1.2, 2.0]。

params.bm25_b

ドキュメント長が正規化される度合いを制御します。通常は 0 から 1 の間の値が使用され、デフォルト値は 0.75 です。値が 0 の場合は長さの正規化を行わないことを意味し、値が 1 の場合は完全な長さの正規化を意味します。

コレクションの作成​

次に、定義したスキーマとインデックスパラメーターを使用してコレクションを作成します。

python
client.create_collection(
collection_name='my_collection',
schema=schema,
index_params=index_params
)
plaintext
auto status = client->CreateCollection(milvus::CreateCollectionRequest()
.WithCollectionName("my_collection")
.WithCollectionSchema(schema)
.AddIndex(std::move(index_params)));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
shell
# Zilliz CLI

テキストデータの挿入​

コレクションとインデックスを設定したら、テキストデータを挿入する準備が整います。このプロセスでは、生のテキストを指定するだけで済みます。先ほど定義した組み込み関数が、各テキストエントリに対応するスパースベクトルを自動的に生成します。

python
client.insert('my_collection', [
{'text': 'information retrieval is a field of study.'},
{'text': 'information retrieval focuses on finding relevant information in large datasets.'},
{'text': 'data mining and information retrieval overlap in research.'},
])

コレクションにデータを挿入したら、生のテキストクエリを使用して全文検索を実行できます。Zilliz Cloud はクエリを自動的にスパースベクトルに変換し、BM25 アルゴリズムを使用して一致した検索結果をランク付けしてから、topK(limit)の結果を返します。

python
search_params = {
'params': {'level': 10},
}

res = client.search(
collection_name='my_collection',
data=['whats the focus of information retrieval?'],
anns_field='sparse',
output_fields=['text'], # Fields to return in search results; sparse field cannot be output
limit=3,
search_params=search_params
)

print(res)
パラメーター説明
search_params検索パラメーターを含むディクショナリ。
params.level簡素化された検索最適化を使用して検索精度を制御します。詳細については、再現率の調整 を参照してください。
data自然言語の生のクエリテキスト。Zilliz Cloud は、BM25 関数を使用してテキストクエリを自動的にスパースベクトルに変換します。事前に計算されたベクトルは指定しないでください。
anns_field内部で生成されたスパースベクトルを含むフィールドの名前。
output_fields検索結果で返すフィールド名のリスト。BM25 で生成された埋め込みを含む スパースベクトルフィールドを除く すべてのフィールドをサポートします。一般的な出力フィールドには、プライマリキーフィールド(例: id)と元のテキストフィールド(例: text)があります。詳細については、FAQ を参照してください。
limit返す上位一致の最大数。

FAQ​

いいえ。BM25 関数によって生成されるスパースベクトルは、全文検索では直接参照したり出力したりすることはできません。詳細は以下の通りです。

  • BM25 関数は、ランキングと取得のためにスパースベクトルを内部的に生成します

  • これらのベクトルはスパースフィールドに格納されますが、output_fields に含めることはできません

  • 出力できるのは、元のテキストフィールドとメタデータ(id、text など)のみです

例:

python
# ❌ This throws an error - you cannot output the sparse field
client.search(
collection_name='my_collection',
data=['query text'],
anns_field='sparse',
output_fields=['text', 'sparse'], # 'sparse' causes an error
limit=3,
search_params=search_params
)

# ✅ This works - output text fields only
client.search(
collection_name='my_collection',
data=['query text'],
anns_field='sparse',
output_fields=['text'],
limit=3,
search_params=search_params
)
plaintext
// Searching with the sparse field in output_fields throws an error.
// Only output the original text and metadata fields.
milvus::SearchRequest request = milvus::SearchRequest()
.WithCollectionName("my_collection")
.AddEmbeddedText("query text")
.WithLimit(3)
.WithAnnsField("sparse")
.AddOutputField("text");
shell
# Zilliz CLI

アクセスできないのに、スパースベクトルフィールドを定義する必要があるのはなぜですか?​

スパースベクトルフィールドは、ユーザーが直接操作しないデータベースのインデックスと同様に、内部的な検索インデックスとして機能します。

設計の根拠:

  • 関心の分離: ユーザーが扱うのはテキスト (input/output), Milvus が扱うのはベクトル(内部処理)です

  • パフォーマンス: 事前に計算されたスパースベクトルによって、クエリ中の高速な BM25 ランキングが可能になります

  • ユーザーエクスペリエンス: 複雑なベクトル操作をシンプルなテキストインターフェイスの背後に抽象化します

ベクトルへのアクセスが必要な場合:

  • 全文検索の代わりに、手動のスパースベクトル操作を使用します

  • カスタムのスパースベクトルワークフロー用に別々のコレクションを作成します

詳細については、スパースベクトル を参照してください。