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

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

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

Qx7UwgI6jhrku8bAxZqcYxZMnSe

マルチベクターハイブリッド検索は、異なる検索手法を統合したり、さまざまなモダリティの埋め込みを横断的に扱ったりします。

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

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

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

  • Semantic Text Search: これは、高密度ベクトルを使用して商品のテキスト説明をクエリするものです。テキスト埋め込みは、BERTTransformers のようなモデル、または OpenAI のようなサービスを使用して生成できます。

  • Full-Text Search: ここでは、スパースベクトルを使用したキーワードマッチによって商品のテキスト説明をクエリします。BM25 のようなアルゴリズムや、BGE-M3SPLADE のようなスパース埋め込みモデルをこの目的に使用できます。

  • Multimodal Image Search: この手法では、高密度ベクトルを使用したテキストクエリで画像を検索します。画像埋め込みは、CLIP のようなモデルで生成できます。

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

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

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

スキーマを定義する

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

この例では、次のフィールドをスキーマに追加します。

  • id: テキスト ID を保存するためのプライマリキーとして機能します。このフィールドのデータ型は INT64 です。

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

  • text_dense: テキストの高密度ベクトルを保存するために使用します。このフィールドのデータ型は FLOAT_VECTOR で、ベクトル次元は 768 です。

  • text_sparse: テキストのスパースベクトルを保存するために使用します。このフィールドのデータ型は SPARSE_FLOAT_VECTOR です。

  • image_dense: 商品画像の高密度ベクトルを保存するために使用します。このフィールドのデータ型は FLOAT_VETOR で、ベクトル次元は 512 です。

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

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

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

# Init schema with auto_id disabled
schema = client.create_schema(auto_id=False)

# Add fields to schema
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")

# Add function to schema
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: テキストの高密度ベクトルフィールドに対して、タイプが AUTOINDEX、メトリクスタイプが IP のインデックスを作成します。

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

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

python
# Prepare index parameters
index_params = client.prepare_index_params()

# Add indexes
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 という名前のコレクションを作成します。

python
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 を使用しない場合は、スパース埋め込みを事前に計算して自分で指定する必要があります。

python
import random

# Generate example vectors
def generate_dense_vector(dim):
return [random.random() for _ in range(dim)]

data=[
{
"id": 0,
"text": "Red cotton t-shirt with round neck",
"text_dense": generate_dense_vector(768),
"image_dense": generate_dense_vector(512)
},
{
"id": 1,
"text": "Wireless noise-cancelling over-ear headphones",
"text_dense": generate_dense_vector(768),
"image_dense": generate_dense_vector(512)
},
{
"id": 2,
"text": "Stainless steel water bottle, 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 パラメータを構成することで、ハイブリッド検索のフィルタ条件を設定できます。詳しくは、フィルタ付き検索 および フィルタリングの解説 を参照してください。

📘Notes

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

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

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

  • text_sparse は全文検索またはキーワードマッチング用で、テキスト内の単語やフレーズの完全一致に焦点を当てます。

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

python
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)

# text semantic search (dense)
search_param_1 = {
"data": [query_dense_vector],
"anns_field": "text_dense",
"limit": 2
}
request_1 = AnnSearchRequest(**search_param_1)

# full-text search (sparse)
search_param_2 = {
"data": [query_text],
"anns_field": "text_sparse",
"limit": 2
}
request_2 = AnnSearchRequest(**search_param_2)

# text-to-image search (multimodal)
search_param_3 = {
"data": [query_multimodal_vector],
"anns_field": "image_dense",
"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 は複数のタイプの再ランキング戦略を提供しています。これらの再ランキングの仕組みの詳細については、Weighted Ranker または RRF Ranker を参照してください。

この例では、特定の検索クエリを特に重視する必要がないため、RRFRanker 戦略を使用します。

python
ranker = Function(
name="rrf",
input_field_names=[], # Must be an empty list
function_type=FunctionType.RERANK,
params={
"reranker": "rrf",
"k": 100 # Optional
}
)

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

python
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)

出力は次のとおりです。

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

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