Recherche hybride avec StructArray

Utilisez cette page pour combiner la recherche vectorielle StructArray avec d’autres recherches vectorielles au sein d’une seule requête de recherche hybride. La recherche hybride StructArray peut produire soit des résultats au niveau de l’entité, soit des résultats au niveau de l’élément, en fonction des objets de la collection « AnnSearchRequest » que vous combinez.

Cette page utilise la collection « tech_articles » issue de la section « Créer un champ StructArray ». Cette collection comporte un champ vectoriel de niveau supérieur nommé « title_vector » et un champ StructArray nommé « chunks ». Le sous-champ « chunks[emb_list_vector] » est indexé pour la recherche EmbeddingList, tandis que « chunks[emb] » est indexé pour la recherche au niveau des éléments.

Comment la recherche hybride s’applique à StructArray

AnnSearchRequest combinaisonPortée finale des candidatsComportement du résultatelement_scope
Champ vectoriel au niveau de la collection + sous-champ EmbeddingList de StructArrayNiveau de l’entitéLes candidats finaux sont indexés par clé primaire.Ne pas utiliser.
Champ vectoriel au niveau de la collection + sous-champ au niveau de l'élément de StructArrayNiveau de l’entitéLes résultats au niveau des éléments sont regroupés en candidats au niveau des entités avant le reclassement hybride.Configuration facultative de regroupement sur l’ AnnSearchRequest au niveau des éléments de StructArray.
Plusieurs sous-champs au niveau des éléments sous le même champ StructArrayNiveau élémentLes candidats finaux sont indexés par la clé primaire et le décalage de l'élément Struct.À ne pas utiliser.
Sous-champs au niveau des éléments sous différents champs StructArrayNiveau de l’entitéLes décalages d’éléments ne partagent pas d’identité commune ; par conséquent, chaque AnnSearchRequest au niveau des éléments de StructArray est regroupée avant le reclassement.AnnSearchRequestConfiguration facultative de regroupement pour chaque sous-champ au niveau des éléments de StructArray.

Avertissement

Utilisez l’ element_scope uniquement pour configurer la réduction des objets d’ AnnSearchRequest s au niveau des éléments de StructArray dans une recherche hybride au niveau des éléments ne portant pas sur la même structure. Ne l’utilisez pas pour les requêtes EmbeddingList, les requêtes vectorielles au niveau des collections ou la recherche hybride au niveau des éléments portant sur la même structure StructArray.

Avant de commencer

Préparez la collection, les données et les index avant d'exécuter une recherche hybride.

PrérequisDétails
Champ StructArrayLa collection contient un champ StructArray tel que chunks.
Sous-champs vectorielsUtilisez des sous-champs vectoriels distincts pour la recherche dans EmbeddingList et la recherche au niveau des éléments.
Les indexchunks[emb_list_vector] utilise une métrique de type « MAX_SIM* ». La fonction « chunks[emb] » utilise une métrique vectorielle classique telle que COSINE, IP ou L2.
RerankerChoisissez un réclassificateur hybride tel que RRFRanker ou un autre réclassificateur pris en charge par votre application.

Pour la configuration de l'index, consultez la section Champs StructArray de l'index.

Lancer une recherche hybride avec une requête EmbeddingList

La recherche EmbeddingList sur un sous-champ vectoriel StructArray s’effectue au niveau de l’entité dans le cadre d’une recherche hybride. Elle se comporte comme une requête de recherche vectorielle au niveau de l’entité et ne renvoie pas un seul offset d’élément Struct correspondant.

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]",
    ],
)

Dans cet exemple, les deux objets ` AnnSearchRequest ` produisent des candidats au niveau de l’entité. Le résultat final est indexé par la clé primaire de l’entité parente. N’ajoutez pas de ` element_scope ` à la requête `EmbeddingList`.

Lorsque tous les objets ` AnnSearchRequest ` ciblent des sous-champs vectoriels au niveau des éléments appartenant au même champ `StructArray`, la recherche hybride peut conserver les candidats au niveau des éléments grâce à un reclassement. Il s’agit du seul mode hybride `StructArray` dans lequel les résultats finaux restent au niveau des éléments.

L’exemple suivant part du principe que le champ StructArray « chunks » comporte deux sous-champs vectoriels au niveau des éléments, « chunks[emb] » et « chunks[code_emb] », et que les deux utilisent des métriques vectorielles standard.

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"],
        )

Les deux objets AnnSearchRequest effectuent une recherche dans les sous-champs vectoriels sous chunks. Le même décalage (à partir de zéro) fait référence au même élément Struct ; le reclassement hybride peut donc classer directement les candidats au niveau des éléments. Ne définissez pas element_scope dans ce mode, car aucun regroupement au niveau des entités n’est effectué.

Si une recherche hybride combine une requête « AnnSearchRequest » au niveau des éléments d’un StructArray avec une requête vectorielle au niveau de la collection, une requête « EmbeddingList » ou une requête au niveau des éléments sous un autre champ du StructArray, le champ d’application final des candidats est le niveau de l’entité. Dans ce cas, chaque « AnnSearchRequest » au niveau des éléments du StructArray est regroupée en candidats au niveau de l’entité avant le reclassement hybride.

Utilisez l’ element_scope à l’intérieur de l’ params de l’ AnnSearchRequest au niveau des éléments de StructArray lorsque vous devez contrôler la manière dont plusieurs éléments correspondants issus de la même entité sont regroupés.

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]",
    ],
)

Dans cet exemple, la stratégie de regroupement ( title_req ) s’applique au niveau de l’entité ; le résultat hybride final est donc également au niveau de l’entité. La requête « chunk_req » renvoie d’abord les occurrences d’éléments issues de l’ chunks[emb], puis regroupe les éléments renvoyés provenant de la même entité en additionnant les trois meilleurs scores d’éléments. Si l’attribut « element_scope » est omis alors qu’un regroupement au niveau de l’entité est nécessaire, la stratégie de regroupement par défaut est « max ».

Choisissez une stratégie de regroupement

StratégieComportementtopkExigence de métrique
maxConserver le meilleur score des éléments renvoyés pour l’entité.Non autorisé.Toute métrique vectorielle régulière prise en charge.
sumFaire la somme de tous les scores des éléments renvoyés pour l'entité.Non autorisé.Uniquement les métriques à corrélation positive, telles que IP ou COSINE.
avgCalculer la moyenne de tous les scores des éléments renvoyés pour l'entité.Non autorisé.Toute métrique vectorielle régulière prise en charge.
topk_sumFaites la somme des meilleurs scores des éléments renvoyés par K pour l’entité.Obligatoire et doit être positif.Uniquement les métriques à corrélation positive, telles que l'IP ou l'COSINE.
topk_avgCalculer la moyenne des meilleurs scores des éléments renvoyés par l'K pour l'entité.Obligatoire et doit être positif.Toute métrique vectorielle régulière prise en charge.

La fonction « Collapse » utilise uniquement les occurrences d’éléments renvoyées par cette AnnSearchRequest au niveau des éléments de StructArray. Elle n’analyse pas chaque élément Struct de l’entité après la recherche ANN. Définissez la limit de la requête à une valeur suffisamment élevée pour fournir les éléments que vous souhaitez rendre disponibles pour la fonction « Collapse ».

Ajouter des filtres, une recherche par plage et un regroupement

Vous pouvez associer des element_filter à une AnnSearchRequest au niveau des éléments de StructArray lorsque des conditions scalaires doivent s’appliquer aux mêmes éléments Struct participant à la recherche vectorielle. Vous pouvez également utiliser une filter de niveau supérieur sur hybrid_search() pour les conditions relatives à l’entité parente.

Les champs vectoriels au niveau des éléments de StructArray prennent en charge la recherche par plage dans le cadre d’une recherche hybride. Ajoutez des requêtes de type « radius » et, éventuellement, des requêtes de type « range_filter » à l’ AnnSearchRequest au niveau des éléments. Les requêtes StructArray au niveau d’EmbeddingList ne prennent pas en charge la recherche par plage.

Le regroupement hybride au niveau des éléments n’est pris en charge que lorsque tous les objets ` AnnSearchRequest ` ciblent des champs vectoriels au niveau des éléments appartenant au même champ `StructArray`, et que ` group_by_field ` doit être la clé primaire. Le regroupement hybride n’est pas pris en charge lorsque la requête mélange des champs vectoriels au niveau des collections, différents champs `StructArray` ou des requêtes au niveau `EmbeddingList`. Ne combinez pas la recherche par plage avec le regroupement.

Interpréter les résultats hybrides

Portée finale des candidatsClé de résultatComportement du décalageQuand cela se produit
Au niveau de l'entitéClé primaire.Aucun décalage d'élément dans le résultat final.La requête hybride inclut un champ vectoriel au niveau de la collection, une requête EmbeddingList ou des requêtes au niveau des éléments sous différents champs StructArray.
Niveau élémentClé primaire, champ StructArray parent et décalage de l'élément.Le décalage de l’élément sélectionné peut être renvoyé lorsqu’il est exposé par l’API ou le SDK.Tous les objets « AnnSearchRequest » sont au niveau des éléments et se trouvent sous le même champ StructArray.

Limitations

  • Utilisez « element_scope » uniquement pour les objets « AnnSearchRequest » au niveau des éléments de StructArray qui doivent être réduits à des candidats au niveau de l’entité dans le cadre d’une recherche hybride.

  • N’utilisez pas « element_scope » pour les requêtes EmbeddingList, les requêtes vectorielles au niveau de la collection ou la recherche hybride au niveau des éléments d’un même StructArray.

  • sum Les stratégies de regroupement « and » et « topk_sum » nécessitent des métriques de corrélation positive, telles que « IP » ou « COSINE ». Ne les utilisez pas avec « L2 ».

  • topk_sum et topk_avg nécessitent une valeur positive pour topk. Les autres stratégies de regroupement ne doivent pas inclure topk.

  • Les requêtes StructArray au niveau EmbeddingList ne prennent pas en charge la recherche par plage ni le regroupement.

  • Le regroupement hybride n’est pris en charge que pour la recherche hybride au niveau des éléments d’un même StructArray et uniquement par clé primaire.

  • Ne combinez pas la recherche par plage avec le regroupement.

Erreurs courantes

  • Ajouter « element_scope » à une requête hybride au niveau des éléments d’un même StructArray. Cette requête reste au niveau des éléments et n’effectue pas de regroupement au niveau des entités.

  • Ajouter des « element_scope » à une requête de type « chunks[emb_list_vector] ». La recherche «EmbeddingList» s’effectue déjà au niveau de l’entité.

  • Supposer que deux champs StructArray partagent les mêmes décalages d’éléments. L’ 3 décalé dans chunks et l’ 3 décalé dans un autre champ StructArray correspondent à des éléments différents ; la requête hybride devient donc de niveau entité.

  • Utilisation de topk_sum avec L2. Utilisez max, avg ou topk_avg pour les métriques de distance négatives.

  • Les résultats hybrides au niveau de l’entité devraient inclure le décalage de l’élément Struct sélectionné après réduction.

Étapes suivantes

  1. Pour découvrir les deux modes de recherche vectorielle de base avec StructArray, consultez la section « Recherche vectorielle de base avec StructArray ».

  2. Pour ajouter des filtres scalaires à la recherche hybride, consultez la section « Recherche filtrée avec StructArray ».

  3. Pour utiliser des limites de score ou de distance dans la recherche hybride, consultez la section « Recherche par plage avec StructArray ».

  4. Pour regrouper les résultats hybrides au niveau des éléments par entité parente, consultez la section « Recherche groupée avec StructArray ».

  5. Pour connaître les limites de recherche de StructArray, consultez la section « Limites de StructArray ».