검색 2차 실험 결과 (임베딩 교체)

아카이브됨 — ** 검색 2차 실험 (임베딩·BM25·리랭커)**로 계획·결과가 합쳐졌다 (2026-07-29)

이 문서의 내용은 전부 합친 문서로 옮겼다. 값 정본도 그쪽이다. 사료로서 보존하되 현행 상태로 읽지 말 것 — 특히 후보 구성 변형 D의 설명이 틀렸다 (D는 리랭커 뒤에서 C와 동치라 아무것도 재지 못한다 → 합친 문서 §9-1).

2차 판정 정본. 계획·측정 조건은 검색 2차 실험 계획 (임베딩·BM25·리랭커) §0-1이 정본이다. 1차 판정 → 검색 실험 결과 (164문항) · 정답지를 고친 기록 → 정답지 편향 제거 (전체 풀링 라벨링)

결론 — 아무것도 안 바꾼다

판정
임베딩e5-small 유지KURE가 +0.0297 앞서지만 신뢰구간 하한이 −0.0042. 확실한 비용 vs 증명되지 않은 이득 → §2
리랭커bge-reranker-v2-m3(R1) 유지한국어 튜닝판 R2는 세 채점 가정 어디서도 유의하게 진다 → §4
BM25⚠️ 미채택이나 재측정 중지금까지의 기각은 후보 확장 효과를 안 잰 반쪽 실험이었다 → §3

현행 e5-small + R1이 그대로 남는다. 단 §3은 열려 있다.


0. 세 줄 요약

  1. dense 단독으로는 새 임베딩이 크게 이긴다 — MRR 0.6402 → 0.7417/0.7416(+0.10). 그런데 리랭커를 켜면 그 이득이 대부분 흡수된다 → §5.
  2. 정답지 편향을 걷어내고 다시 재도 결론은 같았다. 편향 제거 후 KURE 이득이 +0.0068 → +0.0297로 4배 커졌지만, 164문항으로는 이 크기를 우연과 구분할 수 없다 → §2.
  3. 대신 다른 문이 열렸다. BM25 기각은 어휘 검색이 후보를 넓히는 효과를 한 번도 재지 않은 판정이었다. e5가 못 찾은 17문항 중 11문항을 BM25가 건진다 → §3.

1부 · 판정

1. 최종 성적표 ★ 값 정본

164문항 · C_doc(문서범위 + 리랭커) · MRR@10 · 골든셋 v5(편향 제거 후). 기준선은 1차에서 채택한 e5-small + R1. 승격 기준은 측정 전에 정해둔 신뢰구간 하한 > 0(계획 §13).

조합MRR@10기준선 대비95% CI (paired bootstrap 1만 회)판정
e5-small + R1 (현행)0.7443기준선유지
bge-m3 + R10.7640+0.0197[−0.0151, +0.0578]
KURE-v1 + R10.7740+0.0297[−0.0042, +0.0654]아슬아슬하게 기각
e5-small + R20.6805−0.0638[−0.1005, −0.0275] ✱
bge-m3 + R20.6736−0.0707[−0.1169, −0.0243] ✱
KURE-v1 + R20.6856−0.0587[−0.1035, −0.0140] ✱

✱ = 95% 구간이 0을 포함하지 않음

1-1. 참고 — dense 단독 (리랭커 없이, 골든셋 v4 기준)

임베딩 자체의 실력. 판정용이 아니라 진단용이다(계획 §7).

임베딩MRR@10+BM25nDCG@10Recall@5Recall@20정답이 후보에 아예 없음
M0multilingual-e5-small (118M/384d)0.64020.60960.60610.61880.816317
M1BAAI/bge-m3 (568M/1024d)0.74170.61790.69730.71320.855714
M2nlpai-lab/KURE-v1 (0.6B/1024d)0.74160.64910.70820.73350.863113

M1 ≈ M2 — dense 단계에서 한국어 튜닝의 이득은 없다. 계획 §3의 판정표대로 읽으면 **“계열이 관건”**이다. M0의 Recall@20 0.8163은 1차 실험값과 정확히 재현됐다.

2. 왜 임베딩을 안 바꾸나 — “차이가 없다”가 아니다

KURE는 +0.0297로 승격 최소 폭(+0.03)에 사실상 닿았다. 그런데 95% 구간 하한이 −0.0042다. 164문항으로는 이 크기를 우연과 구분할 수 없다.

교환 조건이 이렇다.

치러야 하는 것 (확실)얻는 것 (불확실)
재인덱싱 28.5분MRR +0.0297 — 다만 구간이 0을 품는다
모델 5배 (118M → 0.6B)
HF 캐시 4.3GB (VM 여유 7GB)

**정직하게 쓰면 “교체해도 손해는 없지만 이득이 증명되지 않는다”**이다. “차이가 없다”가 아니다. 점추정은 계속 KURE가 앞섰고, 정답지 편향을 걷어낼수록 격차가 벌어졌다.

2-1. 재판정 조건 — 이 셋 중 하나면 다시 본다

  1. 골든셋이 300문항 이상으로 늘어난다 — 구간이 좁아져 +0.03이 유의해질 수 있다
  2. 다른 이유로 재인덱싱이 필요해진다 — 교체 비용이 사라지면 교환 조건 자체가 바뀐다
  3. Recall@20이 병목인 기능이 생긴다 — e5 0.8163 vs KURE 0.8631(§1-1). 후보를 넓히는 게 중요한 기능이면 판단이 달라진다

3. BM25 판정은 반쪽이었다 ★ 재측정 중

"BM25 미채택"을 어휘 검색 전체를 기각한 것으로 읽으면 안 된다

지금까지 잰 건 BM25가 순서를 바꾸는 효과뿐이고, 후보를 넓히는 효과는 한 번도 재지 않았다.

rerank_on_cache.py의 D 변형이 RRF 융합 후 if c in seen으로 BM25만 찾은 청크를 전부 버렸다. 그래서 D는 dense 후보 20개의 순서만 바꾼 것이 됐다. 검색 실험 결과 (164문항) §4에서 C ≡ D가 수렴한 것도 이 때문이다.

코드에 적힌 이유는 *“BM25 전용 청크는 본문이 없어 추가 Chroma 왕복 필요 — 이득 대비 비용이 커 v1 범위 밖”*이었는데, 실측하니 20개 일괄 조회 0.6ms다. dense 검색 2.05초의 0.03%도 안 된다. 근거가 성립하지 않는다.

3-1. 버려온 것의 크기 (v5 라벨 기준 실측)

임베딩dense_doc가 정답을 하나도 못 찾은 문항그중 BM25가 찾아준 문항
M0 e5-small (현행)1711
M1 bge-m3103
M2 KURE-v193

e5가 못 찾은 17문항 중 11문항을 BM25가 건진다. 이 17문항은 spec.md §10-17이 **“리랭커로 도달 불가능한 상한”**이라고 명시한 바로 그 문항들이다 — 임베딩을 바꿔도 13문항이 남았던(§1-1) 그 영역이다.

3-2. 왜 6.8.5에서는 손해였나

리랭커 없이 RRF 순서를 그대로 썼기 때문이다. 리랭커를 얹으면 나쁜 BM25 후보를 밑으로 내릴 수 있어, 재현율은 얻고 정밀도 손실은 리랭커가 흡수하는 구조가 된다.

6.8.5의 수치(§1-1의 +BM25 열)는 폐기하지 않는다. *“리랭커 없는 조건에서 RRF 순서를 그대로 쓰면 손해”*라는 측정으로 여전히 유효하다.

진짜 하이브리드를 측정 중이다 — E(융합 상위 20) · F(융합 상위 30). 결과가 나오면 이 절을 판정으로 고쳐 쓴다.


2부 · 근거

4. R2는 왜 지나 — 점수가 포화한다

R2(dragonkue/bge-reranker-v2-m3-ko)가 M0·M1·M2 어디에 붙어도 R1보다 −0.06 ~ −0.08이다. 근소한 차이가 아니다.

원인을 실측으로 잡았다 — R2는 점수가 1.0으로 포화한다.

한 문항의 R2 점수
후보 20개 중 고유 점수10개뿐
상위 3개 점수전부 정확히 1.0

점수가 다 같으면 순위를 매길 수 없다. 변별을 못 하는 것이다 → 지표 포화

4-1. 그 포화가 C ≡ D까지 흔들었다

M0 × R2에서만 C_doc 0.6805 vs D_doc 0.6815로 0.001 어긋났다. 계획 §6이 *“확인용 조합이 다르면 결과가 아니라 버그 신호”*라고 못박아 둔 자리라 멈추고 봤는데, 버그가 아니었다.

C와 D는 후보 집합은 같고 순서만 다르다(§3의 if c in seen). 리랭커가 그 순서를 자기 점수로 덮어쓰는데, 점수가 동점이면 안정 정렬이 입력 순서를 그대로 유지한다.

164문항 중 1문항(g200:4406b63d)에서 정답 청크가 C는 3등, D는 2등이 됐다. 그게 0.001이다. R1에서는 한 건도 발생하지 않았다. R2를 쓰면 안 되는 이유가 하나 더 나온 셈이다.

5. 임베딩 교체 이득이 리랭커에 흡수된다

dense 단독:   M0 0.6402  →  M2 0.7416      +0.10    ← 임베딩 실력 차이는 크다
+ 리랭커 R1:  M0 0.7443  →  M2 0.7740      +0.0297  ← 종단에서는 3분의 1 이하로 줄어든다

계획 §2-2가 나눠 적어둔 두 능력으로 읽으면 정확히 맞아떨어진다.

임베딩을 바꿔서 얻는 것예상실측
정답을 20개 안에 넣는 능력리랭커가 못 함 → 값어치 크다Recall@20 0.8163 → 0.8631, 후보 밖 17 → 13 ✅
20개 안에서 위로 올리는 능력리랭커가 이미 함 → 작다종단 +0.0297에 그침 ✅

계획 §14의 예상 1·2번이 둘 다 맞았다. §14가 미리 적어둔 대로 이건 실패가 아니라 “리랭커가 이미 그 몫을 하고 있다”는 유용한 결론이다.

그리고 §3이 바로 여기서 이어진다 — **리랭커가 못 하는 일(후보를 넓히는 것)**을 BM25가 할 수 있다면, 그건 임베딩 교체와 겹치지 않는 이득이다.

6. 한국어 튜닝은 양쪽에서 이득이 없었다

원본 → 한국어 튜닝판결과
임베딩bge-m3 → KURE-v1무승부 (0.7417 vs 0.7416, dense 단독)
리랭커R1 → R2크게 짐 (−0.06 ~ −0.08)

계획 §4가 *“둘 다 미미하면 우연이 아니라 패턴”*이라고 미리 적어둔 자리다. 다만 방향은 예상(§14-5 “근소하다”)보다 나빴다 — 리랭커 쪽은 근소한 게 아니라 크게 졌다.


3부 · 하다가 바로잡은 것

7. 검색과 재정렬이 서로 다른 질문을 보고 있었다 ★

리랭킹을 처음 돌렸을 때 0.7747이라는 값이 나왔다. 기준선 대비 +0.03을 훌쩍 넘는 수라 승격처럼 보였는데, 가짜 상승이었다.

원인은 질문 파일이었다.

단계무엇을 봤나
1단계 — dense 후보 캐시qid_query_200.jsonl (병합본)
2단계 — 리랭킹goldenset_200.jsonl (원본) ← 여기가 틀렸다

두 파일은 후속 질문 29문항의 텍스트가 다르다.

원본:    "그 사업의 안정화기간은?"
병합본:  "한영대학교 …사업기간은 어떻게 되나요? 그 사업의 안정화기간은?"

그래서 검색은 맥락이 붙은 질문으로 후보를 뽑았는데, 리랭커는 “그 사업”이 뭔지 모르는 채로 그 29문항의 순서를 매겼다. 그 어긋남이 0.7747이라는 상승으로 나타났다.

골든셋·정답지·채점 기준에는 문제가 없었다. 잘못은 전적으로 실행 인자 쪽이다.

교훈 — 1단계(후보 캐시)와 2단계(리랭킹)는 반드시 같은 질문 파일을 봐야 한다

이것도 검색 실험 결과 (164문항) §8(인덱스 혼동)과 같은 조용한 실패다. 파일 이름이 둘 다 그럴듯하고, 문항 수도 맞고, 에러도 안 난다. 성적이 올라서 발견됐다. 성적이 내려갔으면 “새 임베딩이 별로네”로 넘어갔을 수도 있다.

7-1. 두 질문 파일의 관계

파일무엇인가필드문항
goldenset_200.jsonl정본 골든셋qid / question / 유형 / 선행_턴 / 대상_doc_id / expected_answer_기준200
qid_query_200.jsonl위에서 파생된 검색 실험용 질문 텍스트qid / query 둘뿐 (정답 정보 없음)164
rerank_labels_200.jsonl정답 라벨. VM 골든셋의 rerank_labels.jsonl과 gold 청크 전건 일치164
goldenset_200.jsonl (200문항)
    │  선행_턴 + question 을 이어붙임
    │  − 모른다 15 − 반문 15 − 빈 정답 6
    ▼
qid_query_200.jsonl (164문항, qid + query)   ← 검색·리랭킹은 항상 이걸 본다

goldenset_200.jsonl을 검색 인자로 넣으면 문항 수 필터링과 선행 턴 병합이 둘 다 빠진다.

8. 그 밖에 바로잡은 것

무엇어디에
정답지가 e5에 편향돼 새 모델을 과소평가하던 것정답지 편향 제거 (전체 풀링 라벨링)
정답률 1.3%를 보고 “미채택”으로 판단했다가 철회한 경위같은 문서 §7
캐시 생성 1,887초 → 136초 · Chroma 필터 검색이 근사라는 발견후보 캐시
chunk_id 게이트 (임베딩을 바꿔도 청크 경계가 안 밀림)검색 2차 실험 계획 (임베딩·BM25·리랭커) §8

9. 관련 문서

문서무엇을 보러
검색 2차 실험 계획 (임베딩·BM25·리랭커)§0-1 = 측정 조건 정본 · 설계 근거 · 승격 기준(§13)
정답지 편향 제거 (전체 풀링 라벨링)정답지를 어떻게 고쳤나 — 6.8.7·6.8.8 전 과정
검색 실험 결과 (164문항)1차 판정 — 이 실험의 기준선(0.7443)
후보 캐시dense_doc/dense_full/bm25 구분, 검색을 한 번만 돌리는 법
개념 색인MRR·nDCG·BM25·리랭커 개념

코드: scripts/build_retrieval_cache.py · scripts/rerank_on_cache.py · scripts/rerank_bias_bounds.py · scripts/promote_decision.py 정본: Plans.md 6.8 · spec.md §10-17