HuggingFace 문서 임베딩

yozzum·2025년 6월 25일
0

GenAI

목록 보기
21/21

🤖 HuggingFace 문서 임베딩 개념 완전 정복

이 글은 Hugging Face 모델을 활용한 문서 임베딩의 전체 과정을 정리한 글입니다.
tokenizer, chunking, truncation, padding, CLS 임베딩까지 헷갈리기 쉬운 개념들을 하나하나 설명합니다.


✅ 전체 흐름 개요

문서를 임베딩해 벡터 DB에 저장하기 위한 전체 과정은 다음과 같은 흐름으로 진행됩니다:

  • 문서를 문장 단위로 나누거나, 그대로 긴 텍스트로 유지
  • 문장을 여러 개 묶어 chunk로 구성
  • 각 chunk를 tokenizer로 토크나이징
  • 모델에 입력하여 CLS 임베딩 추출
  • 벡터를 리스트로 변환하여 벡터 DB에 저장

📌 핵심 개념 정리

Tokenizer란?

Tokenizer는 문장을 숫자 토큰 ID 리스트로 바꿔주는 도구입니다.
원-핫 벡터는 아니며, 각 단어/서브워드는 고유한 숫자 ID로 변환됩니다.
사용되는 vocab(사전)은 모델마다 다릅니다.

tokenizer("I love meat")  
# → [101, 1045, 2293, 3111, 102]

Chunking이란?

Chunking은 긴 문서를 모델이 처리 가능한 길이로 쪼개는 작업입니다.
보통 토큰 수를 기준으로 쪼개며, 512 토큰 이하로 유지합니다.
중요한 문맥 손실을 방지하기 위해 슬라이딩 윈도우 방식으로 겹치게 자르기도 합니다.

chunk1: 토큰 0 ~ 511  
chunk2: 토큰 412 ~ 923 (chunk_overlap = 100)

각 chunk는 문장 2~5개 정도로 구성되며, 이 하나의 chunk가 임베딩 단위가 됩니다.


Padding과 Truncation

토큰화 과정에서 짧은 chunk는 padding으로 0을 채우고,
너무 긴 chunk는 max_length까지만 남기고 나머지는 잘라냅니다.

tokenizer(
  chunk,
  padding=True,
  truncation=True,
  max_length=512,
  return_tensors="pt"
)
  • padding=True: 짧은 입력의 뒷부분을 0으로 채움
  • truncation=True: 긴 입력은 자르고 나머지 버림
  • max_length=512: 대부분의 BERT 모델은 512 토큰까지 입력 가능

결과적으로 모든 입력은 길이가 딱 512 토큰으로 맞춰집니다.


모델 예측과 CLS 임베딩 추출

토크나이징된 chunk를 모델에 넣으면, 각 토큰의 출력 벡터가 나옵니다.
그 중 첫 번째 토큰([CLS])의 벡터만 추출해서 해당 chunk 전체의 의미를 대표하는 임베딩으로 사용합니다.

with torch.no_grad():
    output = model(**inputs)

embeddings = output.last_hidden_state[:, 0, :]
  • output.last_hidden_state: 각 토큰의 벡터들 ([batch, seq_len, hidden])
  • [:, 0, :]: 각 chunk의 첫 번째 토큰([CLS]) 벡터만 추출

즉, chunk 하나당 하나의 벡터가 생성됩니다.


임베딩 벡터 변환 및 저장

추출된 텐서를 numpy 배열로 바꾸고, 리스트로 변환하여 DB나 파일로 저장합니다.

vectors = embeddings.cpu().numpy().tolist()

🧪 전체 코드 예시

from transformers import AutoTokenizer, AutoModel
import torch

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")

chunks = [
  "삼겹살은 맛있다. 비 오는 날에 더 맛있다.",
  "불판에 구우면 재미도 있고 소주와 잘 어울린다."
]

inputs = tokenizer(
    chunks,
    return_tensors="pt",
    padding=True,
    truncation=True,
    max_length=512
)

with torch.no_grad():
    output = model(**inputs)

embeddings = output.last_hidden_state[:, 0, :]  # CLS 벡터 추출
vectors = embeddings.cpu().numpy().tolist()

✅ 요약 정리

개념설명
Tokenizer문장을 숫자 토큰 ID로 변환
Chunk여러 문장을 모아 만든 덩어리 (임베딩 단위)
Padding짧은 입력은 0으로 채움
Truncation긴 입력은 잘라냄
CLS 벡터chunk 전체 의미를 요약한 벡터
임베딩 단위항상 청크 하나당 벡터 하나

🎯 마무리 한 줄 요약

HuggingFace 기반 문서 임베딩에서 중요한 건
항상 chunk 단위로 임베딩하고,
CLS 토큰 벡터를 통해 그 chunk 전체의 의미를 벡터로 뽑아낸다는 것입니다.

profile
yozzum

0개의 댓글