RAG & LANCHAIN (3)- Langchain 개념 & 문법 정리 ch.08 임베딩

이영락·2024년 8월 30일
0

인공지능 공부

목록 보기
14/33

🏖️ CH08 임베딩(Embedding)

임베딩은 Retrieval-Augmented Generation(RAG) 시스템의 세 번째 단계로, 문서 분할 단계에서 생성된 문서 단위들을 기계가 이해할 수 있는 수치적 형태로 변환하는 과정입니다. 이 단계는 RAG 시스템의 핵심적인 부분 중 하나로, 문서의 의미를 벡터(숫자의 배열) 형태로 표현하여 사용자가 입력한 질문(Query)에 대해 데이터베이스에 저장된 문서 조각/단락(Chunk)을 검색하고 유사도 계산을 수행하는 데 활용됩니다.

임베딩의 필요성

  • 의미 이해: 자연 언어는 매우 복잡하고 다양한 의미를 내포하고 있습니다. 임베딩을 통해 이러한 텍스트를 정량화된 형태로 변환함으로써, 컴퓨터가 문서의 내용과 의미를 더 잘 이해하고 처리할 수 있습니다.
  • 정보 검색 향상: 수치화된 벡터 형태로의 변환은 문서 간의 유사성을 계산하는 데 있어 필수적입니다. 이는 관련 문서를 검색하거나, 질문에 가장 적합한 문서를 찾는 작업을 용이하게 합니다.

예시

임베딩: 문장을 수치 표현으로 변환

문서를 임베딩하면 다음과 같이 벡터 형태로 변환됩니다:

  • 1번 단락: [0.1, 0.5, 0.9, ..., 0.1, 0.2]
  • 2번 단락: [0.7, 0.1, 0.3, ..., 0.5, 0.6]
  • 3번 단락: [0.9, 0.4, 0.5, ..., 0.4, 0.3]

질문과의 유사도 계산 예시

질문: "시장조사기관 IDC가 예측한 AI 소프트웨어 시장의 연평균 성장률은 어떻게 되나요?"

해당 질문이 다음 벡터로 임베딩됩니다:

  • [0.1, 0.5, 0.9, ..., 0.2, 0.4]

유사도 계산 결과:

  • 1번 단락: 80% -> 선택!
  • 2번 단락: 30%
  • 3번 단락: 25%

코드 예제

from langchain_openai import OpenAIEmbeddings

# 단계 3: 임베딩(Embedding) 생성
embeddings = OpenAIEmbeddings()

# 텍스트를 임베딩하여 벡터 형태로 변환합니다.
text = "시장조사기관 IDC가 예측한 AI 소프트웨어 시장의 연평균 성장률은 어떻게 되나요?"
embedded_text = embeddings.embed_text(text)

print(embedded_text)

참고

  • 임베딩: 자연어를 벡터화하여 컴퓨터가 처리할 수 있는 수치 데이터로 변환하는 기술.
  • LangChain Text Embeddings: LangChain 라이브러리를 활용하여 텍스트 데이터를 임베딩하는 도구.

임베딩은 문서의 의미를 이해하고, 이를 바탕으로 관련성을 판단하여 문서를 효과적으로 검색하는 데 필수적인 역할을 합니다.


🏖️ 02. 캐시 임베딩(CacheBackedEmbeddings)

CacheBackedEmbeddings는 임베딩을 캐시하여 재계산을 피하고 성능을 향상시키는 방법입니다. 캐시된 임베딩은 키-값 저장소에 저장되며, 동일한 텍스트를 다시 임베딩할 필요 없이 빠르게 접근할 수 있습니다.

LocalFileStore에서 임베딩 사용 (영구 보관)

설정

로컬 파일 시스템을 사용하여 임베딩을 저장하고, 캐시를 활용하여 임베딩을 생성하는 방법입니다.

from langchain.storage import LocalFileStore
from langchain_openai import OpenAIEmbeddings
from langchain.embeddings import CacheBackedEmbeddings

# OpenAI 임베딩을 사용하여 기본 임베딩 설정
embedding = OpenAIEmbeddings()

# 로컬 파일 저장소 설정
store = LocalFileStore("./cache/")

# 캐시를 지원하는 임베딩 생성
cached_embedder = CacheBackedEmbeddings.from_bytes_store(
    underlying_embeddings=embedding,
    document_embedding_cache=store,
    namespace=embedding.model,  # 네임스페이스로 모델 이름 사용
)

# store에서 키들을 순차적으로 가져옵니다.
list(store.yield_keys())

출력 예시:

['text-embedding-ada-0020fd71f95-1342-512d-9d5b-3e3ab3c6bbe0', ...]

문서 임베딩 및 벡터 저장소 생성

문서를 로드하고 청크로 분할한 다음, 각 청크를 임베딩하여 벡터 저장소에 로드합니다.

from langchain.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
from langchain.vectorstores import FAISS

# 문서 로드
raw_documents = TextLoader("./data/appendix-keywords.txt").load()

# 문자 단위로 텍스트 분할 설정
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)

# 문서 분할
documents = text_splitter.split_documents(raw_documents)

# 코드 실행 시간을 측정합니다.
%time db = FAISS.from_documents(documents, cached_embedder)

출력 예시:

CPU times: user 3.87 ms, sys: 1.49 ms, total: 5.35 ms
Wall time: 4.3 ms

벡터 저장소를 다시 생성하려고 하면, 캐시 덕분에 훨씬 더 빠르게 처리됩니다.

# 캐싱된 임베딩을 사용하여 FAISS 데이터베이스 생성
%time db2 = FAISS.from_documents(documents, cached_embedder)

출력 예시:

CPU times: user 4.22 ms, sys: 1.44 ms, total: 5.66 ms
Wall time: 4.55 ms

InMemoryByteStore 사용 (비영구적)

설정

비영구적인 메모리 내 저장소를 사용하여 임베딩을 캐시하는 방법입니다.

from langchain.embeddings import CacheBackedEmbeddings
from langchain.storage import InMemoryByteStore

# 메모리 내 바이트 저장소 생성
store = InMemoryByteStore()

# 캐시 지원 임베딩 생성
cached_embedder = CacheBackedEmbeddings.from_bytes_store(
    embedding, store, namespace=embedding.model
)

🏖️ 03. 허깅페이스 임베딩(HuggingFace Embeddings)

HuggingFace 임베딩은 텍스트 데이터를 벡터로 변환하여 의미를 수치적으로 표현하는 방식입니다. 이 벡터 표현은 텍스트 간 유사도를 계산하거나, 문서 검색, 추천 시스템 등 다양한 응용 분야에서 사용될 수 있습니다.

HuggingFace Endpoint Embedding

HuggingFaceEndpointEmbeddings는 InferenceClient를 사용하여 임베딩을 계산하며, 다양한 언어 모델을 지원합니다.

from langchain_huggingface.embeddings import HuggingFaceEndpointEmbeddings

model_name = "intfloat/multilingual-e5-large-instruct"

hf_embeddings = HuggingFaceEndpointEmbeddings(
    model=model_name,
    task="feature-extraction",
    huggingfacehub_api_token=os.environ["HUGGINGFACEHUB_API_TOKEN"],
)

texts = [
    "안녕, 만나서 반가워.",
    "LangChain simplifies the process of building applications with large language models",
    "랭체인 한국어 튜토리얼은 LangChain의 공식 문서, cookbook 및 다양한 실용 예제를 바탕으로 하여 사용자가 LangChain을 더 쉽고 효과적으로 활용할 수 있도록 구성되어 있습니다. ",
    "LangChain은 초거대 언어모델로 애플리케이션을 구축하는 과정을 단순화합니다.",
    "Retrieval-Augmented Generation (RAG) is an effective technique for improving AI responses.",
]

# Document Embedding 수행
embedded_documents = hf_embeddings.embed_documents(texts)

print("[HuggingFace Endpoint Embedding]")
print(f"Model: \t\t{model_name}")
print(f"Dimension: \t{len(embedded_documents[0])}")

출력 예시:

[HuggingFace Endpoint Embedding]
Model:      intfloat/multilingual-e5-large-instruct
Dimension:  1024

이 방법을 통해 텍스트를 벡터로 변환하고, 다양한 응용 분야에서 활용할 수 있습니다.

유사도 계산

벡터 내적을 통해 임베딩된 텍스트 간의 유사도를 계산할 수 있습니다.

import numpy as np

# 쿼리 임베딩 생성
embedded_query = hf_embeddings.embed_query("LangChain 에 대해서 알려주세요.")

# 벡터 내적을 통한 유사도 계산
similarities = np.array(embedded_query) @ np.array(embedded_documents).T
sorted_idx = similarities.argsort()[::-1]

print("[Query] LangChain 에 대해서 알려주세요.\n====================================")
for i, idx in enumerate(sorted_idx):
    print(f"[{i}] {texts[idx]}")
    print()

출력 예시:

[Query] LangChain 에 대해서 알려주세요.
====================================
[0] LangChain은 초거대 언어모델로 애플리케이션을 구축하는 과정을 단순화합니다.

[1] LangChain simplifies the process of building applications with large language models

[2] 랭체인 한국어 튜토리얼은 LangChain의 공식 문서, cookbook 및 다양한 실용 예제를 바탕으로 하여 사용자가 LangChain을 더 쉽고 효과적으로 활용할 수 있도록 구성되어 있습니다. 

[3] 안녕, 만나서 반가워.

[4] Retrieval-Augmented Generation (RAG) is an effective technique for improving AI responses.

HuggingFace Embeddings

HuggingFaceEmbeddings를 사용하여 다양한 모델을 활용한 임베딩을 수행할 수 있습니다.

from langchain_huggingface.embeddings import HuggingFaceEmbeddings

model_name = "intfloat/multilingual-e5-large-instruct"

hf_embeddings = HuggingFaceEmbeddings(
    model_name=model_name,
    model_kwargs={"device": "cuda"},  # CUDA 또는 CPU 설정
    encode_kwargs={"normalize_embeddings": True},
)

# Document Embedding 수행
embedded_documents = hf_embeddings.embed_documents(texts)

print(f"Model: \t\t{model_name}")
print(f"Dimension: \t{len(embedded_documents[0])}")

출력 예시:

Model:      intfloat/multilingual-e5-large-instruct
Dimension:  1024

BGE-M3 임베딩

BGE-M3 모델을 사용하여 임베딩을 생성하는 방법입니다.

from langchain_huggingface.embeddings import HuggingFaceEmbeddings

model_name = "BAAI/bge-m3"
model_kwargs = {"device": "cuda"}
encode_kwargs = {"normalize_embeddings": True}

hf_embeddings = HuggingFaceEmbeddings(
    model_name=model_name, model_kwargs=model_kwargs, encode_kwargs=encode_kwargs
)

# Document Embedding 수행
embedded_documents = hf_embeddings.embed_documents(texts)

print(f"Model: \t\t{model_name}")
print(f"Dimension: \t{len(embedded_documents[0])}")

출력 예시:

Model:      BAAI/bge-m3
Dimension:  1024

FlagEmbedding을 활용한 접근법

FlagEmbedding에서는 세 가지 접근법을 제공하여 더욱 강력한 검색 시스템을 구축할 수 있습니다.

Dense Vector

from FlagEmbedding import BGEM3FlagModel

model_name = "BAAI/bge-m3"
bge_embeddings = BGEM3FlagModel(
    model_name, use_fp16=True
)

bge_embedded = bge_embeddings.encode(
    texts,
    batch_size=12,
    max_length=8192,
)["dense_vecs"]

print(f"Model: \t\t{model_name}")
print(f"Dimension: \t{bge_embedded.shape}")

출력 예시:

Model:      BAAI/bge-m3
Dimension:  (5, 1024)

Sparse Embedding (Lexical Weight)

bge_flagmodel = BGEM3FlagModel("BAAI/bge-m3", use_fp16=True)

bge_encoded = bge_flagmodel.encode(texts, return_sparse=True)
lexical_scores1 = bge_flagmodel.compute_lexical_matching_score(
    bge_encoded["lexical_weights"][0], bge_encoded["lexical_weights"][0]
)
lexical_scores2 = bge_flagmodel.compute_lexical_matching_score(
    bge_encoded["lexical_weights"][0], bge_encoded["lexical_weights"][1]
)

print(lexical_scores1)
print(lexical_scores2)

출력 예시:

0.30167388916015625
0

Multi-Vector (ColBERT)

bge_flagmodel = BGEM3FlagModel("BAAI/bge-m3", use_fp16=True)

bge_encoded = bge_flagmodel.encode(texts, return_colbert_vecs=True)
colbert_scores1 = bge_flagmodel.colbert_score(
    bge_encoded["colbert_vecs"][0], bge_encoded["colbert_vecs"][0]
)
colbert_scores2 = bge_flagmodel.colbert_score(
    bge_encoded["colbert_vecs"][0], bge_encoded["colbert_vecs"][1]
)

print(colbert_scores1)
print(colbert_scores2)

출력 예시:

tensor(1.)
tensor(0.3748)

🏖️ 04. Upstage 임베딩(UpstageEmbeddings)

Upstage는 인공지능(AI) 기술, 특히 대규모 언어 모델(LLM)과 문서 AI 분야에 특화된 국내 스타트업입니다. Upstage의 임베딩 모델을 활용하면 텍스트 데이터를 벡터 형태로 변환하여 다양한 자연어 처리 작업에 활용할 수 있습니다.

API 키 설정

먼저, API 키를 환경 변수로 설정하여 보안성을 유지합니다.

from dotenv import load_dotenv

# API 키 정보 로드
load_dotenv()
True

임베딩 모델 선택 및 사용

Upstage에서는 다양한 임베딩 모델을 제공하며, 각 모델은 특정 용도에 최적화되어 있습니다.

  • Query 임베딩 모델: 사용자의 질문을 임베딩하는 데 최적화된 모델
  • Passage 임베딩 모델: 문서나 텍스트를 임베딩하는 데 최적화된 모델
from langchain_upstage import UpstageEmbeddings

# 쿼리 전용 임베딩 모델
query_embeddings = UpstageEmbeddings(model="solar-embedding-1-large-query")

# 문서 전용 임베딩 모델
passage_embeddings = UpstageEmbeddings(model="solar-embedding-1-large-passage")

Query 임베딩

주어진 질문을 임베딩하여 벡터 형태로 변환합니다.

# 쿼리 임베딩
embedded_query = query_embeddings.embed_query("LangChain 에 대해서 상세히 알려주세요.")

# 임베딩 차원 출력
print(len(embedded_query))  # 출력: 4096

문서 임베딩

다양한 텍스트 데이터를 임베딩하여 벡터로 변환합니다.

texts = [
    "안녕, 만나서 반가워.",
    "LangChain simplifies the process of building applications with large language models",
    "랭체인 한국어 튜토리얼은 LangChain의 공식 문서, cookbook 및 다양한 실용 예제를 바탕으로 하여 사용자가 LangChain을 더 쉽고 효과적으로 활용할 수 있도록 구성되어 있습니다.",
    "LangChain은 초거대 언어모델로 애플리케이션을 구축하는 과정을 단순화합니다.",
    "Retrieval-Augmented Generation (RAG) is an effective technique for improving AI responses.",
]

# 문서 임베딩
embedded_documents = passage_embeddings.embed_documents(texts)

유사도 계산 및 결과 출력

임베딩된 쿼리와 문서 간의 유사도를 계산하여 가장 관련성이 높은 문서를 찾습니다.

import numpy as np

# 질문(embedded_query): LangChain 에 대해서 알려주세요.
similarity = np.array(embedded_query) @ np.array(embedded_documents).T

# 유사도 기준 내림차순 정렬
sorted_idx = similarity.argsort()[::-1]

# 결과 출력
print("[Query] LangChain 에 대해서 알려주세요.\n====================================")
for i, idx in enumerate(sorted_idx):
    print(f"[{i}] 유사도: {similarity[idx]:.3f} | {texts[idx]}")
    print()

출력 예시:

[Query] LangChain 에 대해서 알려주세요.
====================================
[0] 유사도: 0.487 | LangChain은 초거대 언어모델로 애플리케이션을 구축하는 과정을 단순화합니다.

[1] 유사도: 0.465 | LangChain simplifies the process of building applications with large language models

[2] 유사도: 0.432 | 랭체인 한국어 튜토리얼은 LangChain의 공식 문서, cookbook 및 다양한 실용 예제를 바탕으로 하여 사용자가 LangChain을 더 쉽고 효과적으로 활용할 수 있도록 구성되어 있습니다. 

[3] 유사도: 0.194 | Retrieval-Augmented Generation (RAG) is an effective technique for improving AI responses.

[4] 유사도: 0.151 | 안녕, 만나서 반가워.

🏖️ 05. Ollama 임베딩(OllamaEmbeddings)

Ollama는 로컬 환경에서 대규모 언어 모델(LLM)을 쉽게 실행할 수 있게 해주는 오픈소스 프로젝트입니다. 이 도구는 다양한 LLM을 간단한 명령어로 다운로드하고 실행할 수 있게 해주며, 개발자들이 AI 모델을 자신의 컴퓨터에서 직접 실험하고 사용할 수 있도록 지원합니다. Ollama를 활용하여 텍스트 데이터를 벡터 형태로 변환하고, 이를 바탕으로 유사도를 계산할 수 있습니다.

임베딩 모델 선택 및 사용

Ollama에서 제공하는 임베딩 모델을 사용하여 텍스트 데이터를 벡터로 변환할 수 있습니다.

from langchain_community.embeddings import OllamaEmbeddings

# Ollama 임베딩 모델 설정
ollama_embeddings = OllamaEmbeddings(
    model="nomic-embed-text",  # 사용할 임베딩 모델
    # model="chatfire/bge-m3:q8_0" # BGE-M3 모델 사용 예시
)

Query 임베딩

주어진 질문을 임베딩하여 벡터 형태로 변환합니다.

# 쿼리 임베딩
embedded_query = ollama_embeddings.embed_query("LangChain 에 대해서 상세히 알려주세요.")

# 임베딩 차원 출력
print(len(embedded_query))  # 출력: 768

문서 임베딩

다양한 텍스트 데이터를 임베딩하여 벡터로 변환합니다.

texts = [
    "안녕, 만나서 반가워.",
    "LangChain simplifies the process of building applications with large language models",
    "랭체인 한국어 튜토리얼은 LangChain의 공식 문서, cookbook 및 다양한 실용 예제를 바탕으로 하여 사용자가 LangChain을 더 쉽고 효과적으로 활용할 수 있도록 구성되어 있습니다.",
    "LangChain은 초거대 언어모델로 애플리케이션을 구축하는 과정을 단순화합니다.",
    "Retrieval-Augmented Generation (RAG) is an effective technique for improving AI responses.",
]

# 문서 임베딩
embedded_documents = ollama_embeddings.embed_documents(texts)

유사도 계산 및 결과 출력

임베딩된 쿼리와 문서 간의 유사도를 계산하여 가장 관련성이 높은 문서를 찾습니다.

import numpy as np

# 질문(embedded_query): LangChain 에 대해서 알려주세요.
similarity = np.array(embedded_query) @ np.array(embedded_documents).T

# 유사도 기준 내림차순 정렬
sorted_idx = similarity.argsort()[::-1]

# 결과 출력
print("[Query] LangChain 에 대해서 알려주세요.\n====================================")
for i, idx in enumerate(sorted_idx):
    print(f"[{i}] 유사도: {similarity[idx]:.3f} | {texts[idx]}")
    print()

출력 예시:

[Query] LangChain 에 대해서 알려주세요.
====================================
[0] 유사도: 399.644 | LangChain은 초거대 언어모델로 애플리케이션을 구축하는 과정을 단순화합니다.

[1] 유사도: 356.518 | 랭체인 한국어 튜토리얼은 LangChain의 공식 문서, cookbook 및 다양한 실용 예제를 바탕으로 하여 사용자가 LangChain을 더 쉽고 효과적으로 활용할 수 있도록 구성되어 있습니다.

[2] 유사도: 322.359 | LangChain simplifies the process of building applications with large language models

[3] 유사도: 321.078 | 안녕, 만나서 반가워.

[4] 유사도: 224.858 | Retrieval-Augmented Generation (RAG) is an effective technique for improving AI responses.

🏖️ 06. GPT4All 임베딩(GPT4AllEmbeddings)

GPT4All은 로컬 환경에서 실행할 수 있는 무료 챗봇이며, 개인정보 보호를 중시하는 AI 도구입니다. 이 도구는 GPU나 인터넷 연결 없이도 다양한 인기 모델을 실행할 수 있도록 지원합니다. 이번 섹션에서는 GPT4All을 활용하여 텍스트 데이터를 임베딩하는 방법을 설명합니다.

GPT4All의 Python 바인딩 설치

먼저, GPT4All의 Python 바인딩을 설치해야 합니다. 다음 명령어를 실행하여 필요한 패키지를 설치합니다.

%pip install --upgrade --quiet gpt4all > /dev/null

GPT4AllEmbeddings 클래스 사용

GPT4AllEmbeddings 클래스를 사용하여 텍스트 데이터를 벡터로 변환할 수 있습니다.

from langchain_community.embeddings import GPT4AllEmbeddings

# GPT4All 임베딩 객체 생성
gpt4all_embd = GPT4AllEmbeddings()

임베딩 테스트

아래 코드는 "임베딩 테스트를 하기 위한 샘플 문장입니다." 라는 텍스트를 임베딩하는 과정을 보여줍니다.

# 테스트용 문서 텍스트
text = "임베딩 테스트를 하기 위한 샘플 문장입니다."

# 쿼리 임베딩 생성
query_result = gpt4all_embd.embed_query(text)

# 임베딩된 차원의 크기 확인
print(len(query_result))  # 출력: 384

여러 문서 임베딩

embed_documents 메서드를 사용하여 여러 개의 텍스트를 임베딩할 수 있습니다.

texts = [
    "안녕, 만나서 반가워.",
    "LangChain simplifies the process of building applications with large language models",
    "랭체인 한국어 튜토리얼은 LangChain의 공식 문서, cookbook 및 다양한 실용 예제를 바탕으로 하여 사용자가 LangChain을 더 쉽고 효과적으로 활용할 수 있도록 구성되어 있습니다.",
    "LangChain은 초거대 언어모델로 애플리케이션을 구축하는 과정을 단순화합니다.",
    "Retrieval-Augmented Generation (RAG) is an effective technique for improving AI responses.",
]

# 여러 문서를 임베딩하여 벡터 생성
doc_result = gpt4all_embd.embed_documents(texts)

# 첫 번째 문서의 임베딩된 차원 크기 확인
print(len(doc_result[0]))  # 출력: 384

임베딩 결과 해석

임베딩된 벡터는 다양한 자연어 처리 작업에서 활용될 수 있습니다. 예를 들어, 문서 분류, 감성 분석, 기계 번역 등의 작업에서 입력 데이터로 사용되어 모델의 성능을 향상시킬 수 있습니다.

GPT4All 임베딩을 사용하면 로컬 환경에서 효율적으로 텍스트 데이터를 벡터로 변환하여 사용할 수 있으며, 특히 개인정보 보호가 중요한 프로젝트에 적합합니다.

profile
AI Engineer / 의료인공지능

0개의 댓글

관련 채용 정보