이전 시간에 이어, 파이프라인 코드를 리뷰하며 정리했던 내용들을 아래에 기록한다.
그냥 읽고 지나갈 수 있는 내용이더라도, 직접 터미널에 세부 내용들을 출력하며 확인해가는 과정을 통해 RAG를 알아갈 수 있는 시간이라 생각한다.
딕셔너리의 get() 메서드는 두개의 인자를 받을 수 있다.
.py 파일 단위로 작성 (import로 가져오기)local()은 특정 함수 내에서 사용되는 로컬 변수들의 변수명 및 현재 값을 알고 싶을 때 사용한다.
from pathlib import Path
data_dir = Path("./data") # 'data' 폴더에 대한 경로 객체 생성 → 상대 경로 ./data를 Path 객체로 변환
json_files = list(data_dir.glob("*.json")) # data 폴더에 있는 모든 .json 파일을 리스트로 수집
print(f">> json 파일 목록 확인: {json_files}\n")
>> json 파일 목록 확인: [PosixPath('data/(제3호__심의)_퀀텀이니셔티브_안건_최종.json'),
✅ 해당 코드를 알아보자.
👽 Path("./data")는 ./data라는 상대 경로를 PosixPath 객체로 만들어 준다.
- 리눅스/맥에서는 PosixPath, 윈도우에서는 WindowsPath 객체가 생성됨.
👽 .glob("*.json")은 해당 디렉토리 안의 모든 .json 파일들을 Path 객체로 찾는다.
- 이때 각 파일 경로는 PosixPath로 표현됩니다.
👽 json_files는 다음과 같은 리스트가 된다:
[PosixPath('data/(제3호__심의)_퀀텀이니셔티브_안건_최종.json'), ...]
print() 함수로 이 리스트를 출력하면 → 객체의 문자열 표현(repr)이 출력되므로 PosixPath(...) 형태가 보이는 것뿐!✅ 그럼 PosixPath를 알아보자.
pathlib은 파일 시스템 경로를 문자열이 아닌 객체로 다루게 해주는 표준 라이브러리
pathlib.Path를 사용할 때, 운영체제에 따라 실제로 반환되는 객체 타입이 달라지는데:
PosixPathWindowsPathPosixPath는 유닉스 계열 OS에서 사용되는 경로 객체print(path)처럼 그냥 출력하면 "data/file.json"만 보이지만,
👉 만약 그 객체를 리스트에 담거나 JSON처럼 처리하려고 하면
# [PosixPath('data/file.json')] 처럼 보일 수 있다.
PosixPath를 문자열로 바꾸려면 str(path)
Milvus는 벡터 기반의 검색을 빠르게 처리하기 위해 인덱스(Index)를 사용한다.

👉 벡터 인덱스는 "가까운 벡터를 빠르게 찾기 위해" 미리 계산해두는 데이터 구조
👉 Milvus에서 지원하는 인덱스 타입: 벡터 유사도 검색에 특화된 다양한 인덱스 알고리즘 제공
| 인덱스 이름 | 설명 | 장점 | 단점 |
|---|---|---|---|
FLAT | 모든 벡터를 비교 (브루트포스) | 정확도 100% | 느림, 대규모에 부적합 |
IVF_FLAT (default) | 벡터를 K개의 클러스터로 나누고, 일부만 검색 | 속도 향상, 구현 단순 | 정확도↓ |
IVF_SQ8 | IVF + 양자화 (int8 압축) | 공간 절약 + 빠름 | 정밀도 손실 가능 |
IVF_PQ | IVF + Product Quantization | 더 높은 압축률 | 정밀도 손실 가능 |
HNSW (성능) | 그래프 기반 탐색 (Hierarchical Navigable Small World) | 매우 빠름, 정확도 높음 | 메모리 사용 많음 |
ANNOY | 트리 기반 근사 탐색 | 빠름, 구현 단순 | 정확도↓ |
NSG | 그래프 기반 탐색 (Milvus 1.x에서 사용) | 빠름, 효율적 | 구축 느림 |
AUTOINDEX | Milvus가 상황에 맞게 자동 선택 | 편리함 | 컨트롤 부족 |
✍ 그렇다면 파이썬으로 인덱스 파라미터는 어떻게 설정할 수 있을까?
# 인덱스 파라미터 설정
index_params = self.client.prepare_index_params()
index_params.add_index(
field_name=self.vector_field_name,
metric_type="COSINE", # 거리 측정 방식 - 유사도 계산 방법
index_type="IVF_FLAT", # 인덱스 타입
params={"nlist": 2048}, # 인덱스 세부 파라미터 - nlist: 벡터를 몇 개의 클러스터로 나눌지 설정
)
COSINE은 두 벡터 사이의 각도를 기반으로 유사도를 측정 (값이 1에 가까울수록 유사함.)IVF_FLAT는 Inverted File Index + Brute-force(flat) 검색 방식 ( 전체 벡터들을 K개의 클러스터(= 셀 또는 버킷) 로 나눠 저장 → 검색 시 일부 클러스터만 대상으로 비교)nlist : 벡터를 몇 개의 클러스터로 나눌지 설정하는 값nlist개의 그룹(cluster)로 나눈 후, 검색 시 일부 클러스터(nprobe)만 탐색Q. 벡터 말고 varchar에도 인덱스를 지정할 수 있나?
A. 가능하다.
VARCHAR, INT64, BOOL 같은 스칼라 필드(일반 필드) 에도 인덱스를 지정할 수 있다.STL_SORTSTL_SORTSTL_SORT는 내부적으로 정렬 기반으로 동작하여 필터링 성능을 향상✅ 먼저: "청크의 메타데이터"란?
→ 청크(문서 조각)를 벡터로 임베딩할 때, 그 벡터와 함께 저장하는 부가적인 정보
아래는 메타데이터의 예시이다.
{
"content": "이 문서는 Milvus의 인덱스에 대해 설명합니다.",
"metadata": {
"source": "milvus_docs.pdf",
"page": 12,
"category": "milvus",
"doc_id": "1234"
}
}
filter or expr)"category == 'milvus'", "source == 'contract.pdf'", "page >= 10"results = collection.search(
data=[query_vector],
anns_field="embedding",
param={"metric_type": "COSINE", "params": {"nprobe": 10}},
limit=5,
expr="source == 'milvus_docs.pdf'" # 메타데이터 필터링
)
➡️ 사용자의 질문에 맞는 범위의 청크만 검색해서 정확도를 높여준다.
🔎 검색 결과:
문서: milvus_docs.pdf
페이지: 12
내용: "IVF_FLAT 인덱스는 벡터를 여러 클러스터로 나누고..."
💬 LLM에게 이렇게 전달:
"사용자의 질문은 다음과 같고, 아래는 관련 문서 내용입니다. 참고해 답변하세요:
- 문서: milvus_docs.pdf (p.12)
- 내용: IVF_FLAT 인덱스는..."
➡️ 답변이 더 근거 중심, 출처 명확, 신뢰 가능해짐.
"이 내용은 'milvus_docs.pdf' 12페이지를 참조했습니다."
➡️ RAG 기반 서비스의 신뢰도와 사용자 경험(UX) 향상
✅ 요약
| 활용 목적 | 설명 |
|---|---|
| 🔎 검색 필터링 | 특정 문서, 페이지, 카테고리만 검색 |
| 🧠 LLM에게 컨텍스트 제공 | 답변 품질과 신뢰도 향상 |
| 📎 출처 표기 및 설명 | 사용자에게 참고 문서 표시 |
| 🔄 후처리/정렬/그룹핑 | 검색 결과 정리 및 분석 |