LangChain으로 RAG 시스템 구축하기 📚
LangChain으로 RAG 시스템 구축하기 📚
RAG란?
RAG (Retrieval-Augmented Generation)는 LLM의 한계를 극복하는 핵심 기술입니다.
LLM의 문제점:
- ❌ 학습 데이터 이후 정보 모름
- ❌ 회사 내부 문서 모름
- ❌ 할루시네이션 (거짓 정보 생성)
RAG의 해결책:
- ✅ 외부 문서에서 관련 정보 검색
- ✅ 검색된 정보를 컨텍스트로 제공
- ✅ 근거 기반 응답 생성
🏗️ 아키텍처
1
2
3
4
5
[문서] → [청킹] → [임베딩] → [Vector DB]
↓
[질문] → [임베딩] → [유사도 검색] → [관련 문서]
↓
[LLM + 컨텍스트] → [응답]
💻 구현 코드
1. 필요한 패키지 설치
1
pip install langchain langchain-openai chromadb pypdf
2. 문서 로드 및 청킹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# PDF 문서 로드
loader = PyPDFLoader("company_docs.pdf")
documents = loader.load()
# 청킹 (문서를 작은 단위로 분할)
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
separators=["\n\n", "\n", ".", " "]
)
chunks = text_splitter.split_documents(documents)
print(f"총 {len(chunks)}개의 청크 생성")
3. 벡터 DB 구축
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# 임베딩 모델
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# Chroma DB에 저장
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)
# 검색기 생성
retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 3} # 상위 3개 문서 검색
)
4. RAG 체인 구성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParser
# LLM
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 프롬프트 템플릿
template = """다음 컨텍스트를 기반으로 질문에 답변해주세요.
컨텍스트에 없는 내용은 "해당 정보를 찾을 수 없습니다"라고 답변하세요.
컨텍스트:
{context}
질문: {question}
답변:"""
prompt = ChatPromptTemplate.from_template(template)
# RAG 체인
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# 실행
response = rag_chain.invoke("회사의 연차 정책이 어떻게 되나요?")
print(response)
🔧 고급 기능
1. Hybrid Search (키워드 + 의미 검색)
1
2
3
4
5
6
7
8
9
10
11
12
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
# BM25 (키워드 기반)
bm25_retriever = BM25Retriever.from_documents(chunks)
bm25_retriever.k = 3
# 앙상블 (하이브리드)
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, retriever],
weights=[0.4, 0.6]
)
2. Reranker로 정확도 향상
1
2
3
4
5
6
7
8
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=retriever
)
3. 대화 기록 유지
1
2
3
4
5
6
7
8
9
10
11
12
13
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True
)
qa_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=retriever,
memory=memory
)
💡 실전 팁
- 청크 사이즈는 실험적으로 - 500~1500 사이에서 테스트
- 오버랩은 필수 - 문맥이 끊기지 않도록
- 메타데이터 활용 - 출처, 페이지 번호 등
- 평가 지표 설정 - Faithfulness, Relevance 측정
🎯 마무리
RAG는 기업용 AI 챗봇의 핵심 기술입니다.
이 기본 구조를 이해하면:
- 사내 문서 Q&A 봇
- 고객 지원 챗봇
- 법률/의료 문서 분석
등 다양한 응용이 가능합니다!
다음 글에서는 프로덕션 RAG 시스템 최적화를 다뤄보겠습니다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.