Milvus와 WhyHow 통합하기 (Integrate Milvus with WhyHow)
이 가이드에서는 whyhow.ai와 Milvus Lite를 사용해 규칙 기반 검색(Rule-based Retrieval)을 수행하는 방법을 보여 드려요.
출처: Milvus 문서
본문
개요 (Overview)
WhyHow는 개발자에게 복잡한 RAG를 수행하기 위해 비구조화 데이터를 정리하고, 맥락화하고, 안정적으로 검색하는 데 필요한 구성 요소를 제공하는 플랫폼이에요. Rule-based Retrieval 패키지는 WhyHow가 개발한 Python 패키지로, 고급 필터링 기능을 갖춘 RAG(R retrieval Augmented Generation) 애플리케이션을 만들고 관리할 수 있게 해 줘요.
설치 (Installation)
시작하기 전에 나중에 사용할 필수 Python 패키지를 모두 설치하세요.
pip install --upgrade pymilvus, whyhow_rbr
다음으로 Milvus Lite를 사용해 Rule-based Retrieval을 구현하기 위해 Milvus 클라이언트를 초기화해야 해요.
from pymilvus import MilvusClient
# Milvus Lite local path
path="./milvus_demo.db" # random name for local milvus lite db path
# Initialize the ClientMilvus
milvus_client = ClientMilvus(path)
Milvus Cloud를 통해 Milvus 클라이언트를 초기화할 수도 있어요.
from pymilvus import MilvusClient
# Milvus Cloud credentials
YOUR_MILVUS_CLOUD_END_POINT = "YOUR_MILVUS_CLOUD_END_POINT"
YOUR_MILVUS_CLOUD_TOKEN = "YOUR_MILVUS_CLOUD_TOKEN"
# Initialize the ClientMilvus
milvus_client = ClientMilvus(
milvus_uri=YOUR_MILVUS_CLOUD_END_POINT,
milvus_token=YOUR_MILVUS_CLOUD_TOKEN,
)
컬렉션 만들기 (Create Collection)
필요한 변수 정의 (Defining necessary variables)
# Define collection name
COLLECTION_NAME="YOUR_COLLECTION_NAME" # take your own collection name
# Define vector dimension size
DIMENSION=1536 # decide by the model you use
스키마 추가 (Add schema)
Milvus Lite 데이터베이스에 데이터를 삽입하기 전에 먼저 데이터 필드를 정의해야 해요. 여기서는 이를 스키마라고 부르죠. CollectionSchema 객체를 만들고 add_field()로 데이터 필드를 추가하면 데이터 타입과 특성을 제어할 수 있어요. 이 단계는 Milvus에 데이터를 삽입하기 전에 필수예요.
schema = milvus_client.create_schema(auto_id=True) # Enable id matching
schema = milvus_client.add_field(schema=schema, field_name="id", datatype=DataType.INT64, is_primary=True)
schema = milvus_client.add_field(schema=schema, field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=DIMENSION)
인덱스 생성 (Create index)
각 스키마에 인덱스가 있으면 쿼리가 훨씬 효율적이에요. 인덱스를 만들려면 먼저 index_params가 필요하고, 이후 이 IndexParams 객체에 인덱스 데이터를 더 추가해요.
# Start to indexing data field
index_params = milvus_client.prepare_index_params()
index_params = milvus_client.add_index(
index_params=index_params, # pass in index_params object
field_name="embedding",
index_type="AUTOINDEX", # use autoindex instead of other complex indexing method
metric_type="COSINE", # L2, COSINE, or IP
)
이 메서드는 공식 Milvus 구현의 얇은 래퍼예요 (공식 문서 참고).
컬렉션 생성 (Create collection)
모든 데이터 필드를 정의하고 인덱싱했다면 이제 데이터베이스 컬렉션을 만들어 데이터에 빠르고 정확하게 접근할 수 있어요. 참고로 우리는 enable_dynamic_field를 true로 초기화해서 원하는 데이터를 자유롭게 업로드할 수 있게 했어요. 단점은 데이터 쿼리가 비효율적일 수 있다는 점이에요.
# Create Collection
milvus_client.create_collection(
collection_name=COLLECTION_NAME,
schema=schema,
index_params=index_params
)
문서 업로드 (Upload documents)
컬렉션을 만든 후에는 문서로 채울 준비가 됐어요. whyhow_rbr에서 이 작업은 MilvusClient의 upload_documents 메서드로 수행해요. 이 메서드는 내부적으로 다음 단계를 수행해요.
- 전처리(Preprocessing): 제공된 PDF 파일을 읽고 청크로 분할해요.
- 임베딩(Embedding): 모든 청크를 OpenAI 모델로 임베딩해요.
- 삽입(Inserting): 임베딩과 메타데이터를 Milvus Lite에 업로드해요.
# get pdfs
pdfs = ["harry-potter.pdf", "game-of-thrones.pdf"] # replace to your pdfs path
# Uploading the PDF document
milvus_client.upload_documents(
collection_name=COLLECTION_NAME,
documents=pdfs
)
질문 답변 (Question answering)
이제 드디어 retrieval augmented generation으로 넘어갈 수 있어요.
# Search data and implement RAG!
res = milvus_client.search(
question='What food does Harry Potter like to eat?',
collection_name=COLLECTION_NAME,
anns_field='embedding',
output_fields='text'
)
print(res['answer'])
print(res['matches'])
규칙 (Rules)
앞선 예시에서는 인덱스의 모든 문서를 고려했어요. 하지만 때로는 사전에 정의된 조건(예: filename=harry-potter.pdf)을 충족하는 문서만 검색하는 것이 유용할 수 있어요. whyhow_rbr에서 Milvus Lite를 통해 이는 검색 파라미터를 조정해 수행할 수 있어요.
규칙은 다음 메타데이터 속성을 제어할 수 있어요.
filename파일의 이름page_numbers페이지 번호에 해당하는 정수 목록(0 인덱싱)id청크의 고유 식별자 (가장 "극단적인" 필터)- Boolean Expressions에 기반한 기타 규칙
# RULES(search on book harry-potter on page 8):
PARTITION_NAME='harry-potter' # search on books
page_number='page_number == 8'
# first create a partitions to store the book and later search on this specific partition:
milvus_client.crate_partition(
collection_name=COLLECTION_NAME,
partition_name=PARTITION_NAME # separate base on your pdfs type
)
# search with rules
res = milvus_client.search(
question='Tell me about the greedy method',
collection_name=COLLECTION_NAME,
partition_names=PARTITION_NAME,
filter=page_number, # append any rules follow the Boolean Expression Rule
anns_field='embedding',
output_fields='text'
)
print(res['answer'])
print(res['matches'])
이 예시에서는 먼저 harry-potter 관련 PDF를 저장할 파티션을 만들고, 이 파티션 안에서 검색해 가장 직접적인 정보를 얻어요. 또한 페이지 번호를 필터로 적용해 검색하고자 하는 정확한 페이지를 지정해요. 참고로 filter 파라미터는 boolean rule을 따라야 해요.
정리 (Clean up)
마지막으로 모든 지침을 구현한 후에는 drop_collection()을 호출해 데이터베이스를 정리할 수 있어요.
# Clean up
milvus_client.drop_collection(
collection_name=COLLECTION_NAME
)
더 알아보기 (Learn more)
- WhyHow — 플랫폼과 Rule-based Retrieval 패키지
- Milvus Boolean Expressions — 필터 표현식 규칙
- Milvus 공식 문서 — api 참고 자료