LLM 엔지니어링7장 · 자체 임베딩과 벡터DB, 검색 품질5 / 22← 이전목차다음 →MetaContents

7장. 자체 임베딩과 벡터DB, 검색 품질

임베딩 모델 고르기

신발을 살 때는 발 크기, 쓰임새, 무게, 값을 따집니다. 임베딩 모델도 우리 문서의 언어, PC 의 사양, 쓸 수 있는 범위에 맞춰 고릅니다.

언어, 크기, 차원, 라이선스의 네 가지 기준을 카드로 놓은 그림

네 카드가 임베딩 모델을 고르는 기준입니다. 한국어를 배운 모델인지, 내 PC 에서 돌릴 만한 크기인지, 벡터가 몇 차원이라 저장 공간이 얼마나 드는지, 회사에서 써도 되는 라이선스인지 봅니다. 여기서 발 크기가 언어, 신발 무게가 모델 크기입니다.

이 장에서 쓰는 모델

모델하는 일크기차원라이선스
intfloat/multilingual-e5-small임베딩(바이 인코더). 한국어 포함 100여 언어파라미터 1억 1,800만, 파일 470MB 쯤384MIT
cross-encoder/mmarco-mMiniLMv2-L12-H384-v1재정렬(크로스 인코더). 여러 언어파라미터 1억 1,800만쯤점수 하나Apache 2.0

이 PC 의 CPU 에서 임베딩은 조각 30개에 1초가 안 걸렸고, 재정렬은 질문 하나(후보 10개)에 0.2초쯤 걸렸습니다. 더 큰 모델(예: multilingual-e5-large, BAAI/bge-m3)은 검색이 나아질 수 있지만 몇 배 크고 느립니다. 공개된 순위표(MTEB 등)에서 한국어 점수를 참고하되, 결국 우리 문서와 질문으로 재서 고릅니다.

저장 공간 어림하기

임베딩 하나는 차원 × 4바이트(float32)입니다.

Python
for dim in [384, 768, 1024]:
    for n in [30, 100_000]:
        mb = n * dim * 4 / 1024 ** 2          # 조각 수 × 차원 × 4바이트
        print(f"차원 {dim:4d} · 조각 {n:7,d}개 → {mb:8.2f} MB")

조각 10만 개라면 384차원은 146MB, 1024차원은 391MB 입니다. 이 장의 30개는 0.04MB 남짓이라 걱정할 것이 없습니다.

코드에 나오는 함수

코드쉬운 뜻
100_000십만이다. 밑줄은 읽기 쉽게 끊어 쓴 것이고 값에는 영향이 없다
n * dim * 4조각 수 × 숫자 개수 × 숫자 하나의 바이트 수다. float32(32비트 실수)는 숫자 하나에 4바이트를 쓴다
/ 1024 ** 2바이트를 MB(메가바이트)로 바꾼다. 1MB 를 1024 × 1024 바이트로 셈했다
f"{n:7,d}"정수를 7칸에 맞추고 세 자리마다 쉼표를 넣는다
f"{mb:8.2f}"실수를 8칸에 맞추고 소수 둘째 자리까지 적는다

이 코드가 뜻하는 것

이사할 때 "상자 수 × 상자 하나의 크기"로 트럭 크기를 어림하는 것과 같습니다. 여기서 상자가 조각 하나의 임베딩, 상자 크기가 "차원 × 4바이트"입니다.

셈384차원 · 조각 10만 개
임베딩 하나384 × 4 = 1,536바이트
조각 10만 개1,536 × 100,000 = 153,600,000바이트
MB 로153,600,000 ÷ (1024 × 1024) = 약 146MB

차원이 384 에서 1024 로 2.7배쯤 늘면 저장 공간도 똑같이 2.7배쯤 늡니다. 이 셈에는 원문과 메타데이터, 인덱스가 따로 쓰는 공간이 빠져 있으므로 실제로는 이보다 조금 더 듭니다.

주의할 점

  • 모델 카드에 적힌 최대 길이(e5-small 은 512토큰)를 넘는 글은 잘려서 뒷부분이 임베딩에 들어가지 않습니다. 조각을 알맞게 나누는 까닭 가운데 하나입니다.
  • 라이선스는 모델 카드의 표기를 확인합니다. 학습 데이터의 조건이 따로 붙는 모델도 있습니다.
← 이전 절7장 · 의미 검색다음 절 →7장 · 벡터DB 와 인덱스