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

全文検索

全文検索は、テキストデータセットから特定の用語やフレーズを含むドキュメントを取得し、関連性に基づいて結果をランキングする機能です。この機能により、正確な用語を見逃しがちなセマンティック検索の限界を補い、より精度高く文脈に即した結果を得られます。さらに、生のテキスト入力をそのまま受け付けて自動的にスパース埋め込みに変換するため、ベクトル埋め込みを手動で生成することなくベクトル検索を実行できます。

関連性スコアリングに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

上記の設定において、各項目は以下の通りです。

  • 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 フィールドの生テキストを BM25 対応のスパースベクトルに変換し、sparse フィールドに格納します。
input_field_namesテキストからスパースベクトルへの変換対象となる VARCHAR フィールドの名前です。FunctionType.BM25 では、このパラメーターに指定できるフィールド名は 1 つだけです。
output_field_names内部で生成されたスパースベクトルの格納先フィールドの名前です。FunctionType.BM25 では、このパラメーターに指定できるフィールド名は 1 つだけです。
function_type使用する関数のタイプです。FunctionType.BM25 を指定する必要があります。
📘Notes

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

インデックスの設定

必要なフィールドと組み込み関数を含むスキーマを定義したら、コレクションのインデックスを設定します。手順を簡略化するには、AUTOINDEXindex_type として使用します。これにより、Zilliz Cloud がデータ構造に基づいて最適なインデックスタイプを自動的に選択・設定できます。

python
index_params = client.prepare_index_params()

index_params.add_index(
field_name="sparse",
index_type="AUTOINDEX",
metric_type="BM25"
)

パラメーター

説明

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 は、最大影響スコアを利用して競合しないドキュメントをスキップすることで評価対象のヒット数を削減しますが、ヒットごとのオーバーヘッドが高くなります。そのため、スキップの効果が高い小さな k 値や短いクエリに対してより効率的です。

  • "TAAT_NAIVE": 基本的な Term-at-a-Time (TAAT) クエリ処理です。DAAT_MAXSCOREDAAT_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
)

テキストデータの挿入

コレクションとインデックスの準備ができたら、テキストデータを挿入できます。この際、指定が必要なのは生のテキストのみです。前述の組み込み関数により、各テキストに対応するスパースベクトルが自動的に生成されます。

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 に含めることはできません。

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

例:

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
)

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

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

設計上の理由:

  • 関心の分離: ユーザーはテキスト(入力/output), Milvus)を扱い、システムはベクトル(内部処理)を処理します。

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

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

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

  • 全文検索の代わりに、手動でのスパースベクトル操作を利用してください。

  • カスタムスパースベクトルワークフローには、専用のコレクションを作成してください。

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

Ctrl I