70%였던 Basic RAG의 한계를 하이브리드 서치와 필터링으로 90%까지 끌어올렸다. 하지만 여전히 해결되지 않은 2문제(q06, q20)가 발목을 잡고 있었다.
이 마지막으로, 리랭킹(Re-ranking)을 도입하여 컨텍스트의 순도를 극한으로 높여보는 시도를 기록해본다.
- Cohere Rerank API 연동 및 리랭커 설정
- Hybrid Search 결과물을 리랭킹하여 Top-3 선별
- Advanced RAG 최종 정답률 측정 (전수 조사)
- Basic vs Advanced 성능 비교 및 기여도 분석
1. [Step 2-3] Re-ranking: 검색 결과의 '질서'를 다시 세우기
하이브리드 서치로 가져온 5~10개의 청크 안에는 정답이 분명 들어있었다. 하지만 문제는 '순위'였다. 정답 청크가 3~4위에 밀려나 있으면, LLM은 앞선 노이즈 청크들에 현혹되어 오답을 내뱉곤 한다.
구현 전략: Cohere Rerank v3.5 활용
Cohere Rerank API는 무료 티어(월 1,000회)를 제공하며 한국어를 포함한 다국어를 지원한다.
Login | Cohere
Login for access to advanced Large Language Models and NLP tools through one easy-to-use API.
dashboard.cohere.com
질문과 문서의 관계를 딥러닝 모델(Cross-encoder)이 직접 채점하게 하여, 질문의 의도와 가장 밀접한 청크를 1순위로 강제 배치했다.
from langchain_cohere import CohereRerank
from langchain.retrievers import ContextualCompressionRetriever
# 1. 리랭커 설정 (Cohere API 사용)
reranker = CohereRerank(model="rerank-v3.5", top_n=3)
# 2. 하이브리드 리트리버와 결합
compression_retriever = ContextualCompressionRetriever(
base_compressor=reranker,
base_retriever=ensemble_retriever # 이전 단계의 하이브리드 리트리버
)
2. [실전 결과] 이미 완벽한 100%에 리랭킹은 무엇을 더했을까?
하이브리드 서치와 메타데이터 필터링을 도입한 시점에서 이미 정답률은 100%에 도달했다. 하지만 로그를 정밀하게 분석해 보니 불안한 요소들이 있기는 하였다. 검색된 5~7개의 청크 중에서 정답의 근거가 되는 조각이 하위권(4~5위)에 간신히 걸쳐 있거나, 연도가 다른 청크들이 가중치 계산에 의해 상단에 섞여 들어오는 현상이 있었기 때문이다.
이때 도입한 Cohere Rerank는 단순히 정답을 찾는 것을 넘어, 검색 결과의 '질서'를 완전히 다시 세운다.
리랭킹 적용 후의 드라마틱한 변화 (Top-1의 선명도)
실제 로그에서 발견된 Basic vs Hybrid vs Rerank의 결정적 차이이다.
| 비교 항목 |
하이브리드 서치 (Step 2) | 리랭킹 적용 후 (Step 3) | 변화의 핵심 |
| 청크 출처의 혼합도 | ['2025', '2025', '2026', '2025', '2026'] (q01 기준) | ['2025', '2025', '2026'] (정렬 완료) | 질문에 맞는 연도 청크를 상위권으로 압축 |
| 정답 근거의 순위 | 정답 청크가 2~3위에 위치하는 경우 발생 | 1위 배치 (관련도 0.8~0.9점대) | LLM이 가장 먼저 읽는 정보의 정확도 상승 |
| 검색 신뢰도 지표 | 유사도 거리(Distance) 기반 (직관적이지 않음) | Relevance Score (0.94, 0.92 등) | 이 청크가 왜 정답인지 모델이 점수로 증명 |
가장 인상적인 지점은 q20(노숙인 시설 기간 비교) 문항이다.


리랭킹 후에는 0.91점이라는 높은 점수와 함께 두 연도의 핵심 비교 데이터가 Top-1, 2에 나란히 배치된 것이다. 덕분에 LLM은 헷갈릴 틈 없이 "2025년은 ~까지, 2026년은 ~까지"라는 완벽하고 신뢰적인 대조 답변을 내놓을 수 있었다.
3. [Step 3] 최종 성적표: Basic vs Advanced 비교 분석
모든 기법을 적용한 후, 개선된 골든 데이터셋 20문항에 대한 최종 평가 결과이다.
정답률 비교 테이블
| 방식 |
전체 정답률 | Easy | Medium | Hard | Cross-year | 년도 검색 정확도 |
| Basic RAG | 14/20 (70%) | 6/6 | 6/8 | 1/4 | 1/2 | 약 45% (혼동 심각) |
| Advanced RAG | 20/20 (100%) | 6/6 | 8/8 | 4/4 | 2/2 | 100% (완벽 분리) |
기법별 기여도 분석
- Basic (Vector Only): 문맥은 이해하나, 연도 숫자를 무시하고 전문 용어(조산아, 노숙인 등) 검색에서 취약함. (정답률 70%)
- + Hybrid & Filtering: BM25가 키워드를 잡고, 필터링이 연도를 강제 격리하면서 사실관계의 정확성을 확보. (정답률 100% 도달)
- + Re-ranking (최종): 검색된 후보 중 노이즈를 뒤로 밀어내고 '진짜 정답'을 LLM 바로 앞(Top-1)에 배달하여 답변의 품질과 신뢰도를 완성.
4. 4주차 최종 회고
이번 4주차 실습은 "모델의 지능에 기대기보다 시스템의 구조로 승부해야 한다"는 깨달음도 주었습다.
- 메타데이터 필터링의 위력: 2025년과 2026년처럼 닮은 꼴 데이터를 구분하는 데 가장 정직하고 강력한 도구였다.
- 하이브리드의 균형: 벡터 검색의 '유연함'과 키워드 검색의 '정교함'이 만날 때 비로소 도메인 특화 지식을 다룰 수 있었다.
- 리랭킹의 한 끗: 단순히 "정답을 맞혔다"를 넘어, LLM이 엉뚱한 정보에 현혹되지 않도록 지식의 위계질서를 세워주었다.
실전 팁: Trial Key의 한계 (429 Error)
실행 과정에서 TooManyRequestsError를 마주하며 실무에서의 API 레이트 리밋(Rate Limit) 관리의 중요성도 체감했다. 코드에 time.sleep()을 넣어 1분당 호출 횟수를 조절하는 '현장 대응' 능력까지 덤으로 얻었다.
지금까지 진행한 정확한 흐름을 정리
PDF
↓
[Indexing] 청킹 + 임베딩 → ChromaDB (벡터 저장소)
→ BM25 인덱스 (메모리)
↓
[Pre-Retrieval] 벡터 검색 + BM25 키워드 검색 동시 실행
→ EnsembleRetriever로 결과 병합 (후보 10+10개)
↓
[Post-Retrieval] Cohere Rerank로 후보 재정렬 → 상위 3개만 선별
↓
[Generation] LLM에 컨텍스트로 전달 → 답변 생성
지식베이스 구축 → 두 방식으로 후보 선별Pre- Retrieval) → 한 번 더 정제(Post-Retrieval) → LLM 생성의 과정을 진행한 것이다.
그리고 진행했던 Cohere Rerank는 Cross-encoder 방식이다.
입력: (질문, 청크1), (질문, 청크2), ... (질문, 청크10)
↓
Cohere 서버의 Cross-encoder 모델이
질문과 청크를 함께 넣고 관련도 점수 계산
↓
출력: 각 쌍마다 relevance_score (0~1)
그리고, 이 Cohere Rerank는 우리가 API 호출할 때 청크 텍스트를 실시간으로 전송하는 것이다. Cohere 서버에서 그 텍스트를 질문이랑 같이 모델에 넣어서 "이 질문에 이 텍스트가 얼마나 관련있냐"를 즉석에서 판단하는 것이다.
벡터 검색 (Top-10) ┐
├→ 후보 10+10개 → 중복제거 → Cohere API로 전송
BM25 검색 (Top-10) ┘
Cohere한테 보내는 건 질문 1개와 위와 같은 '선별된 청크'들인 것이다 (최대 20개 내외). Cohere는 그걸 받아서 각 청크마다 질문과의 관련도 점수를 매기고 돌려준다. 우리는 그 점수 순서대로 상위 3개만 LLM에 전달하는 것이다.
전체 DB에 청크가 수백 개 있어도 Cohere는 그걸 모르고, 우리가 골라서 넘긴 후보만 보는 것이다.
벡터 검색(Bi-encoder)이랑 차이
| 벡터 검색 | Cohere Rerank | |
| 방식 | 질문 따로, 청크 따로 임베딩 후 거리 계산 | 질문 + 청크를 같이 모델에 입력 |
| 속도 | 빠름 (미리 저장된 벡터 비교) | 느림 (매번 새로 추론) |
| 정확도 | 상대적으로 낮음 | 높음 (두 텍스트의 상호작용을 포착) |
그래서 전체 수만 개 청크에는 못 쓰고, 1차로 좁힌 10개 후보에만 쓰는 것이다. API 비용도 이유지만 근본적으로 느리기 때문이다.
'AI > RAG (Advanced & Evaluation)' 카테고리의 다른 글
| 5-1. RAG 평가: 감(Intuition)에서 데이터(Data)로 (0) | 2026.04.26 |
|---|---|
| 4-6. [리뷰]: Naive RAG의 한계 → Agentic RAG로 (0) | 2026.04.25 |
| 4-4. Advanced RAG: Hybrid Search와 메타데이터 필터링 (0) | 2026.04.19 |
| 4-3. Basic RAG: 다년도 인덱싱, 파이프라인 연결 (0) | 2026.04.19 |
| 4-2. RAG의 기준 세우기: 다년도 골든 데이터셋 구축 (0) | 2026.04.19 |