StructArray を使用したハイブリッド検索
このページでは、StructArrayベクトル検索と他のベクトル検索を組み合わせて、1つのハイブリッド検索リクエストとして実行できます。StructArrayハイブリッド検索では、組み合わせるAnnSearchRequest オブジェクトに応じて、エンティティレベルの結果または要素レベルの結果が得られます。
このページでは、「StructArrayフィールドの作成」のtech_articles コレクションを使用しています。このコレクションには、title_vector という名前の最上位ベクトルフィールドと、chunks という名前のStructArrayフィールドがあります。chunks[emb_list_vector] サブフィールドはEmbeddingList検索用にインデックス化されており、chunks[emb] は要素レベル検索用にインデックス化されています。
StructArray に対するハイブリッド検索の適用方法
AnnSearchRequest 組み合わせ | 最終的な候補スコープ | 結果の挙動 | element_scope |
|---|---|---|---|
| コレクションレベルのベクトルフィールド + StructArrayのEmbeddingListサブフィールド | エンティティレベル | 最終候補は主キーでキー付けされます。 | 使用しないでください。 |
| コレクションレベルのベクトルフィールド + StructArray 要素レベルのサブフィールド | エンティティレベル | 要素レベルのヒットは、ハイブリッド再ランク付けの前にエンティティレベルの候補に集約されます。 | StructArray 要素レベルのAnnSearchRequest に対するオプションの折りたたみ設定。 |
| 同じ StructArray フィールドの下にある複数の要素レベルのサブフィールド | 要素レベル | 最終候補は、主キーと Struct 要素のオフセットを組み合わせたキーで指定されます。 | 使用しないでください。 |
| 異なる StructArray フィールドの下にある要素レベルのサブフィールド | エンティティレベル | 要素オフセットは識別子を共有しないため、再ランク付けの前に、各 StructArray 要素レベルのAnnSearchRequest が折りたたまれます。 | 各 StructArray 要素レベルのAnnSearchRequest に対する、オプションの折りたたみ設定。 |
警告
element_scope は、異なる構造体間の要素レベルのハイブリッド検索において、StructArray 要素レベルのAnnSearchRequest オブジェクトの折りたたみを設定する場合にのみ使用してください。EmbeddingList リクエスト、コレクションレベルのベクトルリクエスト、または同一 StructArray 要素レベルのハイブリッド検索には使用しないでください。
開始する前に
ハイブリッド検索を実行する前に、コレクション、データ、およびインデックスを準備してください。
| 要件 | 詳細 |
|---|---|
| StructArray フィールド | コレクションには、chunks などの StructArray フィールドが含まれています。 |
| Vector サブフィールド | EmbeddingList 検索と要素レベルの検索には、それぞれ個別のベクトルサブフィールドを使用してください。 |
| インデックス | chunks[emb_list_vector] は、MAX_SIM* メトリックを使用します。chunks[emb] は、COSINE 、IP 、またはL2 などの通常のベクトルメトリックを使用します。 |
| 再ランク付けアルゴリズム | RRFRanker などのハイブリッド・リランカー、またはお使いのアプリケーションでサポートされている他のリランカーを選択してください。 |
インデックスの設定については、「Index StructArray フィールド」を参照してください。
EmbeddingList リクエストを使用したハイブリッド検索の実行
ハイブリッド検索において、StructArray ベクトルサブフィールドに対する EmbeddingList 検索はエンティティレベルで行われます。これはエンティティレベルのベクトル検索リクエストと同様に動作し、一致した Struct 要素のオフセットを 1 つ返すことはありません。
from pymilvus import AnnSearchRequest, MilvusClient, RRFRanker
from pymilvus.client.embedding_list import EmbeddingList
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus",
)
query_vector = [0.19, 0.24, 0.30, 0.37]
query_list = EmbeddingList()
query_list.add([0.12, 0.21, 0.32, 0.44])
query_list.add([0.18, 0.23, 0.29, 0.36])
title_req = AnnSearchRequest(
data=[query_vector],
anns_field="title_vector",
limit=10,
)
chunk_list_req = AnnSearchRequest(
data=[query_list],
anns_field="chunks[emb_list_vector]",
limit=10,
)
results = client.hybrid_search(
collection_name="tech_articles",
reqs=[title_req, chunk_list_req],
ranker=RRFRanker(),
limit=5,
output_fields=[
"doc_id",
"title",
"category",
"chunks[text]",
"chunks[section]",
],
)
この例では、両方のAnnSearchRequest オブジェクトがエンティティレベルの候補を生成します。最終結果は、親エンティティのプライマリキーをキーとして返されます。EmbeddingListリクエストにelement_scope を追加しないでください。
同一の StructArray に対する要素レベルのハイブリッド検索を実行する
すべてのAnnSearchRequest オブジェクトが、同じStructArrayフィールドの下にある要素レベルのベクトルサブフィールドを対象としている場合、ハイブリッド検索では再ランク付けを通じて要素レベルの候補を維持できます。これは、最終結果が要素レベルのままとなる唯一のStructArrayハイブリッドモードです。
次の例では、chunks のStructArrayフィールドに、chunks[emb] とchunks[code_emb] という2つの要素レベルのベクトルサブフィールドがあり、両方が通常のベクトルメトリックを使用していることを想定しています。
index_chunk_req = AnnSearchRequest(
data=[query_vector],
anns_field="chunks[emb]",
limit=10,
expr='element_filter(chunks, $[section] == "index")',
)
code_chunk_req = AnnSearchRequest(
data=[code_query_vector],
anns_field="chunks[code_emb]",
limit=10,
expr='element_filter(chunks, $[has_code] == true)',
)
results = client.hybrid_search(
collection_name="tech_articles",
reqs=[index_chunk_req, code_chunk_req],
ranker=RRFRanker(),
limit=5,
output_fields=[
"doc_id",
"title",
"chunks[text]",
"chunks[section]",
"chunks[quality_score]",
],
)
for hits in results:
for hit in hits:
print(
"doc_id:", hit["id"],
"distance:", hit["distance"],
"offset:", hit.get("offset"),
"entity:", hit["entity"],
)
両方のAnnSearchRequest オブジェクトは、chunks 配下のベクトルサブフィールドを検索します。同じ0を基点とするオフセットは同じStruct要素を指すため、ハイブリッド再ランク付け機能は要素レベルの候補を直接ランク付けできます。このモードではエンティティレベルの集約が行われないため、element_scope を設定しないでください。
エンティティレベルのハイブリッド検索における要素レベルのヒットの集約
ハイブリッド検索において、StructArrayの要素レベルのAnnSearchRequest が、コレクションレベルのベクトルリクエスト、EmbeddingListリクエスト、または別のStructArrayフィールド下の要素レベルのリクエストと組み合わされる場合、最終的な候補の範囲はエンティティレベルとなります。この場合、ハイブリッド再ランク付けの前に、各StructArray要素レベルのAnnSearchRequest はエンティティレベルの候補に集約されます。
同一エンティティからの複数の一致要素をどのように集約するかを制御する必要がある場合は、StructArray要素レベルのAnnSearchRequest のparams 内でelement_scope を使用してください。
title_req = AnnSearchRequest(
data=[query_vector],
anns_field="title_vector",
limit=10,
)
chunk_req = AnnSearchRequest(
data=[query_vector],
anns_field="chunks[emb]",
param={
"params": {
"element_scope": {
"collapse": {
"strategy": "topk_sum",
"topk": 3,
},
},
},
},
limit=30,
expr='element_filter(chunks, $[quality_score] > 0.8)',
)
results = client.hybrid_search(
collection_name="tech_articles",
reqs=[title_req, chunk_req],
ranker=RRFRanker(),
limit=5,
output_fields=[
"doc_id",
"title",
"category",
"chunks[text]",
"chunks[section]",
"chunks[quality_score]",
],
)
この例では、title_req はエンティティレベルであるため、最終的なハイブリッド結果もエンティティレベルになります。chunk_req リクエストは、まずchunks[emb] から要素ヒットを返し、次に同じエンティティからの返された要素を、上位3つの要素スコアの合計を算出することで集約します。エンティティレベルの集約が必要な場合にelement_scope が省略されると、集約戦略はデフォルトでmax になります。
集約戦略の選択
| 戦略 | 動作 | topk | メトリックの要件 |
|---|---|---|---|
max | そのエンティティに対して、返された要素のうち最高のスコアを保持します。 | 使用不可。 | サポートされている任意の正規ベクトルメトリック。 |
sum | そのエンティティに対して返されたすべての要素のスコアを合計する。 | 使用不可。サポートされている任意の通常のベクトルメトリック。そのエンティティに対して返されたすべての要素のスコアを合計する。 | IP やCOSINE など、正の相関を持つメトリクスのみ。 |
avg | そのエンティティについて、返されたすべての要素スコアの平均を算出します。 | 使用不可。 | サポートされている任意の正規ベクトルメトリック。 |
topk_sum | そのエンティティに対して返された要素スコアのうち、K で最高となったものを合計します。 | 必須であり、正の値でなければなりません。 | IP やCOSINE など、正の相関を持つメトリクスのみ。 |
topk_avg | そのエンティティに対して返されたK の要素スコアのうち、最も高いものの平均を算出します。 | 必須であり、正の値でなければなりません。xml-ph-0000@deepl.internal や xml-ph-0001@deepl.internal など、正の相関メトリクスのみ。そのエンティティに対して返された xml-ph-0000@deepl.internal の最高要素スコアの平均を算出します。 | サポートされている任意の正規ベクトルメトリック。 |
Collapse は、その StructArray 要素レベルのAnnSearchRequest によって返された要素ヒットのみを使用します。ANN 検索の後、エンティティ内のすべての Struct 要素をスキャンすることはありません。Collapse で利用可能な要素を確保できるよう、リクエストのlimit を十分に高い値に設定してください。
フィルタ、範囲検索、およびグループ化の追加
AnnSearchRequest スカラー条件を、ベクトル検索に参加する同じStruct要素に適用する必要がある場合は、StructArray要素レベルのelement_filter に を添付できます。また、親エンティティの条件については、hybrid_search() に対してトップレベルのfilter を使用することもできます。
StructArrayの要素レベルのベクトルフィールドは、ハイブリッド検索における範囲検索をサポートしています。要素レベルのAnnSearchRequest にradius を追加し、必要に応じてrange_filter を追加してください。EmbeddingListレベルのStructArrayリクエストは、範囲検索をサポートしていません。
要素レベルのハイブリッドグループ化は、すべてのAnnSearchRequest オブジェクトが同一のStructArrayフィールド下の要素レベルのベクトルフィールドを対象としている場合にのみサポートされ、group_by_field は主キーでなければなりません。リクエストにコレクションレベルのベクトルフィールド、異なるStructArrayフィールド、またはEmbeddingListレベルのリクエストが混在している場合、ハイブリッドグループ化はサポートされません。範囲検索とグループ化を組み合わせて使用しないでください。
ハイブリッド結果の解釈
| 最終候補範囲 | 結果キー | オフセットの挙動 | 発生条件 |
|---|---|---|---|
| エンティティレベル | 主キー。 | 最終結果に要素オフセットは含まれません。 | ハイブリッドリクエストには、コレクションレベルのベクトルフィールド、EmbeddingList リクエスト、または異なる StructArray フィールドの下にある要素レベルのリクエストが含まれています。 |
| 要素レベル | 主キーに加え、親の StructArray フィールドおよび要素オフセット。 | 選択された要素オフセットは、API または SDK によって公開されている場合、返されることがあります。 | すべてのAnnSearchRequest オブジェクトは要素レベルであり、同じStructArrayフィールドの下にあります。 |
制限事項
element_scopeは、ハイブリッド検索においてエンティティレベルの候補に折りたたまれる必要がある、StructArray 要素レベルのAnnSearchRequestオブジェクトにのみ使用してください。EmbeddingList リクエスト、コレクションレベルのベクトルリクエスト、または同じ StructArray 要素レベルのハイブリッド検索には、
element_scopeを使用しないでください。sumおよびtopk_sumの折りたたみ戦略では、IPやCOSINEなどの正の相関メトリクスが必要です。L2と一緒に使用しないでください。topk_sumまた、topk_avgには、正のtopk値が必要です。その他の折りたたみ戦略には、topkを含めてはなりません。EmbeddingList レベルの StructArray リクエストは、範囲検索やグループ化をサポートしていません。
ハイブリッドグループ化は、同じ StructArray 要素レベルのハイブリッド検索においてのみ、かつ主キーによる場合のみサポートされます。
範囲検索とグループ化を組み合わせて使用しないでください。
よくある間違い
同じ StructArray 要素レベルのハイブリッドリクエストに
element_scopeを追加すること。そのリクエストは要素レベルのままとなり、エンティティレベルの折りたたみは実行されません。chunks[emb_list_vector]にelement_scopeを追加すること。EmbeddingList 検索はすでにエンティティレベルです。2つのStructArrayフィールドが要素オフセットを共有していると仮定すること。
chunks内のオフセット3と、別のStructArrayフィールド内のオフセット3は異なる要素であるため、ハイブリッドリクエストはエンティティレベルになります。topk_sumをL2と共に使用します。負の距離メトリックについては、max、avg、またはtopk_avgを使用してください。エンティティレベルのハイブリッド検索結果には、折りたたみ後に選択された Struct 要素のオフセットが含まれることを期待しています。
次の手順
StructArray による 2 つの基本的なベクトル検索モードについては、「StructArray を使用した基本的なベクトル検索」を参照してください。
ハイブリッド検索にスカラーフィルタを追加するには、「StructArray を使用したフィルタ付き検索」を参照してください。
ハイブリッド検索でスコアまたは距離の境界を使用するには、「StructArray を使用した範囲検索」を参照してください。
要素レベルのハイブリッド検索結果を親エンティティごとにグループ化するには、「StructArray を使用したグループ化検索」を参照してください。
StructArrayの検索制限を確認するには、「StructArrayの制限」を参照してください。