embedding과 Vector Stores를 얕게 알아보자

임베딩(Embedding)이란?

임베딩에 대해 이야기하기 위해 우리는 먼저 우리가 사용하는 LLM의 작동방식을 한번 떠올려 봐야합니다.

우리가 사용하는 LLM은 쉽게 이야기해 인풋으로 들어온 입력값과 가장 연관있는 출력값을 확률적으로 구하고 그 확률을 바탕으로 출력하는 것입니다. 이해하기 어렵죠?

예를들어 “철수는 밥을” 이라는 문장이 있다면 뒤이어서 “먹었다”, “먹을 것이다”, “버렸다” 등의 단어가 따라옵니다.

이 때 학습한 데이터에 따라서 다음에 올 단어가 달라질것입니다. “철수는 밥을 먹었다.”, “영희는 밥을 먹었다” 를 학습한 언어 모델은 “철수는 밥을”을 입력하면 뒤이어서 “먹었다”를 출력할 것입니다. 이게 우리가 사용하는 LLM을 가장 단순하게 설명하는 방식입니다.

이렇게 단어와 단어간의 관계와 확률를 벡터값으로 즉 숫자로 전환하는게 임베딩 입니다.

좀 어렵게 이야기하면 텍스트나 이미지와 같은 비정형 데이터(비정형 데이터는 설계된 모델이나 구조로 구성되지 않은 데이터를 말합니다.)를 고차원의 벡터 형태로 변환하는 것을 의미합니다.

이러한 변환 과정을 통해서 단어의 의미를 컴퓨터가 이해 할 수 있는 형식의 데이터로 저장할 수 있게되고 이것이 임베딩 입니다.


벡터 스토어(Vector Stores)란?

앞에서 알아본 임베딩을 이해했다면, 이제 벡터 스토어가 감이 오실 겁니다.

우리가 가진 데이터(문장, 이미지 등의 비정형 데이터)를 벡터값으로 변환하고 이 벡터값과 데이터를 묶어서(indexing) 저장했다가 필요할때 벡터값으로 데이터를 꺼내오는 데이터베이스 입니다.

왜 이런 번거로운걸 할까요?

왜냐하면 우리는 어떤 값이 주어질지 알 수 없기 때문입니다.

형식이 정해지지 않은채 마구잡이로 들어오는 텍스트, 이미지들의 형식만으로 우리가 가진 데이터를 꺼내오는데에는 한계가 있어서 그렇습니다.

여기 두 문장과 하나의 질문이 있습니다.(FAISS는 메타에서 만든 벡터스토어 입니다.)

embed_query = ["FAISS is an important library", "LangChain supports FAISS"]
Question = "FAISS is a vector store."


사람은 이 3가지 문장들을 보고 "FAISS is a vector store.” 라는 질문이 “FAISS is an important library” 라는 문장과 가장 연관이 있는 것을 알수 있습니다. 하지만 이걸 컴퓨터는 어떻게 알수 있을까요?

앞에서 임베딩은 단어의 의미를 컴퓨터가 이해할 수 있는 형태의 데이터로 변환한 것이라고 설명했습니다.

그래서 이 문장들을 임베딩해서 벡터값으로 변환하여 문장과 함께 벡터 스토어에 저장했다가. 벡터스토어에 찾고자 하는 문장이 있으면 그 문장을 임베딩해 벡터값으로 변환하고 그 변화시킨 벡터 값과 가장 유사한 벡터를 가진 문장을 출력하게 합니다.

이것이 벡트 스토어의 동작 방식중 가장 대표적인 유사도(similarity)검색 입니다.


이걸 그림으로 표현하면 다음과 같습니다.

이제 이걸 간단한 코드를 첨부해서 사용한 예시를 보여 드리겠습니다.

from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores.faiss import FAISS
import dotenv
import os


dotenv.load_dotenv(verbose=True)
key = os.getenv('OPENAI_API_KEY')
llm = ChatOpenAI(api_key=key, temperature=0)

embeddings = OpenAIEmbeddings(model="text-embedding-3-large")

query_text = "FAISS"
query_text2 = "FAISS is a vector store."
query_text3 = "LangChain"
query_text4 = "LangChain is a library."


embed_query = embeddings.embed_query(query_text)
embed_query2 = embeddings.embed_query(query_text2)
embed_query3 = embeddings.embed_query(query_text3)
embed_query4 = embeddings.embed_query(query_text4)
print(embed_query[:5])
print(embed_query2[:5])
print(embed_query3[:5])
print(embed_query4[:5])

input = "FAISS is a vector store."

texts = ["FAISS is an important library", "LangChain supports FAISS"]
faiss_instance = FAISS.from_texts(texts, embeddings)
similar_docs = faiss_instance.similarity_search(input, k=1)
print(similar_docs)


출력결과

[-0.025621170015367976, 0.055452696626935624, -0.016107065500861325, 0.004124681904798366, -0.01677615371124864]

[-0.018773654308977546, 0.06172926669101836, -0.030134200782019487, 0.017685776419236545, -0.014709655064758435]

[-0.02307139062512355, 0.011841633835293212, -0.0221535741256067, 0.04002400334503806, -0.006447212058208196]

[-0.021855882782398372, 0.00823327879469269, -0.026812271510989506, 0.04024826639884145, -0.018272952674949626]

Warning: model not found. Using cl100k_base encoding.

Warning: model not found. Using cl100k_base encoding.

[Document(page_content='FAISS is an important library')]


다음 시간에는 이 벡터 스토어를 랭체인에서 활용하는 과정을 설명하겠습니다. 감사합니다.


#9기랭체인

4

👉 이 게시글도 읽어보세요