RAG (Retrieval-Augmented Generation)
업데이트:
개념
RAG란 무엇인가?
RAG (Retrieval-Augmented Generation)는 대규모 언어 모델(LLM)의 성능을 향상시키기 위해 검색(Retrieval) 단계를 생성(Generation) 단계 이전에 추가하는 방식입니다.
핵심 특징
- 검색 기반: 외부 지식 베이스에서 관련 문서를 검색하여 활용
- 생성 기반: 검색된 정보를 바탕으로 텍스트 생성
- 정보 신뢰성 향상: 최신 정보와 도메인 특화 정보 활용 가능
- 할루시네이션 감소: 검색된 문서 기반으로 생성하여 거짓 정보 생성 감소
RAG의 필요성
일반적인 LLM의 문제점을 해결합니다:
- 오래된 정보: 학습 데이터 기준 이후의 정보 부재
- 도메인 지식 부족: 특화된 분야 정보 제한
- 할루시네이션: LLM이 존재하지 않는 정보 생성
- 투명성 부족: 답변의 출처를 알 수 없음
메커니즘
RAG의 작동 원리
RAG는 크게 3가지 단계로 동작합니다:
1. 검색 단계 (Retrieval)
사용자의 질문(쿼리)을 받으면:
사용자 질문 → 쿼리 임베딩 → 유사도 검색 → 관련 문서 추출
과정:
- 쿼리를 벡터로 변환 (Embedding)
- 벡터 데이터베이스에서 유사한 문서 검색
- 상위 K개 문서 선택
2. 증강 단계 (Augmentation)
검색된 문서를 쿼리와 함께 프롬프트에 추가합니다:
프롬프트 = "다음 문서를 참고하여 질문에 답변하세요.\n문서: [검색 결과]\n질문: [사용자 질문]"
3. 생성 단계 (Generation)
LLM이 증강된 프롬프트를 입력받아 답변을 생성합니다:
LLM(증강된 프롬프트) → 생성된 답변
내부 구조
RAG 시스템의 구성 요소
┌─────────────────────────────────────────────────────┐
│ 사용자 질문 입력 │
└────────────────────┬────────────────────────────────┘
│
▼
┌────────────────────────┐
│ 쿼리 임베딩 변환 │
│ (Query Embedding) │
└────────┬───────────────┘
│
▼
┌──────────────────────────┐
│ 벡터 데이터베이스 │
│ (Vector Database) │
│ [문서1] [문서2] [문서3] │
└────────┬─────────────────┘
│
▼
┌────────────────────────────┐
│ 유사 문서 검색 및 추출 │
│ (Semantic Search) │
└────────┬───────────────────┘
│
▼
┌──────────────────────────────────┐
│ 프롬프트 증강 │
│ (Context + Query) │
└────────┬─────────────────────────┘
│
▼
┌──────────────────────────┐
│ LLM (언어 모델) │
│ (GPT, Claude 등) │
└────────┬─────────────────┘
│
▼
┌──────────────────────────────────┐
│ 생성된 답변 (최종 결과) │
└──────────────────────────────────┘
주요 컴포넌트
| 컴포넌트 | 설명 | 예시 |
|---|---|---|
| 문서 저장소 | 검색할 원본 문서 저장소 | PDF, 웹 페이지, DB |
| 임베딩 모델 | 텍스트를 벡터로 변환 | sentence-transformers, OpenAI API |
| 벡터 DB | 임베딩된 벡터 저장 및 검색 | Pinecone, Weaviate, Milvus |
| 검색 엔진 | 유사도 기반 문서 검색 | BM25, 코사인 유사도 |
| LLM | 최종 답변 생성 | GPT-4, Claude, Llama |
주요 제품
상용 솔루션
1. LangChain
- 특징: RAG 구현을 위한 프레임워크
- 장점: 다양한 LLM 및 벡터 DB 지원, 풍부한 문서
- 링크: LangChain
2. LlamaIndex
- 특징: 데이터 인덱싱 및 쿼리 최적화
- 장점: 다양한 데이터 소스 지원, 구조화된 인덱싱
- 링크: LlamaIndex
3. Pinecone
- 특징: 완전 관리형 벡터 데이터베이스
- 장점: 확장성, 낮은 지연시간, 간편한 API
- 링크: Pinecone
4. Weaviate
- 특징: 오픈소스 벡터 데이터베이스
- 장점: 자체 호스팅 가능, GraphQL API, 좋은 스케일링
- 링크: Weaviate
5. Milvus
- 특징: 오픈소스 벡터 데이터베이스
- 장점: 고성능, 다양한 인덱스 지원, 커뮤니티 지원
- 링크: Milvus
6. Haystack
- 특징: 오픈소스 검색 엔진 프레임워크
- 장점: 유연한 파이프라인, 다양한 검색 방식 지원
- 링크: Haystack
활용 샘플
사용 사례
1. 기술 문서 질의응답 (Q&A)
- 나만의 API 문서 기반 답변 시스템
- 회사 내부 문서 검색 시스템
2. 고객 지원 (Customer Support)
- FAQ 기반 자동 답변
- 제품 매뉴얼 기반 지원
3. 법률 및 의료 관련
- 의료 기록 기반 진단 지원
- 법률 문서 검색 및 분석
4. 뉴스 및 연구
- 최신 뉴스 기반 요약
- 학술 논문 기반 분석
주요 코드
1. LangChain을 이용한 기본 RAG 구현
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# 1. 문서 로드
loader = PyPDFLoader("document.pdf")
documents = loader.load()
# 2. 문서 분할
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(documents)
# 3. 임베딩 및 벡터 DB 생성
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(splits, embeddings)
# 4. 검색 및 생성
llm = OpenAI()
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vectorstore.as_retriever()
)
# 5. 질의
result = qa_chain.run("문서에 대해 설명해주세요")
print(result)
2. LlamaIndex를 이용한 RAG
from llama_index import SimpleDirectoryReader, GPTVectorStoreIndex, ServiceContext
from llama_index.llms import OpenAI
# 1. 문서 로드
documents = SimpleDirectoryReader("./data").load_data()
# 2. 인덱스 생성
service_context = ServiceContext.from_defaults(llm=OpenAI(model="gpt-4"))
index = GPTVectorStoreIndex.from_documents(
documents,
service_context=service_context
)
# 3. 쿼리 엔진 생성
query_engine = index.as_query_engine()
# 4. 질의
response = query_engine.query("제 질문은 무엇입니까?")
print(response)
3. 간단한 Python 예제 (로컬 임베딩 사용)
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# 1. 임베딩 모델 로드
model = SentenceTransformer('all-MiniLM-L6-v2')
# 2. 문서 준비
documents = [
"RAG는 검색 기반 생성 방식입니다.",
"벡터 데이터베이스는 임베딩을 저장합니다.",
"LLM은 대규모 언어 모델입니다."
]
# 3. 문서 임베딩
doc_embeddings = model.encode(documents)
# 4. 쿼리 임베딩
query = "RAG의 개념은 무엇인가?"
query_embedding = model.encode([query])
# 5. 유사도 계산
similarities = cosine_similarity(query_embedding, doc_embeddings)[0]
# 6. 상위 문서 선택
top_idx = np.argsort(similarities)[-1]
print(f"가장 유사한 문서: {documents[top_idx]}")
print(f"유사도 점수: {similarities[top_idx]:.4f}")
4. Pinecone을 이용한 벡터 DB 관리
import pinecone
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Pinecone
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
# 1. Pinecone 초기화
pinecone.init(api_key="YOUR_API_KEY", environment="us-west1-gcp")
# 2. 인덱스 생성
pinecone.create_index("rag-index", dimension=1536)
# 3. 임베딩 및 벡터 저장
embeddings = OpenAIEmbeddings()
vectorstore = Pinecone.from_documents(
documents,
embeddings,
index_name="rag-index"
)
# 4. RAG 체인 구성
llm = ChatOpenAI(model_name="gpt-4")
qa = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vectorstore.as_retriever()
)
# 5. 질의
answer = qa.run("당신의 질문")
print(answer)
동작 흐름 예제
질문에서 답변까지의 전체 과정
질문: “RAG의 장점은 무엇인가요?”
Step 1: 임베딩
"RAG의 장점은 무엇인가요?"
→ [0.234, -0.123, 0.456, ...] (벡터)
Step 2: 검색
유사도 점수:
- 문서 1: "RAG는 최신 정보를 활용합니다." (점수: 0.92)
- 문서 2: "할루시네이션 감소에 효과적입니다." (점수: 0.88)
- 문서 3: "벡터 DB는 임베딩을 저장합니다." (점수: 0.65)
Step 3: 증강
프롬프트:
"다음 문서를 참고하여 질문에 답변하세요.
문서:
1. RAG는 최신 정보를 활용합니다.
2. 할루시네이션 감소에 효과적입니다.
질문: RAG의 장점은 무엇인가요?"
Step 4: 생성
답변: "RAG의 주요 장점은 다음과 같습니다:
1. 최신 정보 활용: 검색을 통해 최신 정보 제공
2. 할루시네이션 감소: 검색된 문서 기반으로 답변
3. 투명성 향상: 답변의 출처 제시 가능
..."
구현 시 고려사항
최적화 팁
1. 문서 분할 (Chunking)
- 너무 작음: 충분한 컨텍스트 부족
- 너무 큼: 무관한 정보 포함
- 권장: 512~1024 토큰 범위
2. 검색 결과 개수
- 적게: 필요한 정보 부족
- 많게: 비용 증가, 생성 속도 저하
- 권장: 3~5개 문서
3. 임베딩 모델 선택
- 경량: 빠르지만 정확도 낮음
- 대규모: 정확하지만 비용 높음
- 권장: 도메인에 맞는 모델 선택
4. 하이브리드 검색
# BM25 + 의미적 유사도 결합
hybrid_results = bm25_search(query, top_k=5) + semantic_search(query, top_k=5)
댓글남기기