メインコンテンツまでスキップ
バージョン: User Guides (Cloud)

マルチベクトルハイブリッド検索

多くのアプリケーションでは、タイトルや説明文などの豊富な情報を使用してオブジェクトを検索したり、テキスト、画像、音声などの複数のモダリティで検索したりできます。たとえば、テキストと画像が含まれるツイートは、テキストまたは画像が検索クエリのセマンティクスに一致する場合に検索する必要があります。ハイブリッド検索は、これらの多様なフィールドにわたる検索を組み合わせて検索体験を向上させます。Zilliz Cloudは、複数のベクトルフィールドでの検索を許可し、複数の近似最近傍(ANN)検索を同時に実行することでこれをサポートしています。マルチベクトルハイブリッド検索は、テキストと画像の両方を検索したい場合、同じオブジェクトを記述する複数のテキストフィールドを検索したい場合、または検索品質を向上させるために密ベクトルと疎ベクトルを組み合わせたい場合に特に有効です。

Qx7UwgI6jhrku8bAxZqcYxZMnSe

マルチベクトルハイブリッド検索は、異なる検索方法またはさまざまなモダリティからの埋め込みを統合します。

  • 疎密ベクトル検索密ベクトルはセマンティックな関係を捉えるのに優れている一方、疎ベクトルは正確なキーワードマッチングに非常に効果的です。ハイブリッド検索はこれらのアプローチを組み合わせて、広範な概念的理解と正確な用語の関連性の両方を提供し、検索結果を改善します。各方法の強みを活かすことで、ハイブリッド検索は個々のアプローチの限界を克服し、複雑なクエリに優れたパフォーマンスを提供します。セマンティック検索と全文検索を組み合わせたハイブリッド検索の詳細なガイドはこちらです。

  • マルチモーダルベクトル検索:マルチモーダルベクトル検索は、テキスト、画像、音声などさまざまなデータ型を横断して検索できる強力な技術です。このアプローチの主な利点は、異なるモダリティをシームレスで統合された検索体験に統合できる能力です。たとえば、商品検索では、ユーザーはテキストと画像の両方で記述された商品を見つけるためにテキストクエリを入力できます。ハイブリッド検索方法でこれらのモダリティを組み合わせることで、検索の精度を高めたり、検索結果を豊かにしたりできます。

各製品にテキスト説明と画像が含まれる現実のユースケースを考えてみましょう。利用可能なデータに基づいて、3種類の検索を実施できます。

  • セマンティックテキスト検索:これは、密ベクトルを使用して製品のテキスト説明をクエリします。BERTTransformersなどのモデルやOpenAIなどのサービスを使用してテキスト埋め込みを生成できます。

  • 全文検索:ここでは、疎ベクトルを使用してキーワードマッチで製品のテキスト説明をクエリします。BM25BGE-M3SPLADEなどの疎埋め込みモデルをこの目的に使用できます。

  • マルチモーダル画像検索:この方法は、密ベクトルを使用してテキストクエリで画像をクエリします。CLIPなどのモデルで画像埋め込みを生成できます。

このガイドでは、上記の検索方法を組み合わせたマルチモーダルハイブリッド検索の例を説明します。商品の生テキスト説明と画像埋め込みを前提に、マルチベクトルデータを保存し、リランキング戦略でハイブリッド検索を実行する方法を示します。

複数のベクトルフィールドを持つコレクションを作成する

コレクションの作成プロセスには、コレクションスキーマの定義、インデックスパラメータの構成、コレクションの作成の3つの主要なステップがあります。

スキーマの定義

マルチベクトルハイブリッド検索では、コレクションスキーマ内に複数のベクトルフィールドを定義する必要があります。コレクションで許可されるベクトルフィールドの数に関する制限の詳細については、Zilliz Cloudの制限を参照してください。

この例では、スキーマに以下のフィールドを組み込みます。

  • id:テキストIDを格納するための主キーとして機能します。このフィールドはINT64データ型です。

  • text:テキストコンテンツを格納するために使用されます。このフィールドはVARCHARデータ型で、最大長は1000バイトです。enable_analyzerオプションはTrueに設定して、全文検索を容易にします。

  • text_dense:テキストの密ベクトルを格納するために使用されます。このフィールドは768次元のFLOAT_VECTORデータ型です。

  • text_sparse:テキストの疎ベクトルを格納するために使用されます。このフィールドはSPARSE_FLOAT_VECTORデータ型です。

  • image_dense:製品画像の密ベクトルを格納するために使用されます。このフィールドは512次元のFLOAT_VECTORデータ型です。

テキストフィールドで全文検索を実行するために組み込みBM25アルゴリズムを使用するため、スキーマにMilvusのFunctionを追加する必要があります。詳細については、全文検索を参照してください。

from pymilvus import (
MilvusClient, DataType, Function, FunctionType
)

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

# auto_idを無効にしてスキーマを初期化
schema = client.create_schema(auto_id=False)

# スキーマにフィールドを追加
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, description="product id")
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1000, enable_analyzer=True, description="raw text of product description")
schema.add_field(field_name="text_dense", datatype=DataType.FLOAT_VECTOR, dim=768, description="text dense embedding")
schema.add_field(field_name="text_sparse", datatype=DataType.SPARSE_FLOAT_VECTOR, description="text sparse embedding auto-generated by the built-in BM25 function")
schema.add_field(field_name="image_dense", datatype=DataType.FLOAT_VECTOR, dim=512, description="image dense embedding")

# スキーマに関数を追加
bm25_function = Function(
name="text_bm25_emb",
input_field_names=["text"],
output_field_names=["text_sparse"],
function_type=FunctionType.BM25,
)
schema.add_function(bm25_function)

インデックスの作成

コレクションスキーマを定義した後、次のステップはベクトルインデックスを構成し、類似性メトリックを指定することです。この例では:

  • text_dense_index:テキスト密ベクトルフィールドに対して、IPメトリックタイプを持つAUTOINDEXタイプのインデックスが作成されます。

  • text_sparse_index:テキスト疎ベクトルフィールドに対して、BM25メトリックタイプを持つSPARSE_INVERTED_INDEXタイプのインデックスが使用されます。

  • image_dense_index:画像密ベクトルフィールドに対して、IPメトリックタイプを持つAUTOINDEXタイプのインデックスが作成されます。

# インデックスパラメータを準備
index_params = client.prepare_index_params()

# インデックスを追加
index_params.add_index(
field_name="text_dense",
index_name="text_dense_index",
index_type="AUTOINDEX",
metric_type="IP"
)

index_params.add_index(
field_name="text_sparse",
index_name="text_sparse_index",
index_type="AUTOINDEX",
metric_type="BM25"
)

index_params.add_index(
field_name="image_dense",
index_name="image_dense_index",
index_type="AUTOINDEX",
metric_type="IP"
)

コレクションの作成

前回の2つのステップで設定したコレクションスキーマとインデックスを使用して、demoという名前のコレクションを作成します。

client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params
)

データの挿入

このセクションでは、以前に定義したスキーマに基づいてmy_collectionコレクションにデータを挿入します。挿入時には、自動生成される値を持つフィールドを除き、すべてのフィールドに正しい形式でデータを提供してください。この例では:

  • id:製品IDを表す整数

  • text:製品説明を含む文字列

  • text_dense:テキスト説明の密埋め込みを表す768個の浮動小数点値のリスト

  • image_dense:製品画像の密埋め込みを表す512個の浮動小数点値のリスト

各フィールドの密埋め込みを生成するために同じまたは異なるモデルを使用できます。この例では、2つの密埋め込みに異なる次元があり、異なるモデルによって生成されたことを示しています。後の各検索を定義する際には、対応するモデルを使用して適切なクエリ埋め込みを生成してください。

この例では、テキストフィールドから疎埋め込みを生成するために組み込みBM25関数を使用しているため、手動で疎ベクトルを提供する必要はありません。ただし、BM25を使用しない場合は、疎埋め込みを事前に計算して自分で提供する必要があります。

import random

# 例のベクトルを生成
def generate_dense_vector(dim):
return [random.random() for _ in range(dim)]

data=[
{
"id": 0,
"text": "ラウンドネックの赤いコットンTシャツ",
"text_dense": generate_dense_vector(768),
"image_dense": generate_dense_vector(512)
},
{
"id": 1,
"text": "ワイヤレスノイズキャンセリングオーバーヘッドヘッドフォン",
"text_dense": generate_dense_vector(768),
"image_dense": generate_dense_vector(512)
},
{
"id": 2,
"text": "ステンレススチール製水筒、500ml",
"text_dense": generate_dense_vector(768),
"image_dense": generate_dense_vector(512)
}
]

res = client.insert(
collection_name="my_collection",
data=data
)

ステップ1:複数のAnnSearchRequestインスタンスを作成

ハイブリッド検索は、hybrid_search()関数で複数のAnnSearchRequestを作成することによって実装されます。各AnnSearchRequestは、特定のベクトルフィールド用の基本的なANN検索リクエストを表します。したがって、ハイブリッド検索を実施する前に、各ベクトルフィールド用のAnnSearchRequestを作成する必要があります。

さらに、AnnSearchRequestexprパラメータを構成することにより、ハイブリッド検索のフィルタリング条件を設定できます。フィルター検索およびフィルタリングの説明を参照してください。

📘ノート

ハイブリッド検索では、各AnnSearchRequestは1つのクエリデータのみをサポートします。

さまざまな検索ベクトルフィールドの機能を示すために、サンプルクエリを使用して3つのAnnSearchRequest検索リクエストを作成します。このプロセスで事前に計算された密ベクトルも使用します。検索リクエストは、以下のベクトルフィールドを対象とします。

  • text_denseはセマンティックなテキスト検索用で、直接のキーワード一致ではなく意味に基づいた文脈的理解と取得を可能にします。

  • text_sparseは全文検索またはキーワード一致用で、テキスト内の正確な単語または語句の一致に焦点を当てます。

  • image_denseはマルチモーダルなテキストから画像への検索用で、クエリのセマンティックなコンテンツに基づいて関連する製品画像を取得します。

from pymilvus import AnnSearchRequest

query_text = "white headphones, quiet and comfortable"
query_dense_vector = generate_dense_vector(768)
query_multimodal_vector = generate_dense_vector(512)

# テキストセマンティック検索(密)
search_param_1 = {
"data": [query_dense_vector],
"anns_field": "text_dense",
"param": {"nprobe": 10},
"limit": 2
}
request_1 = AnnSearchRequest(**search_param_1)

# 全文検索(疎)
search_param_2 = {
"data": [query_text],
"anns_field": "text_sparse",
"param": {"drop_ratio_search": 0.2},
"limit": 2
}
request_2 = AnnSearchRequest(**search_param_2)

# テキストから画像への検索(マルチモーダル)
search_param_3 = {
"data": [query_multimodal_vector],
"anns_field": "image_dense",
"param": {"nprobe": 10},
"limit": 2
}
request_3 = AnnSearchRequest(**search_param_3)

reqs = [request_1, request_2, request_3]

limitパラメータが2に設定されているため、各AnnSearchRequestは2つの検索結果を返します。この例では3つのAnnSearchRequestインスタンスが作成され、合計で6つの検索結果が得られます。

ステップ2:リランキング戦略の構成

ANN検索結果のセットを統合・リランキングし、適切なリランキング戦略を選択するには、選択が不可欠です。Zilliz Cloudは複数のタイプのリランキング戦略を提供しています。これらのリランキングメカニズムの詳細については、重み付きランカーまたはRRFランカーを参照してください。

この例では、特定の検索クエリに特に重点を置くことはないため、RRFRanker戦略を進めます。

ranker = Function(
name="rrf",
input_field_names=[], # 空のリストでなければならない
function_type=FunctionType.RERANK,
params={
"reranker": "rrf",
"k": 100 # オプショナル
}
)

ハイブリッド検索を開始する前に、コレクションがロードされていることを確認してください。コレクション内のベクトルフィールドにインデックスがない場合、またはメモリにロードされていない場合は、ハイブリッド検索メソッドの実行時にエラーが発生します。

res = client.hybrid_search(
collection_name="my_collection",
reqs=reqs,
ranker=ranker,
limit=2
)
for hits in res:
print("TopK results:")
for hit in hits:
print(hit)

以下は出力です。

["['id: 1, distance: 0.006047376897186041, entity: {}', 'id: 2, distance: 0.006422005593776703, entity: {}']"]

limit=2パラメータがハイブリッド検索に対して指定されているため、Zilliz Cloudは3つの検索から得られた6つの結果をリランキングします。最終的に、最も類似した上位2つの結果のみが返されます。