1. Embedding ๊ธฐ์ด
: ๋ถํ ๋ ํ ์คํธ๋ฅผ ๋ฒกํฐ๋ก ๋ณํํ๋ ๊ณผ์ ๋ค๋ฃธ. LangChain ์๋ฒ ๋ฉ ๋ชจ๋ธ์ ๊ณตํต ์ธํฐํ์ด์ค๋ก ๋ ๋ฉ์๋ ์ ๊ณต
• embed_documents(texts: List[str]) : ์ฌ๋ฌ ๋ฌธ์(์ปจํ ์คํธ) ํ ๋ฒ์ ๋ฒกํฐํ
• embed_query(text: str) : ์ง๋ฌธ ํ๋๋ฅผ ๋ฒกํฐํ
from langchain_openai import OpenAIEmbeddings
e_model = OpenAIEmbeddings(model='text-embedding-3-large')
# ์ฌ๋ฌ ๋ฌธ์ ์๋ฒ ๋ฉ
embedding_docs = e_model.embed_documents(docs) # list[list[float]]
# ์ง๋ฌธ ์๋ฒ ๋ฉ
query_vector = e_model.embed_query(query) # list[float]
• text-embedding-3-small → 1536์ฐจ์, text-embedding-3-large → 3072์ฐจ์
2. ์ฝ์ฌ์ธ ์ ์ฌ๋ ๊ธฐ๋ฐ ๊ฒ์
: ์ฝ์ฌ์ธ ์ ์ฌ๋ = ๋ ๋ฒกํฐ์ ๋ด์ / ๊ฐ ๋ฒกํฐ ํฌ๊ธฐ(L2 norm)์ ๊ณฑ → -1 ~ 1 ๋ฒ์(1์ ๊ฐ๊น์ธ์๋ก ์ ์ฌ)
# ๋ฒกํฐDB ์์ด numpy๋ก ์ง์ ์ ์ฌ๋ ๊ณ์ฐ, ์์ k๊ฐ ๋ฝ๊ธฐ
import numpy as np
def cosin_similarity(vector1, vector2):
v1, v2 = np.array(vector1), np.array(vector2)
return (v1 @ v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
search_list = [(i, cosin_similarity(doc_v, query_vector)) for i, doc_v in enumerate(embedded_docs)]
search_list.sort(key=lambda x: x[1], reverse=True) # ์ ์ฌ๋ ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ
top_k = 3
doc_idx = [idx for idx, score in search_list[:top_k]
3. ๋ฒกํฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฐ๋
: ๋น์ ํ ๋ฐ์ดํฐ(๋ฑ์คํธ, ์ด๋ฏธ์ง ๋ฑ)๋ฅผ ๊ณ ์ฐจ์ ๋ฒกํฐ๋ก ๋ณํ·์ ์ฅ, ์ ์ฌ๋/ANN(๊ทผ์ฌ ์ต๊ทผ์ ์ด์) ๊ธฐ๋ฐ์ผ๋ก ๋น ๋ฅด๊ฒ ๊ฒ์ํ๋ ํน์ DB
- ๋น์ทํ ๋ฐ์ดํฐ๋ ์๋ฒ ๋ฉ ๊ณต๊ฐ์์ ๊ฐ๊น๊ฒ, ๋ค๋ฅธ ๋ฐ์ดํฐ๋ ๋ฉ๊ฒ ๋ฐฐ์น๋๋ ์ฑ์ง ์ด์ฉ
• ์ฃผ์ ๋ฒกํฐ DB : Qdrant(Rust ๊ธฐ๋ฐ ๊ณ ์ฑ๋ฅ), Pinecone(์์ ๊ด๋ฆฌํ ํด๋ผ์ฐ๋), Chroma(์คํ์์ค, ๋๊ท๋ชจ ์ ์ฅ ์ต์ ํ), FAISS(Meta ๊ฐ๋ฐ, GPU ํ์ฉ ANNS), Milvus(๋ถ์ฐ ์ํคํ ์ฒ, ๋๊ท๋ชจ ๋ฐ์ดํฐ์ ์ฉ) ๋ฑ
4. LangChain Vector Store ์ฐ๋
• ์ฐ๊ฒฐ ๋ฐฉ๋ฒ
- VectorStore.from_documents() : ๋ฌธ์๋ฅผ insertํ๋ฉด์ ๋์ ์ฐ๊ฒฐ
- VectorStore() : DB ์ฐ๊ฒฐ๋ง ์ํ
4-1. InMemoryVectorStore ๊ธฐ๋ณธ ์ฌ์ฉ
from langchain_core.documents import Document
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_huggingface import HuggingFaceEmbeddings
# Upsert(SQL:insert) ํ Document ๋ฆฌ์คํธ ์์ฑ
d1 = Document(id=1, page_coutent="Apple, Pear, Watermelon", metadata={"category":"fruit"})
d2 = Document(id=2, page_content="Python, Java, C++", metadata={"category":"IT"})
d3 = Document(id=3, page_content="Football, Baseball, Basketball", metadata={"category":"Sport"})
# ์๋ฒ ๋ฉ ๋ชจ๋ธ ์์ฑ
embedding_model = HuggingFaceEmbeddings(model="codefuse-ai/F2LLM-v2-1.7B")
# # VectorStore ์์ฑ(VectorDB์ ์ฐ๊ฒฐ) -> ์๋ฒ ๋ฉ ๋ชจ๋ธ ๋ฃ์ด ์์ฑ(์๋ฒ ๋ฉ ๋ฒกํฐ ๋ณํ์ VectorStore ๋ด๋น)
vectorstore = InMemoryVectorStore(embedding_model)
# Upsert - add_documents(list[Document])
# Document.page_content๋ฅผ Embedding Vector๋ก ๋ณํ -> indedx, Document๋ฅผ value๋ก ์ ์ฅ
vectorstore.add_documents(documents=[d1, d2, d3]
result = vectorstore.similarity_search(query="์๋์ปต", k=2) # ๊ฒ์๋ง
result = vectorstore.similarity_search_with_score(query="์๋์ปต", k=2) # (๋ฌธ์, ์ ์ฌ๋ ์ ์) ๋ฐํ
4-2. MMR(Maximal Marginal Relevance) ์๊ณ ๋ฆฌ์ฆ
: ๊ฒ์ ๊ฒฐ๊ณผ ๊ด๋ จ์ฑ&๋ค์์ฑ ๋์ ๊ณ ๋ คํ๋ ๊ธฐ๋ฒ
• ์์ : MMR = λ·Sim(d,Q) - (1-λ)·max Sim(d,d') - λ๋ก ๊ด๋ จ์ฑ&๋ค์์ฑ ๋น์ค ์กฐ์
result_docs_mmr = vectorstore.max_marginal_relevance_search(
query=query,
k=5, # ๋ฐํํ ๋ฌธ์ ์
fetch_k=15, # ๋ค์์ฑ ๊ณ์ฐ ์ํด ์ฐ์ ๊ฐ์ ธ์ฌ ํ๋ณด ์
lambda_mult=0.5 # ๊ด๋ จ์ฑ vs ๋ค์์ฑ ๋น์ค(1=๊ด๋ จ์ฑ ์์ฃผ, 0=๋ค์์ฑ ์์ฃผ)
)
# ์ผ๋ฐ ์ ์ฌ๋ ๊ฒ์๊ณผ ๋น๊ต
vectorstore.similarity_search(query=query, k=5)
→ ์ผ๋ฐ ๊ฒ์ : ์ ์ฌํ ๋ฌธ์๋ผ๋ฆฌ ์ค๋ณต๋ ์ ์์ vs MMR : ์ค๋ณต ์ค์ด๊ณ ๋ค์ํ ์ ๋ณด ํจ๊ป ๊ฐ์ ธ์ด
'STUDY > LLM' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [LLM] Qdrant - langchain (0) | 2026.07.03 |
|---|---|
| [LLM] Qdrant (1) | 2026.07.02 |
| [LLM] RAG (1) | 2026.06.30 |
| [LLM] Chain - LCEL (0) | 2026.06.27 |
| [LLM] Output Parser (0) | 2026.06.26 |