Фильтрация метаданных с помощью LlamaIndex и Milvus
Этот блокнот иллюстрирует использование векторного хранилища Milvus в LlamaIndex, уделяя особое внимание возможностям фильтрации метаданных. Вы узнаете, как индексировать документы с метаданными, выполнять векторный поиск с помощью встроенных в LlamaIndex фильтров метаданных и применять собственные выражения фильтрации Milvus к векторному хранилищу.
К концу этого блокнота вы поймете, как использовать функции фильтрации Milvus для сужения результатов поиска на основе метаданных документа.
Необходимые условия
Установка зависимостей
Прежде чем приступить к работе, убедитесь, что у вас установлены следующие зависимости:
$ pip install llama-index-vector-stores-milvus llama-index
Если вы используете Google Colab, вам может потребоваться перезапустить среду выполнения (перейдите в меню "Runtime" в верхней части интерфейса и выберите "Restart session" из выпадающего меню).
Настройка учетных записей
В этом учебнике используется OpenAI для встраивания текста и генерации ответов. Вам необходимо подготовить ключ API OpenAI.
import openai
openai.api_key = "sk-"
Чтобы использовать векторное хранилище Milvus, укажите свой сервер Milvus URI (и, по желанию, TOKEN). Чтобы запустить сервер Milvus, вы можете настроить его, следуя руководству по установке Milvus, или просто бесплатно попробовать Zilliz Cloud.
URI = "./milvus_filter_demo.db" # Use Milvus-Lite for demo purpose
# TOKEN = ""
Подготовьте данные
В этом примере мы будем использовать несколько книг с похожими или одинаковыми названиями, но разными метаданными (автор, жанр и год издания) в качестве образца данных. Это поможет продемонстрировать, как Milvus может фильтровать и извлекать документы на основе как векторного сходства, так и атрибутов метаданных.
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,
},
),
]
Построение индекса
В этом разделе мы сохраним образцы данных в Milvus, используя модель встраивания по умолчанию (OpenAI's text-embedding-ada-002). Заголовки будут преобразованы в текстовые вкрапления и сохранены в плотном поле вкраплений, а все метаданные будут сохранены в скалярных полях.
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)
Фильтры метаданных
В этом разделе мы применим встроенные в LlamaIndex фильтры метаданных и условия к поиску в Milvus.
Определение фильтров метаданных
from llama_index.core.vector_stores import (
MetadataFilter,
MetadataFilters,
FilterOperator,
)
filters = MetadataFilters(
filters=[
MetadataFilter(
key="year", value=2000, operator=FilterOperator.GT
) # year > 2000
]
)
Получение данных из векторного хранилища с помощью фильтров
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}
Несколько фильтров метаданных
Вы также можете комбинировать несколько фильтров метаданных для создания более сложных запросов. LlamaIndex поддерживает условия AND и OR для объединения фильтров. Это позволяет более точно и гибко находить документы на основе их атрибутов метаданных.
Условие AND
Попробуйте в качестве примера отфильтровать книги, опубликованные в период с 1979 по 2010 год (в частности, если 1979 < год ≤ 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}
Условие OR
Попробуйте другой пример, который фильтрует книги, написанные либо Жоржем Переком, либо Китом Ричардсом:
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}
Использование аргументов ключевых слов Milvus
В дополнение к встроенным возможностям фильтрации вы можете использовать собственные выражения фильтрации Milvus с помощью аргумента ключевого слова string_expr. Это позволяет передавать определенные выражения фильтрации непосредственно в Milvus во время поисковых операций, выходя за рамки стандартной фильтрации метаданных и получая доступ к расширенным возможностям фильтрации Milvus.
Milvus предоставляет мощные и гибкие возможности фильтрации, которые позволяют выполнять точные запросы к векторным данным:
- Основные операторы: Операторы сравнения, фильтры диапазонов, арифметические операторы и логические операторы.
- Шаблоны выражений фильтрации: Предопределенные шаблоны для распространенных сценариев фильтрации
- Специализированные операторы: Операторы, специфичные для типов данных, для полей JSON или массивов.
Для получения полной документации и примеров использования выражений фильтрации Milvus обратитесь к официальной документации 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}