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

フルテキスト検索

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

関連性スコアリングに BM25 アルゴリズムを使用するこの機能は、retrieval-augmented generation(RAG)のシナリオで特に有用であり、特定の検索語句に最も近く一致するドキュメントを優先します。

📘注意

フルテキスト検索をセマンティックベースの密ベクトル検索と統合することで、検索結果の精度と関連性を向上させることができます。詳細については、Hybrid Search を参照してください。

Zilliz Cloud では、プログラムまたは Web コンソールを使ってフルテキスト検索を有効化できます。このページでは、プログラムでフルテキスト検索を有効化する方法に焦点を当てています。Web コンソールでの操作の詳細については、Manage Collections (Console) を参照してください。

BM25 実装

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

Zilliz Cloud のフルテキスト検索は、以下のワークフローに従います。

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

  2. テキスト解析: Zilliz Cloud は analyzer を使用して、テキストをインデックス化および検索可能な意味のある用語に処理します。

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

  4. コレクションストア: Zilliz Cloud は、生成されたスパース埋め込みをコレクションに保存し、高速な取得とランク付けを可能にします。

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

DfPMwP6ZahhHlLbIN0gcG9d7nQM

フルテキスト検索を使用するには、次の主な手順に従います。

  1. Create a collection: 必要なフィールドを設定し、生テキストをスパース埋め込みに変換する BM25 関数を定義します。

  2. Insert data: 生のテキストドキュメントをコレクションに取り込みます。

  3. Perform searches: 自然言語のクエリテキストを使用して、BM25 の関連性に基づくランク付き結果を取得します。

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

スキーマフィールドを定義する

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

  • Primary field: コレクション内の各エンティティを一意に識別します。

  • String field (VARCHAR または TEXT): 生のテキストドキュメントを格納します。Zilliz Cloud が BM25 関連性ランク付けのためにテキストを処理できるよう、enable_analyzer=True を設定する必要があります。デフォルトでは、Zilliz Cloud はテキスト解析に standard analyzer を使用します。別の analyzer を設定するには、Analyzer Overview を参照してください。このページの例では VARCHAR を使用しています。長いテキストの場合は、入力フィールドを TEXT として定義し、max_length を省略できます。完全な例については、Text Field を参照してください。

  • Sparse vector field (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: primary key として機能し、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)
Parameter説明
name関数の名前です。この関数は、text フィールドの生テキストを BM25 対応のスパースベクトルに変換し、それを sparse フィールドに保存します。
input_field_namesテキストからスパースベクトルへの変換が必要な VARCHAR フィールドの名前です。FunctionType.BM25 では、このパラメータは 1 つのフィールド名のみ受け付けます。
output_field_names内部生成されたスパースベクトルが保存されるフィールドの名前です。FunctionType.BM25 では、このパラメータは 1 つのフィールド名のみ受け付けます。
function_type使用する関数のタイプです。FunctionType.BM25 である必要があります。
📘注意

複数の 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"
)

Parameter

説明

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 の場合は完全な長さ正規化を意味します。

collection を作成する

次に、定義した schema と index パラメータを使用して collection を作成します。

python
client.create_collection(
collection_name='my_collection',
schema=schema,
index_params=index_params
)

テキストデータを挿入する

collection と index の設定が完了したら、テキストデータを挿入できます。このプロセスでは、生のテキストを指定するだけで済みます。先ほど定義した組み込み関数が、各テキストエントリに対応する sparse vector を自動的に生成します。

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.'},
])

collection にデータを挿入したら、生のテキストクエリを使ってフルテキスト検索を実行できます。Zilliz Cloud はクエリを自動的に sparse vector に変換し、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)
Parameter説明
search_params検索パラメータを含むディクショナリです。
params.level簡略化された検索最適化における検索精度を制御します。詳細については、再現率を調整する を参照してください。
data自然言語による生のクエリテキストです。Zilliz Cloud は BM25 関数を使用してテキストクエリを自動的に sparse vector に変換します。事前計算済み vector は指定しないでください。
anns_field内部生成された sparse vector を含むフィールド名です。
output_fields検索結果で返すフィールド名のリストです。BM25 によって生成された embedding を含む sparse vector フィールドを除く すべてのフィールドをサポートします。一般的な出力フィールドには、主キー フィールド(例: id)や元のテキストフィールド(例: text)があります。詳細については、FAQ を参照してください。
limit返される上位一致結果の最大件数です。

FAQ

いいえ。BM25 関数によって生成された sparse vector は、フルテキスト検索では直接アクセスしたり出力したりできません。詳細は以下のとおりです。

  • BM25 関数は、ランキングと取得のために内部的に sparse vector を生成します

  • これらの vector は sparse field に保存されますが、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
)

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

sparse vector フィールドは、ユーザーが直接操作しないデータベース index と同様に、内部的な検索 index として機能します。

設計上の理由:

  • 関心の分離: ユーザーはテキスト(入力/出力)を扱い、Milvus は vector(内部処理)を扱います

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

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

vector へのアクセスが必要な場合:

  • フルテキスト検索の代わりに、手動の sparse vector 操作を使用してください

  • カスタム sparse vector ワークフロー用に別の collection を作成してください

詳細については、Sparse Vector を参照してください。

Ctrl I