1P by GN⁺ | ★ favorite | 댓글 1개
  • WordLlama는 LLM의 토큰 임베딩을 재활용해 퍼지 중복 제거, 유사도 계산, 랭킹, 클러스터링, 의미 기반 텍스트 분할을 수행하는 빠르고 가벼운 NLP 툴킷임
  • 추론은 토큰 조회와 평균 풀링 중심으로 동작하며, NumPy만으로 실행 가능한 경량 파이프라인과 CPU 최적화를 내세움
  • 기본 모델은 256차원 16MB이며, Matryoshka 표현으로 차원을 줄일 수 있고 바이너리 임베딩은 Hamming 유사도로 더 빠른 계산을 지원함
  • MTEB 표에서 WL64~WL1024는 GloVe 300d와 Komninos보다 여러 지표에서 높은 점수를 보이며, all-MiniLM-L6-v2보다는 대체로 낮은 점수를 기록함
  • pip install wordllamaWordLlama.load()로 사용할 수 있고, .key(query)sorted, min, max 같은 표준 라이브러리 함수에 넣을 수 있는 호출 가능 함수를 반환함

WordLlama가 하는 일

  • WordLlama는 퍼지 중복 제거, 유사도 계산, 랭킹, 클러스터링, 의미 기반 텍스트 분할 같은 NLP 유틸리티 작업을 위한 경량 툴킷임
  • LLaMA 2, LLaMA 3 70B 같은 최신 LLM에서 토큰 임베딩 코드북을 추출해, GloVe·Word2Vec·FastText와 비슷한 compact word representation을 만듦
  • 추론 시 의존성이 적고 CPU 하드웨어에 최적화되어 있어 리소스 제약 환경 배포에 적합함
  • 빠르고 작은 크기 덕분에 탐색적 분석, LLM 출력 평가기, multi-hop 또는 agentic workflow의 준비 작업 같은 유틸리티 용도로 사용할 수 있음

설치와 기본 사용

  • 설치는 pip로 수행함
pip install wordllama
  • 기본 256차원 모델WordLlama.load()로 로드함
from wordllama import WordLlama

wl = WordLlama.load()
  • .key(query)Callable[[str], float]를 반환해 후보 문자열을 쿼리와의 유사도 기준으로 정렬하거나 최댓값을 고를 수 있음
query = "Machine learning methods"
candidates = [
    "Foundations of neural science",
    "Introduction to neural networks",
    "Cooking delicious pasta at home",
    "Introduction to philosophy: logic",
]

sim_key = wl.key(query)

sorted_candidates = sorted(candidates, key=sim_key, reverse=True)
best_candidate = max(candidates, key=sim_key)
  • 예시 결과에서 "Introduction to neural networks"가 점수 0.3414로 가장 높은 후보가 됨

주요 기능

  • 임베딩 생성: 단순 토큰 조회와 평균 풀링으로 텍스트 임베딩을 빠르게 생성함
  • 유사도 계산: 두 텍스트 사이의 cosine similarity를 계산함
  • 문서 랭킹: 쿼리와 후보 문서의 유사도를 기준으로 순위를 매김
  • 퍼지 중복 제거: 유사도 임계값을 기준으로 중복 텍스트를 제거함
  • 클러스터링: KMeans로 문서를 그룹화함
  • 필터링: 쿼리와의 유사도가 기준 이상인 문서만 남김
  • Top-K 검색: 쿼리와 가장 유사한 K개 문서를 반환함
  • 의미 기반 텍스트 분할: 텍스트를 의미적으로 응집된 청크로 나눔
  • 바이너리 임베딩: Hamming 유사도로 더 빠른 계산을 지원함
  • Matryoshka 표현: 필요에 따라 임베딩 차원을 잘라 모델 크기와 성능을 조절함

모델 구조와 성능

  • WordLlama는 범용 임베딩 프레임워크 안에서 context-less 소형 모델을 학습함
  • 기본 모델은 256차원 16MB 크기임
  • README의 MTEB 표는 WL64, WL128, WL256, WL512, WL1024를 GloVe 300d, Komninos, all-MiniLM-L6-v2와 비교함
    • WL256은 Clustering 33.25, Reranking 52.03, Classification 58.21, Pair Classification 78.22, STS 67.91, CQA DupStack 24.12, SummEval 30.99를 기록함
    • GloVe 300d는 같은 항목에서 각각 27.73, 43.29, 57.29, 70.92, 61.85, 15.47, 28.87을 기록함
    • all-MiniLM-L6-v2는 Clustering 42.35, Reranking 58.04, Classification 63.05, Pair Classification 82.37, STS 78.90, CQA DupStack 41.32, SummEval 30.81을 기록함
  • l2_supercat은 LLaMA 2 vocabulary 모델임
    • LLaMA 2 70B와 phi 3 medium 등 여러 모델의 codebook에서 추가 special token을 제거한 뒤 연결해 학습함
    • LLaMA 2 tokenizer를 사용한 여러 모델의 codebook을 함께 연결해 학습할 수 있음
    • LLaMA 3 70B codebook 학습과 비슷한 성능을 보이면서 vocabulary는 32k128k로 4배 작음
  • LLaMA 3 기반 모델로 l3_supercat이 제공됨
  • 추가 결과는 Results에 있음

의미 기반 텍스트 분할

  • .split()은 긴 텍스트를 의미적 청크로 나눔
long_text = "Your very long text goes here... " * 100
chunks = wl.split(long_text, target_size=1536)

print(list(map(len, chunks)))

# Output: [1055, 1055, 1187]
  • target_size는 목표 크기이면서 최대 크기임
  • 분할 과정은 텍스트 순서, 문장 구조, 가능한 경우 문단 구조를 유지하려고 함
  • WordLlama 임베딩을 사용해 더 자연스러운 분할 인덱스를 찾음
  • 출력 청크 크기는 target_size 이하 범위에서 달라질 수 있음
  • 권장 target size는 512~2048자이며 기본값은 1536
  • 더 큰 청크가 필요하면 분할 후 여러 semantic chunk를 배치로 묶는 방식을 권장함
  • 자세한 내용은 technical overview에 있음

Model2Vec와 직접 추론

  • 2025-01-04 업데이트로 Model2Vec static embeddings 지원이 추가됨
  • WordLlama.load_m2v()로 Model2Vec 모델을 로드할 수 있음
wl = WordLlama.list_configs()

wl = WordLlama.load_m2v("potion_base_8m")  # 256-dim model
wl = WordLlama.load_m2v("m2v_multilingual")  # multilingual model
  • Model2Vec은 PCA를 사용해 static embedding을 만드는 다른 방식임
  • Model2Vec 쪽은 multilingual model과 glove 기반 모델을 만들었고, word similarity task에서 좋은 점수를 낸다고 되어 있음
  • Hugging Face의 minishlab에서 확인할 수 있음
  • WordLlamaInference는 로더 대신 (n_vocab, dim) 형태의 static embedding 배열과 tokenizer를 직접 넣어 사용할 수 있음
from wordllama import WordLlamaInference
from tokenizers import Tokenizer

tokenizer = Tokenizer.from_pretrained(...)
wl = WordLlamaInference(np_embeddings_ar, tokenizer)

학습과 임베딩 추출

  • 바이너리 임베딩 모델은 고차원에서 개선 폭이 더 뚜렷했고, 바이너리 임베딩에는 512 또는 1024차원이 권장됨
  • L2 Supercat 모델은 단일 A100 GPU에서 batch size 51212시간 학습됨
  • LLaMA 모델에서 토큰 임베딩을 추출하려면 사용자 계약에 동의하고 Hugging Face CLI에 로그인해야 함
from wordllama.extract.extract_safetensors import extract_safetensors

extract_safetensors("llama3_70B", "path/to/saved/model-0001-of-00XX.safetensors")
  • 임베딩은 보통 첫 번째 safetensors 파일에 있지만 항상 그렇지는 않음
    • manifest가 있을 수도 있음
    • 직접 살펴보고 찾아야 할 수도 있음
  • 학습에는 저장소의 스크립트를 사용하며, 기존 설정을 복사하거나 수정해 configuration file을 추가해야 함
pip install wordllama[train]
python train.py train --config your_new_config
python train.py save --config your_new_config --checkpoint ... --outdir /path/to/weights/
  • 저장 단계는 Matryoshka 차원별로 모델을 하나씩 저장함

업데이트, 로드맵, 라이선스

  • 2025-02-01 업데이트로 sorted, min, max 같은 표준 라이브러리 함수에 쓸 수 있는 callable 지원이 추가됨
  • 2024-10-04 업데이트로 semantic splitting inference algorithm이 추가됨
  • 로드맵에는 DSPy evaluator와 Retrieval-Augmented Generation, 즉 RAG pipeline 예제 노트북 추가가 있음
  • 커뮤니티 프로젝트로 Gradio Demo HF SpaceCPU-ish RAG가 있음
  • 프로젝트 라이선스는 MIT License

댓글과 토론

Hacker News 의견들
  • 작은 크기가 정말 마음에 듦. 이미 SBERT의 가장 작은 모델보다도 장점이 있음
    다만 기술적으로는 꽤 오래된 접근처럼 보이고, 성능과의 절충이라는 점은 이해함. 그래도 의미적 유사도, 자연어 추론(NLI), 명사 추상화 같은 유사도 유형 전환을 제공할 수 있을지 궁금함
    예를 들어 신문 기사를 “극단적 환경 사건” 같은 범주로 묶을 때는 “Freezing”과 “Burning”이 매우 비슷하게 나오길 원함. MTEB/Sentence-Similarity나 고전적인 Word2Vec/GloVe처럼 동작하는 경우임. 하지만 화학 기사라면 둘이 반대에 가깝게 나와야 하고, 자연어 추론 임베딩으로 두 사물 사이의 인과관계를 보고 싶을 때도 있음
    뒤의 두 임베딩 유형은 2019년 이후의 비교적 최근 방식이라 기술적 기회가 더 크다고 봄. 오래된 MTEB/의미 유사도 계열은 2014년부터 여러 용도에 충분했고, 2019년에 mini-lm-v2 등으로 크게 개선됐음
    위 세 가지 임베딩 유형은 SBERT로도 가능하지만 차원이 크고 모델도 커서, 유형별로 여러 모델을 로드하면 자원 부담이 큼. 생성형 임베딩 모델이나 E5, 자연어 추론 모델이 커서 종종 6GB 정도가 필요함

    • 좋은 아이디어임. 몇 가지 실험을 해보고 실현 가능성을 확인해보겠음
      단일 유사도 유형으로 학습했을 때 성능이 어떤지 보고 싶음. 문맥 계산 없이 이를 처리할 다른 방법이 있을지는 확신이 없음. 모델을 전환해야 할 수도 있지만, 그 자체는 큰 문제는 아님
    • 이건 17MB 모델이고, 벤치마크상 MiniLM v2, 즉 SBERT보다 당연히 낮게 나옴. 나는 23MB 모델로 ONNX에서 V3를 거의 모든 플랫폼에서 돌리고 있음
      폄하하려는 뜻은 아니고, 이런 작업을 맥락 속에서 이해하는 게 중요함. 여기서는 LLM을 깊이 이해하다 보면 LLM에도 임베딩이 있다는 점을 발견하고, 그 관점에서는 임베딩 분야 전체의 현황을 다시 훑기보다 그 임베딩을 만져보며 한 걸음 나아가는 편이 더 자연스럽다는 맥락임
    • “ChatGPT 임베딩”이 OpenAI 임베딩 모델을 뜻한다면, “burning”과 “freezing”은 전혀 반대가 아님. text-embedding-large-3의 1024차원으로 돌리면 코사인 유사도가 0.46 정도임. 완전히 반대인 임베딩이라면 유사도가 -1이어야 함
      반대 의미의 단어가 반대 임베딩을 가진다고 생각하는 건 흔한 착각임. 실제로는 반대 의미의 단어끼리도 공통점이 많음. “burning”과 “freezing”은 둘 다 온도와 물리와 관련 있고, 영어 단어이며, 동사·명사·형용사로 모두 쓰일 수 있고, 철자도 올바름. 이런 특징들이 모두 임베딩에 들어감
  • 임베딩은 학습 데이터와 목적 함수에 따라 많은 의미 정보를 담고, 여러 유용한 작업에 독립적으로 활용할 수 있음
    예전에 CLIP 모델의 텍스트 인코더 임베딩을 써서, 프롬프트가 대응 이미지와 더 잘 맞도록 보강한 적이 있음. 예를 들어 프롬프트에 “building”이 있으면 임베딩 행렬에서 “concrete”, “underground” 같은 최근접 이웃을 찾아 해당 단어 뒤에 치환하거나 덧붙였음. 제한적인 실험에서는 대부분의 질의에서 재현율이 높아졌음

    • 맞음. 이런 도메인 내 문맥 관계를 임베딩 모델에 학습시킬 수 있음
      https://www.marqo.ai/blog/generalized-contrastive-learning-f...
    • 정말 멋진 아이디어임. 이 구현에도 가능해 보이니 더 생각해보겠음
      wordllama에서 토큰 임베딩의 크기를 보면, 보강할 중요한 토큰을 식별하는 데도 도움이 될 수 있을 것 같음. 다만 이 작업에 맞게 선별한 데이터로 학습하면 훨씬 더 잘 동작할 수 있음
  • 영어 이외의 언어 계획도 있는지 궁금함. 프랑스어에는 완벽한 도구가 될 것 같음

    • 충분히 가능함. 학습용 말뭉치를 구성해야 하는데, 프랑스어에 어떤 자료가 있는지는 잘 모름
      Mistral 계열 모델로 학습을 조금 해본 적이 있어서, 프랑스어 말뭉치에서는 그쪽을 먼저 시도해볼 것 같음
      이슈를 열어주면 시간이 날 때 작업해보겠음
  • 큰 말뭉치, 예를 들어 10,000개 이상의 문장에서 각 문장을 문서로 보는 용도라면, TF-IDF 희소 행렬 벡터를 k-means로 군집화해도 비슷한 결과를 얻을 수 있음
    다만 이 도구에는 이진화 같은 방식으로 k-means 부분을 더 빠르게 만드는 유틸리티가 꽤 있는 것 같음. 앞으로 몇 주 동안 벤치마크를 해볼 생각임

  • 몇 년 전에 비슷한 함수들을 쓰는 언어 게임 모음을 만든 적이 있음: https://github.com/Hellisotherpeople/Language-games

  • 임베딩으로 Little Alchemy를 풀어보자는 생각을 해본 사람이 있는지 궁금함. #sample-use

  • 멋져 보임. mini-lm 모델 대비 장점이 있는지 궁금함. 대부분의 MTEB 작업에서는 mini-lm이 더 좋아 보이는데, 추론 속도 같은 면에서 나은 부분이 있는지 궁금함

    • Mini-lm이 더 나은 임베딩 모델임. 이 모델은 어텐션 계산을 하지 않고, 학습 이후에는 딥러닝 프레임워크도 쓰지 않음. 그래서 트랜스포머 모델의 문맥적 이점은 얻을 수 없음
      최신 최고 성능 모델을 목표로 한 것도 아님. 의존성, 크기, 하드웨어 요구사항을 낮추고 속도를 높이기 위해 꽤 제한적인 조건을 둔 모델임
      단어 임베딩 모델로 봐도 꽤 가벼운 편임. 보통 그런 모델들은 훨씬 큰 어휘집을 갖고 몇 GB 규모인 경우가 많음
    • 모델 자체의 크기 차이로 보임. 더 가볍고 빠름. mini-lm은 80MB이고, 여기서 가장 작은 모델은 16MB임
  • 게임 제작에 아주 유용해 보임

  • 토큰 자체에 얼마나 많은 의미 내용이 들어 있는지 잘 보여줌

  • PostgreSQL 확장으로 만들 수 있을까?