Filtrage des métadonnées avec LlamaIndex et Milvus
Ce bloc-notes illustre l'utilisation du magasin vectoriel Milvus dans LlamaIndex, en se concentrant sur les capacités de filtrage des métadonnées. Vous apprendrez à indexer des documents avec des métadonnées, à effectuer des recherches vectorielles avec les filtres de métadonnées intégrés de LlamaIndex et à appliquer les expressions de filtrage natives de Milvus au magasin vectoriel.
A la fin de ce carnet, vous comprendrez comment utiliser les fonctions de filtrage de Milvus pour limiter les résultats de recherche en fonction des métadonnées des documents.
Conditions préalables
Installer les dépendances
Avant de commencer, assurez-vous que les dépendances suivantes sont installées :
$ pip install llama-index-vector-stores-milvus llama-index
Si vous utilisez Google Colab, il se peut que vous deviez redémarrer le runtime (Naviguez vers le menu "Runtime" en haut de l'interface, et sélectionnez "Restart session" dans le menu déroulant).
Configurer les comptes
Ce tutoriel utilise OpenAI pour l'intégration de texte et la génération de réponses. Vous devez préparer la clé API OpenAI.
import openai
openai.api_key = "sk-"
Pour utiliser le magasin de vecteurs Milvus, indiquez votre serveur Milvus URI (et éventuellement TOKEN). Pour démarrer un serveur Milvus, vous pouvez configurer un serveur Milvus en suivant le guide d'installation Milvus ou simplement en essayant Zilliz Cloud gratuitement.
URI = "./milvus_filter_demo.db" # Use Milvus-Lite for demo purpose
# TOKEN = ""
Préparer les données
Pour cet exemple, nous utiliserons quelques livres avec des titres similaires ou identiques mais des métadonnées différentes (auteur, genre et année de publication) comme échantillon de données. Cela permettra de démontrer comment Milvus peut filtrer et récupérer des documents en fonction de la similarité vectorielle et des attributs de métadonnées.
from llama_index.core.schema import TextNode
nodes = [
TextNode(
text="Life: A User's Manual",
metadata={
"author": "Georges Perec",
"genre": "Postmodern Fiction",
"year": 1978,
},
),
TextNode(
text="Life and Fate",
metadata={
"author": "Vasily Grossman",
"genre": "Historical Fiction",
"year": 1980,
},
),
TextNode(
text="Life",
metadata={
"author": "Keith Richards",
"genre": "Memoir",
"year": 2010,
},
),
TextNode(
text="The Life",
metadata={
"author": "Malcolm Knox",
"genre": "Literary Fiction",
"year": 2011,
},
),
]
Création d'un index
Dans cette section, nous stockerons des échantillons de données dans Milvus à l'aide du modèle d'intégration par défaut (OpenAI's text-embedding-ada-002). Les titres seront convertis en embeddings de texte et stockés dans un champ d'embedding dense, tandis que toutes les métadonnées seront stockées dans des champs scalaires.
from llama_index.vector_stores.milvus import MilvusVectorStore
from llama_index.core import StorageContext, VectorStoreIndex
vector_store = MilvusVectorStore(
uri=URI,
# token=TOKEN,
collection_name="test_filter_collection", # Change collection name here
dim=1536, # Vector dimension depends on the embedding model
overwrite=True, # Drop collection if exists
)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex(nodes, storage_context=storage_context)
2025-04-22 08:31:09,871 [DEBUG][_create_connection]: Created new connection using: 19675caa8f894772b3db175b65d0063a (async_milvus_client.py:547)
Filtres de métadonnées
Dans cette section, nous allons appliquer les filtres de métadonnées et les conditions intégrés de LlamaIndex à la recherche Milvus.
Définir les filtres de métadonnées
from llama_index.core.vector_stores import (
MetadataFilter,
MetadataFilters,
FilterOperator,
)
filters = MetadataFilters(
filters=[
MetadataFilter(
key="year", value=2000, operator=FilterOperator.GT
) # year > 2000
]
)
Récupération dans le magasin de vecteurs avec des filtres
retriever = index.as_retriever(filters=filters, similarity_top_k=5)
result_nodes = retriever.retrieve("Books about life")
for node in result_nodes:
print(node.text)
print(node.metadata)
print("\n")
The Life
{'author': 'Malcolm Knox', 'genre': 'Literary Fiction', 'year': 2011}
Life
{'author': 'Keith Richards', 'genre': 'Memoir', 'year': 2010}
Filtres de métadonnées multiples
Vous pouvez également combiner plusieurs filtres de métadonnées pour créer des requêtes plus complexes. LlamaIndex prend en charge les conditions AND et OR pour combiner les filtres. Cela permet une recherche plus précise et plus flexible des documents en fonction de leurs attributs de métadonnées.
Condition AND
Essayez un exemple de filtrage des livres publiés entre 1979 et 2010 (plus précisément, lorsque 1979 < année ≤ 2010) :
from llama_index.core.vector_stores import FilterCondition
filters = MetadataFilters(
filters=[
MetadataFilter(
key="year", value=1979, operator=FilterOperator.GT
), # year > 1979
MetadataFilter(
key="year", value=2010, operator=FilterOperator.LTE
), # year <= 2010
],
condition=FilterCondition.AND,
)
retriever = index.as_retriever(filters=filters, similarity_top_k=5)
result_nodes = retriever.retrieve("Books about life")
for node in result_nodes:
print(node.text)
print(node.metadata)
print("\n")
Life and Fate
{'author': 'Vasily Grossman', 'genre': 'Historical Fiction', 'year': 1980}
Life
{'author': 'Keith Richards', 'genre': 'Memoir', 'year': 2010}
Condition OR
Essayez un autre exemple qui filtre les livres écrits par Georges Perec ou Keith Richards :
filters = MetadataFilters(
filters=[
MetadataFilter(
key="author", value="Georges Perec", operator=FilterOperator.EQ
), # author is Georges Perec
MetadataFilter(
key="author", value="Keith Richards", operator=FilterOperator.EQ
), # author is Keith Richards
],
condition=FilterCondition.OR,
)
retriever = index.as_retriever(filters=filters, similarity_top_k=5)
result_nodes = retriever.retrieve("Books about life")
for node in result_nodes:
print(node.text)
print(node.metadata)
print("\n")
Life
{'author': 'Keith Richards', 'genre': 'Memoir', 'year': 2010}
Life: A User's Manual
{'author': 'Georges Perec', 'genre': 'Postmodern Fiction', 'year': 1978}
Utiliser les arguments de mots-clés de Milvus
Outre les capacités de filtrage intégrées, vous pouvez utiliser les expressions de filtrage natives de Milvus à l'aide de l'argument de mot-clé string_expr. Cela vous permet de transmettre des expressions de filtrage spécifiques directement à Milvus pendant les opérations de recherche, en allant au-delà du filtrage standard des métadonnées pour accéder aux capacités de filtrage avancées de Milvus.
Milvus offre des options de filtrage puissantes et flexibles qui permettent une interrogation précise de vos données vectorielles :
- Opérateurs de base : Opérateurs de comparaison, filtres de plage, opérateurs arithmétiques et opérateurs logiques.
- Modèles d'expression de filtre : Modèles prédéfinis pour les scénarios de filtrage les plus courants
- Opérateurs spécialisés : Opérateurs spécifiques au type de données pour les champs JSON ou les tableaux
Pour une documentation complète et des exemples d'expressions de filtrage Milvus, reportez-vous à la documentation officielle de Milvus Filtering.
retriever = index.as_retriever(
vector_store_kwargs={
"string_expr": "genre like '%Fiction'",
},
similarity_top_k=5,
)
result_nodes = retriever.retrieve("Books about life")
for node in result_nodes:
print(node.text)
print(node.metadata)
print("\n")
The Life
{'author': 'Malcolm Knox', 'genre': 'Literary Fiction', 'year': 2011}
Life and Fate
{'author': 'Vasily Grossman', 'genre': 'Historical Fiction', 'year': 1980}
Life: A User's Manual
{'author': 'Georges Perec', 'genre': 'Postmodern Fiction', 'year': 1978}