정적 임베딩

정적 임베딩 (Static Embeddings)

⏱️ 소요 시간 20분 | 난이도: 중급 출처: Qdrant 공식 문서 — static-embeddings

여러분, 컴퓨팅 자원이 제한된 환경에서 조용한 혁명이 일어나고 있어요. 트랜스포머가 인상적인 능력으로 리더보드를 장악하고 있지만, **정적 임베딩(static embeddings)**이 놀라운 속도 향상과 예상외로 작은 품질 손실을 안고 예상치 못한 귀환을 하고 있거든요. Qdrant 사용자들이 이 르네상스에서 어떤 이점을 얻을 수 있는지 평가했고, 그 결과는 유망해요.

임베딩에 관한 한 트랜스포머가 유일한 길로 여겨지는 경우가 많아요. 어텐션 메커니즘을 사용하면 입력 토큰 간 관계를 포착해서, 각 토큰이 토큰 자체뿐 아니라 주변 토큰에도 정의되는 문맥 인식(context-aware) 벡터 표현을 얻을 수 있어요. 트랜스포머 기반 모델은 단어당 단일 벡터 임베딩만 만들 수 있는 word2vec이나 GloVe 같은 오래된 방법의 품질을 쉽게 능가해요. 그 결과 "bank"라는 단어는 "river bank"와 "financial institution"이라는 문맥에서 동일한 표현을 가졌었죠.

트랜스포머 기반 모델은 "bank"라는 단어를 각 문맥에서 다르게 표현해요. 하지만 트랜스포머에는 비용이 따르죠. 계산적으로 비싸고 보통 많은 메모리가 필요해요. 임베딩 모델은 보통 LLM보다 매개변수가 적긴 하지만, 그럼에도 추론만 하더라도 GPU가 선호돼요.

하지만 정적 임베딩도 여전히 유효해요! MinishLab이 2024년 10월 model2vec 기법을 소개하면서 모델 크기 15배 축소, 최대 500배 속도 향상을 인상적인 성능 수준을 유지한 채 달성했어요. 그들의 아이디어는 트랜스포머 기반 문장 트랜스포머(sentence transformer)의 지식을 증류해서, 훨씬 빠르고 메모리를 덜 쓰는 정적 임베딩 모델을 만드는 것이었어요. 이 소개가 정적 임베딩 르네상스의 촉매가 된 것 같아요. 정적 임베딩이 인기 있는 Sentence Transformers 라이브러리에도 통합되기 시작했으니까요. Hugging Face 블로그의 최근 게시물(Tom Aarsen 작성)은 Sentence Transformers를 사용해 정적 임베딩 모델을 학습하면서도 트랜스포머 수준 품질의 최대 85%를 계산 비용의 일부로 얻는 방법을 설명해요. 그 게시물은 영어 텍스트 검색용 임베딩 모델인 static-retrieval-mrl-en-v1도 소개해요.

벡터 데이터베이스 관점에서 보면, 정적 임베딩은 다른 임베딩 모델과 다르지 않아요. 어차피 밀집 벡터(dense vector)니까 Qdrant 컬렉션에 그냥 저장하면 돼요. sentence-transformers/static-retrieval-mrl-en-v1 모델로 하는 방법을 볼게요:

import uuid

from sentence_transformers import SentenceTransformer
from qdrant_client import QdrantClient, models

# 이 모델은 크기 1024의 벡터를 만든다
model = SentenceTransformer(
    "sentence-transformers/static-retrieval-mrl-en-v1"
)

# "my_collection"이라는, "static"이라는 단일 벡터를 가진
# 컬렉션이 있다고 가정하자
client = QdrantClient("http://localhost:6333")

# 트랜스포머 모델로 텍스트를 인코딩하는 것은
# 다른 모델과 다르지 않다
client.upsert(
    "my_collection",
    points=[
        models.PointStruct(
            id=uuid.uuid4().hex,
            vector=model.encode("Hello, world!"),
            payload={"static": "Hello, world!"},
        )
    ]
)

정적 임베딩을 쓴다고 해서 검색 자체가 더 빨라지진 않아요. 하지만 데이터에서 벡터를 만드는 과정이 크게 빨라지는데, 이것이 보통 병목 지점이에요. Hugging Face 블로그 게시물은 이 모델이 CPU에서 최첨단 임베딩 모델보다 최대 400배 더 빠를 수 있다고 언급해요.

우리는 인코딩 속도에 대한 정식 벤치마크는 수행하지 않았어요. 하지만 BeIRTREC-COVID 데이터셋에서 수행한 실험 하나는 171K 문서를 Qdrant에서 인코딩하고 완전히 인덱싱하는 데 약 7.5분이 걸렸다는 것을 보여줘요. 전부 GPU 가속 없이 소비자용 노트북에서요.

검색을 실제로 더 빠르게 만들 수 있는 것은 Matryoshka Embeddings를 사용하는 건데, static-retrieval-mrl-en-v1 모델이 그 기법을 염두에 두고 학습됐기 때문이에요. 하지만 그게 검색을 빠르게 하는 유일한 방법은 아니에요. 양자화(Quantization) 방법이 사용자들 사이에서 정말 인기 있는데, 우리는 이를 정적 임베딩에도 같은 성공으로 적용할 수 있는지 확인해보고 싶었어요.

static-retrieval-mrl-en-v1 모델을 가져와 BeIR의 여러 하위 집합에서 이진 양자화(Binary Quantization) 유무에 따라 테스트해 검색 품질에 얼마나 영향을 주는지 봤어요. 결과는 정말 유망한데, 우리의 NDCG@10 측정값에서 보여요 (이 메트릭은 검색 결과의 랭킹 품질을 평가하며, 점수가 높을수록 성능이 좋음을 뜻해요):

| | NDCG@10 | | | 데이터셋 | 원본 벡터 | 이진 양자화, 재스코링 없음 | |---|---|---| | SciFact | 0.59348 | 0.54195 | | TREC-COVID | 0.4428 | 0.44185 | | ArguAna | 0.44393 | 0.42164 | | NFCorpus | 0.30045 | 0.28027 |

이진 양자화는 확실히 검색을 빠르고 저렴하게 만들고, 어떤 경우에는 검색 품질에 크게 영향을 주지 않는 것 같아요. 하지만 이것은 여러분 자신의 데이터에서 신중히 검증해야 할 사항이에요. Qdrant 사용자라면 기존 컬렉션에 양자화를 활성화하고 검색 품질에 미치는 영향을 측정하면 돼요.

우리가 한 모든 테스트는 beir-qdrant를 사용해 수행됐고, 프로젝트 저장소의 스크립트를 실행해 재현할 수 있어요.

정적 임베딩은 애플리케이션에 의미론적 검색을 쓰고 싶지만 표준 표현 모델을 호스팅할 여유가 없거나, 하드웨어 제약 때문에 그렇게 할 수 없는 사람들에게 합리적인 비용의 옵션으로 보여요. 몇몇 사용 사례를 들어볼게요:

  • 모바일 애플리케이션 — 많은 스마트폰이 강력한 CPU나 GPU를 갖췄지만 배터리 수명은 여전히 걱정거리예요. 정적 임베딩은 품질과 전력 소비 사이의 좋은 타협점이 될 수 있어요. 게다가 정적 임베딩은 오프라인 모드가 필요한 애플리케이션에도 쓸 수 있어요.
  • 웹 브라우저 확장 프로그램 — 웹 브라우저에서 트랜스포머 모델을 실행하는 건 보통 불가능에 가까워요. 하지만 정적 임베딩은 매개변수가 적고 인코딩이 빠르므로 좋은 선택이 될 수 있어요.
  • 임베디드 시스템 — 정적 임베딩은 IoT 기기나 마이크로컨트롤러처럼 컴퓨팅 파워가 제한된 기기에 좋은 선택이에요.

위 중 하나에 해당한다면 정적 임베딩을 꼭 시도해봐야 해요. 그리고 검색 품질이 최우선이 아니라면, 고성능 환경에서도 정적 임베딩 사용을 고려해볼 만해요. 인코딩 과정의 속도 향상이 여러분에게 판도를 바꿀 수 있어요.

마지막으로, Tom Aarsen이 공개한 학습 파이프라인으로 여러분 자신의 정적 임베딩 모델을 학습할 수 있어요. 그래서 데이터의 특성에 맞게 쉽게 조정할 수 있어요. 이 학습 과정도 트랜스포머 기반 모델보다 훨씬 빠르므로, 더 자주 재학습할 수도 있어요. 임베딩을 다시 계산하는 것은 의미론적 검색 시스템의 병목인데, 정적 임베딩이 이 문제에 좋은 해결책이 될 수 있어요. 맞춤 정적 임베딩 모델이 일반 사전 학습 모델을 이길 수 있을지는 여전히 열린 질문이지만, 시도해볼 가치가 충분해요.

더 알아보기 (Learn more)