상세 컨텐츠

본문 제목

[LangChain] Similarity vs MMR vs MultiQuery vs Hybrid

본문

단순 구현을 넘어, 실제 출력 로그와 함께 Retriever 전략을 비교 실험해본 기록입니다.


1️⃣ 실험 환경

  • LLM: llama3.2:3b (Ollama)
  • Embedding: all-MiniLM-L6-v2 (384d)
  • VectorStore: FAISS
  • 문서: CNN 기반 음악 예측 논문 PDF
  • chunk_size=1000 / overlap=200

2️⃣ Retriever 전략 비교 실험

2.1 Similarity Search (k 실험)

코드

retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 3},
)

docs = retriever.invoke("What was the CNN model accuracy?")
 
 
 

🔎 실행 결과 (k=3)

 
 
[Similarity k=3 결과]

1️⃣ Page 12
"The CNN model achieved an accuracy of 95.68% on the test set..."

2️⃣ Page 13
"The evaluation metrics included accuracy, precision, recall..."

3️⃣ Page 11
"The proposed CNN architecture consists of three convolutional layers..."
 

🔎 실행 결과 (k=10)

 
 
[Similarity k=10 결과]

...
7️⃣ Page 12 (중복 섹션)
8️⃣ Page 13
9️⃣ Page 12 (유사 청크)
 

📊 분석

k중복 발생컨텍스트 밀도토큰 소비
3 거의 없음 높음 낮음
10 있음 희석 높음

👉 결론:

  • k가 커질수록 Recall은 증가
  • 하지만 중복 + 노이즈 증가
  • 실제 운영에서는 k=3~5가 가장 효율적

2.2 MMR (다양성 실험)

코드

mmr_retriever = vectorstore.as_retriever(
search_type="mmr",
search_kwargs={
"k": 4,
"fetch_k": 20,
"lambda_mult": 0.5,
},
)
 

🔎 lambda_mult=1.0 (Similarity와 동일)

 
 
Page 12 - Accuracy result
Page 12 - Accuracy detail
Page 13 - Evaluation
Page 12 - Table 3
 

→ 특정 섹션 집중


🔎 lambda_mult=0.0 (최대 다양성)

 
 
Page 12 - Accuracy
Page 5 - Dataset
Page 3 - Related Work
Page 18 - Conclusion
 

→ 논문 전반에서 추출


📊 분석

MMR은 사실상 다음 문제를 해결합니다:

"상위 문서들이 너무 비슷하다"

특히 chunk overlap이 큰 경우 효과적입니다.

λ=0.5가 가장 균형적이었음.


2.3 MultiQueryRetriever 실험

코드

multi_retriever = MultiQueryRetriever.from_llm(
retriever=base_retriever,
llm=llm,
)
 
 

🔎 실제 생성된 쿼리 로그

 
 
[Generated Queries]

1. What accuracy did the CNN model achieve?
2. What was the evaluation performance of the CNN?
3. How well did the CNN perform on test data?
 

🔎 검색 결과

 
 
총 반환 문서 수: 8
고유 페이지 수: 6
 

Similarity(k=3): 3개
MultiQuery: 8개


⏱️ 응답 시간 비교

전략평균 응답 시간
Similarity 1.2s
MMR 1.4s
MultiQuery 3.6s

👉 LLM 호출이 3번 추가되기 때문


📌 결론

  • Recall 증가
  • 비용/지연시간 2~3배 증가
  • 정밀도는 약간 희석

프로덕션에서는 “고난도 질문”에만 선택적 사용이 적절


3️⃣ Hybrid 검색 (BM25 + Vector)

3.1 BM25 단독

bm25_retriever = BM25Retriever.from_documents(docs, k=4)
 

🔎 키워드 질문 실험

질문:

 
 
"What is the F1 score?"
 

BM25 결과:

 
 
Page 13 - F1 score = 0.94
Page 14 - Evaluation metrics table
 

Vector 결과:

 
 
Page 12 - Accuracy description
Page 11 - CNN structure
 

👉 키워드 매칭에서는 BM25가 우수


3.2 EnsembleRetriever

ensemble = EnsembleRetriever(
retrievers=[bm25, faiss_ret],
weights=[0.5, 0.5],
)
 
 
 

🔎 Hybrid 결과

 
 
1️⃣ Page 13 (공통 상위)
2️⃣ Page 12
3️⃣ Page 14
4️⃣ Page 11
 

RRF 특성:

여러 retriever에서 동시에 높은 순위 → 최종 점수 상승


📊 가중치 실험

BM25FAISS결과 특성
0.7 0.3 키워드 우선
0.5 0.5 균형
0.3 0.7 의미 중심

전문 용어 질문에서는 BM25 가중치 ↑가 유리


4️⃣ Stateless RAG의 한계 실험

실험 시나리오

Q1 : What model did the paper use?



A : he paper used a CNN model.



Q2 : What was its accuracy?




❌ 기본 RAG 결과

 
 
Retriever 검색어: "its accuracy"

검색 결과:
- Page 3
- Page 18
- Page 7
 

→ 엉뚱한 문서 검색


문제 원인

Retriever는 히스토리를 모른다.

LLM은 문맥 이해 가능
Retriever는 문자열 기반 검색


5️⃣ History-Aware Retrieval 실험

질문 재작성 로그

 
 
Original: "What was its accuracy?"
Rewritten: "What was the CNN model's accuracy?"
 

검색 결과

 
 
Page 12 - Accuracy 95.68%
 

📊 개선 비교

StatelessHistory-aware
검색 정확도 낮음 높음
LLM 호출 1회 2회
응답 시간 1.3s 2.5s

6️⃣ 핵심 엔지니어링 인사이트

1️⃣ Retrieval Error Propagation

검색이 틀리면:

→ 잘못된 컨텍스트
→ LLM hallucination
→ 잘못된 답변

LLM 성능보다 검색 전략이 더 중요


2️⃣ Token Budget 문제

k=10 + MultiQuery 사용 시

  • context 4000 tokens 초과
  • truncation 발생 가능

운영 환경에서는 최근 N턴 유지, 오래된 히스토리 요약, adaptive k 전략 필요


3️⃣ 비용 구조

전략LLM 호출 수

 

 

Similarity 1
MultiQuery 4
History-aware 2
둘 다 5

RAG 설계는 모델 문제가 아니라 시스템 설계 문제


7️⃣ 이번 실험을 통해 배운 점

  1. Retriever 전략에는 정답이 없다.
  2. 데이터 도메인에 따라 BM25 비중이 달라진다.
  3. History-aware는 검색 단계 품질을 극적으로 개선한다.
  4. MultiQuery는 비용 대비 효과를 검증해야 한다.
  5. RAG는 LLM 문제가 아니라 Retrieval 시스템 설계 문제다.

관련글 더보기