[Langchain] Embedding Model

Hunie_07·2025년 3월 28일
0

Langchain

목록 보기
8/35

📌 Embedding Model

문서 로드

from langchain_community.document_loaders import PyPDFLoader

# PDF 로더 초기화
pdf_loader = PyPDFLoader('./data/transformer.pdf')

# 동기 로딩
pdf_docs = pdf_loader.load()
print(f'PDF 문서 개수: {len(pdf_docs)}')

- 출력

PDF 문서 개수: 15


텍스트 분할

from langchain_text_splitters import RecursiveCharacterTextSplitter

# 텍스트 분할기 초기화
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,             # 청크 크기  
    chunk_overlap=200,           # 청크 중 중복되는 부분 크기
    length_function=len,         # 글자 수를 기준으로 분할
    separators=["\n\n", "\n", " ", ""],  # 구분자 - 재귀적으로 순차적으로 적용 
)

# PDF 문서를 텍스트로 분할
chunks = text_splitter.split_documents(pdf_docs)
print(f"생성된 텍스트 청크 수: {len(chunks)}")
print(f"각 청크의 길이: {list(len(chunk.page_content) for chunk in chunks)}")

- 출력

생성된 텍스트 청크 수: 52
각 청크의 길이: [986, 910, 975, 452, 933, 995, 902, 907, 996, 385, 924, 954, 216, 923, 900, 950, 992, 913, 908, 870, 945, 975, 946, 997, 196, 980, 980, 946, 938, 999, 943, 920, 734, 958, 946, 945, 617, 983, 988, 994, 624, 944, 909, 940, 913, 983, 924, 924, 845, 812, 815, 818]

문서 임베딩 (Document Embedding)

  • 개념:

    • 텍스트를 벡터(숫자 배열)로 변환하는 과정
    • 문서의 의미적 특성을 수치화하여 컴퓨터가 이해하고 처리할 수 있는 형태로 변환
  • 목적:

    • 텍스트 간 유사도 계산 가능
    • 벡터 데이터베이스 저장 및 검색
    • 의미 기반 문서 검색 구현
  • LangChain의 임베딩 모델 종류:

    • OpenAI 임베딩
    • HuggingFace 임베딩
    • Ollama 임베딩

1️⃣ OpenAI

  • LangChain에서 가장 널리 사용되는 임베딩 모델 중 하나

  • 주요 특징:

    1. 고품질의 임베딩 생성
    2. 다양한 언어 지원 (다국어 지원)
    3. 일관된 성능
    4. 손쉬운 통합
  • 사용시 주의사항:

    1. API 키 설정이 필요 (환경 변수 OPENAI_API_KEY)
    2. API 사용량에 따른 비용 발생
    3. 긴 텍스트는 자동으로 분할되지 않으므로 필요시 TextSplitter를 사용
  • 모델별 특징

    모델                    페이지/달러    MTEB 성능     최대입력
    text-embedding-3-small  62,500       62.3%       8191
    text-embedding-3-large   9,615       64.6%       8191
    text-embedding-ada-002  12,500       61.0%       8191
  • 임베딩 벡터 특성

    1. small: 1536 차원
    2. large: 3072 차원
    3. dimensions 파라미터로 차원 축소 가능

1. Embedding 모델

from langchain_openai import OpenAIEmbeddings

# OpenAIEmbeddings 모델 생성
embeddings_model = OpenAIEmbeddings(
    model="text-embedding-3-large",  # 사용할 모델 이름
    dimensions=None, # 원하는 임베딩 차원 수를 지정 가능 (기본값: None)
    )

# 임베딩 객체 출력
embeddings_model

- 출력

OpenAIEmbeddings(client=<openai.resources.embeddings.Embeddings object at 0x0000026275095520>, async_client=<openai.resources.embeddings.AsyncEmbeddings object at 0x0000026274209700>, model='text-embedding-3-large', dimensions=None, deployment='text-embedding-ada-002', openai_api_version=None, openai_api_base=None, openai_api_type=None, openai_proxy=None, embedding_ctx_length=8191, openai_api_key=SecretStr('**********'), openai_organization=None, allowed_special=None, disallowed_special=None, chunk_size=1000, max_retries=2, request_timeout=None, headers=None, tiktoken_enabled=True, tiktoken_model_name=None, show_progress_bar=False, model_kwargs={}, skip_empty=False, default_headers=None, default_query=None, retry_min_seconds=4, retry_max_seconds=20, http_client=None, http_async_client=None, check_embedding_ctx_length=True)

한번에 임베딩 가능한 토큰 수

# 임베딩 모델의 컨텍스트 길이 확인
embeddings_model.embedding_ctx_length

- 출력

8191

임베딩 모델 차원 확인 및 지정

# 임베딩 모델의 임베딩 차원 확인 - 기본값 (None)
embeddings_model.dimensions
# OpenAIEmbeddings 모델 생성할 때 임베딩 차원을 지정하는 예시
embeddings_model = OpenAIEmbeddings(
    model="text-embedding-3-small",  # 사용할 모델 이름
    dimensions=1024, # 원하는 임베딩 차원 수를 지정 가능 (기본값: None)
    )

# 임베딩 모델의 임베딩 차원 확인 
embeddings_model.dimensions

- 출력

1024

# OpenAIEmbeddings 모델 생성
embeddings_openai = OpenAIEmbeddings(model="text-embedding-3-small")

# 임베딩 객체 출력
embeddings_openai

- 출력

OpenAIEmbeddings(client=<openai.resources.embeddings.Embeddings object at 0x000001C27D888F80>, async_client=<openai.resources.embeddings.AsyncEmbeddings object at 0x000001C27D85E810>, model='text-embedding-3-small', dimensions=None, deployment='text-embedding-ada-002', openai_api_version=None, openai_api_base=None, openai_api_type=None, openai_proxy=None, embedding_ctx_length=8191, openai_api_key=SecretStr('**********'), openai_organization=None, allowed_special=None, disallowed_special=None, chunk_size=1000, max_retries=2, request_timeout=None, headers=None, tiktoken_enabled=True, tiktoken_model_name=None, show_progress_bar=False, model_kwargs={}, skip_empty=False, default_headers=None, default_query=None, retry_min_seconds=4, retry_max_seconds=20, http_client=None, http_async_client=None, check_embedding_ctx_length=True)

2. embed_documents

# 문서 컬렉션
documents = [
    "인공지능은 컴퓨터 과학의 한 분야입니다.",
    "머신러닝은 인공지능의 하위 분야입니다.",
    "딥러닝은 머신러닝의 한 종류입니다.",
    "자연어 처리는 컴퓨터가 인간의 언어를 이해하고 생성하는 기술입니다.",
    "컴퓨터 비전은 컴퓨터가 디지털 이미지나 비디오를 이해하는 방법을 연구합니다."
]

# 문서 임베딩
document_embeddings_openai = embeddings_openai.embed_documents(documents)

# 임베딩 결과 출력
print(f"임베딩 벡터의 개수: {len(document_embeddings_openai)}")
print(f"임베딩 벡터의 차원: {len(document_embeddings_openai[0])}")
print(document_embeddings_openai[0])

- 출력

임베딩 벡터의 개수: 5
임베딩 벡터의 차원: 1536
[-0.002310403622686863, 0.012099752202630043, ... ]

3. embed_query

embedded_query_openai = embeddings_openai.embed_query("인공지능이란 무엇인가요?")

# 쿼리 임베딩 결과 출력
print(f"쿼리 임베딩 벡터의 차원: {len(embedded_query_openai)}")
print(embedded_query_openai)

- 출력

쿼리 임베딩 벡터의 차원: 1536
[-0.02255643531680107, 0.022176697850227356, ... ]

4. 유사도 기반 검색

  • 문서 임베딩과 쿼리 임베딩의 코사인 유사도 기반으로 검색
from langchain_community.utils.math import cosine_similarity
import numpy as np

# 쿼리와 가장 유사한 문서 찾기 함수
def find_most_similar(
        query: str, 
        doc_embeddings: np.ndarray,
        embeddings_model=OpenAIEmbeddings(model="text-embedding-3-small")
        ) -> tuple[str, float]:
    
    # 쿼리 임베딩: OpenAI 임베딩 사용 
    query_embedding = embeddings_model.embed_query(query)

    # 코사인 유사도 계산
    similarities = cosine_similarity([query_embedding], doc_embeddings)[0]

    # 가장 유사한 문서 인덱스 찾기
    most_similar_idx = np.argmax(similarities)

    # 가장 유사한 문서와 유사도 반환: 문서, 유사도
    return documents[most_similar_idx], similarities[most_similar_idx]

# 예제 쿼리
queries = [
    "인공지능이란 무엇인가요?",
    "딥러닝과 머신러닝의 관계는 어떻게 되나요?",
    "컴퓨터가 이미지를 이해하는 방법은?"
]

# 각 쿼리에 대해 가장 유사한 문서 찾기
for query in queries:
    most_similar_doc, similarity = find_most_similar(
        query, 
        document_embeddings_openai, 
        embeddings_model=embeddings_openai
        )
    print(f"쿼리: {query}")
    print(f"가장 유사한 문서: {most_similar_doc}")
    print(f"유사도: {similarity:.4f}")
    print()

- 출력

쿼리: 인공지능이란 무엇인가요?
가장 유사한 문서: 인공지능은 컴퓨터 과학의 한 분야입니다.
유사도: 0.7115

쿼리: 딥러닝과 머신러닝의 관계는 어떻게 되나요?
가장 유사한 문서: 딥러닝은 머신러닝의 한 종류입니다.
유사도: 0.6817

쿼리: 컴퓨터가 이미지를 이해하는 방법은?
가장 유사한 문서: 컴퓨터 비전은 컴퓨터가 디지털 이미지나 비디오를 이해하는 방법을 연구합니다.
유사도: 0.7053

2️⃣ HuggingFace

  • LangChain에서 오픈소스 기반의 대표적인 임베딩 모델

  • 주요 특징:

    1. 로컬 환경에서 실행 가능
    2. 다양한 사전학습 모델 지원
    3. 커스텀 모델 학습 및 적용 가능
    4. 무료 사용 가능 (API 비용 없음)
  • 사용시 주의사항:

    1. 로컬 컴퓨팅 자원 필요 (CPU/GPU)
    2. 초기 모델 다운로드 시간 소요
    3. 메모리 사용량 고려 필요
    4. transformers 라이브러리 설치 필요
  • 대표적인 임베딩 모델:

    모델                            차원      언어             특징      
    all-MiniLM-L6-v2               384     다국어     빠른 속도, 적은 메모리
    all-mpnet-base-v2              768     다국어     높은 성능, 중간 크기
    multilingual-e5-large         1024     다국어     최고 성능, 큰 메모리
  • 임베딩 벡터 특성:

    1. 모델별로 다양한 차원 제공 (128 ~ 1024)
    2. sentence-transformers 기반 구현
    3. BERT 계열 모델 구조 사용
    4. 코사인 유사도 기반 검색 최적화

1. Embedding 모델

  • 설치: pip install langchain_huggingface / poetry add langchain_huggingface
from langchain_huggingface.embeddings import HuggingFaceEmbeddings  

# Hugging Face의 임베딩 모델 생성
embeddings_bgem3 = HuggingFaceEmbeddings(
    model_name="BAAI/bge-m3",          # 사용할 모델 이름 - 알리바바 AI의 BGE-m3 모델 (한국어 성능 우수)
    cache_folder="./embeddings_cache",
    # model_kwargs={'device': 'cuda'}  # GPU 사용시
    # model_kwargs={'device': 'mps'}   # Mac M1 사용시
)

# 임베딩 객체 출력
embeddings_bgem3

- 출력

HuggingFaceEmbeddings(model_name='BAAI/bge-m3', cache_folder='./embeddings_cache', model_kwargs={}, encode_kwargs={}, multi_process=False, show_progress=False)

2. embed_documents

# 문서 임베딩
document_embeddings_bgem3 = embeddings_bgem3.embed_documents(documents)

# 임베딩 결과 출력
print(f"임베딩 벡터의 개수: {len(document_embeddings_bgem3)}")
print(f"임베딩 벡터의 차원: {len(document_embeddings_bgem3[0])}")
print(document_embeddings_bgem3[0])

- 출력

임베딩 벡터의 개수: 5
임베딩 벡터의 차원: 1024
[-0.03941445052623749, 0.008764867670834064, ... ]

3. embed_query

embedded_query = embeddings_bgem3.embed_query("인공지능이란 무엇인가요?")

# 쿼리 임베딩 결과 출력
print(f"쿼리 임베딩 벡터의 차원: {len(embedded_query)}")
print(embedded_query)

- 출력

쿼리 임베딩 벡터의 차원: 1024
[-0.037039123475551605, -0.004837991204112768, ... ]

4. 유사도 기반 검색

  • find_most_similar 는 위에서 정의한 함수
# 예제 쿼리
queries = [
    "인공지능이란 무엇인가요?",
    "딥러닝과 머신러닝의 관계는 어떻게 되나요?",
    "컴퓨터가 이미지를 이해하는 방법은?"
]

# 각 쿼리에 대해 가장 유사한 문서 찾기
for query in queries:
    most_similar_doc, similarity = find_most_similar(query, document_embeddings_bgem3, embeddings_model=embeddings_bgem3) 
    print(f"쿼리: {query}")
    print(f"가장 유사한 문서: {most_similar_doc}")
    print(f"유사도: {similarity:.4f}")
    print()

- 출력

쿼리: 인공지능이란 무엇인가요?
가장 유사한 문서: 인공지능은 컴퓨터 과학의 한 분야입니다.
유사도: 0.7269

쿼리: 딥러닝과 머신러닝의 관계는 어떻게 되나요?
가장 유사한 문서: 딥러닝은 머신러닝의 한 종류입니다.
유사도: 0.7057

쿼리: 컴퓨터가 이미지를 이해하는 방법은?
가장 유사한 문서: 컴퓨터 비전은 컴퓨터가 디지털 이미지나 비디오를 이해하는 방법을 연구합니다.
유사도: 0.6843

3️⃣ Ollama

  • LangChain에서 로컬 실행에 최적화된 경량 임베딩 모델

  • 주요 특징:

    1. 완전한 로컬 실행 환경 제공
    2. 빠른 추론 속도
    3. 간단한 설치 및 실행 과정
    4. Docker 기반 손쉬운 배포
  • 사용시 주의사항:

    1. Ollama 서버 실행 필요
    2. 모델별 시스템 요구사항 확인
    3. API 엔드포인트 설정 필요
    4. 동시 요청 처리량 고려
  • 대표적인 임베딩 모델:

    모델                차원       언어        특징
    llama2              4096      영어       범용성 높은 기본 모델
    nomic-embed-text    768       영어       경량화된 고성능 모델
    codellama          2048       다국어     코드 특화 임베딩
  • 임베딩 벡터 특성:

    1. 모델별 고정 차원 사용
    2. 최적화된 양자화 지원
    3. 배치 처리 최적화

1. Embedding 모델

  • 설치: pip install langchain_ollama / poetry add langchain_ollama
from langchain_ollama import OllamaEmbeddings 

# OllamaEmbeddings 모델 생성
# embeddings_ollama = OllamaEmbeddings(
#     model="nomic-embed-text",          # 사용할 모델 이름
#     base_url="http://localhost:11434"  # Ollama 서버 주소
# )
embeddings_ollama = OllamaEmbeddings(model="bge-m3")

# 임베딩 객체 출력
embeddings_ollama

- 출력

OllamaEmbeddings(model='bge-m3', base_url=None, client_kwargs={}, mirostat=None, mirostat_eta=None, mirostat_tau=None, num_ctx=None, num_gpu=None, num_thread=None, repeat_last_n=None, repeat_penalty=None, temperature=None, stop=None, tfs_z=None, top_k=None, top_p=None)

2. embed_documents

# 문서 컬렉션
documents = [
    "인공지능은 컴퓨터 과학의 한 분야입니다.",
    "머신러닝은 인공지능의 하위 분야입니다.",
    "딥러닝은 머신러닝의 한 종류입니다.",
    "자연어 처리는 컴퓨터가 인간의 언어를 이해하고 생성하는 기술입니다.",
    "컴퓨터 비전은 컴퓨터가 디지털 이미지나 비디오를 이해하는 방법을 연구합니다."
]

# 문서 임베딩
document_embeddings_ollama = embeddings_model.embed_documents(documents)

# 임베딩 결과 출력
print(f"임베딩 벡터의 개수: {len(document_embeddings_ollama)}")
print(f"임베딩 벡터의 차원: {len(document_embeddings_ollama[0])}")
print(document_embeddings_ollama[0])

- 출력

임베딩 벡터의 개수: 5
임베딩 벡터의 차원: 1024
[-0.002606647787615657, 0.013988534919917583, ... ]

3. embed_query

embedded_query = embeddings_ollama.embed_query("인공지능이란 무엇인가요?")

# 쿼리 임베딩 결과 출력
print(f"쿼리 임베딩 벡터의 차원: {len(embedded_query)}")
print(embedded_query)

- 출력

쿼리 임베딩 벡터의 차원: 1024
[-0.03680821, -0.0049144696, ... ]

4. 유사도 기반 검색

# 예제 쿼리
queries = [
    "인공지능이란 무엇인가요?",
    "딥러닝과 머신러닝의 관계는 어떻게 되나요?",
    "컴퓨터가 이미지를 이해하는 방법은?"
]

# 각 쿼리에 대해 가장 유사한 문서 찾기
for query in queries:
    most_similar_doc, similarity = find_most_similar(query, document_embeddings_ollama, embeddings_model=embeddings_ollama) 
    print(f"쿼리: {query}")
    print(f"가장 유사한 문서: {most_similar_doc}")
    print(f"유사도: {similarity:.4f}")
    print()

- 출력

쿼리: 인공지능이란 무엇인가요?
가장 유사한 문서: 컴퓨터 비전은 컴퓨터가 디지털 이미지나 비디오를 이해하는 방법을 연구합니다.
유사도: 0.0528

쿼리: 딥러닝과 머신러닝의 관계는 어떻게 되나요?
가장 유사한 문서: 컴퓨터 비전은 컴퓨터가 디지털 이미지나 비디오를 이해하는 방법을 연구합니다.
유사도: 0.0293

쿼리: 컴퓨터가 이미지를 이해하는 방법은?
가장 유사한 문서: 인공지능은 컴퓨터 과학의 한 분야입니다.
유사도: 0.0153

0개의 댓글