Vector Search 기반 Semantic Search 구현 #0
전통적인 검색
기존 검색이라고 한다면, text matching이 기본이 된다.
가장 유명한 알고리즘은 BM25으로 검색어가 문서에 얼마나 반복하여 등장하는지를 기준으로 가장 관련성 있는 문서의 score를 계산하게 된다.
이에 전통적인 검색엔진인 elastic search에서는 bm25를 기반으로 full text query를 지원한다.
Semantic Search (의미 검색)
문장의 유사도를 통해 검색어와 검색 결과가 유사한지를 활용해 검색에 활용한다.
예를 들어, 검색어로 most delicious fruit 을 검색한다면, 같은 임베딩 모델을 거친 apple, banana, peach가 유사한 의미로 벡터 공간상에 위치하게 된다.
그림상에는 단순히 2차원 상의 벡터 차원으로 추상화 했지만, 모델에 따라 dimension이 달라지게 된다.
Embedding Model
이때 기본이 되는 것이 embedding model인데, 자연어 데이터를 벡터 데이터로 변환하게 된다.
임베딩 모델은 BERT와 같은 language 모델에서 튜닝된 Sentence Transformer 모델이 주로 사용되는데,
문서의 크기, 언어의 종류, 학습한 언어 데이터셋의 도메인에 따라 원하는 목적에 맞는 임베딩 모델을 사용한다.
Sentence Transformer 모델 중 output이 일정한 차원의 벡터로 출력하는 Bi Encoder 모델을 사용하게 된다.
Vector Search
검색을 위해선 검색할 문서들을 미리 임베딩하여 벡터화 시켜놓은 후, vector store에 저장한다.
검색할 쿼리와 기존 문서들간의 cosine similiarity를 통해 벡터간 유사도를 측정하여 score를 매기게 된다.
왜 벡터간의 유사도를 측정하는데 Euclidean Distance가 아닌 Cosine Similiarity를 사용하는가?
임베딩 모델의 출력 값은 고차원 데이터 (Dense Vector)로, 크기보다는 방향(의미적 유사성)을 기반으로 데이터 간 관계를 표현한다.
코사인 유사도는 데이터의 크기보다는 방향성을 비교하기 때문에 우리가 원하는 유사도를 측정하기에는 Cosine Similarity가 더 적합하다.
텍스트 유사성 외에 추천 시스템, NLP 에서도 많이 사용된다.
POC
from sentence_transformers import SentenceTransformer
import numpy as np
# 1. 모델 로드
model = SentenceTransformer('sentence-transformers/all-MiniLM-L12-v2')
# 2. 문장 및 질의 정의
documents = [
"apple",
"banana",
"cherry",
"date",
"cookie",
"eggplant",
"fig",
"grape",
]
query = "most delicious fruit"
# 3. 문장 및 질의 임베딩
document_embeddings = model.encode(documents)
query_embedding = model.encode(query)
# 4. 코사인 유사도 직접 계산
def cosine_similarity(vec1, vec2):
dot_product = np.dot(vec1, vec2)
norm_vec1 = np.linalg.norm(vec1)
norm_vec2 = np.linalg.norm(vec2)
return dot_product / (norm_vec1 * norm_vec2)
# 5. 유사도 계산 및 출력
print("Query:", query)
for i, doc in enumerate(documents):
similarity = cosine_similarity(query_embedding, document_embeddings[i])
print(f"Document: {doc} | Similarity: {similarity:.4f}")
Query: most delicious fruit
Document: apple | Similarity: 0.4374
Document: banana | Similarity: 0.6019
Document: cherry | Similarity: 0.4790
Document: date | Similarity: 0.1023
Document: cookie | Similarity: 0.2391
Document: eggplant | Similarity: 0.2774
Document: fig | Similarity: 0.2566
Document: grape | Similarity: 0.5352