모델을 고를 때 확인할 항목입니다.
6-1. 차원 수 (Dimension)
벡터 하나가 몇 개의 숫자로 이루어지는지입니다. 보통 384, 768, 1024, 1536, 3072 같은 값입니다.
| 차원이 크면 | 차원이 작으면 |
|---|
| 미묘한 의미 차이를 더 담을 여지가 있다 | 저장 공간, 메모리가 적게 든다 |
| 저장, 검색 비용이 커진다 | 검색이 빠르다 |
| 반드시 성능이 좋은 건 아니다 | 품질이 떨어질 수 있다 |
저장 공간은 단순 계산으로 가늠할 수 있습니다.
float32 1개 = 4바이트
1,000,000개 청크 × 1024차원 × 4바이트 ≈ 4.1GB
1,000,000개 청크 × 3072차원 × 4바이트 ≈ 12.3GB
(인덱스 오버헤드는 별도)
일부 모델은 차원을 줄여서 쓸 수 있게 학습되어 있습니다(Matryoshka Representation Learning 방식). 예를 들어 OpenAI text-embedding-3 계열은 dimensions 파라미터로 더 짧은 벡터를 받을 수 있습니다. 차원을 줄이면 품질이 조금 떨어지는 대신 비용이 크게 줄어듭니다.
6-2. 최대 입력 토큰 (Max Tokens)
모델이 한 번에 받을 수 있는 텍스트 길이입니다. 이 길이를 넘는 부분은 잘려서 무시되거나 에러가 납니다.
| 모델 예 | 최대 입력 | 차원 |
|---|
| intfloat/multilingual-e5-large | 512 토큰 | 1024 |
| BAAI/bge-m3 | 8192 토큰 | 1024 |
| OpenAI text-embedding-3-small | 8191 토큰 | 1536 (축소 가능) |
| OpenAI text-embedding-3-large | 8191 토큰 | 3072 (축소 가능) |
최대 토큰이 길다고 해서 긴 문서를 통째로 넣는 게 좋은 건 아닙니다. 긴 텍스트를 벡터 하나로 압축하면 여러 주제가 섞여서 어느 주제와도 애매하게 비슷한 벡터가 됩니다. 그래서 RAG에서는 보통 수백 토큰 단위로 잘라서(청킹) 임베딩합니다.
6-3. 다국어와 한국어
영어 위주로 학습된 모델은 한국어 문장을 제대로 구분하지 못할 수 있습니다. 한국어 문서를 다룬다면 다음을 확인합니다.
- 모델 카드에 multilingual 지원 여부와 학습 언어가 적혀 있는가
- 한국어 질문으로 한국어 문서를 찾는 실제 테스트에서 잘 되는가
- 한국어 질문으로 영어 문서를 찾아야 하는가 (교차 언어 검색, Cross-lingual)
한국어에서 자주 쓰이는 선택지는 다국어 모델(BGE-M3, multilingual-E5 계열, 상용 API의 다국어 모델)이나, 이런 모델을 한국어 데이터로 추가 학습한 모델입니다. 어떤 모델이 가장 좋은지는 계속 바뀌므로, 아래 리더보드와 자기 데이터 테스트로 확인하는 게 맞습니다.
토큰 수도 주의해야 합니다. 같은 내용이라도 한국어는 토크나이저에 따라 영어보다 토큰이 더 많이 나오는 경우가 많습니다. 최대 토큰과 비용을 계산할 때 영어 기준 감각을 그대로 쓰면 안 됩니다.
6-4. MTEB 리더보드
MTEB(Massive Text Embedding Benchmark)는 임베딩 모델을 검색, 분류, 군집화, 문장 유사도 등 여러 과제로 평가하는 벤치마크입니다. Hugging Face에서 리더보드를 운영하며, 다국어 확장판(MMTEB)도 있습니다.
리더보드를 볼 때 주의할 점입니다.
| 주의할 점 | 이유 |
|---|
| 평균 점수보다 Retrieval 점수를 본다 | RAG에 필요한 건 검색 성능이다. 분류, 군집화 점수가 평균을 끌어올릴 수 있다 |
| 언어별 점수를 본다 | 영어 1등이 한국어에서도 1등이라는 보장이 없다 |
| 모델 크기, 차원, 최대 토큰을 같이 본다 | 점수가 조금 높아도 너무 무거우면 운영이 힘들다 |
| 라이선스를 확인한다 | 상업적 사용이 제한된 모델이 있다 |
| 최종 판단은 내 데이터로 한다 | 벤치마크 데이터와 사내 문서는 분포가 다르다 |
6-5. 내 데이터로 간단히 비교하기
리더보드보다 확실한 건 직접 비교입니다. 질문과 정답 문서 쌍을 20~50개만 만들어도 차이가 꽤 보입니다.
from sentence_transformers import SentenceTransformer
import numpy as np
# (질문, 정답 문서 인덱스)
qa = [("연차 쓰는 법", 0), ("카페 몇 시까지 해요?", 2)]
docs = ["휴가 신청은 그룹웨어에서...", "연차 수당은 1월에...", "사내 카페는 오후 6시까지..."]
def hit_rate_at_k(model_name, k=1):
m = SentenceTransformer(model_name)
d = m.encode(docs, normalize_embeddings=True)
hits = 0
for q, answer in qa:
s = d @ m.encode(q, normalize_embeddings=True)
hits += answer in np.argsort(-s)[:k]
return hits / len(qa)
for name in ["BAAI/bge-m3", "intfloat/multilingual-e5-large"]:
print(name, hit_rate_at_k(name))
이건 가장 단순한 형태이고, 체계적인 평가 지표(Recall@k, MRR, nDCG 등)는 RAG 평가 노트에서 다룹니다. 참고로 E5 계열은 아래 7-4의 접두어 규칙을 지켜야 제 성능이 나옵니다.