Metadaten-Filterung mit LlamaIndex und Milvus
Dieses Notizbuch veranschaulicht die Verwendung des Milvus-Vektorspeichers in LlamaIndex und konzentriert sich dabei auf die Möglichkeiten der Metadatenfilterung. Sie werden lernen, wie man Dokumente mit Metadaten indiziert, Vektorsuchen mit den in LlamaIndex eingebauten Metadatenfiltern durchführt und die nativen Filterausdrücke von Milvus auf den Vektorspeicher anwendet.
Am Ende dieses Notebooks werden Sie wissen, wie Sie die Filterfunktionen von Milvus nutzen können, um die Suchergebnisse auf der Grundlage von Dokument-Metadaten einzugrenzen.
Voraussetzungen
Abhängigkeiten installieren
Bevor Sie beginnen, stellen Sie sicher, dass Sie die folgenden Abhängigkeiten installiert haben:
$ pip install llama-index-vector-stores-milvus llama-index
Wenn Sie Google Colab verwenden, müssen Sie möglicherweise die Runtime neu starten (navigieren Sie zum Menü "Runtime" am oberen Rand der Benutzeroberfläche und wählen Sie "Sitzung neu starten" aus dem Dropdown-Menü).
Konten einrichten
Dieses Tutorial verwendet OpenAI für Texteinbettungen und die Generierung von Antworten. Sie müssen den OpenAI-API-Schlüssel vorbereiten.
import openai
openai.api_key = "sk-"
Um den Milvus-Vektorspeicher zu verwenden, geben Sie Ihren Milvus-Server URI (und optional mit der TOKEN) an. Um einen Milvus-Server zu starten, können Sie einen Milvus-Server einrichten, indem Sie die Milvus-Installationsanleitung befolgen oder einfach Zilliz Cloud kostenlos ausprobieren.
URI = "./milvus_filter_demo.db" # Use Milvus-Lite for demo purpose
# TOKEN = ""
Daten vorbereiten
Für dieses Beispiel werden wir einige Bücher mit ähnlichen oder identischen Titeln, aber unterschiedlichen Metadaten (Autor, Genre und Erscheinungsjahr) als Beispieldaten verwenden. Auf diese Weise lässt sich demonstrieren, wie Milvus Dokumente auf der Grundlage von Vektorähnlichkeit und Metadatenattributen filtern und abrufen kann.
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,
},
),
]
Index aufbauen
In diesem Abschnitt werden wir Beispieldaten in Milvus unter Verwendung des Standard-Einbettungsmodells (OpenAI's text-embedding-ada-002) speichern. Die Titel werden in Texteinbettungen umgewandelt und in einem dichten Einbettungsfeld gespeichert, während alle Metadaten in skalaren Feldern gespeichert werden.
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)
Metadaten-Filter
In diesem Abschnitt werden wir die in LlamaIndex integrierten Metadatenfilter und -bedingungen auf die Milvus-Suche anwenden.
Definieren von Metadatenfiltern
from llama_index.core.vector_stores import (
MetadataFilter,
MetadataFilters,
FilterOperator,
)
filters = MetadataFilters(
filters=[
MetadataFilter(
key="year", value=2000, operator=FilterOperator.GT
) # year > 2000
]
)
Abruf aus Vektorspeicher mit Filtern
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}
Mehrere Metadaten-Filter
Sie können auch mehrere Metadatenfilter kombinieren, um komplexere Abfragen zu erstellen. LlamaIndex unterstützt sowohl AND als auch OR Bedingungen, um Filter zu kombinieren. Dies ermöglicht eine präzisere und flexiblere Abfrage von Dokumenten auf der Grundlage ihrer Metadatenattribute.
Bedingung AND
Probieren Sie ein Beispiel aus, bei dem nach Büchern gefiltert wird, die zwischen 1979 und 2010 veröffentlicht wurden (insbesondere, wenn 1979 < Jahr ≤ 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}
Bedingung OR
Probieren Sie ein weiteres Beispiel aus, das Bücher filtert, die entweder von Georges Perec oder Keith Richards geschrieben wurden:
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}
Verwenden Sie die Schlüsselwortargumente von Milvus
Zusätzlich zu den eingebauten Filtermöglichkeiten können Sie die nativen Filterausdrücke von Milvus mit dem Schlüsselwortargument string_expr verwenden. Dies erlaubt Ihnen, spezifische Filterausdrücke während der Suchoperationen direkt an Milvus zu übergeben und so über die Standard-Metadatenfilterung hinaus auf die erweiterten Filterfähigkeiten von Milvus zuzugreifen.
Milvus bietet leistungsstarke und flexible Filtermöglichkeiten, die eine präzise Abfrage Ihrer Vektordaten ermöglichen:
- Grundlegende Operatoren: Vergleichsoperatoren, Bereichsfilter, arithmetische Operatoren und logische Operatoren
- Vorlagen für Filterausdrücke: Vordefinierte Muster für gängige Filterszenarien
- Spezialisierte Operatoren: Datentypspezifische Operatoren für JSON- oder Array-Felder
Eine umfassende Dokumentation und Beispiele für Milvus-Filterausdrücke finden Sie in der offiziellen Dokumentation von 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}