Milvus向量存储 - 元数据过滤器
本笔记本展示了如何在LlamaIndex中使用Milvus向量数据库,重点介绍元数据过滤功能。您将学习如何使用元数据索引文档,通过LlamaIndex内置的元数据过滤器执行向量搜索,以及向向量数据库应用Milvus原生过滤表达式。
在本笔记本结束时,您将了解如何利用 Milvus 的过滤功能,根据文档元数据来缩小搜索结果范围。
安装依赖项
在开始之前,请确保已安装以下依赖项:
! pip install llama-index-vector-stores-milvus llama-indexIf you’re using Google Colab, you may need to restart the runtime (Navigate to the “Runtime” menu at the top of the interface, and select “Restart session” from the dropdown menu.)
设置账户
This tutorial uses OpenAI for text embeddings and answer generation. You need to prepare the OpenAI API key.
import openai
openai.api_key = "sk-"To use the Milvus vector store, specify your Milvus server URI (and optionally with the TOKEN). To start a Milvus server, you can set up a Milvus server by following the Milvus installation guide or simply trying Zilliz Cloud for free.
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, }, ),]在本节中,我们将使用默认的嵌入模型(OpenAI的text-embedding-ada-002)将示例数据存储到Milvus中。标题将被转换为文本嵌入并存储在稠密嵌入字段中,而所有元数据将存储在标量字段中。
from llama_index.vector_stores.milvus import MilvusVectorStorefrom 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 的关键字参数
Section titled “Use Milvus’s Keyword Arguments”除了内置的过滤功能外,您还可以通过 string_expr 关键字参数使用 Milvus 的原生过滤表达式。这使您能够在搜索操作期间直接将特定过滤表达式传递给 Milvus,超越标准元数据过滤以访问 Milvus 的高级过滤功能。
Milvus 提供强大而灵活的过滤选项,使您能够精确查询向量数据:
- 基础运算符:比较运算符、范围筛选器、算术运算符和逻辑运算符
- 筛选表达式模板:用于常见筛选场景的预定义模式
- 专用运算符:针对 JSON 或数组字段的数据类型特定运算符
有关 Milvus 过滤表达式的完整文档和示例,请参阅 Milvus 过滤 的官方文档。
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}