문서/RAG/고급 RAG 기법

고급 RAG 기법

RAG 성능을 극대화하는 고급 기법들

고급 RAG 기법

기본 RAG를 넘어 성능과 정확도를 높이는 고급 기법들을 알아봅니다.

1. 청킹 전략

시맨틱 청킹

from langchain.text_splitter import RecursiveCharacterTextSplitter

# 의미 단위로 분할
splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    separators=["

", "
", ".", "!", "?", ",", " "],
    length_function=len
)

chunks = splitter.split_documents(documents)

문서 구조 기반 청킹

from langchain.text_splitter import MarkdownHeaderTextSplitter

headers_to_split = [
    ("#", "header1"),
    ("##", "header2"),
    ("###", "header3"),
]

splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=headers_to_split
)

chunks = splitter.split_text(markdown_document)

2. 하이브리드 검색

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever

# 키워드 기반 검색
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 4

# 벡터 기반 검색
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# 앙상블
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.4, 0.6]
)

3. 재순위화 (Re-ranking)

from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank

reranker = CohereRerank(model="rerank-multilingual-v3.0")

compression_retriever = ContextualCompressionRetriever(
    base_compressor=reranker,
    base_retriever=vector_retriever
)

# 더 관련성 높은 문서 반환
docs = compression_retriever.invoke("질문")

4. 쿼리 변환

쿼리 확장

from langchain.retrievers import MultiQueryRetriever

multi_query_retriever = MultiQueryRetriever.from_llm(
    retriever=vector_retriever,
    llm=llm
)

# 여러 변형 쿼리로 검색
docs = multi_query_retriever.invoke("원본 질문")

HyDE (Hypothetical Document Embeddings)

from langchain.chains import HypotheticalDocumentEmbedder

hyde = HypotheticalDocumentEmbedder.from_llm(
    llm=llm,
    embeddings=embeddings,
    prompt_key="web_search"
)

# 가상 문서를 생성하여 검색
docs = hyde.invoke("질문")

5. Self-RAG

class SelfRAG:
    def __init__(self, retriever, llm):
        self.retriever = retriever
        self.llm = llm

    def invoke(self, query):
        # 1. 검색 필요 여부 판단
        if self._needs_retrieval(query):
            docs = self.retriever.invoke(query)

            # 2. 문서 관련성 평가
            relevant_docs = self._filter_relevant(docs, query)

            # 3. 답변 생성
            answer = self._generate(query, relevant_docs)

            # 4. 답변 품질 평가
            if self._is_supported(answer, relevant_docs):
                return answer
            else:
                return self._regenerate(query, relevant_docs)
        else:
            return self.llm.invoke(query)

6. 메타데이터 필터링

# 메타데이터 포함 저장
vectorstore.add_documents([
    Document(
        page_content="내용",
        metadata={
            "source": "manual.pdf",
            "chapter": 3,
            "date": "2024-01-15",
            "category": "setup"
        }
    )
])

# 필터링 검색
docs = vectorstore.similarity_search(
    query,
    filter={"category": "setup", "chapter": {"$gte": 2}}
)

성능 최적화

  • 임베딩 캐싱: 동일 문서 재임베딩 방지
  • 배치 처리: 대량 문서 병렬 처리
  • 인덱스 최적화: HNSW, IVF 등 적절한 인덱스 선택
  • 양자화: 벡터 크기 축소로 속도 향상