- WordLlama ist ein schnelles, leichtgewichtiges NLP-Toolkit, das Token-Embeddings von LLMs wiederverwendet, um Fuzzy-Deduplizierung, Ähnlichkeitsberechnung, Ranking, Clustering und semantische Textaufteilung durchzuführen
- Die Inferenz basiert vor allem auf Token-Lookups und Average Pooling und setzt auf eine leichtgewichtige Pipeline, die nur mit NumPy lauffähig ist, sowie CPU-Optimierungen
- Das Standardmodell hat 256 Dimensionen und 16 MB; mit Matryoshka-Repräsentationen lassen sich die Dimensionen reduzieren, und binäre Embeddings unterstützen schnellere Berechnungen über Hamming-Ähnlichkeit
- In der MTEB-Tabelle erzielen WL64 bis WL1024 bei mehreren Metriken höhere Werte als GloVe 300d und Komninos, liegen aber meist unter
all-MiniLM-L6-v2
- Nach
pip install wordllama kann es mit WordLlama.load() verwendet werden; .key(query) gibt eine aufrufbare Funktion zurück, die sich an Standardbibliotheksfunktionen wie sorted, min und max übergeben lässt
Was WordLlama macht
- WordLlama ist ein leichtgewichtiges Toolkit für NLP-Utility-Aufgaben wie Fuzzy-Deduplizierung, Ähnlichkeitsberechnung, Ranking, Clustering und semantische Textaufteilung
- Es extrahiert Token-Embedding-Codebooks aus aktuellen LLMs wie LLaMA 2 und LLaMA 3 70B und erstellt daraus kompakte Word Representations ähnlich wie GloVe, Word2Vec oder FastText
- Bei der Inferenz hat es wenige Abhängigkeiten und ist für CPU-Hardware optimiert, wodurch es sich für den Einsatz in ressourcenbeschränkten Umgebungen eignet
- Dank hoher Geschwindigkeit und geringer Größe kann es für Utility-Zwecke wie explorative Analysen, Evaluatoren für LLM-Ausgaben sowie Vorverarbeitung in Multi-Hop- oder agentischen Workflows genutzt werden
Installation und grundlegende Nutzung
- Die Installation erfolgt per pip
pip install wordllama
- Das standardmäßige 256-dimensionale Modell wird mit
WordLlama.load() geladen
from wordllama import WordLlama
wl = WordLlama.load()
.key(query) gibt Callable[[str], float] zurück, sodass Kandidaten-Strings nach ihrer Ähnlichkeit zur Query sortiert oder der beste Treffer ausgewählt werden können
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)
- Im Beispielergebnis wird
"Introduction to neural networks" mit einem Score von 0.3414 zum Kandidaten mit dem höchsten Wert
Hauptfunktionen
- Embedding-Erzeugung: Erzeugt Text-Embeddings schnell über einfache Token-Lookups und Average Pooling
- Ähnlichkeitsberechnung: Berechnet die Cosine Similarity zwischen zwei Texten
- Dokument-Ranking: Ordnet Kandidatendokumente nach ihrer Ähnlichkeit zu einer Query
- Fuzzy-Deduplizierung: Entfernt doppelte Texte anhand eines Ähnlichkeitsschwellenwerts
- Clustering: Gruppiert Dokumente mit KMeans
- Filterung: Behält nur Dokumente, deren Ähnlichkeit zur Query über einem Schwellenwert liegt
- Top-K-Suche: Gibt die K Dokumente zurück, die einer Query am ähnlichsten sind
- Semantische Textaufteilung: Teilt Text in semantisch kohärente Chunks
- Binäre Embeddings: Unterstützt schnellere Berechnungen über Hamming-Ähnlichkeit
- Matryoshka-Repräsentationen: Schneidet Embedding-Dimensionen nach Bedarf ab, um Modellgröße und Leistung anzupassen
Modellstruktur und Leistung
- WordLlama trainiert ein kleines kontextloses Modell innerhalb eines allgemeinen Embedding-Frameworks
- Das Standardmodell hat 256 Dimensionen und 16 MB
- Die MTEB-Tabelle im README vergleicht WL64, WL128, WL256, WL512 und WL1024 mit GloVe 300d, Komninos und
all-MiniLM-L6-v2
- WL256 erreicht bei Clustering
33.25, Reranking 52.03, Classification 58.21, Pair Classification 78.22, STS 67.91, CQA DupStack 24.12 und SummEval 30.99
- GloVe 300d erreicht in denselben Kategorien jeweils
27.73, 43.29, 57.29, 70.92, 61.85, 15.47 und 28.87
all-MiniLM-L6-v2 erreicht bei Clustering 42.35, Reranking 58.04, Classification 63.05, Pair Classification 82.37, STS 78.90, CQA DupStack 41.32 und SummEval 30.81
- l2_supercat ist ein LLaMA-2-Vocabulary-Modell
- Es wurde trainiert, indem aus den Codebooks mehrerer Modelle, darunter LLaMA 2 70B und phi 3 medium, zusätzliche Special Tokens entfernt und die Codebooks anschließend zusammengeführt wurden
- Codebooks mehrerer Modelle, die den LLaMA-2-Tokenizer verwenden, können gemeinsam zusammengeführt und trainiert werden
- Es zeigt eine ähnliche Leistung wie das Training mit dem LLaMA-3-70B-Codebook, während das Vocabulary mit
32k gegenüber 128k viermal kleiner ist
- Als LLaMA-3-basiertes Modell wird l3_supercat bereitgestellt
- Weitere Ergebnisse stehen unter Results
Semantische Textaufteilung
.split() teilt lange Texte in semantische Chunks
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 ist sowohl Zielgröße als auch Maximalgröße
- Der Aufteilungsprozess versucht, die Textreihenfolge, Satzstruktur und, wenn möglich, Absatzstruktur beizubehalten
- WordLlama-Embeddings werden genutzt, um natürlichere Aufteilungsindizes zu finden
- Die Größe der Ausgabe-Chunks kann unterhalb von
target_size variieren
- Die empfohlene Zielgröße liegt bei 512 bis 2048 Zeichen, der Standardwert ist
1536
- Wenn größere Chunks benötigt werden, wird empfohlen, nach der Aufteilung mehrere semantische Chunks zu Batches zusammenzufassen
- Details stehen in der technical overview
Model2Vec und direkte Inferenz
- Mit dem Update vom 2025-01-04 wurde Unterstützung für statische Model2Vec-Embeddings hinzugefügt
- Model2Vec-Modelle können mit
WordLlama.load_m2v() geladen werden
wl = WordLlama.list_configs()
wl = WordLlama.load_m2v("potion_base_8m") # 256-dim model
wl = WordLlama.load_m2v("m2v_multilingual") # multilingual model
- Model2Vec ist ein anderer Ansatz, bei dem PCA zur Erstellung statischer Embeddings verwendet wird
- Auf der Model2Vec-Seite wurden ein mehrsprachiges Modell und ein GloVe-basiertes Modell erstellt; diese sollen bei Word-Similarity-Tasks gute Werte erzielen
- Zu finden ist das bei minishlab auf Hugging Face
WordLlamaInference kann statt eines Loaders direkt mit einem statischen Embedding-Array der Form (n_vocab, dim) und einem Tokenizer verwendet werden
from wordllama import WordLlamaInference
from tokenizers import Tokenizer
tokenizer = Tokenizer.from_pretrained(...)
wl = WordLlamaInference(np_embeddings_ar, tokenizer)
Training und Extraktion von Embeddings
- Bei binären Embedding-Modellen war die Verbesserung in hohen Dimensionen deutlicher; für binäre Embeddings werden 512 oder 1024 Dimensionen empfohlen
- Das L2-Supercat-Modell wurde auf einer einzelnen A100-GPU mit Batch Size
512 12 Stunden lang trainiert
- Um Token-Embeddings aus LLaMA-Modellen zu extrahieren, muss man der Nutzervereinbarung zustimmen und sich per Hugging Face CLI anmelden
from wordllama.extract.extract_safetensors import extract_safetensors
extract_safetensors("llama3_70B", "path/to/saved/model-0001-of-00XX.safetensors")
- Die Embeddings befinden sich normalerweise in der ersten
safetensors-Datei, aber nicht immer
- Es kann ein Manifest geben
- Unter Umständen muss man selbst nachsehen und sie finden
- Für das Training werden die Skripte im Repository verwendet; dazu muss man eine bestehende Konfiguration kopieren oder ändern und eine Configuration File hinzufügen
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/
- Der Speicherschritt legt für jede Matryoshka-Dimension ein eigenes Modell ab
Updates, Roadmap und Lizenz
- Mit dem Update vom 2025-02-01 wurde Unterstützung für Callables hinzugefügt, die sich in Standardbibliotheksfunktionen wie
sorted, min und max verwenden lassen
- Mit dem Update vom 2024-10-04 wurde ein semantischer Splitting-Inferenzalgorithmus hinzugefügt
- Auf der Roadmap stehen Beispiel-Notebooks für einen DSPy-Evaluator und Retrieval-Augmented Generation, also eine RAG-Pipeline
- Community-Projekte sind Gradio Demo HF Space und CPU-ish RAG
- Die Projektlizenz ist die MIT License
1 Kommentare
Hacker-News-Meinungen
Die geringe Größe gefällt mir wirklich. Schon jetzt hat es Vorteile gegenüber dem kleinsten Modell von SBERT.
Technisch gesehen wirkt der Ansatz allerdings ziemlich alt, und ich verstehe, dass es ein Kompromiss bei der Leistung ist. Trotzdem frage ich mich, ob es möglich wäre, zwischen Ähnlichkeitstypen umzuschalten, etwa semantischer Ähnlichkeit, Natural Language Inference (NLI) oder Substantiv-Abstraktion.
Wenn man zum Beispiel Zeitungsartikel in Kategorien wie „extreme Umweltereignisse“ gruppiert, möchte man, dass „Freezing“ und „Burning“ sehr ähnlich ausfallen. Das entspricht eher MTEB/Sentence-Similarity oder klassischem Word2Vec/GloVe. Bei Chemieartikeln sollten die beiden dagegen nahezu Gegensätze sein, und manchmal möchte man mit Natural-Language-Inference-Embeddings auch kausale Beziehungen zwischen zwei Dingen betrachten.
Die beiden letzteren Embedding-Typen sind relativ neuere Ansätze seit 2019, daher sehe ich dort größere technische Chancen. Die ältere MTEB-/semantische-Ähnlichkeits-Linie war seit 2014 für viele Anwendungsfälle ausreichend und wurde 2019 mit mini-lm-v2 und Ähnlichem deutlich verbessert.
Die drei oben genannten Embedding-Typen sind auch mit SBERT möglich, aber die Dimensionen sind groß und die Modelle ebenfalls. Wenn man mehrere Modelle je Typ lädt, wird das ressourcenseitig teuer. Generative Embedding-Modelle, E5 oder Natural-Language-Inference-Modelle sind groß und benötigen oft etwa 6 GB.
Ich möchte sehen, wie die Leistung ist, wenn man auf einen einzelnen Ähnlichkeitstyp trainiert. Ich bin nicht sicher, ob es eine andere Möglichkeit gibt, das ohne Kontextberechnung zu erledigen. Vielleicht muss man das Modell wechseln, aber das ist an sich kein großes Problem.
Das ist nicht abwertend gemeint; es ist wichtig, solche Arbeiten im Kontext zu verstehen. Hier ist der Kontext: Wenn man LLMs tiefgehend versteht, entdeckt man, dass auch LLMs Embeddings haben. Aus dieser Perspektive ist es natürlicher, mit diesen Embeddings herumzuspielen und einen Schritt weiterzugehen, statt erst den gesamten Stand des Embedding-Felds erneut zu überblicken.
Es ist ein verbreiteter Irrtum zu glauben, dass Wörter mit gegensätzlicher Bedeutung auch gegensätzliche Embeddings haben. Tatsächlich haben Wörter mit gegensätzlicher Bedeutung viele Gemeinsamkeiten. „burning“ und „freezing“ haben beide mit Temperatur und Physik zu tun, sind englische Wörter, können als Verb, Substantiv und Adjektiv verwendet werden und sind korrekt geschrieben. All diese Merkmale gehen in die Embeddings ein.
Embeddings enthalten je nach Trainingsdaten und Zielfunktion viele semantische Informationen und können unabhängig für verschiedene nützliche Aufgaben verwendet werden.
Vor einiger Zeit habe ich Embeddings des Text-Encoders eines CLIP-Modells genutzt, um Prompts so zu erweitern, dass sie besser zu den entsprechenden Bildern passen. Wenn ein Prompt zum Beispiel „building“ enthielt, habe ich in der Embedding-Matrix nächste Nachbarn wie „concrete“ oder „underground“ gesucht und sie hinter dem entsprechenden Wort ersetzt oder angehängt. In begrenzten Experimenten stieg bei den meisten Anfragen der Recall.
https://www.marqo.ai/blog/generalized-contrastive-learning-f...
Wenn man sich bei wordllama die Größe der Token-Embeddings ansieht, könnte das auch helfen, wichtige Tokens für die Erweiterung zu identifizieren. Allerdings würde es mit Daten, die speziell für diese Aufgabe kuratiert wurden, wahrscheinlich deutlich besser funktionieren.
Ich frage mich, ob es auch Pläne für andere Sprachen als Englisch gibt. Für Französisch wäre das vermutlich ein perfektes Tool.
Ich habe ein wenig mit Modellen aus der Mistral-Familie trainiert, daher würde ich bei einem französischen Korpus vermutlich zuerst diese Richtung ausprobieren.
Wenn du ein Issue eröffnest, schaue ich mir das an, sobald ich Zeit habe.
Für ein großes Korpus, zum Beispiel mehr als 10.000 Sätze, bei denen jeder Satz als Dokument betrachtet wird, kann man mit TF-IDF-Sparse-Matrix-Vektoren und k-means-Clustering ähnliche Ergebnisse erzielen.
Allerdings scheint dieses Tool einige Utilities zu haben, die den k-means-Teil etwa durch Binärisierung schneller machen. Ich plane, in den nächsten Wochen Benchmarks dazu zu machen.
Vor ein paar Jahren habe ich eine Sammlung von Sprachspielen erstellt, die ähnliche Funktionen verwenden: https://github.com/Hellisotherpeople/Language-games
https://github.com/plasticityai/magnitude
Ich frage mich, ob schon jemand daran gedacht hat, Little Alchemy mit Embeddings zu lösen. #sample-use
Sieht cool aus. Ich frage mich, ob es gegenüber mini-lm-Modellen Vorteile gibt. Bei den meisten MTEB-Aufgaben scheint mini-lm besser zu sein; mich würde interessieren, ob es etwa bei der Inferenzgeschwindigkeit Vorteile hat.
Es zielt auch nicht auf aktuelle Spitzenleistung ab. Es ist ein Modell mit recht engen Einschränkungen, um Abhängigkeiten, Größe und Hardware-Anforderungen zu senken und die Geschwindigkeit zu erhöhen.
Selbst als Wort-Embedding-Modell ist es ziemlich leichtgewichtig. Üblicherweise haben solche Modelle ein viel größeres Vokabular und sind oft mehrere GB groß.
Sieht für die Spieleentwicklung sehr nützlich aus.
Es zeigt sehr gut, wie viel semantischer Inhalt in den Tokens selbst steckt.
Könnte man daraus eine PostgreSQL-Erweiterung machen?