Relevance and Ranking

Relevance scoring, hybrid ranking and semantic reranking in Azure Search

Relevance scoring과 ranking 알고리즘(BM25, vector, RRF, semantic reranker)과 실무적 하이브리드 패턴을 정리한다. 파라미터 튜닝, fusion 전략, 성능·비용 고려사항을 다룬다.

AI
Cloud
Azure
저자

Kwangmin Kim

공개

2025년 12월 26일

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의 수학적 직관과 효과

      1. 상위권 민감도 조절
      • 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)\) 이다.

      1. rank 큰 값에 대한 둔감성
      • rank가 커질수록 1/(k+rank)는 작아지고 기여는 급격히 줄어든다. k 값이 크면 ‘중간/하위권’ 기여는 더 작아진다.
      • k=60은 실무에서 상위권(예: 1~10)에만 의미 있는 기여를 주고, 그 외는 거의 누락 수준으로 처리하려는 의도에 가깝다.
      1. 안정성(stability)과 로버스트성
      • k가 충분히 크면 어떤 단일 랭킹에서의 1위 문서가 전체 결합에서 과도하게 지배하는 일을 방지한다.
      • 특히 랭킹 간 스케일이나 품질 차이가 클 때(예: 어떤 랭킹이 노이즈가 심함) 이상치에 덜 민감해진다.
      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위의 차이를 상대적으로 작게 반영할 수 있음).
  • 실무 팁
    • 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
}

응답:

{
  "value": [
    {
      "@search.score": 8.5,           // BM25 score
      "@search.rerankerScore": 3.2,   // Semantic score [0-4]
      "id": "doc1",
      "title": "Search Optimization Guide"
    }
  ]
}

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 (카테고리 매칭):

{
  "functions": [
    {
      "type": "tag",
      "fieldName": "tags",
      "boost": 8,
      "tag": {
        "tagsParameter": "preferredTags"
      }
    }
  ]
}

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"
    }
  ]
}

쿼리:

{
  "search": "laptop",
  "scoringProfile": "product-ranking"
}

점수 계산: \[\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 = ndcg

3단계: 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단계: 프로덕션 배포

# Shadow testing
production_results = query_with_config(prod_config)
canary_results = query_with_config(new_config)

if canary_ndcg > production_ndcg + 0.05:  # 5% 개선
    deploy_to_production(new_config)

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.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 한계점

  1. BM25 파라미터 영향:
    • 최적 k1, b 값은 데이터셋마다 다름
    • 공개 벤치마크 수치는 특정 컬렉션 기준
    • 실제 적용 시 ±10-20% 변동 가능
  2. RRF 상수 k=60:
    • Azure는 k=60 고정 (변경 불가)
    • 학술 연구에서는 k=10-100 범위에서 큰 차이 없음을 입증
    • 그러나 특정 도메인에서 최적값은 다를 수 있음
  3. Semantic Ranking 정확도:
    • MS MARCO 벤치마크는 영어 중심
    • 다른 언어, 도메인에서 성능 불명확
    • 내부 모델 구조 비공개로 fine-tuning 불가
  4. 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 불확실성 영역

  1. Semantic Ranking 내부 모델:
    • 정확한 아키텍처 (BERT variant, 파라미터 수) 비공개
    • 학습 데이터 구성 비공개
    • Fine-tuning 가능 여부 불명확
  2. RRF k 값 최적화:
    • Azure가 k=60 선택한 근거 불명확
    • 도메인별 최적값 가이드 부족
  3. Scoring Profile 성능 영향:
    • 복잡한 function 조합 시 지연시간 증가 정도 불명확
    • 대규모 환경 (10M+ 문서)에서 실제 성능 데이터 제한적
  4. 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 기준 우선순위:

  1. Hybrid Search (무료, +20% 정확도)
    • 구현 난이도: 낮음
    • 즉시 적용 가능
  2. Scoring Profile (무료, +10% 정확도)
    • 구현 난이도: 중간
    • 도메인 지식 필요
  3. BM25 튜닝 (무료, +5% 정확도)
    • 구현 난이도: 낮음
    • 그리드 서치 필요
  4. Semantic Ranking (+$500/month, +12% 정확도)
    • 구현 난이도: 낮음
    • 비용 대비 효과 평가 필요

1.14 참고 링크

1.14.1 Microsoft Learn 공식 문서

  1. Relevance Overview:
  2. Ranking Mechanisms:
  3. Semantic Search:

1.14.2 학술 자료

  1. 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.
  2. 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.
  3. Evaluation Benchmarks:

1.14.3 Azure Pricing

  1. Cost Calculation:

Subscribe

Enjoy this blog? Get notified of new posts by email: