200===Dev Language/RAG

RAG와 문맥 검색의 완벽 가이드 🎯 (Part 1)

블로글러 2024. 11. 4. 12:36

안녕하세요! 오늘은 RAG와 문맥 검색에 대해 더욱 깊이 파헤쳐볼게요. 이해하기 쉽도록 단계별로 설명해드릴게요!

1. 전통적인 RAG의 작동 방식 🔍

1.1 문서 분할 (Chunking)

# 예시 코드
def split_document(document, chunk_size=500):
    chunks = []
    # 문서를 500토큰 단위로 분할
    return chunks

분할 방식의 종류:

  • 고정 크기 분할: 일정 토큰 수로 나누기
  • 의미 기반 분할: 문단이나 섹션 단위로 나누기
  • 오버랩 분할: 겹치는 부분을 포함해 나누기

1.2 벡터화 (Vectorization)

# 임베딩 생성 예시
from sentence_transformers import SentenceTransformer

model = SentenceTransformer('model_name')
embeddings = model.encode(chunks)

주요 임베딩 모델들:

  1. Gemini

    • 장점: 높은 정확도
    • 특징: 최신 문맥 이해력
  2. Voyage

    • 장점: 빠른 처리 속도
    • 특징: 효율적인 리소스 사용

1.3 검색 시스템

# 벡터 유사도 검색 예시
def search_similar(query, embeddings, top_k=5):
    query_embedding = model.encode(query)
    similarities = cosine_similarity(query_embedding, embeddings)
    return top_k_results

2. BM25 검색 방식 🎯

2.1 BM25란?

단어 기반 검색 알고리즘으로, 다음을 고려합니다:

  1. 단어 빈도 (TF)
  2. 문서 내 중요도 (IDF)
  3. 문서 길이 정규화
# BM25 점수 계산 예시
def calculate_bm25_score(query_terms, document, k1=1.5, b=0.75):
    score = 0
    for term in query_terms:
        tf = term_frequency(term, document)
        idf = inverse_document_frequency(term)
        score += bm25_formula(tf, idf, k1, b)
    return score

3. 문맥 검색의 혁신 🚀

3.1 문맥 추가 프로세스

# 문맥 추가 예시
def add_context(chunk, document):
    context = f"""
    문서 제목: {document.title}
    작성일: {document.date}
    섹션: {document.section}
    이전 문맥: {get_previous_context(chunk)}
    """
    return context + chunk

3.2 개선된 성능 지표

방식 검색 실패율 감소
기본 RAG 기준선
문맥 임베딩 35% 감소
문맥 + BM25 49% 감소
문맥 + BM25 + 재순위화 67% 감소

4. 실제 구현 예시 💻

4.1 기본 설정

from transformers import AutoTokenizer, AutoModel
import numpy as np

class ContextualRAG:
    def __init__(self):
        self.tokenizer = AutoTokenizer.from_pretrained("model_name")
        self.model = AutoModel.from_pretrained("model_name")
        self.chunks = []
        self.embeddings = []

4.2 문맥 처리

def process_with_context(self, document):
    # 1. 문서 분할
    chunks = self.split_document(document)

    # 2. 문맥 추가
    contextualized_chunks = []
    for chunk in chunks:
        context = self.generate_context(chunk, document)
        contextualized_chunks.append(context + chunk)

    # 3. 임베딩 생성
    self.embeddings = self.create_embeddings(contextualized_chunks)

5. 최적화 팁 🔧

5.1 청크 크기 최적화

  • 너무 작게: 문맥 손실
  • 너무 크게: 처리 비효율
  • 권장: 300-800 토큰

5.2 문맥 품질 향상

def enhance_context(chunk, document):
    key_entities = extract_key_entities(chunk)
    related_definitions = get_definitions(key_entities)
    temporal_info = get_temporal_context(chunk)

    return combine_context(key_entities, related_definitions, temporal_info)

5.3 캐싱 전략

from functools import lru_cache

@lru_cache(maxsize=1000)
def get_embedding(text):
    return model.encode(text)

6. 성능 모니터링 📊

6.1 주요 메트릭스

  • 검색 정확도 (Precision)
  • 검색 재현율 (Recall)
  • 응답 시간 (Latency)
  • 리소스 사용량
def evaluate_performance(self, test_queries):
    metrics = {
        'precision': [],
        'recall': [],
        'latency': [],
        'memory_usage': []
    }
    # 성능 측정 로직
    return metrics

마치며 ✨

문맥 검색은 AI의 정보 검색과 이해를 획기적으로 개선하는 기술입니다. 적절한 구현과 최적화를 통해 더 정확하고 유용한 AI 시스템을 만들 수 있습니다.

다음 포스트에서는 더 진보된 기술과 최적화 방법에 대해 다루도록 하겠습니다!


자세한 내용이 궁금하시다면 댓글로 남겨주세요! 😊

728x90