使用 StructArray 進行混合搜尋

請使用此頁面,將 StructArray 向量搜尋與其他向量搜尋結合,整合為單一的混合搜尋請求。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 欄位該集合包含一個 StructArray 欄位,例如chunks
向量子欄位請分別使用獨立的向量子欄位來執行 EmbeddingList 搜尋與元素層級搜尋。
索引chunks[emb_list_vector] 使用MAX_SIM* 指標。chunks[emb] 則使用常規向量指標,例如COSINEIPL2
重新排序器請選擇混合型重新排序器,例如RRFRanker 或您應用程式所支援的其他重新排序器。

有關索引設定,請參閱《Index StructArray 欄位》。

使用 EmbeddingList 請求執行混合搜尋

在混合搜尋中,針對 StructArray 向量子欄位的 EmbeddingList 搜尋屬於實體層級。其運作方式類似實體層級的向量搜尋請求,且不會返回單一匹配的 Struct 元素偏移量。

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 物件均產生實體層級的候選結果。最終結果以父實體的主鍵作為索引。請勿將 `element_scope ` 加入 EmbeddingList 請求中。

當所有 `AnnSearchRequest ` 物件皆針對同一 `StructArray` 欄位下的元素層級向量子欄位時,混合搜尋可透過重新排序來保留元素層級候選結果。這是唯一一種最終結果仍維持在元素層級的 `StructArray` 混合模式。

以下範例假設chunks 的 StructArray 欄位包含兩個元素級向量子欄位:chunks[emb]chunks[code_emb] ,且兩者均使用標準向量度量。

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 下搜尋向量子欄位。由於相同的以零為起點的偏移量指向同一個 Struct 元素,因此混合重新排序器可直接對元素候選項進行排序。請勿在此模式下設定element_scope ,因為不會執行實體層級的彙總。

若混合搜尋同時包含 StructArray 元素層級的AnnSearchRequest ,以及集合層級的向量請求、EmbeddingList 請求,或位於不同 StructArray 欄位下的元素層級請求,則最終候選範圍為實體層級。在此情況下,每個 StructArray 元素層級的AnnSearchRequest 都會在混合重新排序前,彙總為實體層級的候選項目。

當您需要控制如何彙總來自同一實體的多個匹配元素時,請在 StructArray 元素層級AnnSearchRequestparams 中使用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] 返回元素命中結果,接著透過將來自同一實體的返回元素中最佳的三個元素分數相加,來彙總這些元素。若在需要實體層級彙總時省略element_scope ,彙總策略將預設為max

選擇彙總策略

策略行為topk指標要求
max保留該實體所返回的最佳元素分數。不允許。任何受支援的常規向量指標。
sum將該實體所有回傳元素的分數相加。不允許。僅限正相關指標,例如IPCOSINE
avg將該實體所有回傳元素的評分求平均值。不允許。任何受支援的常規向量指標。
topk_sum將該實體所返回的元素中最佳的K 分數相加。此為必填項目,且數值必須為正數。僅限正相關指標,例如IPCOSINE
topk_avg對該實體所返回的最佳K 元素分數求平均值。此參數為必填且必須為正數。任何受支援的常規向量指標。

Collapse 僅使用該 StructArray 元素級別AnnSearchRequest 所返回的元素命中結果。它在 ANN 搜尋後不會掃描實體中的每個 Struct 元素。請將請求的limit 設定得足夠高,以提供您希望用於 Collapse 的元素。

新增篩選器、範圍搜尋與分組

當標量條件需套用至參與向量搜尋的相同 Struct 元素時,可將element_filter 附加至 StructArray 元素層級的AnnSearchRequest 。您亦可針對父實體條件,在hybrid_search() 上使用頂層的filter

StructArray 元素層級向量欄位在混合搜尋中支援範圍搜尋。請將radius 以及(若需)range_filter 新增至元素層級的AnnSearchRequest 中。EmbeddingList 層級的 StructArray 請求不支援範圍搜尋。

僅當所有 `AnnSearchRequest ` 物件皆針對同一 `StructArray` 欄位下的元素層級向量欄位,且 `group_by_field ` 必須為主鍵時,才支援元素層級的混合分組。若請求混合了集合層級的向量欄位、不同的 `StructArray` 欄位,或 `EmbeddingList` 層級的請求,則不支援混合分組。請勿將範圍搜尋與分組結合使用。

解讀混合結果

最終候選範圍結果鍵偏移量行為發生時
實體層級主鍵。最終結果中不包含元素偏移量。混合請求包含集合層級的向量欄位、EmbeddingList 請求,或位於不同 StructArray 欄位下的元素層級請求。
元素層級主鍵加上父級 StructArray 欄位,再加上元素偏移量。當 API 或 SDK 公開時,可返回所選元素的偏移量。所有 `AnnSearchRequest ` 物件均為元素層級,且位於同一個 `StructArray` 欄位之下。

限制

  • 請僅將 `element_scope ` 用於 StructArray 元素層級的 `AnnSearchRequest ` 物件,這些物件在混合搜尋中必須摺疊為實體層級的候選項目。

  • 請勿將element_scope 用於 EmbeddingList 請求、集合層級向量請求,或同一 StructArray 元素層級的混合搜尋。

  • sum 以及topk_sum 收斂策略均需正相關指標,例如IPCOSINE 。請勿將其與L2 搭配使用。

  • topk_sumtopk_avg 需要正的topk 值。其他彙總策略不得包含topk

  • 嵌入式清單層級的 StructArray 請求不支援範圍搜尋或分組。

  • 混合分組僅支援相同 StructArray 元素層級的混合搜尋,且僅限透過主鍵進行。

  • 請勿將範圍搜尋與分組操作結合使用。

常見錯誤

  • 在同一 StructArray 元素層級的混合請求中加入element_scope 。該請求仍維持在元素層級,且不會執行實體層級的彙總。

  • 將 `element_scope ` 新增至 `chunks[emb_list_vector]`。`EmbeddingList` 搜尋本身已是實體層級的。

  • 假設兩個 StructArray 欄位共享元素偏移量。chunks 中的偏移量3 與另一個 StructArray 欄位中的偏移量3 對應不同的元素,因此混合請求將轉為實體層級。

  • 若使用topk_sum 搭配L2 ,請使用maxavgtopk_avg 來處理負數距離度量值。

  • 預期實體層級的混合結果在摺疊後將包含所選的 Struct 元素偏移量。

後續步驟

  1. 若要了解兩種基本的 StructArray 向量搜尋模式,請參閱《使用 StructArray 進行基本向量搜尋》。

  2. 若要將標量篩選器新增至混合搜尋,請參閱《使用 StructArray 進行篩選搜尋》。

  3. 若要在混合搜尋中使用分數或距離範圍,請參閱《使用 StructArray 進行範圍搜尋》。

  4. 若要依父實體將元素層級的混合搜尋結果分組,請參閱《使用 StructArray 進行分組搜尋》。

  5. 若要查看 StructArray 的搜尋限制,請參閱《StructArray 限制》