Milvus
Zilliz
  • Home
  • Blog
  • Déverrouiller la recherche au niveau de l'entité : Nouvelles capacités de tableaux de structures et de MAX_SIM dans Milvus

Déverrouiller la recherche au niveau de l'entité : Nouvelles capacités de tableaux de structures et de MAX_SIM dans Milvus

  • Engineering
December 05, 2025
Jeremy Zhu, Min Tian

Si vous avez développé des applications d'intelligence artificielle à partir de bases de données vectorielles, vous avez probablement rencontré le même problème : la base de données récupère les encastrements de morceaux individuels, alors que votre application se préoccupe des entités. Ce décalage rend l'ensemble du flux de travail de récupération complexe.

Vous avez probablement vu cette situation se répéter à maintes reprises :

  • Bases de connaissances RAG : Les articles sont découpés en fragments de paragraphes, de sorte que le moteur de recherche renvoie des fragments épars au lieu du document complet.

  • Recommandation pour le commerce électronique : Un produit a plusieurs images intégrées, et votre système renvoie cinq angles du même article au lieu de cinq produits uniques.

  • Plateformes vidéo : Les vidéos sont divisées en clips intégrés, mais les résultats de recherche font apparaître des tranches de la même vidéo plutôt qu'une seule entrée consolidée.

  • Recherche de type ColBERT / ColPali : Les documents s'étendent sur des centaines de jetons ou de patchs, et vos résultats apparaissent sous forme de minuscules morceaux qui doivent encore être fusionnés.

Tous ces problèmes découlent de la même lacune architecturale: la plupart des bases de données vectorielles traitent chaque intégration comme une ligne isolée, alors que les applications réelles opèrent sur des entités de plus haut niveau - documents, produits, vidéos, articles, scènes. Par conséquent, les équipes d'ingénieurs sont obligées de reconstruire les entités manuellement en utilisant la logique de déduplication, de regroupement, de mise en bacs et de reclassement. Cela fonctionne, mais c'est fragile, lent et gonfle votre couche d'application avec une logique qui n'aurait jamais dû s'y trouver.

Milvus 2.6.4 comble cette lacune avec une nouvelle fonctionnalité : Les tableaux de structures avec le type métrique MAX_SIM. Ensemble, ils permettent à tous les embeddings d'une même entité d'être stockés dans un seul enregistrement et permettent à Milvus de noter et de renvoyer l'entité de manière holistique. Finis les ensembles de résultats remplis en double. Plus de post-traitement complexe comme le reranking et la fusion.

Dans cet article, nous verrons comment fonctionnent les tableaux de structures et MAX_SIM, et nous les démontrerons à l'aide de deux exemples réels : La recherche de documents dans Wikipédia et la recherche de documents basée sur des images dans ColPali.

Qu'est-ce qu'un tableau de structures ?

Dans Milvus, un champ Tableau de structures permet à un enregistrement unique de contenir une liste ordonnée d'éléments Struct, chacun suivant le même schéma prédéfini. Une structure peut contenir plusieurs vecteurs ainsi que des champs scalaires, des chaînes de caractères ou tout autre type pris en charge. En d'autres termes, elle vous permet de regrouper tous les éléments appartenant à une entité - enchâssements de paragraphes, vues d'images, vecteurs de jetons, métadonnées - directement à l'intérieur d'une ligne.

Voici un exemple d'entité issue d'une collection qui contient un champ Array of Structs.

{
    'id': 0,
    'title': 'Walden',
    'title_vector': [0.1, 0.2, 0.3, 0.4, 0.5],
    'author': 'Henry David Thoreau',
    'year_of_publication': 1845,
    // highlight-start
    'chunks': [
        {
            'text': 'When I wrote the following pages, or rather the bulk of them...',
            'text_vector': [0.3, 0.2, 0.3, 0.2, 0.5],
            'chapter': 'Economy',
        },
        {
            'text': 'I would fain say something, not so much concerning the Chinese and...',
            'text_vector': [0.7, 0.4, 0.2, 0.7, 0.8],
            'chapter': 'Economy'
        }
    ]
    // hightlight-end
}

Dans l'exemple ci-dessus, le champ chunks est un champ de type tableau de structures, et chaque élément de structure contient ses propres champs, à savoir text, text_vector et chapter.

Cette approche résout un problème de modélisation de longue date dans les bases de données vectorielles. Traditionnellement, chaque intégration ou attribut doit devenir sa propre ligne, ce qui oblige les entités multi-vectorielles (documents, produits, vidéos) à être divisées en dizaines, centaines, voire milliers d'enregistrements. Avec les tableaux de structures, Milvus vous permet de stocker l'ensemble de l'entité multivectorielle dans un seul champ, ce qui en fait une solution naturelle pour les listes de paragraphes, les incorporations de jetons, les séquences de clips, les images multivues ou tout autre scénario dans lequel un élément logique est composé de plusieurs vecteurs.

Comment fonctionne un tableau de structures avec MAX_SIM ?

Au-dessus de cette nouvelle structure de tableaux de structures se trouve MAX_SIM, une nouvelle stratégie de notation qui rend la recherche sémantique consciente des entités. Lorsqu'une requête arrive, Milvus la compare à chaque vecteur à l'intérieur de chaque tableau de structures et prend la similarité maximale comme score final de l'entité. L'entité est ensuite classée et renvoyée en fonction de ce score unique. Cela permet d'éviter le problème classique des bases de données vectorielles qui consiste à récupérer des fragments dispersés et à transférer la charge du regroupement, de la déduplication et du reclassement dans la couche applicative. Avec MAX_SIM, la recherche au niveau de l'entité devient intégrée, cohérente et efficace.

Pour comprendre comment MAX_SIM fonctionne en pratique, examinons un exemple concret.

Note : Tous les vecteurs de cet exemple sont générés par le même modèle d'intégration, et la similarité est mesurée par la similarité cosinus dans l'intervalle [0,1].

Supposons qu'un utilisateur recherche un "cours d'apprentissage automatique pour débutants".

La requête est transformée en trois jetons:

  • Apprentissage automatique

  • débutant

  • cours

Chacun de ces tokens est ensuite converti en un vecteur d'intégration par le même modèle d'intégration que celui utilisé pour les documents.

Imaginons maintenant que la base de données vectorielle contienne deux documents :

  • doc_1 : Guide d'introduction aux réseaux neuronaux profonds avec Python

  • doc_2 : Guide avancé de lecture d'articles de LLM

Les deux documents ont été intégrés dans des vecteurs et stockés dans un tableau de structures.

Étape 1 : Calcul de MAX_SIM pour doc_1

Pour chaque vecteur de requête, Milvus calcule sa similarité en cosinus par rapport à chaque vecteur dans doc_1 :

Introductionguideréseaux neuronaux profondspython
apprentissage automatique0.00.00.90.3
débutant0.80.10.00.3
cours0.30.70.10.1

Pour chaque vecteur de requête, MAX_SIM sélectionne la similarité la plus élevée dans sa ligne :

  • apprentissage automatique → réseaux neuronaux profonds (0.9)

  • débutant → introduction (0.8)

  • cours → guide (0.7)

La somme des meilleures correspondances donne à doc_1 un score MAX_SIM de 2,4.

Étape 2 : Calculer le score MAX_SIM pour doc_2

Nous répétons maintenant le processus pour le document_2 :

avancéguideLLMpapierlecture
apprentissage automatique0.10.20.90.30.1
débutant0.40.60.00.20.5
cours0.50.80.10.40.7

Les meilleures correspondances pour doc_2 sont :

  • "machine learning" → "LLM" (0.9)

  • "débutant" → "guide" (0.6)

  • "cours" → "guide" (0.8)

La somme de ces scores donne à doc_2 un score MAX_SIM de 2,3.

Étape 3 : Comparer les scores

Parce que 2,4 > 2,3, doc_1 est mieux classé que doc_2, ce qui est intuitivement logique, puisque doc_1 est plus proche d'un guide d'introduction à l'apprentissage automatique.

Cet exemple nous permet de mettre en évidence trois caractéristiques essentielles de MAX_SIM :

  • Sémantique d'abord, et non basée sur des mots-clés : MAX_SIM compare des embeddings, et non des textes littéraux. Même si "machine learning" et "deep neural networks" ne partagent aucun mot qui se chevauche, leur similarité sémantique est de 0,9. MAX_SIM est donc résistant aux synonymes, aux paraphrases, aux chevauchements conceptuels et aux charges de travail modernes riches en embeddings.

  • Insensible à la longueur et à l'ordre : MAX_SIM n'exige pas que la requête et le document aient le même nombre de vecteurs (par exemple, doc_1 a 4 vecteurs tandis que doc_2 en a 5, et les deux fonctionnent bien). Il ne tient pas compte non plus de l'ordre des vecteurs : le fait que "débutant" apparaisse plus tôt dans la requête et que "introduction" apparaisse plus tard dans le document n'a aucun impact sur le score.

  • Chaque vecteur de la requête est important : MAX_SIM prend la meilleure correspondance pour chaque vecteur de requête et additionne les meilleurs scores. Cela permet d'éviter que des vecteurs non appariés ne faussent le résultat et de s'assurer que chaque élément important de la requête contribue au score final. Par exemple, la correspondance de moindre qualité pour "débutant" dans doc_2 réduit directement son score global.

Pourquoi MAX_SIM + tableau de structures sont-ils importants dans une base de données vectorielle ?

Milvus est une base de données vectorielle open-source très performante qui prend désormais entièrement en charge MAX_SIM et Array of Structs, ce qui permet une recherche multi-vectorielle native au niveau de l'entité :

  • Stockez des entités multi-vectorielles de manière native : Array of Structs vous permet de stocker des groupes de vecteurs apparentés dans un seul champ sans les répartir dans des lignes distinctes ou des tables auxiliaires.

  • Calcul efficace de la meilleure correspondance : Combiné avec des index vectoriels tels que IVF et HNSW, MAX_SIM peut calculer les meilleures correspondances sans analyser chaque vecteur, ce qui permet de maintenir des performances élevées même avec des documents volumineux.

  • Conçu pour les charges de travail à forte composante sémantique : Cette approche excelle dans la recherche de textes longs, l'appariement sémantique multi-facettes, l'alignement document-résumé, les requêtes multi-mots clés et d'autres scénarios d'IA qui nécessitent un raisonnement sémantique flexible et fin.

Quand utiliser un tableau de structures ?

La valeur d'un tableau de structures apparaît clairement lorsque l'on examine ce qu'il permet de faire. À la base, cette fonctionnalité offre trois capacités fondamentales :

  • Elle regroupe des données hétérogènes - vecteurs, scalaires, chaînes, métadonnées - en un seul objet structuré.

  • Elle aligne le stockage sur les entités du monde réel, de sorte que chaque ligne de la base de données correspond clairement à un élément réel tel qu'un article, un produit ou une vidéo.

  • Associé à des fonctions d'agrégation telles que MAX_SIM, il permet une véritable extraction multi-vectorielle au niveau de l'entité, directement à partir de la base de données, ce qui élimine la déduplication, le regroupement ou le reclassement au niveau de la couche applicative.

En raison de ces propriétés, le tableau de structures est une solution naturelle lorsqu'une seule entité logique est représentée par plusieurs vecteurs. Parmi les exemples courants, citons les articles divisés en paragraphes, les documents décomposés en jetons ou les produits représentés par plusieurs images. Si vos résultats de recherche souffrent de doublons, de fragments dispersés ou d'une même entité apparaissant plusieurs fois dans les premiers résultats, les tableaux de structures résolvent ces problèmes au niveau de la couche de stockage et d'extraction, et non par le biais de correctifs apportés après coup dans le code de l'application.

Ce modèle est particulièrement puissant pour les systèmes d'intelligence artificielle modernes qui s'appuient sur la recherche multi-vectorielle. Par exemple :

  • ColBERT représente un document unique sous la forme de 100 à 500 encastrements de jetons pour une correspondance sémantique fine dans des domaines tels que les textes juridiques et la recherche universitaire.

  • ColPali convertit chaque page PDF en 256-1024 patchs d'images pour la recherche multimodale dans les états financiers, les contrats, les factures et d'autres documents numérisés.

Un tableau de Structs permet à Milvus de stocker tous ces vecteurs sous une seule entité et de calculer la similarité agrégée (par exemple, MAX_SIM) de manière efficace et native. Pour que cela soit plus clair, voici deux exemples concrets.

Auparavant, les produits comportant plusieurs images étaient stockés dans un schéma plat - une image par ligne. Un produit avec des photos de face, de côté et de biais produisait trois lignes. Les résultats de recherche renvoyaient souvent plusieurs images du même produit, ce qui nécessitait un dédoublonnage et un reclassement manuels.

Avec un tableau de structures, chaque produit devient une ligne. Toutes les incrustations d'images et les métadonnées (angle, is_primary, etc.) se trouvent dans un champ images sous la forme d'un tableau de structures. Milvus comprend qu'ils appartiennent au même produit et renvoie le produit dans son ensemble, et non ses images individuelles.

Auparavant, un article unique de Wikipedia était divisé en N lignes de paragraphes. Les résultats de la recherche renvoyaient des paragraphes dispersés, obligeant le système à les regrouper et à deviner à quel article ils appartenaient.

Avec un tableau de structures, l'article entier devient une seule ligne. Tous les paragraphes et leurs liens sont regroupés dans un champ paragraphes, et la base de données renvoie l'article complet, et non des morceaux fragmentés.

Didacticiels pratiques : Recherche au niveau du document avec le tableau de structures

1. Recherche de documents dans Wikipédia

Dans ce tutoriel, nous verrons comment utiliser un tableau de structures pour convertir des données de niveau paragraphe en enregistrements de documents complets, ce qui permet à Milvus d'effectuer une véritable recherche au niveau du document plutôt que de renvoyer des fragments isolés.

De nombreux pipelines de bases de connaissances stockent les articles de Wikipédia sous forme de morceaux de paragraphes. Cela fonctionne bien pour l'intégration et l'indexation, mais cela nuit à la recherche : une requête utilisateur renvoie généralement des paragraphes dispersés, ce qui vous oblige à regrouper et à reconstruire manuellement l'article. Avec un tableau de structures et MAX_SIM, nous pouvons redéfinir le schéma de stockage de sorte que chaque article devienne une ligne et que Milvus puisse classer et renvoyer l'ensemble du document de manière native.

Dans les étapes suivantes, nous allons montrer comment :

  1. Charger et prétraiter les données des paragraphes de Wikipédia

  2. Regrouper tous les paragraphes appartenant au même article dans un tableau de structures

  3. Insérer ces documents structurés dans Milvus

  4. Exécuter des requêtes MAX_SIM pour récupérer des articles complets, proprement, sans déduplication ni reclassement.

À la fin de ce tutoriel, vous disposerez d'un pipeline fonctionnel dans lequel Milvus gère directement l'extraction au niveau de l'entité, exactement comme l'attendent les utilisateurs.

Modèle de données :

{
    "wiki_id": int,                  # WIKI ID(primary key) 
    "paragraphs": ARRAY<STRUCT<      # Array of paragraph structs
        text:VARCHAR                 # Paragraph text
        emb: FLOAT_VECTOR(768)       # Embedding for each paragraph
    >>
}

Étape 1 : Grouper et transformer les données

Pour cette démo, nous utilisons l'ensemble de données Simple Wikipedia Embeddings.

import pandas as pd
import pyarrow as pa

# Load the dataset and group by wiki_id df = pd.read_parquet(“train-*.parquet”) grouped = df.groupby(‘wiki_id’)

# Build the paragraph array for each article wiki_data = [] for wiki_id, group in grouped: wiki_data.append({ ‘wiki_id’: wiki_id, ‘paragraphs’: [{‘text’: row[‘text’], ‘emb’: row[‘emb’]} for _, row in group.iterrows()] })

Étape 2 : Création de la collection Milvus

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri=“http://localhost:19530”) schema = client.create_schema() schema.add_field(“wiki_id”, DataType.INT64, is_primary=True)

# Define the Struct schema struct_schema = client.create_struct_field_schema() struct_schema.add_field(“text”, DataType.VARCHAR, max_length=65535) struct_schema.add_field(“emb”, DataType.FLOAT_VECTOR, dim=768)

schema.add_field(“paragraphs”, DataType.ARRAY, element_type=DataType.STRUCT, struct_schema=struct_schema, max_capacity=200)

client.create_collection(“wiki_docs”, schema=schema)

Étape 3 : Insérer les données et créer un index

# Batch insert documents
client.insert("wiki_docs", wiki_data)

# Create an HNSW index index_params = client.prepare_index_params() index_params.add_index( field_name="paragraphs[emb]", index_type=“HNSW”, metric_type=“MAX_SIM_COSINE”, params={“M”: 16, “efConstruction”: 200} ) client.create_index(“wiki_docs”, index_params) client.load_collection(“wiki_docs”)

Étape 4 : Recherche de documents

# Search query
import cohere
from pymilvus.client.embedding_list import EmbeddingList

# The dataset uses Cohere’s multilingual-22-12 embedding model, so we must embed the query using the same model. co = cohere.Client(f"<>") query = ‘Who founded Youtube’ response = co.embed(texts=[query], model=‘multilingual-22-12’) query_embedding = response.embeddings query_emb_list = EmbeddingList()

for vec in query_embedding[0]: query_emb_list.add(vec)

results = client.search( collection_name=“wiki_docs”, data=[query_emb_list], anns_field="paragraphs[emb]", search_params={ “metric_type”: “MAX_SIM_COSINE”, “params”: {“ef”: 200, “retrieval_ann_ratio”: 3} }, limit=10, output_fields=[“wiki_id”] )

# Results: directly return 10 full articles! for hit in results[0]: print(f"Article {hit[‘entity’][‘wiki_id’]}: Score {hit[‘distance’]:.4f}")

Comparaison des résultats : Recherche traditionnelle et tableau de structures

L'impact du tableau de structures apparaît clairement lorsque nous examinons ce que la base de données renvoie réellement :

DimensionApproche traditionnelleTableau de structures
Résultats de la base de donnéesRenvoie les 100 premiers paragraphes (redondance élevée)Renvoie les 10 premiers documents complets - propres et précis
Logique d'applicationNécessite le regroupement, la déduplication et le reclassement (complexe)Aucun post-traitement n'est nécessaire - les résultats au niveau de l'entité proviennent directement de Milvus.

Dans l'exemple de Wikipedia, nous n'avons démontré que le cas le plus simple : combiner les vecteurs de paragraphes dans une représentation unifiée du document. Mais la véritable force de Array of Structs est qu'il se généralise à n'importe quel modèle de données multivectorielles, qu'il s'agisse de pipelines de recherche classiques ou d'architectures d'IA modernes.

Scénarios traditionnels de recherche multivectorielle

De nombreux systèmes de recherche et de recommandation bien établis fonctionnent naturellement sur des entités ayant plusieurs vecteurs associés. Les tableaux de structures s'adaptent parfaitement à ces cas d'utilisation :

ScénarioModèle de donnéesVecteurs par entité
🛍️ Produits de commerce électroniqueUn produit → plusieurs images5-20
🎬 Recherche vidéoUne vidéo → plusieurs clips20-100
📖 Recherche de documentsUn document → plusieurs sections5-15

Charges de travail des modèles d'IA (principaux cas d'utilisation multisectoriels)

Les tableaux de structures deviennent encore plus critiques dans les modèles d'IA modernes qui produisent intentionnellement de grands ensembles de vecteurs par entité pour un raisonnement sémantique fin.

ModèleModèle de donnéesVecteurs par entitéApplication
ColBERTUn document → plusieurs encastrements de jetons100-500Textes juridiques, articles académiques, recherche de documents à grain fin
ColPaliUne page PDF → plusieurs encastrements de patchs256-1024Rapports financiers, contrats, factures, recherche multimodale de documents

Ces modèles nécessitent un modèle de stockage multi-vecteur. Avant Array of Structs, les développeurs devaient diviser les vecteurs en plusieurs lignes et recoudre manuellement les résultats. Avec Milvus, ces entités peuvent désormais être stockées et récupérées de manière native, MAX_SIM gérant automatiquement la notation au niveau du document.

ColPali est un modèle puissant pour la recherche multimodale de documents PDF. Au lieu de s'appuyer sur le texte, il traite chaque page PDF comme une image et la découpe en un maximum de 1024 patchs visuels, en générant un embedding par patch. Dans un schéma de base de données traditionnel, une page unique devrait être stockée sous la forme de centaines ou de milliers de lignes distinctes, ce qui empêcherait la base de données de comprendre que ces lignes appartiennent à la même page. Par conséquent, la recherche au niveau de l'entité devient fragmentée et peu pratique.

Array of Structs résout ce problème en stockant tous les patchs dans un seul champ, ce qui permet à Milvus de traiter la page comme une entité multi-vectorielle cohérente.

La recherche traditionnelle dans les PDF dépend souvent de l'OCR, qui convertit les images des pages en texte. Cette méthode fonctionne pour le texte brut, mais perd les graphiques, les tableaux, la mise en page et d'autres indices visuels. ColPali évite cette limitation en travaillant directement sur les images des pages, en préservant toutes les informations visuelles et textuelles. La contrepartie est l'échelle : chaque page contient désormais des centaines de vecteurs, ce qui nécessite une base de données capable d'agréger de nombreux embeddings en une seule entité - exactement ce que fournit Array of Structs + MAX_SIM.

Le cas d'utilisation le plus courant est Vision RAG, où chaque page PDF devient une entité multi-vecteur. Les scénarios typiques sont les suivants

  • Rapports financiers : recherche dans des milliers de PDF de pages contenant des graphiques ou des tableaux spécifiques.

  • Contrats : recherche de clauses dans des documents juridiques scannés ou photographiés.

  • Factures : recherche de factures par fournisseur, montant ou présentation.

  • Présentations : recherche de diapositives contenant une figure ou un diagramme particulier.

Modèle de données :

{
    "page_id": int,                     # Page ID (primary key) 
    "page_number": int,                 # Page number within the document 
    "doc_name": VARCHAR,                # Document name
    "patches": ARRAY<STRUCT<            # Array of patch objects
        patch_embedding: FLOAT_VECTOR(128)  # Embedding for each patch
    >>
}

Etape 1 : Préparer les donnéesVous pouvez vous référer à la documentation pour plus de détails sur la façon dont ColPali convertit les images ou le texte en représentations multi-vectorielles.

import torch
from PIL import Image

from colpali_engine.models import ColPali, ColPaliProcessor

model_name = “vidore/colpali-v1.3”

model = ColPali.from_pretrained( model_name, torch_dtype=torch.bfloat16, device_map=“cuda:0”, # or “mps” if on Apple Silicon ).eval()

processor = ColPaliProcessor.from_pretrained(model_name) # Example: 2 documents, 5 pages each, total 10 images images = [ Image.open(“path/to/your/image1.png”), Image.open(“path/to/your/image2.png”), … Image.open(“path/to/your/image10.png”) ] # Convert each image into multiple patch embeddings batch_images = processor.process_images(images).to(model.device) with torch.no_grad(): image_embeddings = model(**batch_images)

Étape 2 : Créer la collection Milvus

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri=“http://localhost:19530”) schema = client.create_schema() schema.add_field(“page_id”, DataType.INT64, is_primary=True) schema.add_field(“page_number”, DataType.INT64) schema.add_field(“doc_name”, DataType.VARCHAR, max_length=500)

# Struct Array for patches struct_schema = client.create_struct_field_schema() struct_schema.add_field(“patch_embedding”, DataType.FLOAT_VECTOR, dim=128)

schema.add_field(“patches”, DataType.ARRAY, element_type=DataType.STRUCT, struct_schema=struct_schema, max_capacity=2048)

client.create_collection(“doc_pages”, schema=schema)

Étape 3 : Insérer les données et créer un index

# Prepare data for insertion
page_data=[
    {
        "page_id": 0,
        "page_number": 0,
        "doc_name": "Q1_Financial_Report.pdf",
        "patches": [
            {"patch_embedding": emb} for emb in image_embeddings[0]
        ],
    },
    ...,
    {
        "page_id": 9,
        "page_number": 4,
        "doc_name": "Product_Manual.pdf",
        "patches": [
            {"patch_embedding": emb} for emb in image_embeddings[9]
        ],
    },
]

client.insert(“doc_pages”, page_data)

# Create index index_params = client.prepare_index_params() index_params.add_index( field_name="patches[patch_embedding]", index_type=“HNSW”, metric_type=“MAX_SIM_IP”, params={“M”: 32, “efConstruction”: 200} ) client.create_index(“doc_pages”, index_params) client.load_collection(“doc_pages”)

Étape 4 : Recherche multimodale : Requête textuelle → Résultats d'images

# Run the search
from pymilvus.client.embedding_list import EmbeddingList

queries = [ “quarterly revenue growth chart”
] # Convert the text query into a multi-vector representation batch_queries = processor.process_queries(queries).to(model.device) with torch.no_grad(): query_embeddings = model(**batch_queries)

query_emb_list = EmbeddingList() for vec in query_embeddings[0]: query_emb_list.add(vec) results = client.search( collection_name=“doc_pages”, data=[query_emb_list], anns_field="patches[patch_embedding]", search_params={ “metric_type”: “MAX_SIM_IP”, “params”: {“ef”: 100, “retrieval_ann_ratio”: 3} }, limit=3, output_fields=[“page_id”, “doc_name”, “page_number”] )

print(f"Query: '{queries[0]}'") for i, hit in enumerate(results, 1): entity = hit[‘entity’] print(f"{i}. {entity[‘doc_name’]} - Page {entity[‘page_number’]}") print(f" Score: {hit[‘distance’]:.4f}\n")

Exemple de résultat :

Query: 'quarterly revenue growth chart'
1. Q1_Financial_Report.pdf - Page 2
   Score: 0.9123

2. Q1_Financial_Report.pdf - Page 1 Score: 0.7654

3. Product_Manual.pdf - Page 1 Score: 0.5231

Ici, les résultats renvoient directement des pages PDF complètes. Nous n'avons pas à nous préoccuper de l'intégration des 1024 patchs sous-jacents, car Milvus se charge automatiquement de l'agrégation.

Conclusion

La plupart des bases de données vectorielles stockent chaque fragment comme un enregistrement indépendant, ce qui signifie que les applications doivent réassembler ces fragments lorsqu'elles ont besoin d'un document, d'un produit ou d'une page complète. Un tableau de Structs change la donne. En combinant des scalaires, des vecteurs, du texte et d'autres champs en un seul objet structuré, il permet à une ligne de base de données de représenter une entité complète de bout en bout.

Le résultat est simple mais puissant : le travail qui nécessitait auparavant des opérations complexes de regroupement, de déduplication et de reclassement dans la couche applicative devient une capacité native de la base de données. Et c'est exactement vers cela que se dirige l'avenir des bases de données vectorielles : des structures plus riches, une récupération plus intelligente et des pipelines plus simples.

Pour plus d'informations sur les tableaux de structures et MAX_SIM, consultez la documentation ci-dessous :

Vous avez des questions ou souhaitez approfondir une fonctionnalité de la dernière version de Milvus ? Rejoignez notre canal Discord ou déposez des questions sur GitHub. Vous pouvez également réserver une session individuelle de 20 minutes pour obtenir des informations, des conseils et des réponses à vos questions dans le cadre des Milvus Office Hours.

    Try Managed Milvus for Free

    Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

    Get Started

    Like the article? Spread the word

    Continuer à Lire