RAG는 문서를 검색한 후, 검색된 문서들을 기반으로 LLM이 최종 응답을 생성하는 구조입니다.
이 구조의 성능을 개선하는 대표적 기법 3가지는 다음과 같습니다:
1. LLM 기반 리랭킹 (Re-ranking with LLM)
2. 크로스 인코더 기반 리랭킹
3. HyDE (Hypothetical Document Embedding)
임베딩 기반 검색은 의미 유사성만 고려하므로 정확도가 떨어질 수 있습니다.
→ LLM이 각 문서의 **의미적 관련성**을 판단하여 **정밀하게 재정렬**합니다.
# 벡터 검색
vector_results = vector_store.similarity_search(query, k=4)
# LLM을 통해 각 문서의 관련성 점수 계산
score = llm.invoke(prompt) # prompt에는 질의 + 문서 포함
# 점수 기준으로 상위 2개 문서 선택
ranked_docs = sorted(scored_docs, key=lambda x: x[1], reverse=True)[:2]
# 기본 벡터 검색
basic_retriever = vector_store.as_retriever(search_kwargs={"k": 4})
# 크로스 인코더 모델
cross_encoder = HuggingFaceCrossEncoder("BAAI/bge-reranker-v2-m3")
reranker = CrossEncoderReranker(model=cross_encoder, top_n=2)
# 리랭킹이 포함된 검색기
rerank_retriever = ContextualCompressionRetriever(
base_compressor=reranker,
base_retriever=basic_retriever
)
질문을 바로 검색에 사용하지 않고,
→ 질문에 대한 LLM의 가상 응답(문서)를 생성해 이를 검색 임베딩으로 사용
# LLM을 통해 가상의 문서 생성
hypothetical_doc = llm.invoke(f"'{query}' 에 대한 설명 문서를 작성해줘")
# 해당 문서를 벡터화하여 검색
query_vector = embed_model.embed_query(hypothetical_doc)
results = vector_store.similarity_search_by_vector(query_vector)
| 기법 | 정확도 | 속도 | LLM 호출 |
|---|---|---|---|
| 기본 RAG | 보통 | 빠름 | 1회 |
| LLM 리랭킹 | 높음 | 느림 | 문서 수 + 1회 |
| 크로스 인코더 리랭킹 | 매우 높음 | 느림 | 문서 수만큼 |
| HyDE | 높음 | 중간 | 1회 추가 |