CH08 Embedding

no-glass-otacku·2026년 1월 4일

1. OpenAI 임베딩 모델 실습

주요 도구: OpenAIEmbeddings

지원되는 모델 목록

MODELPAGES PER DOLLARPERFORMANCE ON MTEB EVALMAX INPUT
text-embedding-3-small62,50062.3%8191
text-embedding-3-large9,61564.6%8191
text-embedding-ada-00212,50061.0%8191
모델명특징추천 상황
text-embedding-3-small가장 경제적이며 성능도 준수함가성비가 중요한 대규모 서비스
text-embedding-3-large최고 성능, 가격은 가장 비쌈정확도가 최우선인 전문 검색 서비스
text-embedding-ada-002과거의 표준 모델굳이 새로 쓸 필요 없는 구형 모델

어떤 모델을 사용해서 embedding 할건지 정하고 (여기서는 text-embedding-3-small) 텍스트를 임베딩하면 벡터화(숫자)되어 리스트에 담긴 것을 확인 가능합니다.

embed_query (검색용)

사용자의 질문 단 하나를 벡터로 바꿀 때

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
text = "임베딩 테스트를 하기 위한 샘플 문장입니다."
query_result = embeddings.➡️embed_query(text)

[-0.00776276458054781, 0.03680367395281792, 0.019545823335647583, -0.0196656696498394, 0.017203375697135925]

embed_documents (저장용)

많은 양의 문서를 한꺼번에 벡터로 바꿀 때
-> 항상 문자열의 리스트를 입력받고, 각 문서에 대한 임베딩 벡터를 포함하는 2차원 리스트를 반환함.

구분embed_documentsembed_query
입력 형태리스트 (List of Strings)문자열 (Single String)
주요 용도데이터베이스(Vector Store) 구축용사용자의 질문(검색어) 처리용
특징여러 문서를 한꺼번에 배치(Batch) 처리단일 문장의 의도 파악에 최적화

차원(Dimension) 지정 기능이 필요한 이유?

임베딩 차원 지정은 검색 속도와 저장 비용을 최적화하면서도, 핵심 의미 정보를 유지하여 시스템 효율과 정확도 사이의 최적의 밸런스를 찾기 위해 필요합니다.

'dimensions=1024' 옵션을 추가하여 차원 지정가능

embeddings_1024 = OpenAIEmbeddings(model="text-embedding-3-small", ➡️dimensions=1024)
  • 비용 및 저장소 최적화: 차원을 줄이면 벡터 DB 용량이 감소하여 인프라 유지 비용이 대폭 절감됩니다.

  • 검색 속도(Latency) 향상: 저차원 벡터는 유사도 계산 연산량이 적어 대규모 데이터셋에서 훨씬 빠른 응답 속도를 보장합니다.

  • 정확도 밸런스: '매트료슈카 임베딩' 기술 덕분에 차원을 줄여도 핵심 의미 정보는 대부분 유지되므로, 성능 손실을 최소화하며 효율을 극대화할 수 있습니다.

  • 환경 적응성: 메모리가 제한된 모바일이나 엣지 디바이스 환경에 맞춰 모델 부하를 조절할 수 있습니다.

2. 캐시를 이용한 임베딩 최적화

주요 도구: CacheBackedEmbeddings

이유: 임베딩은 비용(돈/시간)이 듭니다. 똑같은 문장을 매번 새로 계산하는 건 비효율적이죠.

CacheBackedEmbeddings

embeddings를 키-값 저장소에 캐싱하는 embedder 주변에 래퍼입니다.

  • 알맹이: 실제 계산을 담당하는 OpenAIEmbeddings.
  • 껍데기(Wrapper): 계산된 결과를 저장하고 관리하는 CacheBackedEmbeddings.

🛠️ CacheBackedEmbeddings 초기화 매개변수

캐시 임베더를 설정할 때는 from_bytes_store 메서드를 통해 다음 세 가지 핵심 부품을 연결합니다.

  1. underlying_embeddings: 실제 임베딩 계산을 수행할 모델 엔진 (예: OpenAI).
  2. document_embedding_cache: 계산된 벡터를 바이트 단위로 보관할 저장소 (ByteStore).
  3. namespace: 저장소 내의 독립된 구역 이름.
    • 주의: 서로 다른 모델이 동일한 텍스트에 대해 생성한 벡터가 섞이지 않도록, 모델명을 네임스페이스로 지정하는 것이 권장됩니다.

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

# 캐시를 지원하는 임베딩 생성
embedding = OpenAIEmbeddings()

cached_embedder = CacheBackedEmbeddings.from_bytes_store(
    underlying_embeddings=embedding,
    document_embedding_cache=➡️LocalFileStore("./cache/"), # 로컬 파일 저장소 설정
    namespace=embedding.model  # 기본 임베딩과 저장소를 사용하여 캐시 지원 임베딩을 생성
)

InmemoryByteStore 사용 (비영구적)

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

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

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

비용 절감과 데이터 보존이 중요한 실무 환경에는 LocalFile을, 속도가 중요하고 일회성인 작업에는 InMemory를 선택

3. 오픈소스 모델 활용: HuggingFace

주요 도구: HuggingFaceEmbeddings

특징: OpenAI API(유료) 없이 내 로컬(코랩) 환경에서 무료 오픈소스 모델로 갈아타는 방법.

쓸만한 한국어 임베딩 모델

  • intfloat/multilingual-e5-large (3~4위):
    현재 오픈소스 모델 중 최상위권 성능입니다.
    instruct 버전은 질문과 답변의 맥락을 더 잘 구분하도록 튜닝되어 있습니다.

  • BAAI/bge-m3 (6위):
    한국어 임베딩의 교과서 같은 모델입니다.
    성능이 안정적이고, 다국어 지원이 강력해서 실무에서 가장 많이 쓰입니다.

  • e5-base / e5-small (7~8위):
    성능은 상위권 모델보다 조금 낮지만, 가볍고 속도가 매우 빠릅니다.
    컴퓨터 자원이 부족하거나 빠른 응답이 필요할 때 선택합니다.

HuggingFace Endpoint Embedding

모델을 내 컴퓨터가 아닌 별도의 전용 서버(Endpoint)에 올려놓고 API 형태로 호출하는 방식

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["HF_TOKEN"],
)

embedded_documents = hf_embeddings.embed_documents(texts)
embedded_query = hf_embeddings.embed_query("LangChain 에 대해서 알려주세요.")

HuggingFace Embeddings

내 컴퓨터(Local)의 GPU를 사용하여 임베딩을 생성합니다. 비용이 0원이며 보안이 중요한 프로젝트에 필수적

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}, 
    # 추출된 벡터들의 길이를 1로 맞추는 정규화 작업 -> 유사도를 구할 때 복잡한 계산 없이 단순한 '내적'만으로도 정확한 비교가 가능
)

임베딩 방식별 비교표

구분Dense (밀집)b. Sparse (희소)Multi-Vector (다중)
대표 모델OpenAIc. ColBERT
비유문장의 전체적인 분위기문장 속 핵심 단어문장 속 모든 단어의 관계
수학적 특징고정된 차원에 정보 압축단어 사전 기반 점수 부여문장을 여러 벡터로 분할 저장
장점문맥 및 유사어 파악 능력이 좋음고유명사를 정확하게 검색함검색 정밀도가 가장 높음
단점특정 단어 포함 여부 확인이 어려움문맥(의미) 파악이 불가능함저장 용량이 크고 속도가 느림

a. BGE-M3는 세 가지 방식을 모델 하나로 모두 구현하고 있음❕❕❕

a. BGE-M3 임베딩🌟

현재 한국어를 포함한 다국어 검색에서 가장 가성비 좋고 강력한 오픈소스 모델이기 때문에 실무 표준으로 소개됨

from langchain_huggingface 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
)

랭체인(langchain)말고 모델 제조사(BAAI)가 직접 만든 전용 라이브러리(FlagEmbedding)를 사용하는 방법

랭체인의 HuggingFaceEmbeddings는 범용적이지만, BGE-M3 전용 기능(Sparse, Multi-vector 추출 등)을 세밀하게 제어하기에는 한계가 있습니다.

제조사가 제공하는 라이브러리를 쓰면 use_fp16(반정밀도 연산) 같은 속도 최적화 옵션을 더 직접적으로 사용할 수 있습니다.

# FlagEmbedding 설치
!pip install -qU FlagEmbedding

1번 스타일: 일단 계산시키고 dense_vecs만 사용하기

from FlagEmbedding import BGEM3FlagModel

bge_embeddings = BGEM3FlagModel(
    "BAAI/bge-m3", use_fp16=True
)  # use_fp16을 True로 설정하면 약간의 성능 저하와 함께 숫자를 표현하는 비트 수를 줄여 계산량을 줄어 빨라짐.

bge_embedded = bge_embeddings.encode(
    texts,
    batch_size=12,
    max_length=8192,  # 한번에 읽는 토큰수:작은 값을 설정하여 프로세스의 속도를 높일 수 있음.
)➡️["dense_vecs"]

["dense_vecs"]
->BGE-M3는 Dense, Sparse, ColBERT 결과를 동시에 생성하는 멀티태스킹 모델이므로, encode() 결과 중 필요한 데이터 형태(dense_vecs)만 명시적으로 추출하여 사용하려고 넣은 코드.

2번 스타일: 처음부터 dense 결과만 돌려주도록 세팅

from FlagEmbedding import BGEM3FlagModel

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

bge_encoded = bge_flagmodel.encode(texts, ➡️return_dense=True)

b. Sparse Embedding (Lexical Weight)

기존 밀집(Dense) 임베딩은 문맥은 잘 잡지만 "고유 명사(예: 제품명, 이름)" 검색에 약합니다. 이를 보완하기 위해 키워드 일치 방식(Lexical)의 가중치를 더해 검색 정확도를 높임

bge_flagmodel = BGEM3FlagModel(
    "BAAI/bge-m3", use_fp16=True
)  # use_fp16을 True로 설정하면 약간의 성능 저하와 함께 계산 속도가 빨라집니다.
bge_encoded = bge_flagmodel.encode(texts, ➡️return_sparse=True)

여기서는 BGE-M3 모델 사용함

lexical_scores1 = bge_flagmodel.compute_lexical_matching_score(
    bge_encoded["lexical_weights"][0], bge_encoded["lexical_weights"][0]
)
# 0 <-> 0 자기 자신과의 비교
print(lexical_scores1)

0.30167388916015625
= 0번 문서와 0번 문서가 얼마나 '같은 단어'를 공유하는지 계산한 값입니다. 당연히 똑같은 단어들로 구성되어 있으니 모델이 판단한 최대 일치 점수가 나옵니다.

lexical_scores2 = bge_flagmodel.compute_lexical_matching_score(
    bge_encoded["lexical_weights"][0], bge_encoded["lexical_weights"][1]
)
# 0 <-> 1 다른 문서와의 비교
print(lexical_scores2)

0 =두 문서 사이에 겹치는 단어가 하나도 없다. Dense 방식은 단어가 달라도 '분위기'가 비슷하면 0.8 같은 점수를 주지만, Sparse 방식은 글자 자체가 일치하지 않으면 가차 없이 0점.

c. ColBERT

문장 전체를 하나의 점(Vector)으로 찍는 대신, 단어 하나하나의 벡터를 모두 비교합니다. 계산량은 훨씬 많지만, 문맥적 유사도를 찾는 정밀도가 압도적으로 높아 고성능 검색 엔진 구현 시 사용

작동 방식

  1. 문서의 각 토큰에 대해 별도의 벡터를 생성합니다. 즉, 하나의 문서는 여러 개의 벡터로 표현됩니다.
  2. 쿼리도 마찬가지로 각 토큰에 대해 별도의 벡터를 생성합니다.
  3. 검색 시, 쿼리의 각 토큰 벡터와 문서의 모든 토큰 벡터 사이의 유사도를 계산합니다.
  4. 이 유사도들을 종합하여 최종 검색 점수를 계산합니다.
bge_flagmodel = BGEM3FlagModel(
    "BAAI/bge-m3", use_fp16=True
)  # 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]
)
# 0 <-> 0
print(colbert_scores1)
# 0 <-> 1
print(colbert_scores2)

앞서 본 Sparse 방식이 "0점"을 줬던 문장들에 대해, ColBERT는 어떻게 반응하는지 비교하면 , ColBERT는 글자는 다르지만, 단어들의 세부적인 맥락을 보니 의미적 연관성이 있다고 판단해 tensor(0.3748)라고 점수를 부여해줌.

"ColBERT가 좋은 이유" Sparse 방식은 '아이폰'과 '스마트폰'을 완전히 다른 것으로 보지만, ColBERT는 두 단어를 구성하는 토큰(Token) 벡터들이 서로 유사한 영역에 있음을 감지한다.

4. UpstageEmbeddings

국내 AI 기업인 Upstage(업스테이지)의 Solar 모델 실습

업스테이지는 검색의 정확도를 높이기 위해 비대칭 임베딩(Asymmetric Embedding) 전략을 사용하는데
질문과 답변은 문장 구조가 다르기 때문에 각각의 특성에 맞춰 학습시켜, 질문용 모델과 답변용 모델이 분리 되어 있다!

from langchain_upstage import UpstageEmbeddings

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

# 문장 전용 임베딩 모델
passage_embeddings = UpstageEmbeddings(model="solar-embedding-1-large-passage")
# 쿼리 임베딩
embedded_query = query_embeddings.embed_query("LangChain 에 대해서 상세히 알려주세요.")
# 임베딩 차원 출력-> 4096
len(embedded_query)
# 문서 임베딩
embedded_documents = passage_embeddings.embed_documents(texts)

앞서 배운 BGE-M3나 E5 모델은 1024차원이었지만 업스테이지 모델은 4096차원으로 정보를 4배나 더 세밀하게 쪼개서 저장합니다. 그만큼 문장의 미묘한 뉘앙스를 잡아내는 능력이 탁월하지만, 저장 공간(Vector DB)을 더 많이 차지한다는 트레이드오프가 있습니다.

유사도 결과에서도 한국어와 영어의 교차 검색에서 언어가 달라도 의미가 통하면 높은 점수를 주는 등 더 정교한 의미 검색이 가능함!

5. OllamaEmbeddings

Ollama는 로컬 환경에서 대규모 언어 모델(LLM)을 쉽게 실행할 수 있게 해주는 오픈소스 프로젝트로 개발자들이 AI 모델을 자신의 컴퓨터에서 직접 실험하고 사용할 수 있도록 지원합니다.

from langchain_community.embeddings import OllamaEmbeddings

ollama_embeddings = ➡️OllamaEmbeddings(
    model="nomic-embed-text", #768차원짜리 가벼운 모델. 로컬에서 돌려야해서 가장 대중적으로 쓰임.
)

쿼리와 문서를 인베딩하는 방식은 위 다른 실습과 동일하고 특이한 점은 유사도에서 점수가 높게 나왔는데 그 이유는 다른 모델과는 달리 정규화를 거치지 않은 순수 벡터 값을 그대로 내적했기 때문에, 벡터의 크기만큼 점수가 뻥튀기된 것입니다. 점수의 절댓값은 의미가 없고 상대적인 순위만 확인하면 됩니다.

[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.

6. GPT4ALL 임베딩

GPT4All은 무료로 사용할 수 있는 로컬 실행 기반의 개인정보 보호를 고려한 챗봇으로
GPU 없이 CPU만으로도 돌아가는 저사양 환경을 위한 가성비 모델입니다.
업스테이지(4096), BGE-M3(1024)에 비해 훨씬 작은 384차원을 사용합니다. (실습에서 확인가능)

  • 장점: 숫자가 적으니 계산 속도가 빛의 속도만큼 빠르고, 메모리(RAM)를 거의 차지하지 않습니다.
  • 단점: 정보의 '해상도'는 낮습니다. 복잡하고 긴 전문 지식 검색보다는 간단한 일상 대화나 가벼운 문장 검색에 적합합니다.
모델명제공사차원주요 특징추천 용도
OpenAIOpenAI1536유료, 가장 표준적인 성능범용 RAG 서비스 구축
BGE-M3BAAI1024오픈소스, 한국어 성능 최강국내 검색 서비스, 하이브리드 검색
SolarUpstage4096유료, 초고해상도, 비대칭 임베딩정밀도가 중요한 전문 문서 검색
GPT4AllNomic384무료, CPU 최적화(저사양 최적)개인 프로젝트 및 로컬 환경
profile
Move forward

0개의 댓글