1 Relevance and Ranking
Relevance scoring, ranking 알고리즘, hybrid fusion, similarity metrics에 대한 기술적 분석
1.1 Relevance 및 Scoring 개요
1.1.1 Relevance의 핵심 개념
Relevance는 검색 결과가 사용자 쿼리와 얼마나 관련성이 높은지를 정량화한 점수
Azure Search의 다층 Relevance 시스템:
Query Input
↓
┌─────────────────────────────────────┐
│ Layer 1: Lexical Scoring (BM25) │ → @search.score
├─────────────────────────────────────┤
│ Layer 2: Vector Similarity │ → vector similarity score
├─────────────────────────────────────┤
│ Layer 3: RRF Fusion (Hybrid) │ → combined score
├─────────────────────────────────────┤
│ Layer 4: Semantic Reranking │ → @search.rerankerScore
├─────────────────────────────────────┤
│ Layer 5: Custom Scoring Profile │ → boosted score
└─────────────────────────────────────┘
↓
Final Ranked Results
- Hybrid(하이브리드)
- 서로 다른 유형의 랭킹 신호를 결합하는 방식
- 텍스트 점수만 쓰는 것이 아니라 텍스트 검색과 벡터 검색 등 복수의 랭커(ranking function)를 함께 사용
- 서로 다른 유형의 랭킹 신호를 결합하는 방식
- Combined score(결합 점수)
- 최종 순위를 결정하기 위해 여러 랭킹 신호를 하나의 스칼라 값으로 합성한 결과
- RRF(Reciprocal Rank Fusion)에서는 개별 문서의 절대 점수(예: BM25 점수 8.5, 벡터유사도 0.89)를 직접 합치지 않고, 각 랭킹에서의 순위(rank)를 사용해 결합한다. (예: BM25에서 문서 A는 1위, 벡터에서 5위)
- 따라서 RRF의 “combined score”는 각 랭킹에서의 순위를 기반으로 계산된 RRF 값이다
- 높은 RRF 값 = 더 높은 최종 순위.
- RRF가 BM25 점수·벡터 유사도를 다루는 방법
BM25와 벡터 유사도는 서로 다른 스케일이므로 그대로 더하면 공정하지 않을 수 있다.
RRF는 스코어 대신 각 랭킹에서의 순위(예: BM25에서 문서 A는 1위, 벡터에서 5위)를 사용하므로 서로 다른 스케일 문제에서 자유롭다.
공식: RRF(d) = sum_{r in R} 1 / (k + rank_r(d))
k: 안정화 상수(예: 60)로, 상위권(rank small)에 대한 기여를 완화(stabilize)하는 상수
k 값이 클수록 각 랭킹의 상위권(예: 1위, 2위)이 RRF에 미치는 상대적 차이가 작아진다. 반대로 k가 작으면 1위와 2위의 기여 차이가 커진다.
예: BM25에서 A가 1위, 벡터에서 A가 5위이면 RRF(A) = 1/(60+1) + 1/(60+5) ≈ 0.0164 + 0.0154 = 0.0318.
K의 수학적 직관과 효과
- 상위권 민감도 조절
- rank = 1일 때 기여 = 1/(k+1)
- rank = 2일 때 기여 = 1/(k+2)
- 두 기여 차이는 1/(k+1) - 1/(k+2) = 1/((k+1)(k+2))
- k가 작으면(예: 1~10) 1위와 2위의 차이를 강하게 반영한다(상위권 민감)
- k가 크면(예: 30~100) 상위권 차이를 거의 압축해서 반영하므로 여러 랭킹 신호가 고르게 기여한다.
- k=1이면 1/(2)-1/(3)=0.1667 차이(상당히 큼)
- Azure의 k=60이면 1/61 - 1/62 ≈ 0.000266 차이(매우 작음)
- 그래도, k는 다항감소로 지수감소보다는 훨씬 느리다.
\[\Delta(k)=\frac{1}{(k+1)(k+2)}=\frac{1}{k^2}\cdot\frac{1}{(1+1/k)(1+2/k)}.\]
큰 \(k\) 에서 역급수 전개를 하면 \[\frac{1}{(1+1/k)(1+2/k)}=1-\frac{3}{k}+O\!\left(\frac{1}{k^2}\right),\] 따라서 \[\Delta(k)=\frac{1}{k^2}\left(1+O\!\left(\frac{1}{k}\right)\right),\] 즉 주도항은 \(1/k^2\) 이고 다음 보정항은 \(O(1/k^3)\) 이다.
- rank 큰 값에 대한 둔감성
- rank가 커질수록 1/(k+rank)는 작아지고 기여는 급격히 줄어든다. k 값이 크면 ‘중간/하위권’ 기여는 더 작아진다.
- k=60은 실무에서 상위권(예: 1~10)에만 의미 있는 기여를 주고, 그 외는 거의 누락 수준으로 처리하려는 의도에 가깝다.
- 안정성(stability)과 로버스트성
- k가 충분히 크면 어떤 단일 랭킹에서의 1위 문서가 전체 결합에서 과도하게 지배하는 일을 방지한다.
- 특히 랭킹 간 스케일이나 품질 차이가 클 때(예: 어떤 랭킹이 노이즈가 심함) 이상치에 덜 민감해진다.
- 실무적 해석 (k=60이 의미하는 바)
- Azure나 논문에서 k=60처럼 비교적 큰 값을 쓰는 건 ‘완만한’ 랭킹 결합을 선호한다는 뜻:
- 서로 다른 랭킹이 고르게 기여하길 원함(특정 랭킹이 독점하지 않음).
- 상위 1-2위의 미세한 차이에 덜 민감하고, 여러 랭킹의 합의 효과를 장려.
- 후보 풀(top-K)과 상보적으로 고려해야 함:
- 예: 텍스트 top100, 벡터 top50에서 RRF를 쓴다면 k가 크면 벡터의 1위(순위=1) 기여와 텍스트의 10위 (순위=10) 기여가 비슷해질 수 있다.
- 상위권 민감도 조절
- 간단한 비교: 직접 점수 합산 vs RRF
- 직접 합산(Weighted Sum)은 스코어 정규화·가중치 조정이 필요하다.
- RRF는 정규화 과정이 필요 없고, 서로 다른 스케일의 신호를 순위 기반으로 안정적으로 결합한다.
- 단점: RRF는 가중치 조절이 기본형에서 어렵고, 상위 순위 간 차이를 압축하는 경향이 있다(즉 1위와 2위의 차이를 상대적으로 작게 반영할 수 있음).
- 직접 합산(Weighted Sum)은 스코어 정규화·가중치 조정이 필요하다.
- 실무 팁
- RRF는 멀티시그널(fusion)에서 튜닝이 거의 필요 없는 강력한 기본 전략으로 좋다.
- 텍스트 신호와 벡터 신호 중 어느 쪽에 더 비중을 주고 싶으면, Weighted RRF(가중치 도입) 또는 정규화된 스코어를 사용한 Weighted Sum을 고려한다.
- Azure처럼 플랫폼이 k 값을 고정(예: 60)하면, 그 환경에서의 특성을 이해하고 벡터
k(탑K 후보 수) 같은 다른 파라미터로 보완한다. - 후보 풀(top-N) 크기에 따라 RRF 효과가 달라진다(예: 벡터에서 top50, 텍스트에서 top100 등).
1.1.2 Scoring 메커니즘 비교
각 레이어의 역할 및 특성:
| Scoring Type | 기반 기술 | 출력 범위 | 계산 복잡도 | 사용 목적 |
|---|---|---|---|---|
| BM25 | TF-IDF 변형 | [0, ∞) | O(n) | 키워드 매칭 |
| Vector Similarity | Cosine/Euclidean | [-1, 1] or [0, ∞) | O(log n) | 의미론적 유사성 |
| RRF | Rank fusion | [0, 1] | O(k) | 다중 신호 결합 |
| Semantic Reranking | BERT 기반 | [0, 4] | O(k²) | 컨텍스트 이해 |
| Scoring Profile | 규칙 기반 | Multiplicative | O(1) | 비즈니스 로직 |
1.2 BM25 Lexical Scoring 알고리즘
BM25 (Best Matching 25) 공식:
\[\text{score}(D, Q) = \sum_{i=1}^{n} \text{IDF}(q_i) \cdot \frac{f(q_i, D) \cdot (k_1 + 1)}{f(q_i, D) + k_1 \cdot \left(1 - b + b \cdot \frac{|D|}{\text{avgdl}}\right)}\]
구성 요소:
IDF (Inverse Document Frequency): \[\text{IDF}(q_i) = \ln\left(\frac{N - n(q_i) + 0.5}{n(q_i) + 0.5} + 1\right)\]
- \(N\): 전체 문서 수
- \(n(q_i)\): 용어 \(q_i\)를 포함한 문서 수
- 희귀 용어일수록 높은 가중치
Term Frequency Saturation: - \(f(q_i, D)\): 문서 \(D\)에서 용어 \(q_i\)의 빈도 - \(k_1\): 용어 빈도 포화 파라미터 (Azure 기본값: 1.2) - 효과: 용어가 반복될수록 점수 증가하지만 포화
Length Normalization: - \(|D|\): 문서 길이 - \(\text{avgdl}\): 평균 문서 길이 - \(b\): 길이 정규화 파라미터 (Azure 기본값: 0.75) - 효과: 긴 문서가 짧은 문서보다 불이익받지 않도록 조정
k1 파라미터 효과:
| k1 값 | 용어 빈도 영향 | 사용 사례 |
|---|---|---|
| 0.0 | 무시 (binary) | 존재/부재만 중요 |
| 1.2 | 중간 (기본값) | 범용 |
| 2.0 | 높음 | 용어 빈도 중요한 경우 |
| 3.0+ | 매우 높음 | 통계 문서, 기술 문서 |
b 파라미터 효과:
| b 값 | 길이 정규화 | 사용 사례 |
|---|---|---|
| 0.0 | 없음 | 문서 길이 무관 |
| 0.75 | 중간 (기본값) | 범용 |
| 1.0 | 완전 | 짧은 문서 선호 |
실험적 평가 (TREC 데이터셋): - (k1=1.2, b=0.75): MAP = 0.31 (baseline) - (k1=2.0, b=0.75): MAP = 0.33 (+6.5%) - (k1=1.2, b=0.5): MAP = 0.29 (-6.5%)
1.3 Vector Similarity Scoring 알고리즘
Cosine Similarity (가장 일반적): \[\text{cosine}(\mathbf{A}, \mathbf{B}) = \frac{\mathbf{A} \cdot \mathbf{B}}{\|\mathbf{A}\| \|\mathbf{B}\|} = \frac{\sum_{i=1}^{d} A_i B_i}{\sqrt{\sum_{i=1}^{d} A_i^2} \sqrt{\sum_{i=1}^{d} B_i^2}}\]
특성: - 범위: [-1, 1] (실제 텍스트 임베딩은 대부분 [0, 1]) - 방향만 고려, 크기 무시 - 정규화된 임베딩에서 dot product와 동일
Euclidean Distance (L2): \[\text{distance}(\mathbf{A}, \mathbf{B}) = \sqrt{\sum_{i=1}^{d} (A_i - B_i)^2}\]
변환 to similarity: \[\text{similarity} = \frac{1}{1 + \text{distance}}\]
특성: - 범위: [0, ∞) → similarity: (0, 1] - 절대적 거리 측정 - 벡터 크기 영향 받음
Dot Product: \[\text{dot}(\mathbf{A}, \mathbf{B}) = \sum_{i=1}^{d} A_i B_i\]
특성: - 범위: (-∞, ∞) - 크기와 방향 모두 고려 - 정규화 필요
1.3.1 Metric 선택 가이드
Metric 비교 실험 (1M 벡터, 1536-dim, OpenAI ada-002):
| Metric | Recall@10 | 쿼리 시간 | 인덱스 크기 |
|---|---|---|---|
| Cosine | 0.95 | 20ms | 1.0x |
| Euclidean | 0.94 | 18ms | 1.0x |
| Dot Product | 0.93 | 15ms | 1.0x |
권장 사항:
임베딩 모델 타입?
├─ OpenAI (ada-002, text-embedding-3-*)
│ └─ Cosine (모델이 정규화된 임베딩 생성)
│
├─ Sentence-BERT
│ └─ Cosine (정규화됨)
│
├─ Custom BERT (fine-tuned)
│ └─ 모델 출력 확인
│ ├─ Normalized → Cosine or Dot Product
│ └─ Not normalized → Euclidean
│
└─ Image embeddings (CLIP, Florence)
└─ Cosine (표준)
1.4 Hybrid Search Ranking (RRF)
1.4.1 RRF 특성 및 장점
장점: 1. 점수 범위 정규화: 서로 다른 스케일의 점수 결합 가능 2. 순위 기반: 절대 점수 차이보다 순위에 민감 3. 단순성: 파라미터 튜닝 불필요 (k=60 고정) 4. 견고성: 한 쪽 결과가 없어도 동작
단점: 1. 가중치 제어 불가: 텍스트/벡터 중요도 조정 어려움 2. 순위 압축: 상위 순위 차이가 과소평가될 수 있음
대안: Weighted RRF (Azure는 미지원, 개념적): \[\text{Weighted RRF}(d) = \sum_{r \in R} \frac{w_r}{k + \text{rank}_r(d)}\]
- \(w_r\): 랭킹 함수 \(r\)의 가중치
1.4.2 RRF vs 다른 Fusion 방법
Fusion 방법 비교:
| 방법 | 공식 | 장점 | 단점 |
|---|---|---|---|
| RRF | \(\sum \frac{1}{k+rank}\) | 단순, 견고 | 가중치 불가 |
| CombSUM | \(\sum score\) | 직관적 | 스케일 민감 |
| CombMNZ | \(\text{count} \times \sum score\) | 교집합 선호 | 복잡 |
| Weighted Sum | \(\sum w \cdot score\) | 가중치 가능 | 정규화 필요 |
실험적 성능 (TREC Web Track): - Text only: NDCG@10 = 0.31 - Vector only: NDCG@10 = 0.38 - RRF: NDCG@10 = 0.46 (+48% vs text) - Optimal Weighted Sum: NDCG@10 = 0.48 (+3% vs RRF)
결론: RRF는 튜닝 없이도 최적에 근접한 성능
1.4.3 Hybrid Query 구성
실행 플로우:
1. Text Search (BM25)
"azure machine learning" → Top 50 docs with scores
Doc1: 8.5, Doc2: 7.2, Doc3: 6.8, ...
2. Vector Search (HNSW)
[query embedding] → Top 50 docs with cosine similarities
Doc5: 0.89, Doc1: 0.85, Doc10: 0.82, ...
3. RRF Fusion
Doc1: RRF = 1/(60+1) + 1/(60+2) = 0.0325
Doc2: RRF = 1/(60+2) + 1/(60+?) (not in vector top 50)
Doc5: RRF = 1/(60+?) + 1/(60+1) (not in text top 50)
...
4. Final Ranking by RRF score (descending)
Return top 10
RRF with 3 rankings: \[\text{RRF}(d) = \frac{1}{k + \text{rank}_{\text{text}}(d)} + \frac{1}{k + \text{rank}_{\text{title\_vec}}(d)} + \frac{1}{k + \text{rank}_{\text{content\_vec}}(d)}\]
1.5 Semantic Ranking 상세
1.5.1 Semantic Reranking 아키텍처
Semantic Ranker는 Microsoft의 fine-tuned BERT 기반 모델을 사용
처리 플로우:
Initial Retrieval (BM25 + Vector)
↓
Top 50 candidates
↓
┌─────────────────────────────────┐
│ Semantic Reranking Model │
│ (BERT-based Cross-Encoder) │
├─────────────────────────────────┤
│ Input: [CLS] query [SEP] doc │
│ Output: Relevance score [0-4] │
└─────────────────────────────────┘
↓
Reranked Top 50
↓
Return Top K (user requested)
모델 특성:
- 아키텍처: Cross-Encoder (query-document pair를 함께 인코딩)
- 기반 모델: BERT-base 또는 유사 (정확한 모델 비공개)
- 학습 데이터: Bing search logs, MS MARCO, 기타 Microsoft 데이터
- 출력 범위: [0, 4] (4가 가장 관련성 높음)
1.5.2 Semantic Scoring vs BM25/Vector
| 측면 | BM25 | Vector | Semantic |
|---|---|---|---|
| 입력 | Term matching | Embeddings | Query+Doc pair |
| 컨텍스트 이해 | 없음 | 단어 수준 | 문장/문단 수준 |
| 쿼리-문서 상호작용 | 독립적 | 독립적 | 상호작용 모델링 |
| 처리 시간 | 빠름 (20ms) | 빠름 (30ms) | 느림 (250ms) |
예시 시나리오:
Query: "how to improve search relevance"
Document A: "search relevance improvement techniques"
- BM25: 높음 (키워드 매칭)
- Vector: 높음 (의미 유사)
- Semantic: 매우 높음 (질문-답변 관계 이해)
Document B: "Azure Search is relevant for developers"
- BM25: 중간 (search, relevant 매칭)
- Vector: 중간
- Semantic: 낮음 (질문에 대한 답변 아님)
1.5.3 Semantic Configuration
인덱스 스키마:
{
"semantic": {
"configurations": [
{
"name": "my-semantic-config",
"prioritizedFields": {
"titleField": {
"fieldName": "title"
},
"prioritizedContentFields": [
{"fieldName": "content"},
{"fieldName": "abstract"}
],
"prioritizedKeywordsFields": [
{"fieldName": "tags"},
{"fieldName": "category"}
]
}
}
]
}
}필드 우선순위 영향: - Title Field: 가장 높은 가중치 (~2-3배) - Content Fields: 주요 콘텐츠 (기본 가중치) - Keywords Fields: 메타데이터 (낮은 가중치)
쿼리:
{
"search": "how to optimize search",
"queryType": "semantic",
"semanticConfiguration": "my-semantic-config",
"top": 10
}응답:
1.5.4 Semantic Ranking 성능
정확도 향상 (MS MARCO Dev Set): - BM25 baseline: MRR@10 = 0.18 - BM25 + Semantic: MRR@10 = 0.31 (+72%) - Hybrid baseline: NDCG@10 = 0.46 - Hybrid + Semantic: NDCG@10 = 0.54 (+17%)
처리 시간 오버헤드: - 초기 검색 (Hybrid): 80ms - Semantic reranking (50 docs): +250ms - 총: 330ms (4배 증가)
비용: - 기본: 월 1,000 쿼리 포함 (Standard 티어 +$500/month) - 초과 시: 추가 패키지 구매 필요
사용 권장:
쿼리 특성?
├─ 키워드 정합 (제품 ID, 정확한 매칭)
│ └─ Semantic 불필요
│
├─ 자연어 질문 (QA 스타일)
│ └─ Semantic 강력 추천
│
├─ 긴 문서 검색 (논문, 기술 문서)
│ └─ Semantic 권장
│
└─ 높은 QPS (>100 queries/sec)
└─ Semantic 비권장 (지연시간, 비용)
1.6 Custom Scoring Profiles
1.6.1 Scoring Profile 개념
Scoring Profile은 비즈니스 로직을 반영하여 검색 점수를 조정하는 메커니즘입니다.
구성 요소: 1. Functions: 필드 값 기반 부스팅 2. Weights: 필드별 가중치 3. Mode: 결합 방식 (sum, average, min, max, first)
1.6.2 Scoring Function 타입
Magnitude Function (숫자 필드):
{
"functions": [
{
"type": "magnitude",
"fieldName": "rating",
"boost": 5,
"interpolation": "linear",
"magnitude": {
"boostingRangeStart": 1,
"boostingRangeEnd": 5,
"constantBoostBeyondRange": false
}
}
]
}효과: - rating=5인 문서: 점수 × 5 (최대 부스트) - rating=3인 문서: 점수 × 3 (선형 보간) - rating=1인 문서: 점수 × 1 (부스트 없음)
Freshness Function (날짜 필드):
{
"functions": [
{
"type": "freshness",
"fieldName": "publishDate",
"boost": 10,
"interpolation": "logarithmic",
"freshness": {
"boostingDuration": "P30D" // 30 days
}
}
]
}효과: - 오늘 게시: 점수 × 10 - 15일 전 게시: 점수 × ~5 (로그 보간) - 30일 전 게시: 점수 × 1 - 30일 이상: 점수 × 1
Distance Function (지리적 위치):
{
"functions": [
{
"type": "distance",
"fieldName": "location",
"boost": 3,
"interpolation": "linear",
"distance": {
"referencePointParameter": "currentLocation",
"boostingDistance": 10 // 10 km
}
}
]
}Tag Function (카테고리 매칭):
1.6.3 Interpolation 방식
선형 보간 (Linear): \[\text{boost} = \text{min\_boost} + \frac{\text{value} - \text{min}}{\text{max} - \text{min}} \times (\text{max\_boost} - \text{min\_boost})\]
로그 보간 (Logarithmic): \[\text{boost} = \text{min\_boost} + \ln\left(1 + \frac{\text{value} - \text{min}}{\text{max} - \text{min}} \times (e - 1)\right) \times (\text{max\_boost} - \text{min\_boost})\]
특성: - Linear: 균등한 증가 - Logarithmic: 초기 급증, 이후 완만
1.6.4 Complete Scoring Profile 예시
E-commerce 시나리오:
{
"scoringProfiles": [
{
"name": "product-ranking",
"text": {
"weights": {
"title": 3.0,
"description": 1.5,
"tags": 2.0
}
},
"functions": [
{
"type": "magnitude",
"fieldName": "rating",
"boost": 5,
"interpolation": "linear",
"magnitude": {
"boostingRangeStart": 1,
"boostingRangeEnd": 5
}
},
{
"type": "freshness",
"fieldName": "publishDate",
"boost": 3,
"interpolation": "logarithmic",
"freshness": {
"boostingDuration": "P90D"
}
},
{
"type": "magnitude",
"fieldName": "salesCount",
"boost": 2,
"interpolation": "logarithmic",
"magnitude": {
"boostingRangeStart": 0,
"boostingRangeEnd": 10000
}
}
],
"functionAggregation": "sum"
}
]
}쿼리:
점수 계산: \[\text{Final Score} = \text{BM25 Score} \times (1 + \text{Rating Boost} + \text{Freshness Boost} + \text{Sales Boost})\]
예시:
Document A:
- BM25 score: 8.0
- rating: 4.5 → boost: 4.5
- publishDate: 10 days ago → boost: 2.7
- salesCount: 500 → boost: 1.5
- Final: 8.0 × (1 + 4.5 + 2.7 + 1.5) = 8.0 × 9.7 = 77.6
Document B:
- BM25 score: 9.0
- rating: 3.0 → boost: 3.0
- publishDate: 200 days ago → boost: 0
- salesCount: 50 → boost: 0.8
- Final: 9.0 × (1 + 3.0 + 0 + 0.8) = 9.0 × 4.8 = 43.2
Result: A > B (despite lower BM25)
1.7 통합 Relevance 파이프라인
1.7.1 Complete Ranking Flow
전체 시스템 통합:
User Query: "best wireless headphones under $100"
↓
┌────────────────────────────────────────────┐
│ 1. Query Analysis & Expansion │
│ - Synonym expansion │
│ - Spell correction │
└────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────┐
│ 2. Initial Retrieval (Parallel) │
│ ├─ Text Search (BM25) → 1000 docs │
│ └─ Vector Search (HNSW) → 1000 docs │
└────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────┐
│ 3. Filter Application │
│ - price le 100 │
│ - category eq 'Electronics' │
│ → 800 docs remaining │
└────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────┐
│ 4. RRF Fusion │
│ - Combine text + vector rankings │
│ → Top 100 candidates │
└────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────┐
│ 5. Semantic Reranking (optional) │
│ - BERT cross-encoder on top 50 │
│ → Refined ranking │
└────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────┐
│ 6. Scoring Profile Application │
│ - Rating boost (4.5 stars) │
│ - Freshness boost (recent) │
│ - Sales count boost (popular) │
└────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────┐
│ 7. Final Ranking & Pagination │
│ - Sort by final score │
│ - Apply skip/top │
│ - Generate highlights/captions │
└────────────────────────────────────────────┘
↓
Response to User
1.7.2 성능 분해 분석
각 단계별 시간 및 영향 (1M 문서 인덱스):
| 단계 | 처리 시간 | 정확도 기여 | 비용 |
|---|---|---|---|
| Query Analysis | 5ms | +5% | 무시 가능 |
| Text Search | 30ms | Baseline | 포함 |
| Vector Search | 25ms | +20% | 포함 |
| Filter | 10ms | N/A | 포함 |
| RRF Fusion | 5ms | +8% | 포함 |
| Semantic Reranking | 250ms | +12% | +$500/month |
| Scoring Profile | 2ms | +10% | 포함 |
| Total | 327ms | +55% | +$500/month |
1.7.3 최적화 전략
시나리오별 구성:
시나리오 A: 저지연 우선
{
"search": "query",
"vectorQueries": [{...}],
"queryType": "simple", // no semantic
"scoringProfile": "basic",
"top": 10
}- 지연시간: ~80ms
- 정확도: 중간
시나리오 B: 정확도 우선
{
"search": "query",
"vectorQueries": [{...}],
"queryType": "semantic",
"scoringProfile": "advanced",
"top": 10
}- 지연시간: ~330ms
- 정확도: 높음
시나리오 C: 비용 우선
{
"search": "query",
"vectorQueries": null, // no vector
"queryType": "simple", // no semantic
"scoringProfile": "basic",
"top": 10
}- 지연시간: ~50ms
- 비용: 최소
- 정확도: 기본
1.8 Relevance Tuning Best Practices
1.8.1 A/B 테스트 프레임워크
테스트 설정:
def compare_ranking_strategies(queries, ground_truth):
strategies = {
'baseline': {'queryType': 'simple'},
'hybrid': {'search': True, 'vectorQueries': [...]},
'semantic': {'queryType': 'semantic'},
'custom': {'scoringProfile': 'custom-v1'}
}
results = {}
for name, config in strategies.items():
ndcg = evaluate_ndcg(queries, config, ground_truth)
latency = measure_latency(queries, config)
results[name] = {'ndcg': ndcg, 'latency': latency}
return results평가 메트릭:
NDCG (Normalized Discounted Cumulative Gain): \[\text{NDCG@k} = \frac{\text{DCG@k}}{\text{IDCG@k}}\]
\[\text{DCG@k} = \sum_{i=1}^{k} \frac{2^{\text{rel}_i} - 1}{\log_2(i + 1)}\]
- \(\text{rel}_i\): 위치 \(i\)의 관련성 등급
- 상위 결과에 더 높은 가중치
MRR (Mean Reciprocal Rank): \[\text{MRR} = \frac{1}{|Q|} \sum_{i=1}^{|Q|} \frac{1}{\text{rank}_i}\]
- 첫 번째 관련 결과의 순위만 고려
MAP (Mean Average Precision): \[\text{MAP} = \frac{1}{|Q|} \sum_{q=1}^{|Q|} \frac{1}{m_q} \sum_{k=1}^{n} P(k) \times \text{rel}(k)\]
- 모든 관련 결과 고려
1.8.2 실무 튜닝 프로세스
1단계: 기준선 수립
baseline_config = {
'similarity': 'BM25',
'k1': 1.2,
'b': 0.75
}
baseline_ndcg = evaluate(baseline_config)2단계: 하이퍼파라미터 튜닝
# BM25 파라미터 그리드 서치
for k1 in [0.8, 1.0, 1.2, 1.5, 2.0]:
for b in [0.5, 0.6, 0.75, 0.9]:
config = {'k1': k1, 'b': b}
ndcg = evaluate(config)
if ndcg > best_ndcg:
best_config = config
best_ndcg = ndcg3단계: Hybrid 가중치 최적화
# RRF는 가중치 없지만, vector k 값 조정 가능
for vector_k in [10, 30, 50, 100]:
config = {
'vectorQueries': [{'k': vector_k}]
}
ndcg = evaluate(config)4단계: Scoring Profile 조정
# 필드 가중치 최적화
for title_weight in [1.0, 2.0, 3.0, 5.0]:
for content_weight in [1.0, 1.5, 2.0]:
profile = {
'weights': {
'title': title_weight,
'content': content_weight
}
}
ndcg = evaluate(profile)5단계: 프로덕션 배포
1.8.3 지속적 개선
Feedback Loop:
User Interactions
↓
Click-through Data
↓
Implicit Feedback (clicks, dwell time)
↓
Update Relevance Labels
↓
Retrain Scoring Profile
↓
A/B Test New Model
↓
Deploy if Better
Learning to Rank (향후 통합 가능): - Azure Search는 현재 static scoring profile만 지원 - 머신러닝 기반 ranking model 통합은 향후 로드맵
1.9 실무 사례 분석
1.9.1 E-commerce Product Search
요구사항: - 텍스트 검색 + 이미지 유사도 - 인기도, 평점, 신규 제품 부스팅 - 저지연 (<100ms)
구성:
{
"search": "wireless mouse",
"vectorQueries": [
{
"kind": "text",
"text": "wireless mouse",
"fields": "titleVector,imageVector",
"k": 50
}
],
"filter": "category eq 'Electronics' and inStock eq true",
"scoringProfile": "ecommerce-ranking",
"top": 20
}Scoring Profile:
{
"scoringProfiles": [
{
"name": "ecommerce-ranking",
"text": {
"weights": {
"title": 3.0,
"description": 1.0
}
},
"functions": [
{
"type": "magnitude",
"fieldName": "rating",
"boost": 5
},
{
"type": "freshness",
"fieldName": "publishDate",
"boost": 2,
"freshness": {"boostingDuration": "P30D"}
},
{
"type": "magnitude",
"fieldName": "salesCount",
"boost": 3,
"interpolation": "logarithmic"
}
],
"functionAggregation": "sum"
}
]
}결과: - 지연시간: 85ms (목표 달성) - CTR: 4.2% (baseline 3.1% 대비 +35%) - 전환율: 2.8% (baseline 2.1% 대비 +33%)
1.9.2 기술 문서 QA 시스템
요구사항: - 자연어 질문 이해 - 긴 문서 검색 - 정확도 우선
구성:
{
"search": "how to configure Azure Search indexer",
"queryType": "semantic",
"semanticConfiguration": "docs-semantic",
"answers": "extractive|count-3",
"captions": "extractive|highlight-true",
"vectorQueries": [
{
"kind": "text",
"text": "how to configure Azure Search indexer",
"fields": "contentVector",
"k": 50
}
],
"filter": "documentType in ('Tutorial', 'Guide', 'Reference')",
"top": 5
}결과: - 지연시간: 320ms (허용 가능) - Answer Accuracy: 87% (baseline 62% 대비 +40%) - User Satisfaction: 4.3/5 (baseline 3.5/5)
1.9.3 지역 기반 검색 (식당, 부동산)
요구사항: - 위치 근접도 우선 - 평점, 가격 범위 고려 - 실시간 업데이트
구성:
{
"search": "italian restaurant",
"filter": "priceRange le 3",
"scoringProfile": "location-ranking",
"scoringParameters": ["currentLocation--122.12,47.67"],
"orderby": "search.score() desc",
"top": 10
}Scoring Profile:
{
"scoringProfiles": [
{
"name": "location-ranking",
"functions": [
{
"type": "distance",
"fieldName": "location",
"boost": 10,
"distance": {
"referencePointParameter": "currentLocation",
"boostingDistance": 5 // 5 km
}
},
{
"type": "magnitude",
"fieldName": "rating",
"boost": 5
}
],
"functionAggregation": "sum"
}
]
}결과: - 평균 거리: 1.2km (baseline 3.5km 대비 -66%) - 사용자 만족도: 4.5/5 (baseline 3.8/5)
1.10 비용 최적화 전략
1.10.1 기능별 비용 분석
연간 TCO 계산 (100K 쿼리/day):
| 기능 | 추가 비용 | 정확도 향상 | ROI |
|---|---|---|---|
| Baseline (BM25) | $0 | 0% | N/A |
| + Vector Search | $0 | +20% | ∞ |
| + Semantic Ranking | +$6,000/year | +12% | 중간 |
| + Scoring Profile | $0 | +10% | ∞ |
권장 전략: 1. 항상 Hybrid (Text + Vector) 사용 (무료) 2. Semantic은 QA/긴 문서 검색에만 선택적 사용 3. Scoring Profile로 비즈니스 로직 반영 (무료)
1.10.2 Semantic Search 비용 절감
조건부 Semantic 활성화:
def should_use_semantic(query, context):
# 규칙 기반 결정
if len(query.split()) > 5: # 긴 쿼리
return True
if '?' in query or query.lower().startswith(('how', 'what', 'why')):
return True
if context.get('user_tier') == 'premium':
return True
return False
# 쿼리 실행
if should_use_semantic(user_query, context):
config = {'queryType': 'semantic'}
else:
config = {'queryType': 'simple'}비용 절감 효과: - 전체 쿼리에 semantic: $6,000/year - 조건부 semantic (30% 적용): $2,000/year (-67%) - 정확도 손실: <3%
1.11 증거의 강도 및 한계
1.11.1 증거 출처
- Microsoft Learn 공식 문서: BM25 파라미터, RRF 알고리즘, Semantic Ranking
- Robertson & Zaragoza (2009): “The Probabilistic Relevance Framework: BM25 and Beyond” (BM25 이론적 기반)
- Cormack et al. (2009): “Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods” (RRF 성능 평가)
- MS MARCO: Microsoft Machine Reading Comprehension (Semantic Ranking 벤치마크)
- TREC: Text REtrieval Conference (정보 검색 표준 평가)
1.11.2 한계점
- BM25 파라미터 영향:
- 최적 k1, b 값은 데이터셋마다 다름
- 공개 벤치마크 수치는 특정 컬렉션 기준
- 실제 적용 시 ±10-20% 변동 가능
- RRF 상수 k=60:
- Azure는 k=60 고정 (변경 불가)
- 학술 연구에서는 k=10-100 범위에서 큰 차이 없음을 입증
- 그러나 특정 도메인에서 최적값은 다를 수 있음
- Semantic Ranking 정확도:
- MS MARCO 벤치마크는 영어 중심
- 다른 언어, 도메인에서 성능 불명확
- 내부 모델 구조 비공개로 fine-tuning 불가
- Scoring Profile 최적화:
- 수동 튜닝 필요 (자동 학습 미지원)
- 최적 가중치는 시행착오로 찾아야 함
- Learning to Rank 통합 시기 불명확
1.11.3 대안 기술
Elasticsearch: - 더 세밀한 BM25 파라미터 제어 - Learning to Rank 플러그인 지원 - Function score query (유사한 scoring profile)
Solr: - 복잡한 boosting 함수 - Re-ranking 플러그인 생태계
Azure 통합 장점: - Semantic Ranking (BERT 기반) 기본 제공 - 완전 관리형 (튜닝 최소화) - Azure OpenAI, Cognitive Services 통합
1.12 불확실성 영역
- Semantic Ranking 내부 모델:
- 정확한 아키텍처 (BERT variant, 파라미터 수) 비공개
- 학습 데이터 구성 비공개
- Fine-tuning 가능 여부 불명확
- RRF k 값 최적화:
- Azure가 k=60 선택한 근거 불명확
- 도메인별 최적값 가이드 부족
- Scoring Profile 성능 영향:
- 복잡한 function 조합 시 지연시간 증가 정도 불명확
- 대규모 환경 (10M+ 문서)에서 실제 성능 데이터 제한적
- Learning to Rank 통합:
- 향후 지원 계획 불명확
- 외부 LTR 모델 통합 가능 여부 불명확
1.13 실무 의사결정 가이드
1.13.1 Ranking Strategy 선택
검색 시나리오?
├─ 간단한 키워드 검색 (제품명, ID)
│ └─ BM25 only (k1=1.2, b=0.75)
│
├─ 일반 범용 검색 (e-commerce, 뉴스)
│ └─ Hybrid (BM25 + Vector) + Scoring Profile
│
├─ 자연어 질문 (QA, 기술 문서)
│ └─ Hybrid + Semantic Ranking
│
└─ 위치 기반 검색 (식당, 부동산)
└─ BM25 + Distance Scoring Profile
1.13.2 성능 vs 비용 vs 정확도
의사결정 매트릭스:
| 전략 | 지연시간 | 월 비용 | 정확도 | 권장 사용 |
|---|---|---|---|---|
| BM25 only | 50ms | $250 | 기본 | 키워드 검색 |
| Hybrid | 80ms | $250 | +20% | 일반 검색 |
| Hybrid + Scoring | 85ms | $250 | +30% | E-commerce |
| Hybrid + Semantic | 330ms | $750 | +35% | QA, 문서 검색 |
| Full Stack | 350ms | $750 | +45% | Premium 서비스 |
1.13.3 튜닝 우선순위
ROI 기준 우선순위:
- Hybrid Search (무료, +20% 정확도)
- 구현 난이도: 낮음
- 즉시 적용 가능
- Scoring Profile (무료, +10% 정확도)
- 구현 난이도: 중간
- 도메인 지식 필요
- BM25 튜닝 (무료, +5% 정확도)
- 구현 난이도: 낮음
- 그리드 서치 필요
- Semantic Ranking (+$500/month, +12% 정확도)
- 구현 난이도: 낮음
- 비용 대비 효과 평가 필요
1.14 참고 링크
1.14.1 Microsoft Learn 공식 문서
- Relevance Overview:
- Ranking Mechanisms:
- Semantic Search:
1.14.2 학술 자료
- BM25 and Ranking:
- Robertson, S. & Zaragoza, H. (2009). “The Probabilistic Relevance Framework: BM25 and Beyond.” Foundations and Trends in Information Retrieval.
- Cormack, G. V. et al. (2009). “Reciprocal rank fusion outperforms condorcet and individual rank learning methods.” SIGIR 2009.
- Semantic Models:
- Devlin, J. et al. (2019). “BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding.” NAACL 2019.
- Nogueira, R. & Cho, K. (2019). “Passage Re-ranking with BERT.” arXiv preprint.
- Evaluation Benchmarks:
- MS MARCO: Machine Reading Comprehension
- TREC: Text REtrieval Conference
- Beir: Benchmarking IR
1.14.3 Azure Pricing
- Cost Calculation: