Step 20 RAG: Retrieval-Augmented Generation

데이터베이스 검색으로 환각 줄이기

1. LLM의 치명적 약점: 환각(Hallucination)

GPT 같은 LLM은 모르는 것도 자신 있게 틀리게 말합니다. 이를 환각(Hallucination)이라 합니다. RAG는 이 문제를 해결하는 가장 실용적인 방법입니다.

⚠️ LLM만 사용할 때의 문제

❌ 환각

Q: "우리 회사 2024년 매출은?"
A: "약 500억원입니다." (사실 모름, 지어낸 것)

❌ 지식 단절

학습 데이터 이후의 정보는 알 수 없음.
사내 문서, 최신 뉴스 등 반영 불가.

2. RAG란?

Retrieval-Augmented Generation. 생성 전에 관련 문서를 검색(Retrieve)해서 그 내용을 기반으로 답변을 생성(Generate)하는 방식입니다. LLM에게 "오픈북 시험"을 허용하는 것과 같습니다!

🏗️ RAG 전체 파이프라인

RAG 동작 흐름 사용자 질문 입력 질문 → 임베딩 벡터 변환 🗄️ 벡터 DB (ChromaDB, Qdrant...) 사내 문서, PDF, 웹페이지 등이 벡터로 저장됨 유사도 높은 문서 Top-K 검색 (코사인 유사도로 가장 관련된 문서 추출) 프롬프트 = "다음 문서를 참고해 답변하세요: {검색결과} 질문: {질문}" 검색된 문서 + 원래 질문 합치기 ✅ 근거 있는 정확한 답변 생성

3. 임베딩과 벡터 유사도

문서와 질문을 같은 벡터 공간에 매핑하면, 의미가 비슷한 것끼리 거리가 가까워집니다.

📐 코사인 유사도

벡터 공간에서의 의미 유사도 원점 질문: "매출이 얼마야?" "2024년 매출 보고서" → 유사도 0.95 (매우 가까움) "채용 공고 문서" → 유사도 0.12 (멀리 떨어짐) 코사인 유사도 cos(θ) = A·B / (|A||B|) 1에 가까울수록 유사, 0이면 무관

4. RAG 구성 요소

🧩 각 구성 요소 선택 가이드

구성 요소역할대표 옵션
임베딩 모델텍스트 → 벡터 변환OpenAI ada-002, BGE, KoSimCSE (한국어)
벡터 DB벡터 저장 및 검색ChromaDB (간단), Qdrant, Weaviate, FAISS
청킹(Chunking)문서를 적절한 크기로 분할고정 크기, 문장 단위, 의미 단위
검색기(Retriever)유사 문서 Top-K 추출Dense (벡터), Sparse (BM25), Hybrid
리랭커(Reranker)검색 결과 재정렬CrossEncoder, Cohere Rerank
LLM최종 답변 생성GPT-4, Claude, Llama3, EXAONE

5. RAG vs Fine-tuning

⚖️ 언제 뭘 써야 하나?

기준RAGFine-tuning
데이터 업데이트✅ 실시간 가능❌ 재학습 필요
비용✅ 저렴❌ GPU 비용 높음
출처 추적✅ 어느 문서에서 왔는지 알 수 있음❌ 블랙박스
말투/형식 학습❌ 어려움✅ 가능
특수 도메인 용어△ 문서에 있으면 가능✅ 깊이 학습 가능
사내 문서 챗봇✅ 최적!△ 과함

6. 간단한 RAG 구현

💻 LangChain으로 RAG 구현

from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI

# 1. 문서 로드 및 청킹
docs = load_documents("./company_docs/")
chunks = split_documents(docs, chunk_size=500)

# 2. 임베딩 → 벡터 DB 저장
embeddings = OpenAIEmbeddings()
vectordb = Chroma.from_documents(chunks, embeddings)

# 3. RAG 체인 생성
qa_chain = RetrievalQA.from_chain_type(
    llm=OpenAI(),
    retriever=vectordb.as_retriever(search_kwargs={"k": 3}),
)

# 4. 질문 답변
result = qa_chain("우리 회사 휴가 정책은?")
print(result['result'])
# → 취업규칙 문서를 검색해서 정확히 답변!