BM25

글자가 겹치는 것을 찾는 검색. 뜻은 이해하지 못한다.

어떻게 동작하나

질문과 청크에서 겹치는 단어의 개수와 희귀도로 점수를 매긴다.

점수 = Σ (겹친 단어마다)  희귀도 × 등장빈도 보정 × 길이 보정
  • 희귀도(IDF) — 흔한 단어는 점수가 낮다. 시스템보다 ENDURA-5500이 훨씬 값지다
  • 등장빈도 — 많이 나올수록 높지만, 무한정 오르진 않는다 (k1 파라미터)
  • 길이 보정 — 긴 문서는 우연히 겹칠 확률이 높으니 깎는다 (b 파라미터)

강점과 약점

강점고유명사·코드·번호에 강하다. 글자가 있으면 바로 잡는다
약점표현이 다르면 못 찾는다 (사업기간용역기간)
약점긴 질문에서 흔한 단어가 점수를 독식한다 → 아래

⚠️ 우리가 겪은 함정 — 질문 안의 사업명

질문이 "〈사업명 10단어〉에서 〈핵심어 1단어〉는?" 형식이면, 사업명을 반복하는 표지·개요 청크가 정답을 이긴다. 겹친 단어가 10개 대 1개니까.

해결: 검색 범위를 대상 문서 1개로 좁힌다. 그 안에서는 사업명이 어디에나 있어 점수 차가 안 생기고, 핵심어가 비로소 변별력을 갖는다.

반대로 질문에서 사업명을 지우면 더 나빠진다 — 엉뚱한 문서가 올라오기 때문. 사업명은 문서 찾기엔 필수, 청크 고르기엔 방해. 두 역할이 충돌한다.

한국어에서 필수 — 형태소 분석

공백으로만 자르면 제안서를제안서의가 다른 단어가 된다. 조사를 떼어내야 어휘 매칭이 성립한다. 우리는 kiwipiepy를 쓴다.

우리 프로젝트에서

  • 구현: rank_bm25.BM25Okapi (기본 k1=1.5, b=0.75)
  • 현재 꺼져 있고, 켜도 동작하지 않는다 — 조건문이 거꾸로 걸려 있음
  • 1차 판정: 미채택 (2026-07-29, 164문항, e5-small 베이스)

조건부 결론

BM25가 진 이유가 **“dense가 이미 강해서”**일 수 있다. dense가 약한 임베딩 위에서는 기여가 살아날 여지가 있어, 베이스를 바꾸는 2차 실험에서 다시 잰다. → 검색 실험 결과 §4

조건dense 단독+BM25차이
문서 한정0.64020.6096−0.031
전체 코퍼스0.63590.6004−0.036

⚠️ 40문항 예비 측정의 +0.073은 소표본 노이즈였다. 164문항에서 부호가 뒤집혔다.

게이팅(dense가 확신할 땐 BM25 미적용)도 못 살렸다. BM25를 끌수록 좋아지고, 전부 껐을 때가 최고점이었다 → 기여가 순손실.

크로스인코더 리랭커를 켜면 BM25는 수학적으로 무효가 된다. BM25 단독 발굴 청크를 버리는 계약 탓에 후보 집합이 안 바뀌고 순서만 바뀌는데, 리랭커가 그 순서를 자기 점수로 덮어쓴다 → 164문항 전건 동일.

상세 → 검색 실험 결과

관련

Dense 검색 · RRF · 하이브리드 검색 · MRR