-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2_vector_store_rag.py
More file actions
55 lines (44 loc) · 3.32 KB
/
Copy path2_vector_store_rag.py
File metadata and controls
55 lines (44 loc) · 3.32 KB
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_core.embeddings.fake import FakeEmbeddings
class RAGVectorStore:
"""
[Senior 면접용 딥다이브: RAG 고도화 및 한계 극복]
Q1. "일반적인 Vector Search(유사도 검색)의 한계점과 이를 해결할 방법은?"
A1: "단순 코사인 유사도는 의미론적(Semantic)으로는 비슷해도 사용자가 입력한 고유 명사나 '정확한 키워드'를 놓치는 경우가 많습니다.
따라서 실무에서는 BM25(키워드 기반 검색)와 Vector Search를 결합한 'Hybrid Search'를 구축합니다.
더 나아가, 검색된 1차 문서들을 'Cross-Encoder (예: Cohere Rerank)' 모델을 태워 문맥적 관련성으로 재정렬(Re-ranking)하여
LLM에게 넘겨주는 것이 요즘 RAG의 표준(Advanced RAG)입니다."
Q2. "문서 청킹(Chunking) 전략은 어떻게 가져가나요? 무조건 500토큰으로 자르면 되나요?"
A2: "아닙니다. 'Lost in the middle' 현상(LLM이 중간에 낀 컨텍스트를 망각하는 현상)을 막기 위해
문서를 너무 길게도, 너무 짧게도 자르면 안 됩니다.
문맥이 끊기지 않도록 'RecursiveCharacterTextSplitter'를 통해 문단/문장 단위로 의미를 보존하며 자르고,
Overlap(청크간 겹치는 부분)을 10~20% 정도 두어 경계면의 정보 유실을 막습니다.
최근에는 'Parent Document Retriever' 방식을 써서 검색은 작은 청크로 아주 정밀하게 하되,
LLM에게는 그 청크가 포함된 원본 전체(Parent)를 넘겨주어 문맥을 유지하는 기법도 많이 씁니다."
"""
def __init__(self):
self.embeddings_model = FakeEmbeddings(size=1536)
self.vector_store = None
def ingest_documents(self, documents: list):
print("\n[RAG System] 1. Advanced Chunking (Recursive) 시작...")
# 시맨틱 보존을 위한 Recursive Splitter 사용
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50 # Overlap을 통한 경계면 정보 유실 방지
)
chunks = []
for doc in documents:
chunks.extend(text_splitter.split_text(doc))
print(f"[RAG System] 2. 총 {len(chunks)}개의 청크(Chunk) 생성 완료.")
print("[RAG System] 3. 벡터 임베딩 후 인메모리 벡터 DB(FAISS)에 HNSW 알고리즘으로 색인 중...")
self.vector_store = FAISS.from_texts(chunks, self.embeddings_model)
print("[RAG System] 4. 벡터 DB 구축 완료!")
def search_similar_documents(self, query: str, top_k: int = 2) -> str:
if not self.vector_store:
raise ValueError("먼저 ingest_documents()를 호출하여 데이터를 적재하세요.")
print(f"\n[RAG System] 🔍 사용자 쿼리에 대한 Hybrid Search & Re-ranking 모의 수행... (질문: {query})")
docs = self.vector_store.similarity_search(query, k=top_k)
context = "\n---\n".join([doc.page_content for doc in docs])
print(f"[RAG System] ✅ {len(docs)}개의 고품질 관련 문서를 찾았습니다. (LLM 주입용 Context)")
return context