본문 바로가기
C.W.K.
Stream
Lesson 04 of 05 · published

검색 구성 평가와 조정

~22 min · hybrid, evaluation

Level 0Scout
0 XP0/41 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

평가 집합은 가장 값진 산출물이야

검색 개선은 측정하기 전까지 모두 추측이야. 실제 사용자를 반영한 쿼리와 문서 쌍 50–200개에 라벨을 붙여 평가 집합을 만들어. 각 쿼리마다 확실히 관련 있는 문서 ID를 적어 두면, 이 작은 집합이 앞으로 모든 조정의 근거가 돼.

알아둘 지표 네 가지

  • Hit rate @ k — 상위 k개 안에 관련 문서가 하나라도 있는 쿼리의 비율이야.
  • MRR(Mean Reciprocal Rank) — 첫 관련 문서가 나온 위치의 역수야. 맞는 답이 얼마나 위에 놓였는지 보여줘.
  • nDCG @ k — 관련성의 정도와 결과 위치를 함께 반영하는 업계 표준 지표야.
  • Recall @ k — 전체 관련 문서 가운데 실제로 검색한 비율이야. LLM이 관련 자료를 빠짐없이 봐야 하는 RAG에서 특히 중요해.

변경할 때마다 평가해

검색도 코드처럼 다뤄. 청크 크기, 모델, RRF의 k, 재순위화 모델을 바꿀 때마다 번호를 붙여 평가하고 지표를 시간순으로 그려. 작은 변경이 재현율을 망치는 날에는 사용자가 불평하기 전에 그래프가 먼저 알려 줄 거야.

Code

작은 평가 도구 만들기·python
import json
from statistics import mean

EVAL = json.load(open('eval.json'))   # [{'query': str, 'relevant_ids': [str]}]

def hit_rate(retriever, k=5):
    hits = []
    for ex in EVAL:
        results = retriever(ex['query'], k=k)
        ids = [r['id'] for r in results]
        hits.append(any(rid in ids for rid in ex['relevant_ids']))
    return mean(hits)

def mrr(retriever, k=10):
    scores = []
    for ex in EVAL:
        results = retriever(ex['query'], k=k)
        ids = [r['id'] for r in results]
        rank = next((i for i, rid in enumerate(ids) if rid in ex['relevant_ids']), None)
        scores.append(0.0 if rank is None else 1.0 / (rank + 1))
    return mean(scores)

print('hit@5:', hit_rate(vector_only,    5))
print('hit@5:', hit_rate(vector_plus_bm25, 5))
print('mrr:  ', mrr(vector_plus_bm25_then_rerank))

External links

Exercise

실제 코퍼스에서 쿼리와 relevant_ids 목록으로 이루어진 50행 평가 집합을 만들어. 벡터만 사용한 경우, 하이브리드와 RRF를 사용한 경우, 여기에 cross-encoder까지 더한 경우의 hit@5와 MRR을 계산해 저장해. 청킹이나 모델을 바꿀 때마다 다시 실행해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.