더보기
61일 차 회고.
단위 프로젝트 주제는 재료 기반 레시피 검색 서비스로 정해졌다.
1. Native RAG
1-1. Vector DB
Vector DB
- 벡터를 고차원 공간의 포인트로 저장하고, 입력 벡터와 유사한 벡터를 효율적으로 검색한다.
Vector Embedding
- 텍스트, 이미지, 오디오 등 다양한 데이터를 컴퓨터가 이해하고 처리할 수 있도록 고차원 수치 벡터 형태로 변환한다.
Vector DB 동작 원리
- Indexing
- 임베딩된 벡터를 검색 효율을 높이기 위한 데이터 구조에 매핑한다.
- Querying
- 유사도 함수(ex. 코사인 유사도, 유클리디안 거리등)를 적용하여 입력 벡터와 가장 유사한 벡터들을 찾는다.
- Post Processing
- 검색된 후보 중 실제로 가장 유사한 벡터를 최종적으로 선별하고 결과를 반환한다.
- Loader
from langchain_community.document_loaders import TextLoader
loader = TextLoader(DATA_PATH+"")
docs = loader.load()
- Splitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=300,
chunk_overlap=50
)
splitted_docs = text_splitter.split_documents(docs)
- Embedding Model
from langchain_openai import OpenAIEmbeddings
embedding = OpenAIEmbeddings(
model="text-embedding-3-small"
)
- Vector DB
from langchain_chroma import Chroma
chroma_path = "./chroma_db"
chroma_db = Chroma.from_documents(
documents=splitted_docs,
embedding=embedding,
persist_directory=chroma_path,
collection_name="my_db"
)
# 데이터 확인
chroma_db.get().keys()
# dict_keys(['ids', 'embeddings', 'documents', 'uris', 'data', 'metadatas', 'included'])
# 데이터 추가
from langchain_core.documents import Document
add_doc = Document(
page_content="Hello",
metadata={
"source": "mydata.txt"
},
id="1"
)
chroma_db.add_documents([add_doc])
chroma_db.add_texts(
texts=["Hello World", "Bye World"],
metadatas=[
{"source": "mydata.txt"},
{"source": "mydata.txt"}
],
ids=["2", "3"]
)
# 데이터 조건부 확인
chroma_db.get("1")
chroma_db.get(
where={
"source": "mydata.txt"
}
)
# 데이터 삭제
chroma_db.delete(
ids=["1", "2", "3"]
)
chroma_db.reset_collection()
# 유사도 검색
result = chroma_db.similarity_search(
query="",
k=3,
filter={
"source": ""
}
)
# 유사도 검색 - MMR
result = chroma_db.max_marginal_relevance_search(
query="",
k=3,
fetch_k=10
)
FAISS(Facebook AI Similarity Search)
- Loader
from langchain_community.document_loaders import TextLoader
loader = TextLoader(DATA_PATH+"")
docs = loader.load()
- Splitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=300,
chunk_overlap=50
)
splitted_docs = text_splitter.split_documents(docs)
- Embedding Model
from langchain_openai import OpenAIEmbeddings
embedding = OpenAIEmbeddings(
model="text-embedding-3-small"
)
- Vector DB
import faiss
from langchain_community.vectorstores import FAISS
faiss_db = FAISS.from_documents(
documents=splitted_docs,
embedding=embedding
)
# 데이터 확인
faiss_db.docstore._dict
# 데이터 추가
with open(DATA+PATH+"") as f:
file = f.read()
add_doc = FAISS.from_texts(
texts=[file],
embedding=embedding,
metadatas=[
{"source": DATA_PATH+""}
],
ids=[""]
)
# In-Memory
from langchain_community.docstore.in_memory import InMemoryDocstore
embed_size = embedding.embed_query("")
db = FAISS(
embedding_function=embedding,
index=faiss.IndexFlatL2(len(embed_size)),
docstore=InMemoryDocstore(),
index_to_docstore_id={}
)
db.add_documents(
splitted_docs
)
db.add_texts(
texts=["Hello World", "Bye World"],
metadatas=[
{"source": "mydata.txt"},
{"source": "mydata.txt"}
],
ids=["1", "2"]
)
# 데이터 삭제
db.delete(ids=["1", "2"])
# 데이터 저장
faiss_path = "./faiss_db"
db.save_local(
folder_path=faiss_path,
index_name="faiss_index"
)
# 데이터 로드
load_db = FAISS.load_local(
folder_path=faiss_path,
index_name="faiss_index",
embeddings=embedding,
allow_dangerous_deserialization=True
)
# 유사도 검색
result = db.similarity_search(
query="",
k=3,
filter={
"source": DATA_PATH+""
}
)
# 유사도 검색 - MMR
result = db.max_marginal_relevance_search(
query="",
k=3
)
- Retriever
retriever_mmr = db.as_retriever(
search_type="mmr",
search_kwargs={
"k": 3,
"lambda_mult": 0.25
}
)
result = retriever_mmr.invoke(
input=""
)
1-2. RAG
Loader
from langchain_community.document_loaders import PyMuPDFLoader
pdf_path = DATA_PATH + ".pdf"
loader = PyMuPDFLoader(pdf_path)
docs = loader.load()
docs = docs[2:]
Splitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=100
)
split_docs = text_splitter.split_documents(docs)
Embedding Model
from langchain_openai.embeddings import OpenAIEmbeddings
embedding = OpenAIEmbeddings()
Vector DB
from langchain_community.vectorstores import FAISS
vectorstore = FAISS.from_documents(
documents=split_docs,
embedding=embedding
)
Retriever
retriever = vectorstore.as_retriever()
Prompt
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate.from_template(
"""당신은 질문-답변(Question-Answering)을 수행하는 친절한 AI 어시스턴트입니다.
당신의 임무는 주어진 문맥(context) 에서 주어진 질문(question) 에 답하는 것입니다.
검색된 다음 문맥(context) 을 사용하여 질문(question) 에 답하세요.
만약, 주어진 문맥(context) 에서 답을 찾을 수 없다면, 답을 모른다면 `주어진 정보에서 질문에 대한 정보를 찾을 수 없습니다` 라고 답하세요.
한글로 답변해 주세요.
단, 기술적인 용어나 이름은 번역하지 않고 그대로 사용해 주세요.
#Context:
{context}
#Question:
{question}
#Answer:"""
)
LLM Model
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="gpt-4o-mini"
)
Chain
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
rag_chain = (
{
"context": retriever,
"question": RunnablePassthrough()
},
| prompt
| llm
| StrOutputParser()
)
rag_chain.invoke("")
'SK네트웍스 Family AI캠프 10기 > Daily 회고' 카테고리의 다른 글
| 63일차. Modular RAG - LangSmith & Tools (0) | 2025.04.10 |
|---|---|
| 62일차. Advanced RAG - Retriever & Reranker (0) | 2025.04.09 |
| 60일차. RAG - Native RAG(Loader, Splitter) (1) | 2025.04.07 |
| 59일차. 프롬프트 엔지니어링 - LangChain(Output Parser & LCEL) & LLM 프로젝트 (0) | 2025.04.04 |
| 58일차 - Fine Tuning - LLM 평가지표 & 프롬프트 엔지니어링 - LangChain(Prompt & Model) (0) | 2025.04.03 |