ベクトル類似検索の実行

このトピックでは、Milvusを使用してエンティティを検索する方法について紹介します。

Milvusでは、ベクトル類似検索は、クエリベクトルとコレクション内のベクトルとの間の距離(指定された類似度尺度を使用して)を計算し、最も類似した結果を返します。また、スカラーまたはプライマリキーのフィールドをフィルタリングするために論理式を指定して、混合検索を実行できます。

次の例は、データセットに含まれる書籍ID(プライマリキー)、単語数(スカラーフィールド)、および書籍の概要(ベクトルフィールド)を含む2000行のデータでベクトル類似検索を実行する方法を示しており、ベクトル化された記述に基づいて特定の書籍を検索するシミュレーションを行います。Milvusは、クエリベクトルと定義した検索パラメータに基づいて、最も類似した結果を返します。

コレクションの読み込み

Milvus内でのすべての検索およびクエリ操作はメモリ内で実行されます。ベクトル類似検索を実行する前に、コレクションをメモリに読み込みます。

from pymilvus import Collection
collection = Collection("book")      # 既存のコレクションを取得します。
collection.load()

検索パラメータの準備

検索シナリオに対応するパラメータを準備します。次の例では、Euclidean距離を使用して距離を計算し、IVF_FLATインデックスによって構築された10個の最も近いクラスタからベクトルを取得するために検索が使用するパラメータを定義しています。

search_params = {
    "metric_type": "L2",
    "offset": 5,
    "ignore_growing": False,
    "params": {"nprobe": 10}
}
パラメータ 説明
metric_type 検索中にベクトル間の距離を測定するために使用される方法。これは、インデックス構築プロセスで指定された方法と同じである必要があります。詳細については類似度尺度を参照してください。
offset 検索中にスキップするエンティティの数。この値とsearchメソッドのlimitの合計は16384より小さくなければなりません。たとえば、クエリベクトルの9番目と10番目の最近傍をクエリしたい場合は、limitを2に設定し、offsetを8に設定します。
ignore_growing 類似度検索中に成長セグメントを無視するかどうか。デフォルト値はFalseで、検索に成長セグメントが含まれることを示します。
params 指定されたインデックスタイプに固有の検索パラメータ。詳細については、ベクトルインデックスを参照してください。可能なオプションには次のものがあります: - nprobeは検索するクラスタリングユニットの数を示します。このパラメータは、index_typeIVF_FLATIVF_SQ8、またはIVF_PQに設定する場合にのみ使用できます。値はインデックス構築プロセスで指定されたnlistの値より小さい必要があります。 - efは検索範囲を示します。このパラメータはindex_typeHNSWに設定する場合にのみ使用できます。値はtop_k32768の間である必要があります。 - radiusは最も低い類似度を持つベクトルが位置する角度を示します。 - range_filterは、クエリベクトルとの類似度が特定の範囲内にあるベクトルフィールドの値をフィルタリングするために使用されるフィルタを示します。

ベクトル検索の実行

Milvusを使用してベクトル検索を行います。特定のパーティション内で検索するには、パーティション名のリストを指定します。

Milvusでは検索のための一貫性レベルの設定がサポートされています。このトピックの例では、一貫性レベルを「強力」に設定しています。他にも「境界付き」、「セッション」、「最終的に」などの一貫性レベルを設定することができます。Milvusの4つの一貫性レベルについての詳細は一貫性を参照してください。

results = collection.search(
    data=[[0.1, 0.2]], 
    anns_field="book_intro", 
    param=search_params,
    limit=10,
    expr=None,
    output_fields=['title'],
    consistency_level="Strong"
)

results[0].ids

results[0].distances

hit = results[0][0]
hit.entity.get('title')
パラメーター 説明
data 検索に使用されるベクトル。
anns_field 検索されるフィールドの名前。
param インデックスに固有の検索パラメーター。詳細はベクトルインデックスを参照してください。
limit 返される結果の数。この値とparam内のoffsetを合わせたものは16,384未満である必要があります。
expr プロパティをフィルタリングするためのブール式。詳細はブール式のルールを参照してください。
output_fields (オプション) 返されるフィールドの名前。ベクトルフィールドは現在サポートされていません。
consistency_level (オプション) 検索の一貫性レベル。

最も類似したベクトルの主キー値と距離をチェックします。

results[0].ids
results[0].distances

検索が完了したら、Milvusの読み込まれたコレクションを解放してメモリ消費量を削減します。

collection.release()

制限事項

機能 最大制限
コレクション名の長さ 255 文字
コレクション内のパーティション数 4,096
コレクション内のフィールド数 256
コレクション内のシャード数 256
ベクトル次元 32,768
Top K 16,384
入力ベクトル 16,384

複合検索の実行

複合検索は、基本的には属性のフィルタリングとともにベクトル検索です。ブール式を指定することで、特定の条件下で検索を限定できます。

以下の例は、通常のベクトル検索に基づいた複合検索の実行方法を示しています。例えば、要約のベクトル化された書籍を検索したいが、特定の字数の範囲内でのみ検索したい場合、検索パラメーターでword_countフィールドをフィルタリングするブール式を指定します。Milvusは、ブール式に一致するエンティティ内でのみ類似したベクトルを検索します。

ブール式を指定することで、ベクトル検索中にエンティティのスカラーフィールドをフィルタリングすることができます。以下の例では、特定のword_count値の範囲内のベクトルのみを検索範囲として制限しています。

フィルタリング式で動的なフィールドを使用したり、検索リクエストで出力フィールドを使用したりすることができます。例えば、動的パターンを参照してください。

search_param = {
  "data": [[0.1, 0.2]],
  "anns_field": "book_intro",
  "param": {"metric_type": "L2", "params": {"nprobe": 10}, "offset": 0},
  "limit": 10,
  "expr": "word_count <= 11000",
}
res = collection.search(**search_param)

返された結果をチェックします。

assert len(res) == 1
hits = res[0]
assert len(hits) == 2
print(f"- 合計ヒット数: {len(hits)}, ヒットID: {hits.ids} ")
print(f"- Top1 ヒットID: {hits[0].id}, 距離: {hits[0].distance}, スコア: {hits[0].score} ")

範囲検索の実行

範囲検索は、クエリベクトルとベクトルフィールド値との間の距離に基づいて検索結果をフィルタリングする方法です。異なる距離メトリクスを使用して距離を測定することができます。

範囲検索を実行する際、Milvusはまずベクトル類似度検索を行います。その後、指定された距離条件に基づいてベクトルをフィルタリングし、特定の範囲内の距離にあるベクトルを返します。

以下の例は、通常のベクトル検索に基づいた範囲検索の実行方法を示しています。

コレクションの読み込み

Milvusでのすべての検索およびクエリ操作はメモリ内で実行されます。ベクトル類似性検索を実行する前に、コレクションをメモリに読み込む必要があります。

from pymilvus import Collection
collection = Collection("book")      # 既存のコレクションを取得
collection.load()

ベクトルフィルタリング範囲の設定

通常のベクトル検索と比較して、Milvusにおける範囲検索は、特定の検索範囲内で所望の検索結果を取得するために、radiusrange_filterという2つの新しいパラメータを導入して制御されます。

radiusは、ベクトルが類似とみなされる最小の角度を指定します。radiusと併用できるオプションのrange_filterは、クエリベクトルに対する類似性に基づいてベクトルフィールドの値を特定範囲内でフィルタリングするために利用できます。radiusrange_filterの両方のパラメータは、FLOATのデータ型を持ちます。これら2つのパラメータを設定することで、検索の正確さと効率を効果的にバランスさせることができます。

通常、類似性はベクトルフィールドの値とクエリベクトルの間の距離で測定されます。異なる距離メトリクスの選択は、radiusrange_filterの設定に重要な影響を与えます。

例えば、L2距離の場合、検索結果はradiusよりも距離が小さいベクトルフィールドの値でフィルタリングする必要があります。なぜなら、L2距離では、より小さい距離がより大きな類似性を示すからです。この知識をもとに、最も類似するいくつかのベクトルをフィルタリングしたい場合は、range_filterの値をradiusよりも小さい値に指定することができます。

search_params = {
    "metric_type": "L2",
    "params": {
        "radius": 10.0,
        "range_filter" : 5.0
    }
}

一方で、IP距離の場合は状況が異なります。IP距離では、より大きな距離がより大きな類似性を示します。したがって、L2距離とは対照的に、IP距離におけるradiusrange_filterの値は逆になります。つまり、IP距離に基づいて最も類似するいくつかのベクトルをrange_filterでフィルタリングしたい場合、有効なrange_filterの値はradiusよりも大きい必要があり、検索されたベクトルの距離はradiusよりも大きく、かつrange_filter以下である必要があります。

search_params = {
    "metric_type": "IP",
    "params": {
        "radius": 0.8,
        "range_filter" : 1.0
    }
}

範囲検索の実行

距離測定タイプに基づいてradiusrange_filterを指定することで、返される結果ベクトルの範囲を定義することができます。

L2距離に基づいて、類似性の範囲が5.010.0の範囲内で範囲検索を実行します。

search_param = {
  "data": [[0.1, 0.2]], # クエリベクトル
  "anns_field": "book_intro", # 検索するフィールド
  "param": { "metric_type": "L2", "params": { "nprobe": 10, "radius": 10.0, "range_filter" : 5.0 }, "offset": 0 },
  "limit": 2,
  "output_fields": ["int64", "float"]  # 返されるフィールド
}

res = collection.search(**search_param)

IP距離に基づいて、類似性の範囲が1.00.8の範囲内で範囲検索を実行します。

search_param = {
  "data": [[0.1, 0.2]], # クエリベクトル
  "anns_field": "book_intro", # 検索するフィールド
  "param": {"metric_type": "IP", "params": { "nprobe": 10, "radius": 0.8, "range_filter" : 1.0 }, "offset": 0 },
  "limit": 2,
  "output_fields": ["int64", "float"]  # 返されるフィールド
}

res = collection.search(**search_param)

要約

Milvusでは、範囲検索によって指定された距離範囲内で類似するベクトル結果を返すことができます。この機能は、検索パラメータでradiusrange_filterを指定することで有効になります。以下の表は、異なる距離測定タイプにおけるこれら2つのパラメータの設定をまとめたものです。

距離測定タイプ 設定
L2およびその他の距離 range_filter <= distance < radius
IPおよびコサイン距離 radius < distance <= range_filter