46.5k๋ฐ๋ชจ ์˜ˆ์•ฝํ•˜๊ธฐ๋กœ๊ทธ์ธ๋ฌด๋ฃŒ๋กœ ์‹œ์ž‘ํ•˜๊ธฐ

๐Ÿš€ Milvus v2.4.3์˜ Metadata Filtering ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ

Jun 16, 20243 min read

Milvus v2.4.3์—์„œ๋Š” ์ „์ฒด ๋ฌธ์ž์—ด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋งค์นญ์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰ ์ด์ œ ์ ‘๋‘์‚ฌ, ์ค‘์œ„, ์ ‘๋ฏธ์‚ฌ ๋˜๋Š” ๋ฌธ์ž ์™€์ผ๋“œ์นด๋“œ ๊ฒ€์ƒ‰์„ ์‚ฌ์šฉํ•ด ๋ฌธ์ž์—ด์„ ๋งค์นญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# Prefix example, matches any string starting with โ€œTheโ€.
expression='title like "The%"'
# Infix example, matches any string with the word โ€œtheโ€ anywhere in the sentence.
expression='title like "%the%"'
# Postfix example, matches any string ending with โ€œRyeโ€.
expression='title like "%Rye"'
# Single character wildcard example, matches any one single character at a specific position.
expression='title like "Flip_ed"'

์ด์ „ ๋ธ”๋กœ๊ทธ์—์„œ๋Š” ์ ‘๋‘์‚ฌ ๋ฌธ์ž์—ด ๋งค์นญ์— ๋Œ€ํ•ด์„œ๋งŒ ์ด์•ผ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Milvus v2.4.3๋ถ€ํ„ฐ๋Š” ๋ชจ๋“  ๋ณ€ํ˜•์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋ฐฐ์—ด ๊ฐ’๋„ ์ •ํ™•ํžˆ ์ผ์น˜์‹œํ‚ค๊ฑฐ๋‚˜ ๋ฐฐ์—ด์˜ ์–ด๋–ค ์š”์†Œ๋“  ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐฉ์‹(contains_any())์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ—‚๏ธ๐Ÿ”

์ด๋Ÿฌํ•œ ์—…๋ฐ์ดํŠธ๋กœ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง์ด ๋”์šฑ ๋‹ค์žฌ๋‹ค๋Šฅํ•˜๊ณ  ๊ฐ•๋ ฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค!

์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์ด๋ฅผ ๋” ๋ช…ํ™•ํžˆ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๋ธ”๋กœ๊ทธ์—์„œ๋Š” Kaggle์—์„œ ๋‹ค์šด๋กœ๋“œํ•œ IMDB ์˜ํ™” ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

# Import common libraries.
import sys, os, time, pprint
import pandas as pd

# Read CSV data.
df = pd.read_csv("data/original_data.csv")

# Shortcut the data for demo.
df = df.tail(200)
display(df.head())

๊ฐ ์˜ํ™”์—๋Š” ์„ค๋ช…๊ณผ ๋ฆฌ๋ทฐ๊ฐ€ ํฌํ•จ๋œ โ€˜textโ€™ ํ•„๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ“

๊ฐ ์˜ํ™”์—๋Š” ๊ฐœ๋ด‰ ์—ฐ๋„, ํ‰์ , ์žฅ๋ฅด, ๋ฐฐ์šฐ, ํ‚ค์›Œ๋“œ ๋ชฉ๋ก๊ณผ ๊ฐ™์€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽฌโญ๏ธ๐Ÿ“…

๊ฐ โ€œํ–‰โ€์€ ์˜ํ™” ๋ฆฌ๋ทฐ ํ…์ŠคํŠธ ์ฒญํฌ, ๊ทธ ๋ฒกํ„ฐ ํ‘œํ˜„, ๊ทธ๋ฆฌ๊ณ  movie_id, ์˜ํ™” ์ œ๋ชฉ, ํฌ์Šคํ„ฐ ๋งํฌ, ์žฅ๋ฅด, ๋ฐฐ์šฐ์™€ ๊ฐ™์€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ RAG ํŒจํ„ด์„ ๋”ฐ๋ฅด๋ฉด: ๐Ÿ“๐ŸŽฌ

  1. Milvus์— ์—ฐ๊ฒฐ: ๋จผ์ € Milvus์˜ ๋กœ์ปฌ ๋ฐฐํฌํŒ์ธ Milvus Lite์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฒกํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ž…๋‹ˆ๋‹ค. ๐Ÿ–ฅ๏ธ๐Ÿ”—

  2. ์˜ํ™” ํ…์ŠคํŠธ๋ฅผ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜: ์„ค๋ช…๊ณผ ๋ฆฌ๋ทฐ๊ฐ€ ํฌํ•จ๋œ ๊ฐ ์˜ํ™”์˜ ํ…์ŠคํŠธ ํ•„๋“œ๋ฅผ ๊ฐ€์ ธ์™€ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด HuggingFace ๋ชจ๋ธ BAAI/bge-large-en-v1.5์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๐Ÿง โžก๏ธ๐Ÿ“

  3. ๐Ÿ“ฅ๐Ÿ“Š ๋ฒกํ„ฐ์™€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ Milvus์— ์‚ฝ์ž…: ์ด ๋ฒกํ„ฐ๋ฅผ ์›๋ณธ ํ…์ŠคํŠธ(โ€œ์ฒญํฌโ€๋ผ๊ณ  ํ•จ) ๋ฐ ํ•ด๋‹น ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(์—ฐ๋„, ํ‰์ , ์žฅ๋ฅด ๋“ฑ)์™€ ํ•จ๊ป˜ Milvus์— ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ“ฅ๐Ÿ“Š

  4. ์‚ฌ์šฉ์ž ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ: ๋™์ผํ•œ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž์˜ ์ฟผ๋ฆฌ๋ฅผ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ Approximate Nearest Neighbors ๊ฒ€์ƒ‰์„ ์‹คํ–‰ํ•˜์—ฌ ์ฟผ๋ฆฌ ๋ฒกํ„ฐ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ฐ์ดํ„ฐ ๋ฒกํ„ฐ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. ๐Ÿ”๐ŸŽฌ

์ „์ฒด ์ฝ”๋“œ๋Š” ์ œ GitHub์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € Milvus์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. Pymilvus๋ฅผ pip๋กœ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (๋กœ์ปฌ ํŒŒ์ผ ์ด๋ฆ„๋งŒ ์ง€์ •ํ•˜๋ฉด ๋กœ์ปฌ ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ธ Milvus Lite๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. Docker๋‚˜ K8s๋กœ ๋ฐฐํฌ๋œ ๋‹ค๋ฅธ Milvus ๋˜๋Š” ์™„์ „ ๊ด€๋ฆฌํ˜• Zilliz Cloud๊ฐ€ ์žˆ๋‹ค๋ฉด URI์™€ Token์„ ์ง€์ •ํ•ด ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋จธ์ง€ ์ฝ”๋“œ๋Š” ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.)

# !python -m pip install -U pymilvus
import pymilvus
# Connect a client to the Milvus Lite server.
from pymilvus import MilvusClient
client = MilvusClient("milvus_demo.db")

๋‹ค์Œ์œผ๋กœ, ์˜ํ™” ๋ฆฌ๋ทฐ๊ฐ€ ํฌํ•จ๋œ ํ…์ŠคํŠธ ์—ด์„ ์ฒญํฌ๋กœ ๋‚˜๋ˆ„๊ณ  ์ž„๋ฒ ๋”ฉํ•˜์—ฌ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์˜ˆ์‹œ๋Š” ๋งŽ์€ ๋ฆฌ์†Œ์Šค์—์„œ ์ œ๊ณตํ•˜๋ฏ€๋กœ, ์—ฌ๊ธฐ์„œ๋Š” ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ๋ณด์—ฌ๋“œ๋ฆฌ์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ๋Š” ์ฒญํฌํ™”๋œ ํ…์ŠคํŠธ, ๋ฒกํ„ฐ ํ‘œํ˜„, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์กฐํ•ฉํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ Milvus์— ์‚ฝ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

# Create chunk_list and dict_list in a single loop
dict_list = []
for id, title, chunk, vector, poster_url, director,\
   genres, actors, keywords, film_year, rating in zip(
       df.id, df.Name, chunks, converted_values, df.PosterLink,
       df.Director, df.Genres, df.Actors, df.Keywords,
       df.MovieYear, df.RatingValue):
  
   # Assemble embedding vector, original text chunk, metadata.
   chunk_dict = {
       'movie_index': id,
       'title': title,
       'chunk': chunk.page_content,
       'poster_url': poster_url,
       'director': director,
       'genres': genres,
       'actors': actors,
       'keywords': keywords,
       'film_year': film_year,
       'rating': rating,
       'vector': vector,
   }
   dict_list.append(chunk_dict)

# Insert data into the Milvus collection.
print("Start inserting entities")
start_time = time.time()
client.insert(
   COLLECTION_NAME,
   data=dict_list,
   progress_bar=True)

end_time = time.time()
print(f"Milvus insert time for {len(dict_list)} vectors: ", end="")
print(f"{np.round(end_time - start_time, 2)} seconds")

์ด์ œ ๋ฐ์ดํ„ฐ๊ฐ€ Milvus์— ์žˆ์œผ๋ฏ€๋กœ ๊ฒ€์ƒ‰ํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!

๋ฌธ์ž์—ด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒ€์ƒ‰

๋กœ๋ด‡์ด ๋“ฑ์žฅํ•˜๋Š” ๋””์Šคํ† ํ”ผ์•„์  ๋ฏธ๋ž˜๋ฅผ ๋‹ค๋ฃฌ ๋†’์€ ํ‰์ ์˜ SF ์˜ํ™”๋ฅผ ์ฐพ๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. ์˜ˆ์ œ ๋ฐ์ดํ„ฐ์—๋Š” ์ด ๊ฒ€์ƒ‰์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ํผ์ง€ ๋ฌธ์ž์—ด ๋งค์น˜๋ฅผ ์‚ฌ์šฉํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ๋Š” ๊ฐ ๊ฒ€์ƒ‰ ํ›„ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋” ์‰ฝ๊ฒŒ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ณธ Milvus search API๋งŒ ๋ž˜ํ•‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

SAMPLE_QUESTION = "Dystopia science fiction with a robot."
TOP_K = 1
# Metadata filters.
expression='rating >= 7'
# Infix string match.
expression=expression + ' && title like "%Panther%"'
formatted_results, contexts, context_metadata = \
     mc_run_search(SAMPLE_QUESTION, expression, TOP_K)

๋ฆฌ์†Œ์Šค ๋ฐ ์ถ”๊ฐ€ ์ž๋ฃŒ

Milvus ๋น ๋ฅธ ์‹œ์ž‘ ๊ฐ€์ด๋“œ

๋ฐฐ์—ด ํ•„๋“œ ์‚ฌ์šฉ | Milvus ๋ฌธ์„œ

https://github.com/milvus-io/pymilvus/blob/2.4/examples/fuzzy_match.py

https://milvus.io/docs/boolean.md#Usage

https://milvus.io/docs/single-vector-search.md#Filtered-search

Jul 09, 2026์— ์—…๋ฐ์ดํŠธ๋จ