langchain 공부

모든 Retriever(검색기) 비교

필만이 2024. 8. 29. 10:46

Retriever(검색기) 비교

Retriever 기법 장점 단점 사용 시기
Similarity Search - 간단하고 빠른 검색 가능
- 높은 유사성의 문서를 효과적으로 찾음
- 정밀한 검색이 어려울 수 있음
- 다중 의미를 가진 쿼리에 약함
- 쿼리와 관련된 문서를 빠르게 찾고자 할 때
- 단순한 유사성 기반의 검색이 필요한 경우
Maximum Marginal Relevance (MMR) - 정보 다양성을 높여 중복 문서 필터링 가능
- 다양한 답변을 제공할 수 있음
- 계산 비용이 더 많이 듦
- 검색 속도가 느려질 수 있음
- 중복되지 않는 다양한 정보를 원할 때
- 여러 관점을 가진 문서를 선택하고자 할 때
Similarity Score Threshold - 일정 수준 이상의 유사성만 필터링
- 특정 임계값 이상의 관련성 있는 문서만 선택 가능
- 임계값 설정이 까다로울 수 있음
- 임계값이 낮으면 유사하지 않은 문서가 포함될 수 있음
- 특정 수준 이상의 관련성 있는 문서만 필요할 때
- 정확한 문서 검색이 중요한 경우
Parent-Child Document Retrieval - 문서의 계층적 관계를 고려한 검색 가능
- 부모 문서와 자식 문서 간의 관계 파악에 유리
- 구현이 복잡하고 계산 비용이 높음
- 특정 구조의 문서에만 적합
- 논문, 보고서, 기술 문서, 서적 등과 같이 계층적 구조(장-절-단락 등)의 검색시 필요
Dense Passage Retrieval (DPR) - 문서의 의미를 잘 반영하는 임베딩을 통해 검색
- 비슷한 의미를 가진 문서를 효과적으로 검색 가능
- 임베딩 생성에 높은 계산 비용이 필요
- 매우 큰 데이터셋에서의 검색 성능이 떨어질 수 있음
- 의미 기반의 정교한 검색이 필요한 경우
- 동의어, 유사어가 많은 쿼리를 처리해야 할 때
BM25 (Okapi BM25) - 전통적인 TF-IDF 기반의 효율적이고 효과적인 검색
- 문서의 중요도와 관련성을 잘 반영
- 의미 기반의 검색에는 한계가 있음
- 동의어나 유사어 처리에 약함
- 간단하고 효율적인 키워드 기반 검색이 필요할 때
- 문서의 빈도와 역빈도를 고려한 검색이 필요한 경우

간단한 코드 예시

1. Similarity Search

# Similarity Search 설정 및 사용
retriever = vectorstore.as_retriever()

# 쿼리로 문서 검색
query = "확률이란 무엇인가?"
retrieved_docs = retriever.get_relevant_documents(query)

# 결과 출력
for doc in retrieved_docs:
    print(doc.page_content[:200])

2. Maximum Marginal Relevance (MMR)

# MMR 설정 및 사용
retriever = vectorstore.as_retriever(search_type="mmr", search_kwargs={'k': 5})

# 쿼리로 문서 검색
query = "확률이란 무엇인가?"
retrieved_docs = retriever.get_relevant_documents(query)

# 결과 출력
for doc in retrieved_docs:
    print(doc.page_content[:200])

3. Similarity Score Threshold

# Similarity Score Threshold 설정 및 사용
retriever = vectorstore.as_retriever(search_type="similarity_score_threshold", search_kwargs={'k': 5, "score_threshold": 0.7})

# 쿼리로 문서 검색
query = "확률이란 무엇인가?"
retrieved_docs = retriever.get_relevant_documents(query)

# 결과 출력
for doc in retrieved_docs:
    print(doc.page_content[:200])

4. Parent-Child Document Retrieval

# 문서를 청크로 나누기
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=900)
child_splitter = RecursiveCharacterTextSplitter(chunk_size=300)
parent_chunks = parent_splitter.split_text(document_text)

# Parent-Child Document Retrieval 설정 및 사용
retriever = ParentDocumentRetriever(
    vectorstore=vectorstore,
    docstore=InMemoryStore(),
    child_splitter=child_splitter,
    parent_splitter=parent_splitter
)

# 쿼리로 문서 검색
query = "확률이란 무엇인가?"
retrieved_docs = retriever.get_relevant_documents(query)

# 결과 출력
for doc in retrieved_docs:
    print(doc.page_content[:200])

5. Dense Passage Retrieval (DPR)

# DPR 설정 및 사용
retriever = DPRRetriever(vectorstore=vectorstore, embeddings=embeddings)

# 쿼리로 문서 검색
query = "확률이란 무엇인가?"
retrieved_docs = retriever.get_relevant_documents(query)

# 결과 출력
for doc in retrieved_docs:
    print(doc.page_content[:200])

6. BM25 (Okapi BM25)

# BM25 설정 및 사용
retriever = BM25Retriever(vectorstore=vectorstore)

# 쿼리로 문서 검색
query = "확률이란 무엇인가?"
retrieved_docs = retriever.get_relevant_documents(query)

# 결과 출력
for doc in retrieved_docs:
    print(doc.page_content[:200])