Sparse · Dense · Hybrid — RAG를 위한 검색 기술 완전 가이드
| 세대 | 방식 | 핵심 기술 | 한계 |
|---|---|---|---|
| 1세대 | 키워드 매칭 | Boolean, TF-IDF | 동의어·문맥 무시 |
| 2세대 | 통계 기반 랭킹 | BM25 | 의미 유사성 미반영 |
| 3세대 | 의미 기반 검색 | Embedding + ANN | 키워드 정확도 ↓ |
| 4세대 | 하이브리드 + AI | Hybrid Search + LLM | 현재 최적 해법 |
키워드 → 통계 → 벡터 → 하이브리드 로 진화
정보 검색은 컴퓨터 이전부터 시작된 학문 분야
| 연대 | 사건 | 의의 |
|---|---|---|
| 1945 | Vannevar Bush — “As We May Think” | 하이퍼텍스트·정보 검색 개념의 시초 |
| 1950s | Calvin Mooers — “Information Retrieval” 용어 최초 사용 | IR 학문 분야 탄생 |
| 1960s | Gerard Salton — SMART 시스템 | TF-IDF, 벡터 공간 모델(VSM) 정립 |
| 1970s | Robertson & Spärck Jones — 확률 모델 | IDF 개념 공식화, 확률적 랭킹 원리 |
| 1992 | TREC (Text REtrieval Conference) 시작 | IR 평가 표준화, 벤치마크 확립 |
| 1994 | Robertson et al. — BM25 발표 | Okapi BM25, 현재까지 표준 |
| 1998 | Google — PageRank | 링크 구조 기반 웹 검색 혁명 |
| 2013 | Word2Vec (Mikolov) | 단어 임베딩의 시작 |
| 2018 | BERT (Devlin et al.) | 문맥 기반 임베딩 → Dense Retrieval 기반 |
| 2020~ | DPR, ColBERT, Hybrid Search | 밀집 검색 + 하이브리드 시대 개막 |
Gerard Salton (1971) 이 정립한 IR의 수학적 토대
문서와 쿼리를 같은 벡터 공간의 점으로 표현하고, 거리/각도로 유사도를 측정한다
단어2 ↑
│ · 문서A
│ /
│ / θ (코사인 각도)
│ /
│/________· 쿼리Q ──→ 단어1
| 이전 | VSM 이후 |
|---|---|
| Boolean 검색 (있다/없다) | 유사도 점수로 랭킹 |
| 결과 = 집합 | 결과 = 정렬된 리스트 |
| 부분 매치 불가 | 부분 매치 + 가중치 |
오늘날 Sparse Search와 Dense Search 모두 VSM의 후손
단어 존재 여부를 기반으로 문서를 매칭하는 전통적 검색 방식
문서: "검색 엔진은 AI 기술이다"
벡터: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, ...]
↑ ↑ ↑ ↑
검색 엔진 AI 기술
어휘 수 = 벡터 차원 수 → 수만~수십만 차원, 대부분 0
Sparse Search의 사실상 표준 랭킹 함수
score(D, Q) = Σ IDF(qi) · [ f(qi, D) · (k1 + 1) ] / [ f(qi, D) + k1 · (1 - b + b · |D| / avgdl) ]
| 요소 | 의미 | 역할 |
|---|---|---|
| IDF(qi) | 역문서 빈도 | 희귀한 단어일수록 높은 점수 |
| f(qi, D) | 단어 빈도 (TF) | 문서 내 등장 횟수 |
| k1 | TF 포화 파라미터 | 반복 등장의 감쇠율 (기본 1.2) |
| b | 문서 길이 보정 | 긴 문서 패널티 (기본 0.75) |
| avgdl | 평균 문서 길이 | 정규화 기준 |
TF-IDF의 진화형 — TF 포화 + 문서 길이 보정 추가
영어와 달리 한국어는 띄어쓰기만으로 단어를 분리할 수 없다
영어: "I love search engines"
→ Whitespace 분리 → ["I", "love", "search", "engines"]
→ 바로 BM25 적용 가능 ✓
한국어: "검색엔진을 사랑합니다"
→ Whitespace 분리 → ["검색엔진을", "사랑합니다"]
→ "검색엔진" 검색 시 "검색엔진을"과 미매칭 ✗
| 특성 | 영어 | 한국어 |
|---|---|---|
| 어순 | SVO (고정적) | SOV (유연) |
| 조사 | 전치사 (별도 단어) | 조사가 단어에 붙음 |
| 활용 | 어미 변화 적음 | 동사/형용사 어미가 수십 가지 |
| 복합어 | 띄어쓰기로 구분 | 붙여쓰기 빈번 |
| 띄어쓰기 | 규칙적 | 불규칙 (오류 다수) |
형태소 분석 없이는 Sparse Search 정확도가 크게 하락
한국어 문장을 의미 있는 최소 단위(형태소)로 분리하는 도구
입력: "검색엔진을 사랑합니다"
형태소 분석 결과:
검색 / NNG (일반명사)
엔진 / NNG (일반명사)
을 / JKO (목적격 조사)
사랑 / NNG (일반명사)
하 / XSV (동사 파생 접미사)
ㅂ니다 / EF (종결 어미)
| 분석 전 | 분석 후 | 효과 |
|---|---|---|
| “검색엔진을” | “검색” + “엔진” | 복합어 분리 |
| “사랑합니다” | “사랑” + “하다” | 어간 추출 |
| “달리고 있는” | “달리” + “고 있” | 활용 정규화 |
형태소 분석 = Sparse Search의 한국어 전처리 필수 단계
| 분석기 | 개발 | 라이선스 | 특징 |
|---|---|---|---|
| Nori | Elastic (루씬) | Apache 2.0 | ES/OpenSearch 내장, mecab-ko 사전 기반 |
| Mecab-ko | 은전한닢 | GPL/LGPL/BSD | 가장 빠름, C++ 기반, 사전 커스터마이징 |
| Komoran | Shineware | Apache 2.0 | Java 네이티브, 외부 라이브러리 불필요 |
| Hannanum | KAIST | GPL | 학술 목적, 오래된 사전 |
| Kkma | 서울대 IDS | GPL | 정확하지만 느림 |
| Okt (Open Korean Text) | Twitter → 커뮤니티 | Apache 2.0 | 정규화·어구 추출, 비공식 텍스트에 강함 |
| Kiwi | bab2min | LGPL | 최신, Rust/C++ 기반, 빠르고 정확 |
Elasticsearch/OpenSearch 사용 시 → Nori 가 사실상 표준
{
"settings": {
"analysis": {
"tokenizer": {
"nori_custom": {
"type": "nori_tokenizer",
"decompound_mode": "mixed",
"user_dictionary": "userdict_ko.txt"
}
},
"analyzer": {
"korean": {
"type": "custom",
"tokenizer": "nori_custom",
"filter": [
"nori_readingform",
"nori_part_of_speech",
"lowercase"
]
}
}
}
}
}
| 모드 | “삼성전자” 결과 | 용도 |
|---|---|---|
| none | [“삼성전자”] | 복합어 유지 |
| discard | [“삼성”, “전자”] | 분리만 |
| mixed | [“삼성전자”, “삼성”, “전자”] | 추천 — 원본 + 분리 모두 색인 |
"머신러닝" vs "머신 러닝" vs "머신런닝"
→ 형태소 분석기에 따라 다르게 토큰화 → BM25 점수 달라짐
"배" → 과일? 선박? 신체부위? 배수?
→ 형태소 분석기는 문맥 구별 불가
"쿠버네티스", "RAG", "LangChain" → 사전에 없으면 분석 실패
→ 사용자 사전(user_dictionary) 관리 필수
"검색하다" / "검색한다" / "검색했다" / "검색할" / "검색하는"
→ 모두 "검색" + "하다" 로 정규화해야 올바른 매칭
사용자 사전 관리와 분석기 선택이 한국어 검색 품질을 결정
| 문제 | 예시 | Sparse 결과 |
|---|---|---|
| 동의어 | “노트북” vs “랩톱” | 미매칭 |
| 약어 | “쿠버” vs “쿠버네티스” | 미매칭 |
| 한영 혼용 | “AI 검색” vs “인공지능 검색” | 부분 매칭 |
| 오타 | “엘라스틱서치” vs “일래스틱서치” | 미매칭 |
| 의미 검색 | “서버가 느려요” → 성능 최적화 문서 | 키워드 없어 미매칭 |
| 계층 | 전략 | 효과 |
|---|---|---|
| 전처리 | Nori + 사용자 사전 + 동의어 사전 | 기본 품질 확보 |
| 검색 | Hybrid Search (Sparse + Dense) | 의미 매칭 보완 |
| 후처리 | Re-ranking (Cross-encoder / LLM) | 최종 정밀도 향상 |
한국어 RAG에서는 형태소 분석 + Hybrid Search가 필수 조합
의미(Semantic)를 기반으로 문서를 매칭하는 검색 방식
"검색 엔진은 AI 기술이다"
→ Embedding Model
→ [0.23, -0.41, 0.87, 0.12, -0.65, 0.33, ...]
(768 또는 1536 차원의 밀집 벡터)
단어가 아닌 의미를 수치화 → 동의어/유사 표현 검색 가능
Dense Search에서 두 벡터의 유사도를 측정하는 핵심 지표
cos(θ) = (A · B) / (||A|| × ||B||)
| 값 | 의미 |
|---|---|
| 1.0 | 완전히 같은 방향 (매우 유사) |
| 0.0 | 직교 (관련 없음) |
| -1.0 | 반대 방향 (반대 의미) |
코사인 유사도 외에도 IR에서 사용되는 다양한 유사도 측정 방법
| 알고리즘 | 입력 타입 | 값 범위 | 대표 사용처 |
|---|---|---|---|
| Cosine Similarity | 실수 벡터 | -1 ~ 1 | Dense/Sparse 검색 |
| Jaccard 계수 | 집합 | 0 ~ 1 | 키워드 집합 비교 |
| Tanimoto 계수 | 이진/실수 벡터 | 0 ~ 1 | 화학·지문 유사도 |
| 유클리드 거리 | 실수 벡터 | 0 ~ ∞ | kNN, 클러스터링 |
| 내적 (Dot Product) | 실수 벡터 | -∞ ~ ∞ | MIPS 기반 검색 |
| Manhattan 거리 | 실수 벡터 | 0 ~ ∞ | 희소 데이터 |
| Hamming 거리 | 이진 벡터 | 0 ~ n | 해시 기반 검색 |
두 집합의 겹침 정도를 측정하는 가장 직관적인 유사도
J(A, B) = |A ∩ B| / |A ∪ B|
문서A 키워드: {AI, 검색, 엔진, 기술}
문서B 키워드: {AI, 머신러닝, 기술, 딥러닝}
교집합: {AI, 기술} → |A ∩ B| = 2
합집합: {AI, 검색, 엔진, 기술, 머신러닝, 딥러닝} → |A ∪ B| = 6
J(A, B) = 2 / 6 = 0.33
Jaccard 계수를 연속 값 벡터로 확장한 유사도
T(A, B) = (A · B) / (||A||² + ||B||² - A · B)
| 구분 | Jaccard | Tanimoto |
|---|---|---|
| 입력 | 집합 (이진) | 벡터 (실수/이진) |
| 값 범위 | 0 ~ 1 | 0 ~ 1 |
| TF 반영 | ✗ 불가 | ✓ 가능 |
| Jaccard와 관계 | - | 이진 벡터일 때 Jaccard = Tanimoto |
거리 vs 방향 — 무엇을 측정하느냐의 차이
d(A, B) = √(Σ(ai - bi)²)
↑ 차원2
│ · B (0.8, 0.9)
│ /|
│ / | ← 유클리드 거리 (직선)
│ / |
│ · A (0.2, 0.3)
│ θ ← 코사인 각도
└──────────→ 차원1
| 상황 | 코사인 유사도 | 유클리드 거리 |
|---|---|---|
| 같은 방향, 다른 크기 | 1.0 (동일) | 크다 (다름) |
| 다른 방향, 같은 크기 | 낮다 (다름) | 작을 수 있음 |
IR에서는 코사인 유사도가 표준 — 문서 길이 영향을 제거하기 때문
| 상황 | 추천 알고리즘 | 이유 |
|---|---|---|
| Dense 벡터 검색 | Cosine Similarity | 방향 기반, 정규화된 비교 |
| Sparse 키워드 비교 | Jaccard / BM25 | 집합 매칭 / 가중 랭킹 |
| 이진 특성 비교 | Tanimoto / Hamming | 이진 벡터 특화 |
| kNN / 클러스터링 | 유클리드 거리 | 절대적 거리 필요 시 |
| 대규모 ANN 검색 | 내적 (Dot Product) | MIPS 최적화, 속도 우선 |
| 문서 중복 탐지 | Jaccard + MinHash | LSH 기반 확장 가능 |
정답은 없다 — 데이터 특성과 사용 목적에 따라 선택
TF-IDF 벡터 간의 코사인 유사도 계산
문서1: "AI 검색 엔진" → TF-IDF 벡터 A = [0.5, 0.3, 0.4, 0, 0, ...]
문서2: "검색 기술 활용" → TF-IDF 벡터 B = [0, 0.3, 0, 0.6, 0.2, ...]
cos(A, B) = (0×0 + 0.3×0.3 + ...) / (||A|| × ||B||) = 0.12
| 항목 | 설명 |
|---|---|
| 벡터 차원 | 어휘 크기 (수만~수십만) |
| 벡터 타입 | Sparse (대부분 0) |
| 유사도 의미 | 공통 키워드 비율 |
| 한계 | 다른 단어 = 유사도 0 (의미 무시) |
“자동차”와 “차량”은 다른 차원 → cos = 0 (유사하지 않다고 판단)
Embedding 벡터 간의 코사인 유사도 계산
쿼리: "자동차 엔진 문제" → [0.82, -0.31, 0.45, ...]
문서1: "차량 모터 고장" → [0.79, -0.28, 0.51, ...] cos = 0.96
문서2: "비행기 엔진 설계" → [0.21, 0.67, -0.42, ...] cos = 0.34
| 항목 | 설명 |
|---|---|
| 벡터 차원 | 768 ~ 1536 (고정) |
| 벡터 타입 | Dense (모든 값 비-0) |
| 유사도 의미 | 의미적 유사도 |
| 강점 | 동의어/패러프레이즈 매칭 가능 |
“자동차”와 “차량”은 유사한 벡터 → cos ≈ 0.95 (유사하다고 판단)
| 비교 항목 | Text Search (Sparse) | Vector Search (Dense) |
|---|---|---|
| 표현 방식 | TF-IDF / BM25 희소 벡터 | Embedding 밀집 벡터 |
| 벡터 차원 | 어휘 수 (수만~수십만) | 768 ~ 1536 |
| 유사도 기준 | 공통 키워드 존재 | 의미적 거리 |
| 동의어 처리 | ✗ 불가 | ✓ 자동 처리 |
| 정확한 키워드 | ✓ 완벽 매칭 | △ 놓칠 수 있음 |
| 속도 | ✓ 매우 빠름 | △ ANN 인덱스 필요 |
| 모델 의존성 | ✗ 없음 | ✓ Embedding 모델 필수 |
| 설명 가능성 | ✓ 높음 | ✗ 블랙박스 |
둘 다 장단점이 뚜렷 → 결합하면?
Sparse + Dense를 결합하여 양쪽 장점을 취하는 검색 전략
┌─────────────────┐
쿼리 ──→│ Sparse Search │──→ BM25 점수
│ (키워드 매칭) │
└─────────────────┘
──→ 결합(Fusion) ──→ 최종 랭킹
┌─────────────────┐
쿼리 ──→│ Dense Search │──→ 코사인 유사도
│ (의미 매칭) │
└─────────────────┘
| 방법 | 설명 |
|---|---|
| 가중 합산 | α × BM25 + (1-α) × Cosine |
| RRF (Reciprocal Rank Fusion) | 순위 기반 결합, 점수 스케일 무관 |
| Cross-encoder Re-ranking | 후보군 추출 후 LLM으로 재랭킹 |
| 쿼리 | Sparse Only | Dense Only | Hybrid |
|---|---|---|---|
| “GCP VPC 방화벽 설정” | ✓ 정확 매칭 | △ 유사 결과 혼입 | ✓ 정확 + 관련 문서 |
| “클라우드 보안 강화 방법” | △ 키워드 없으면 누락 | ✓ 의미 매칭 | ✓ 폭넓게 커버 |
| “k8s pod OOMKilled” | ✓ 전문 용어 매칭 | △ 일반화 | ✓ 정확 + 맥락 |
| “서버 느려졌어요” | △ 모호한 키워드 | ✓ 의도 파악 | ✓ 최적 결과 |
Hybrid = 정확성(Sparse) + 재현율(Dense) 의 최적 조합
가장 널리 쓰이는 하이브리드 결합 알고리즘
RRF_score(d) = Σ 1 / (k + rank_i(d))
k = 상수 (보통 60)rank_i(d) = i번째 검색 방식에서의 문서 d 순위| 문서 | BM25 순위 | Dense 순위 | RRF 점수 |
|---|---|---|---|
| A | 1 | 3 | 1/61 + 1/63 = 0.032 |
| B | 3 | 1 | 1/63 + 1/61 = 0.032 |
| C | 2 | 2 | 1/62 + 1/62 = 0.032 |
| D | 5 | 10 | 1/65 + 1/70 = 0.030 |
점수 스케일이 달라도 순위 기반으로 공정하게 결합
1차 검색(Retrieval) 결과를 더 정교한 모델로 다시 정렬하는 2단계 전략
[1단계] Retrieval (BM25 / Dense / Hybrid)
→ 수백만 문서에서 Top-K 후보 빠르게 추출 (속도 우선)
[2단계] Re-ranking
→ Top-K 후보만 정밀 분석하여 최종 순위 결정 (정확도 우선)
| 단계 | 모델 | 문서 수 | 속도 | 정확도 |
|---|---|---|---|---|
| 1단계 Retrieval | BM25, Bi-encoder | 수백만 → Top-100 | ✓ 빠름 | △ |
| 2단계 Re-ranking | Cross-encoder, LLM | Top-100 → Top-10 | △ 느림 | ✓✓✓ |
전체 문서를 정밀 분석하면 너무 느림 → 2단계 파이프라인이 현실적 해법
리랭킹을 이해하려면 두 가지 인코더 구조의 차이를 알아야 한다
쿼리 → [Encoder] → 쿼리 벡터 ─┐
├→ Cosine Similarity
문서 → [Encoder] → 문서 벡터 ─┘
✓ 쿼리와 문서를 독립적으로 인코딩
✓ 문서 벡터를 미리 계산(오프라인) 가능 → 빠름
✗ 쿼리-문서 간 상호작용 없음 → 정확도 한계
[쿼리 + 문서] → [Encoder] → 관련성 점수 (0~1)
✓ 쿼리와 문서를 함께 인코딩 → 상호작용 포착
✓ 훨씬 높은 정확도
✗ 매번 쌍(pair)으로 계산 → 느림 (사전 계산 불가)
Bi-encoder = 속도, Cross-encoder = 정확도
| 방식 | 원리 | 정확도 | 속도 | 비용 |
|---|---|---|---|---|
| Cross-encoder | 쿼리+문서 쌍을 BERT 계열로 점수화 | ✓✓ | △ | 중 |
| ColBERT | 토큰 레벨 late interaction | ✓✓ | ✓ | 중 |
| LLM Re-ranker | GPT/Gemini에 후보 문서를 주고 순위 판단 | ✓✓✓ | ✗ 느림 | 높음 |
| Cohere Rerank | API 기반 Cross-encoder 서비스 | ✓✓ | ✓ | 중 |
| Vertex AI Ranking API | Google 자체 LLM 리랭커 | ✓✓✓ | ✓ | 중 |
| 상황 | 추천 |
|---|---|
| 비용 최소화 + 정확도 필요 | Cross-encoder (오픈소스) |
| 대규모 + 빠른 응답 | ColBERT |
| 최고 정확도, 비용 여유 | LLM Re-ranker |
| 관리형 서비스 원하면 | Cohere Rerank / Vertex AI Ranking API |
LLM에게 검색 결과를 주고 관련성 순으로 재정렬 요청
prompt = """
다음은 사용자 질문과 검색된 문서 목록입니다.
각 문서의 관련성을 판단하여 가장 관련 높은 순서로
문서 번호를 나열해주세요.
질문: "쿠버네티스 Pod이 OOMKilled 되는 원인"
[1] 쿠버네티스 메모리 리소스 제한 설정 가이드...
[2] Docker 컨테이너 네트워크 설정 방법...
[3] Pod OOMKilled 트러블슈팅: memory limit 초과 시...
[4] 쿠버네티스 클러스터 오토스케일링 전략...
[5] Linux cgroup 메모리 제어와 OOM Killer 동작 원리...
관련성 순서:
"""
# 결과: [3] > [5] > [1] > [4] > [2]
LLM이 문맥을 이해하므로 키워드 매칭을 넘어선 정밀 랭킹 가능
사용자 쿼리
│
▼
┌──────────────────────────────┐
│ 1단계: Retrieval (빠르게) │
│ Sparse(BM25) + Dense(ANN) │
│ → Hybrid Fusion (RRF) │
│ → Top-100 후보 추출 │
└──────────────────────────────┘
│
▼
┌──────────────────────────────┐
│ 2단계: Re-ranking (정밀하게) │
│ Cross-encoder / LLM │
│ → Top-100 → Top-10 재정렬 │
└──────────────────────────────┘
│
▼
┌──────────────────────────────┐
│ 3단계: Generation (RAG) │
│ LLM이 Top-K 문서 기반 답변 │
│ + Citation / Grounding │
└──────────────────────────────┘
Retrieval → Re-ranking → Generation = 현대 RAG의 표준 3단계
Hybrid Search를 지원하는 주요 오픈소스 검색 엔진
| 엔진 | 라이선스 | Sparse | Dense | Hybrid | 특징 |
|---|---|---|---|---|---|
| Elasticsearch | SSPL / ELv2 | ✓ BM25 | ✓ kNN | ✓ RRF | 가장 넓은 생태계, 8.x부터 벡터 검색 |
| OpenSearch | Apache 2.0 | ✓ BM25 | ✓ kNN | ✓ 가중합 | AWS 주도, ES 포크, 완전 오픈소스 |
| Weaviate | BSD-3 | ✓ BM25 | ✓ HNSW | ✓ 네이티브 | 벡터 네이티브 DB, GraphQL API |
| Qdrant | Apache 2.0 | ✓ Sparse | ✓ HNSW | ✓ Fusion | Rust 기반, 고성능, gRPC/REST |
| Milvus | Apache 2.0 | ✓ Sparse | ✓ 다수 | ✓ RRF | 대규모 벡터 검색 특화, GPU 지원 |
| Vespa | Apache 2.0 | ✓ BM25 | ✓ ANN | ✓ 네이티브 | Yahoo 출신, ML 랭킹 내장 |
| Apache Solr | Apache 2.0 | ✓ BM25 | ✓ kNN | △ 수동 | 전통 강자, 9.x부터 벡터 |
전통 검색 엔진 (Sparse 출발) 벡터 DB (Dense 출발)
───────────────────────── ──────────────────────
Elasticsearch (2010) Milvus (2019)
OpenSearch (2021, ES 포크) Qdrant (2021)
Apache Solr (2004) Weaviate (2019)
Vespa (2017, 오픈소스) Chroma (2022)
───→ 양쪽 모두 Hybrid로 수렴 중 ←───
| 기준 | 추천 |
|---|---|
| 기존 ES/Solr 운영 중 | Elasticsearch 8.x / OpenSearch 업그레이드 |
| 벡터 검색 중심 신규 | Qdrant / Weaviate |
| 대규모 (억 건+) | Milvus / Vespa |
| 완전 오픈소스 필수 | OpenSearch / Qdrant / Milvus |
| 관리형 원하면 | Vertex AI Search / Amazon Kendra |
{
"retriever": {
"rrf": {
"retrievers": [
{
"standard": {
"query": {
"match": {
"content": "클라우드 보안 강화"
}
}
}
},
{
"knn": {
"field": "content_vector",
"query_vector_builder": {
"text_embedding": {
"model_id": "my-embedding-model",
"model_text": "클라우드 보안 강화"
}
},
"k": 10,
"num_candidates": 100
}
}
],
"rank_window_size": 50,
"rank_constant": 60
}
}
}
ES 8.x부터 RRF 기반 하이브리드 검색을 네이티브 지원
from qdrant_client import QdrantClient, models
client = QdrantClient("localhost", port=6333)
results = client.query_points(
collection_name="documents",
prefetch=[
models.Prefetch(
query=models.SparseVector(
indices=[1, 42, 1337],
values=[0.5, 0.8, 0.6]
),
using="bm25-sparse",
limit=20,
),
models.Prefetch(
query=dense_embedding, # [0.23, -0.41, ...]
using="dense-vector",
limit=20,
),
],
query=models.FusionQuery(
fusion=models.Fusion.RRF
),
limit=10,
)
Qdrant는 Sparse + Dense 벡터를 동시 저장하고 RRF로 결합
Google Cloud의 엔터프라이즈 검색 서비스
| 컴포넌트 | 역할 |
|---|---|
| Data Store | 문서 저장소 (웹, Cloud Storage, BigQuery 등) |
| Indexing | 자동 Sparse + Dense 인덱스 생성 |
| Search Engine | 하이브리드 검색 + 랭킹 |
| Serving Config | 부스팅, 필터, 스니펫 설정 |
Vertex AI Search는 자동으로 Hybrid Search를 수행
| 단계 | 기술 | 설명 |
|---|---|---|
| 1. Sparse | 자체 BM25 변형 | 키워드 기반 후보 추출 |
| 2. Dense | Gecko / 자체 Embedding | 의미 기반 후보 추출 |
| 3. Fusion | Google 자체 알고리즘 | Sparse + Dense 결합 |
| 4. Re-ranking | LLM 기반 Re-ranker | 최종 관련성 정렬 |
| 5. Summarization | Gemini | 검색 결과 요약·답변 |
| 설정 | 설명 | 기본값 |
|---|---|---|
| search_type | SEMANTIC / KEYWORD / HYBRID | HYBRID |
| boost_spec | 특정 필드/값 부스팅 | 없음 |
| filter | 메타데이터 필터링 | 없음 |
| snippet_spec | 스니펫 반환 여부 | 활성 |
| content_search_spec | 요약/추출 답변 설정 | 비활성 |
| chunk_spec | 청크 크기/오버랩 | 자동 |
search_type: HYBRID가 기본 — 별도 설정 없이 하이브리드 검색
LLM의 한계를 검색(Retrieval)으로 보완하는 아키텍처
질문 → [1. Retrieval] → 관련 문서 검색
↓
→ [2. Augment] → 프롬프트에 문서 삽입
↓
→ [3. Generate] → LLM이 문서 기반 답변 생성
검색 품질 = RAG 품질 — 검색이 틀리면 답변도 틀린다
| 전략 | RAG 적합도 | 이유 |
|---|---|---|
| Sparse Only | △ | 키워드 정확하지만 의미 누락 |
| Dense Only | △ | 의미 캡처하지만 고유명사 약함 |
| Hybrid | ✓✓ | 정확성 + 재현율 모두 확보 |
| Hybrid + Re-rank | ✓✓✓ | 최종 관련성까지 최적화 |
| 지표 | 의미 | 검색 전략 영향 |
|---|---|---|
| Recall@K | 상위 K개에 정답 포함 비율 | Hybrid > Dense > Sparse |
| Precision@K | 상위 K개 중 정답 비율 | Re-rank 적용 시 ↑ |
| MRR | 첫 정답의 역순위 평균 | Hybrid + Re-rank 최적 |
사용자 질문
↓
[Vertex AI Search] ← 하이브리드 검색 + Re-ranking
↓
관련 청크 (Top-K)
↓
[Prompt 구성] ← 시스템 프롬프트 + 검색 결과 + 사용자 질문
↓
[Gemini API] ← 문서 기반 답변 생성 + Citation
↓
최종 응답 (답변 + 출처)
| 계층 | 기술 | 역할 |
|---|---|---|
| 색인 | Inverted Index + Vector Index | Sparse + Dense 저장 |
| 검색 | BM25 + Embedding + ANN | 후보 문서 검색 |
| 결합 | RRF / 가중 합산 | 하이브리드 점수 산출 |
| 재랭킹 | Cross-encoder / LLM | 최종 관련성 정렬 |
| 생성 | Gemini / GPT / Claude | 문서 기반 답변 생성 |
| 검증 | Grounding / Citation | 출처 확인 + 할루시네이션 방지 |
검색은 RAG의 기초 체력 — 검색이 정확해야 AI가 똑똑해진다
AI와 검색 엔진 — RAG를 위한 검색 기술 가이드
문의: tech.mzgcp.net