day2_practice/failures.pyhybrid.pyrerank_demo.pyeval.py

하이브리드 검색과 재랭킹: 놓친 것을 줍고, 순서를 고친다

벡터 검색이 약한 질문을 재현한 뒤, Kiwi 형태소 토크나이저를 쓴 BM25와 벡터 검색을 EnsembleRetriever 의 가중 RRF로 합치고, CrossEncoder 로 (질문, 후보) 쌍을 다시 채점해 줄을 세웁니다. 마지막으로 eval.py 가 평가 세트를 어떻게 채점하는지 봅니다. RRF 계산은 공식과 가상의 순위 예시로 보여 줍니다.

한눈에 보는 구조

단계를 넘기면 지금 일하는 부품이 파란 테두리로 표시됩니다
검색 · 질문 하나 (hybrid.py, rerank_demo.py) 질문str Kiwi 토크나이저korean_tokenizer BM25Retriever청크 6개 · 메모리 · k=3 벡터 검색기Chroma(./chroma_db) · db.as_retriever(k=3) EnsembleRetrieverweights [0.3, 0.7]가중 RRF · c=60 CrossEncoderbge-reranker-v2-m3(질문, 후보) 채점 상위 3재정렬 순위 3개 순위 3개 후보 3~6개 failures.py 는 이 벡터 검색만 따로 떼어 봅니다 평가 (eval.py) eval_set.json 문항마다 벡터 검색 → 출처 비교 / 거절 문구 확인 정답 N/5 · 기준 4

이 시점의 데이터

세 가지 검색이 각각 보는 것

BM25 (단어 일치)

질문과 청크를 형태소로 쪼갠 뒤 겹치는 단어가 많고, 그 단어가 드물수록 점수를 높게 줍니다. TR-102 같은 기호에 강하고, "월차"처럼 문서에 없는 말로 물으면 아무것도 맞히지 못합니다.

벡터 검색 (의미)

질문과 청크를 따로 임베딩해 거리로 비교합니다. "월차"와 "연차"를 이어 주지만, 기호가 정확히 일치하는지는 보지 않습니다.

EnsembleRetriever (순위 합치기)

점수가 아니라 각 검색기 안에서의 순위를 가중치와 함께 더합니다. BM25 점수와 거리는 단위와 방향이 달라 그대로 더할 수 없기 때문입니다.

CrossEncoder (같이 읽고 채점)

질문과 후보를 한 쌍으로 모델에 넣어 관련도 점수를 받습니다. 더 정확하지만 쌍마다 모델을 돌려야 해서 후보가 적을 때만 씁니다. 후보에 없는 청크는 올릴 수 없습니다.

함정과 주의

관련 파일

파일하는 일
failures.py고유 기호, 청크 경계, 모호한 질문으로 벡터 검색만 돌려 약점을 재현. 모델 호출 없음
hybrid.pyKiwi 토크나이저 + BM25, 벡터 검색기, EnsembleRetriever 결합과 가중치 실험. hybrid 객체를 내보냄
rerank_demo.py하이브리드 후보를 CrossEncoder("BAAI/bge-reranker-v2-m3") 로 다시 채점해 재랭킹 전후 순위를 비교
eval.pyeval_set.json 5문항을 검색 적중과 거절 문구로 자동 채점하고 4문항 기준으로 판정
eval_set.json (레포 루트)질문, 기대 출처, 유형(fact / paraphrase / no_answer)으로 된 평가 세트