본문 바로가기
WIKI 기술 지식 베이스

LlamaIndex와 Milvus로 메타데이터 필터링하기 (Metadata Filtering with LlamaIndex and Milvus)

원문 보기 위키 갱신

이 노트북은 메타데이터 필터링 기능에 초점을 맞춰 LlamaIndex에서 Milvus 벡터 스토어를 사용하는 방법을 보여 드려요. 메타데이터가 있는 문서를 인덱싱하고, LlamaIndex의 내장 메타데이터 필터로 벡터 검색을 수행하며, Milvus의 네이티브 필터링 표현식을 벡터 스토어에 적용하는 방법을 배워요.

이 노트북을 마치면 Milvus의 필터링 기능을 활용해 문서 메타데이터를 기준으로 검색 결과를 좁히는 방법을 이해할 수 있어요.

출처: Milvus 문서

본문

사전 요구 사항 (Prerequisites)

의존성 설치

시작하기 전에 다음 의존성이 설치되어 있는지 확인하세요.

$ pip install llama-index-vector-stores-milvus llama-index

Google Colab을 사용한다면 런타임을 재시작해야 할 수 있어요. (인터페이스 상단의 "Runtime" 메뉴로 이동해 드롭다운에서 "Restart session"을 선택하세요.)

계정 설정

이 튜토리얼은 텍스트 임베딩과 답변 생성을 위해 OpenAI를 사용해요. OpenAI API 키를 준비해야 해요.

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,
        },
    ),
]

인덱스 구축 (Build Index)

이 섹션에서는 기본 임베딩 모델(OpenAI의 text-embedding-ada-002)을 사용해 샘플 데이터를 Milvus에 저장해요. 제목은 텍스트 임베딩으로 변환해 밀집 임베딩 필드에 저장하고, 모든 메타데이터는 스칼라 필드에 저장해요.

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)

메타데이터 필터 (Metadata Filters)

이 섹션에서는 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}

여러 메타데이터 필터 (Multiple Metadata Filters)

여러 메타데이터 필터를 결합해 더 복잡한 쿼리를 만들 수도 있어요. LlamaIndex는 필터를 결합하기 위해 AND와 OR 조건을 모두 지원해요. 이를 통해 메타데이터 속성을 기반으로 문서를 더 정밀하고 유연하게 검색할 수 있어요.

조건 AND

1979년과 2010년 사이(정확히 1979 < year ≤ 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

Georges Perec 또는 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}

Milvus의 키워드 인자 사용 (Use Milvus's Keyword Arguments)

내장 필터링 기능 외에도 string_expr 키워드 인자로 Milvus의 네이티브 필터링 표현식을 사용할 수 있어요. 이렇게 하면 검색 연산 중 특정 필터 표현식을 직접 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}

더 알아보기 (Learn more)