Filtraggio dei metadati con LlamaIndex e Milvus
Questo quaderno illustra l'uso dell'archivio vettoriale Milvus in LlamaIndex, concentrandosi sulle capacità di filtraggio dei metadati. Imparerete a indicizzare i documenti con metadati, a eseguire ricerche vettoriali con i filtri di metadati integrati in LlamaIndex e ad applicare le espressioni di filtraggio native di Milvus all'archivio vettoriale.
Alla fine di questo quaderno, capirete come utilizzare le funzioni di filtraggio di Milvus per restringere i risultati delle ricerche in base ai metadati dei documenti.
Prerequisiti
Installare le dipendenze
Prima di iniziare, assicuratevi di aver installato le seguenti dipendenze:
$ pip install llama-index-vector-stores-milvus llama-index
Se si utilizza Google Colab, potrebbe essere necessario riavviare il runtime (andare al menu "Runtime" nella parte superiore dell'interfaccia e selezionare "Riavvia sessione" dal menu a discesa).
Impostazione degli account
Questa esercitazione utilizza OpenAI per l'incorporazione del testo e la generazione delle risposte. È necessario preparare la chiave API di OpenAI.
import openai
openai.api_key = "sk-"
Per utilizzare l'archivio vettoriale Milvus, specificare il server Milvus URI (e facoltativamente TOKEN). Per avviare un server Milvus, è possibile configurarlo seguendo la guida all'installazione di Milvus o semplicemente provando gratuitamente Zilliz Cloud.
URI = "./milvus_filter_demo.db" # Use Milvus-Lite for demo purpose
# TOKEN = ""
Preparare i dati
Per questo esempio, utilizzeremo alcuni libri con titoli simili o identici ma con metadati diversi (autore, genere e anno di pubblicazione) come dati campione. In questo modo dimostreremo come Milvus possa filtrare e recuperare i documenti in base alla somiglianza vettoriale e agli attributi dei metadati.
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,
},
),
]
Costruire l'indice
In questa sezione, memorizzeremo i dati di esempio in Milvus utilizzando il modello di incorporamento predefinito ( text-embedding-ada-002 di OpenAI). I titoli saranno convertiti in embedding di testo e memorizzati in un campo di embedding denso, mentre tutti i metadati saranno memorizzati in campi scalari.
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)
Filtri dei metadati
In questa sezione, applicheremo i filtri di metadati e le condizioni di LlamaIndex alla ricerca di Milvus.
Definire i filtri dei metadati
from llama_index.core.vector_stores import (
MetadataFilter,
MetadataFilters,
FilterOperator,
)
filters = MetadataFilters(
filters=[
MetadataFilter(
key="year", value=2000, operator=FilterOperator.GT
) # year > 2000
]
)
Recupero dall'archivio vettoriale con i filtri
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}
Filtri multipli per i metadati
È anche possibile combinare più filtri di metadati per creare query più complesse. LlamaIndex supporta sia le condizioni AND che OR per combinare i filtri. Ciò consente di recuperare in modo più preciso e flessibile i documenti in base ai loro attributi di metadati.
Condizione AND
Proviamo a fare un esempio di filtro per i libri pubblicati tra il 1979 e il 2010 (in particolare, dove 1979 < anno ≤ 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}
Condizione OR
Provate un altro esempio che filtra i libri scritti da Georges Perec o 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}
Utilizzare gli argomenti delle parole chiave di Milvus
Oltre alle funzionalità di filtraggio integrate, è possibile utilizzare le espressioni di filtraggio native di Milvus con l'argomento parola chiave string_expr. Ciò consente di passare espressioni di filtro specifiche direttamente a Milvus durante le operazioni di ricerca, andando oltre il filtraggio standard dei metadati per accedere alle capacità di filtraggio avanzate di Milvus.
Milvus offre opzioni di filtraggio potenti e flessibili che consentono di interrogare con precisione i dati vettoriali:
- Operatori di base: Operatori di confronto, filtri di intervallo, operatori aritmetici e operatori logici.
- Modelli di espressione di filtro: Modelli predefiniti per gli scenari di filtraggio più comuni.
- Operatori specializzati: Operatori specifici per tipo di dati per campi JSON o array
Per una documentazione completa ed esempi di espressioni di filtraggio Milvus, consultare la documentazione ufficiale di 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}