Document Loaders로 문서를 load하고 Text Splitters로 문서를 분할하면 이제 문서를 임베딩할 차례이다.
Text Embeddings는 텍스트를 숫자로 변환하여 문장 간의 유사성을 비교할 수 있도록 한다.
사용자의 질문과 유사한 Chunk를 찾기 위해서는 임베딩 벡터가 필요하다. 이 임베딩 벡터로 바꾸는 과정을 임베딩 모델이 담당한다.
물론, 사용자의 질문을 벡터로 변환하는 과정 또한 임베딩 모델이 수행한다.
"How many people live in Berlin?" 이라는 문장은 비정형 데이터이기 때문에 (숫자가 아님) 좌표상에 표시할수가 없다.
이러한 비정형데이터를 수치화해서 좌표상에 표시할 수 있게 해주는게 임베딩 모델이다. 즉, 비정형 데이터를 정형 데이터로 변환해준다.
그럼 임베딩 모델은 어떻게 만드냐? 대부분의 경우 대용량 말뭉치(corpus)를 통해 사전학습된 모델을 통해 쉽게 임베딩한다.
이러한 사전학습 모델을 사용하면 처음 보는 문장에 대해서도 임베딩을 아주 잘 수행한다.
사전학습 모델
사전학습 모데에는 OpenAI의 ada 모델과 허깅페이스의 모델들이 있다. 사용 목적과 요구사항에 따라 적절한 임베딩 모델을 사용하면 된다.
한국어 임베딩 모델은 ko-sbert-nli, koSim~~이 잘 된다.
실습
!pip install openai langchain pypdf tiktoken
Pretrained Embedding(유료)
OpenAIEmbeddings - ada-002
from langchain.embeddings import OpenAIEmbeddings
embeddings_model = OpenAIEmbeddings(openai_api_key = "YOUR_API_KEY")
embeddings = embeddings_model.embed_documents(
[
"안녕하세요",
"제 이름은 홍길동입니다.",
"이름이 무엇인가요?",
"랭체인은 유용합니다.",
"Hello Wordl!"
]
)
len(embeddings), len(embeddings[0])
#유사도 측정을 위한 질문과 답변
embedded_query_q = embeddings_model.embed_query("이 대화에서 언급된 이름이 무엇입니까?")
embedded_query_a = embeddings_model.embed_query("이 대화에서 언급된 이름은 홍길동입니다.")
print(len(embedded_query_q),len(embedded_query_a))
import numpy as np
from numpy import dot
from numpy.linalg import norm
def cos_sim(A,B):
return dot(A,B)/(norm(A)*norm(B))
- 벡터간 유사도를 구할때 cosine similarity를 가장 많이 사용한다.
print(cos_sim(embedded_query_q, embedded_query_a))
print(cos_sim(embedded_query_q, embeddings[1]))
print(cos_sim(embedded_query_q, embeddings[3]))
Local Embedding 모델(무료)
Huggingface Embedding
!pip install sentence_transformers
from langchain.embeddings import HuggingFaceBgeEmbeddings
model_name = "BAAI/bge-small-en"
model_kwargs = {'device':'cpu'}
encode_kwargs = {'normalize_embeddings':True}
hf = HuggingFaceBgeEmbeddings(
model_name = model_name,
model_kwargs = model_kwargs,
encode_kwargs = encode_kwargs
)
- HuggingFaceBgeEmbeddings : huggingface의 bge 모델을 위해 만들어진 임베딩 모델
- model_kwargs : 모델 키워드 argument로 모델 : cpu로 해야한다. 그래야 gpu 없이도 돌릴 수 있음
- encode_kwargs : encode keyword argument로 임베딩을 정규화하는 과정을 거친다. 임베딩 벡터끼리 정규화가 안되면 유사도 비교가 잘 안됨.
embeddings = hf.embed_documents( [ "today is monday", "weather is nice today", "what's the problem?", "langhcain in useful", "Hello World!", "my name is morris" ] )
- embed_documents로 여러 문장을 임베딩
BGE_query_q = hf.embed_query("Hello? who is this?") BGE_query_a = hf.embed_query("hi this is harrison")
print(cos_sim(BGE_query_q,BGE_query_a))
print(cos_sim(BGE_query_q,embeddings[1]))
print(cos_sim(BGE_query_q,embeddings[5]))
```python
sentences = [
"안녕하세요",
"제 이름은 홍길동입니다.",
"이름이 무엇인가요?",
"랭체인은 유용합니다.",
"홍길동 아버지의 이름은 홍상직입니다."
]
ko_embeddings = hf.embed_documents(sentences)
BGE_query_q_2 = hf.embed_query("홍길동은 아버지를 아버지라 부르지 못하였습니다. 홍길동 아버지의 이름은 무엇입니까?")
BGE_query_a_2 = hf.embed_query("홍길동의 아버지는 엄했습니다.")
print("질문: 홍길동은 아버지를 아버지라 부르지 못하였습니다. 홍길동 아버지의 이름은 무엇입니까? \n", "-"*100)
print("홍길동의 아버지는 엄했습니다. \t\t 문장 유사도: ", round(cos_sim(BGE_query_q_2, BGE_query_a_2),2))
print(sentences[1] + "\t\t\t 문장 유사도: ", round(cos_sim(BGE_query_q_2, ko_embeddings[1]),2))
print(sentences[3] + "\t\t\t 문장 유사도: ", round(cos_sim(BGE_query_q_2, ko_embeddings[3]),2))
print(sentences[4] + "\t 문장 유사도: ", round(cos_sim(BGE_query_q_2, ko_embeddings[4]),2))
- bge 모델은 영어를 위주로 개발됨. 따라서, 한국어 임베딩에는 제한이 있다.
한국어로 사전학습된 모델 임베딩 - ko-sbert-nli
from langchain.embeddings import HuggingFaceEmbeddings
model_name = "jhgan/ko-sbert-nli"
model_kwargs = {'device':'cpu'}
encode_kwargs = {'normalize_embeddings':True}
ko = HuggingFaceEmbeddings(
model_name = model_name,
model_kwargs = model_kwargs,
encode_kwargs = encode_kwargs
)
sentences = [
"안녕하세요",
"제 이름은 홍길동입니다.",
"이름이 무엇인가요?",
"랭체인은 유용합니다.",
"홍길동 아버지의 이름은 홍상직입니다."
]
ko_embeddings = ko.embed_documents(sentences)
q = "홍길동은 아버지를 아버지라 부르지 못하였습니다. 홍길동 아버지의 이름은 무엇입니까?"
a = "홍길동의 아버지는 엄했습니다."
ko_query_q = ko.embed_query(q)
ko_query_a = ko.embed_query(a)
print("질문: {} \n".format(q), "-"*100)
print("{} \t\t 문장 유사도: ".format(a), round(cos_sim(ko_query_q, ko_query_a),2))
print("{}\t\t\t 문장 유사도: ".format(sentences[1]), round(cos_sim(ko_query_q, ko_embeddings[1]),2))
print("{}\t\t\t 문장 유사도: ".format(sentences[3]), round(cos_sim(ko_query_q, ko_embeddings[3]),2))
print("{}\t 문장 유사도: ".format(sentences[4]), round(cos_sim(ko_query_q, ko_embeddings[4]),2))
Reference
모두의 AI 유튜브 채널[https://www.youtube.com/@AI-km1yn]
'인공지능 > RAG' 카테고리의 다른 글
LangChain (9) Retrieval - Retriever (0) | 2024.04.08 |
---|---|
LangChain (8) Retrieval - Vectorstores (0) | 2024.04.08 |
LangChain (6) Retrieval - Text Splitters (0) | 2024.04.08 |
Knowledge Distillation (0) | 2024.04.06 |
LangChain (5) Retrieval - Document Loaders (0) | 2024.03.23 |