flowchart LR
wort["Wort und Sprache"]
lemma["Lemma bestimmen (Stanza)"]
filter["Kandidaten filtern"]
rang["nach Kosinus ordnen"]
aus["Lemma, Zahl, Fundstellen"]
wort --> lemma
lemma --> filter
filter --> rang
rang --> aus
Ähnlichkeitssuche
Ähnliche Wörter, Verben und Wendungen im Lemmaindex einer Collection
Zu einem Wort (einem Verb, einer Wendung) gibt die Ähnlichkeitssuche die Lemmata des Index zurück, die ihm in der Bedeutung nahestehen, mit ihrer Häufigkeit und ihren Fundstellen. Sie ist spezifiziert und gemessen, aber noch nicht gebaut: Der Filter fragt die Embeddings heute nicht ab. Die Messung sagt, welches Embedding dafür nicht taugt und dass bisher keines die Aufgabe gut löst.
Ein Beispiel vorweg
Welche Verben stehen versprechen nahe? Im Pilotkorpus (kepler-prim, nur Verben des Deutschen) ordnen die Modelle so:
bge-m3: zusprechen, schwören, gewähren, verpflichten, aussagen
EmbeddingGemma 2 (bf16, Präfix): vertrauen, versichern, versehen, verpflichten, vorschlagen
qwen3-embedding 0.6b: entsprechen, ansprechen, besprechen, versichern, vorsagen
Das ist der Befund, der die Frage bestimmt. Die Nachbarn sind gefiltert (Sprache Deutsch, Wortart Verb, nicht die Anfrage selbst), und trotzdem steht bei zwei Modellen neben echten Verwandten (versichern, verpflichten) Verben, die nur dieselbe Vorsilbe oder Wortendung tragen (versehen, entsprechen, besprechen). Ein Satz-Embedding, das ein einzelnes Wort ohne Kontext bekommt, vergleicht zum Teil die Schreibung. Die Synonyme, die das vorgeschlagene Gold mit der höchsten Note führt (zusagen, geloben, verheißen), fehlen in allen drei Listen. Bei bge-m3 steht verheißen auf Rang 16, zusagen und geloben stehen hinter Rang 50; bei den beiden anderen Modellen liegen alle drei hinter Rang 50.
Die Funktion
Eingabe ist ein Wort mit Sprache. Ausgabe sind Lemmata des Index, nicht Wortformen, jedes mit seiner Zahl im Korpus und mit Fundstellen, damit jeder Treffer ein adressierbarer Beleg ist.
Die Reihenfolge ist Absicht: zuerst filtern, dann ordnen. Der Filter ist exakt und entscheidet ohne Modell, welche Einträge des Index überhaupt Nachbarn sein dürfen (famulus_proof.aehnlichkeit.kandidaten). Das Embedding ordnet nur, was übrig bleibt.
| Filter | Wirkung |
|---|---|
| Sprache | nur Lemmata der Sprache der Anfrage; beim Sprachwechsel nur die Zielsprache |
| Art | Lemma oder Wendung |
| Wortart | bei einem Verb nur Verben |
Mindestzahl n |
seltene Lemmata, meist OCR-Rauschen, scheiden aus; ein Wert wird erst gesetzt, wenn das Prüfverfahren ihn misst |
| nicht die Anfrage | das Wort ist nicht sein eigener Nachbar |
Die Zahl n steht in dem Zählmodus, den jede genannte Zahl tragen muss (canonical: nur das Lemma, kleingeschrieben; ein Satz ist durch das Tripel (doc_id, pidx, sent_idx) bestimmt). Im Pilot wird nach Sprache, Art und Wortart gefiltert; das Vokabular des Pilots enthält nur Einträge mit mindestens drei Vorkommen und, bei Lemmata, mindestens drei Buchstaben. Der Filter wirkt nicht allein: Im Beispiel oben hat er die Verben nicht von den Vorsilben-Nachbarn getrennt. Die Mindestzahl ist zweischneidig: geloben und verheißen kommen in der Stichprobe je sechsmal vor, eine hohe Schwelle entfernte also gerade die gesuchten Synonyme.
Beobachtet wurde außerdem, dass das Wendungsvokabular Zweiwortfolgen mit Funktionswörtern enthält (es natura, natura licet), die bei der Anfrage lex natura unter den Nachbarn stehen. Das ist eine Eigenschaft des Vokabulars, nicht des Embeddings.
Was gemessen wurde
Der Pilot (8. Oktober 2026) verglich Embeddings an vier Aufgaben auf einer Stichprobe von kepler-prim: Wendung (lex naturae), Verb (versprechen), Satz und Sprachwechsel (versprechen zu promitto). Das Gold sind Noten 0 bis 2, die gemini-3.5-flash-lite aus dem gemeinsamen Pool der besten 15 jedes Arms vorgeschlagen hat. Es zählt als Gold erst nach Ihrer Bestätigung (gold_overrides.json); bis dahin ist jedes Urteil vorläufig. Das Verfahren steht in Prüfverfahren der Ähnlichkeitssuche.
nDCG@10, je höher desto besser (1 ist die ideale Ordnung der bekannten Treffer):
| Arm | Wendung | Verb | Satz | Sprachwechsel |
|---|---|---|---|---|
| bge-m3 (Produktion) | 0,575 | 0,378 | 0,216 | 0,380 |
| EmbeddingGemma 2, bf16, Präfix | 0,501 | 0,386 | 0,237 | 0,395 |
| EmbeddingGemma 2, Standard-Tag, Präfix | 0,484 | 0,391 | 0,254 | 0,361 |
| qwen3-embedding 0.6b | 0,478 | 0,307 | 0,096 | 0,325 |
| GLiNER2.5, Encoder | 0,305 | 0,143 | 0,029 | 0,064 |
| GLiNER2.5, Nachsortierung | 0,318 | 0,205 | — | 0,208 |
| GLiNER2.5, Extraktor | — | — | 0,043 | — |
| Anfragen | 15 | 16 | 14 | 18 |
Ob ein Unterschied trägt, entscheidet der gepaarte Bootstrap über die Anfragen, nicht der Abstand der Mittelwerte:
| Arm gegen bge-m3 | Funktion | Differenz nDCG@10 | 95 %-Intervall | Urteil |
|---|---|---|---|---|
| EmbeddingGemma 2, bf16, Präfix | Wendung | -0,074 | -0,208 bis +0,010 | unentschieden |
| EmbeddingGemma 2, bf16, Präfix | Verb | +0,008 | -0,096 bis +0,125 | unentschieden |
| EmbeddingGemma 2, bf16, Präfix | Satz | +0,020 | -0,067 bis +0,117 | unentschieden |
| EmbeddingGemma 2, bf16, Präfix | Sprachwechsel | +0,015 | -0,058 bis +0,093 | unentschieden |
| EmbeddingGemma 2, Standard-Tag, Präfix | Wendung | -0,091 | -0,220 bis -0,009 | schlechter |
| EmbeddingGemma 2, Standard-Tag, Präfix | Verb | +0,013 | -0,092 bis +0,130 | unentschieden |
| EmbeddingGemma 2, Standard-Tag, Präfix | Satz | +0,038 | -0,062 bis +0,137 | unentschieden |
| EmbeddingGemma 2, Standard-Tag, Präfix | Sprachwechsel | -0,019 | -0,080 bis +0,046 | unentschieden |
| qwen3-embedding 0.6b | Wendung | -0,097 | -0,249 bis +0,057 | unentschieden |
| qwen3-embedding 0.6b | Verb | -0,070 | -0,205 bis +0,079 | unentschieden |
| qwen3-embedding 0.6b | Satz | -0,121 | -0,254 bis -0,004 | schlechter |
| qwen3-embedding 0.6b | Sprachwechsel | -0,055 | -0,188 bis +0,059 | unentschieden |
Gesamturteil nach der Entscheidungsregel: EmbeddingGemma 2, bf16, Präfix: kein Grund zum Wechsel; EmbeddingGemma 2, Standard-Tag, Präfix: ersetzt bge-m3 nicht; qwen3-embedding 0.6b: ersetzt bge-m3 nicht. Das Urteil ist vorläufig, solange das Gold nur vorgeschlagen ist.
So ist es zu lesen:
- Bei Verben, Sätzen und beim Sprachwechsel trennen die Daten bge-m3 und EmbeddingGemma 2 nicht. 14 bis 18 Anfragen reichen dafür nicht.
- Bei Wendungen liegt bge-m3 vorn; nur beim Standard-Tag von EmbeddingGemma 2 liegt das Intervall ganz unter null.
- Das Standard-Tag (
270m, auch440m,740m) ist quantisiert und liefert dieselben Vektoren für alle drei Größen;270m-bf16-textist besser. Ohne die Suchpräfixe (task: search result | query:für die Anfrage,title: none | text:für das Dokument) liegt EmbeddingGemma 2 deutlich unter bge-m3. - GLiNER2.5 ist seit dem 8. Oktober 2026 aus der PDAI-Pipeline. Als Encoder, Extraktor und Nachsortierer liegt es überall weit unter den Embeddings.
- Alle Werte der Verbspalte sind niedrig. Der beste liegt bei 0,39. Kein getestetes Embedding löst die Aufgabe so, dass man ihm das Ergebnis ungeprüft überlassen sollte.
Grenzen der Messung
- Das Gold ist vorgeschlagen. Das Modell urteilt zwischen zwei Läufen nicht gleich; es zählen nur die Zahlen des letzten Laufs, die dieser Seite zugrunde liegen.
- Eine Collection (kepler-prim), 14 bis 18 Anfragen je Aufgabe.
- Der Recall ist ein gepoolter Recall: Treffer außerhalb der besten 15 aller Arme sind nach Konstruktion unbekannt. Deshalb werden Anfragen mit Ankerlemmata (alle Sätze mit lex und natura) immer beurteilt.
- Die auf 512, 256 und 128 Dimensionen gekürzten Vektoren wurden nur mit den besten zehn gepoolt; ihre Werte sind Untergrenzen. Auf 256 Dimensionen geht in dieser Stichprobe wenig verloren.
Speicher
Wo die Vektoren liegen, entscheidet über Latenz und Genauigkeit. Die Pilotzeilen tragen EmbeddingGemma-Vektoren (768 Dimensionen, 13.626 Sätze), die Produktionszeilen die bge-m3-Vektoren (1024 Dimensionen) der Collection kepler-prim.
| Speicher | Messung | Latenz p50 | Recall@10 gegen exakt |
|---|---|---|---|
| numpy, exakt | Pilot, 13.626 Vektoren | 1,6 ms | 1,0 |
| Chroma (HNSW) | Pilot | 2,1 ms | 0,987 |
| DuckDB, Brute Force | Pilot | 87,3 ms | 1,000 |
| DuckDB, vss (HNSW) | Pilot | 77,3 ms | 0,982 |
| numpy, exakt | Produktion, 440.581 Vektoren | 84,3 ms | 1,0 |
| Chroma (HNSW) | Produktion | 3,9 ms | 0,906 |
Chroma antwortet im Produktionsmaßstab in 3,9 ms, findet aber nur 90,6 % der exakten zehn nächsten Nachbarn. Für eine Wortliste von einigen Zehntausend Lemmata genügt eine Brute-Force-Suche. DuckDB und vss wurden nur im Pilotmaßstab gemessen. Ihre Werte für den vollen Maßstab sind eine Hochrechnung und nicht verifiziert.
Was noch nicht gemessen ist
Die folgenden Wege kommen aus Quellen, nicht aus einer Messung an den Collections:
| Weg | Warum er für ein einzelnes Wort passt | Quelle |
|---|---|---|
| fastText oder word2vec, auf den Lemmasequenzen der Collection trainiert | der Wortschatz ist der Lemmaindex; Teilwort-Information verbindet Wortfamilien; wirkt auch bei kleiner Datenmenge | lateinische Lemma-Embeddings: 86,9 % bei der Synonymwahl, über 90 % bei gleicher Wortart (Sprugnoli u. a.); deutsche Wortähnlichkeit: einfaches fastText genügt (Type- and Token-based Word Embeddings) |
qwen3-embedding:4b, :8b |
größere Modelle derselben Familie, die 0.6b ist hier schwächer als bge-m3 | Ollama |
snowflake-arctic-embed2, nomic-embed-text-v2-moe |
mehrsprachig, über Ollama zu beziehen | Ollama, Ollama |
| Llama-Embed-Nemotron-8B | offene Gewichte; Spitze der mehrsprachigen Rangliste | NVIDIA |
| ein Wortnetz (GermaNet, OdeNet; lateinisch ein Entsprechendes) | gibt echte Synonyme als Präzisionsfilter über einem Embedding | nicht geprüft |
Ausgeschlossen sind gemini-embedding-001 und jede Cloud-Einbettung: Sie liegen außerhalb der Gemini-Liste der Plattform und sind in Harvest-Skripten nicht erlaubt.
Ob ein Wort-für-Wort-Index auf dem Lemmaindex besser ist als ein Satz-Embedding, entscheidet nur das Prüfverfahren. Neue Kandidaten kommen als Arm in common.py hinzu; die Anfragen, das Gold und die Entscheidungsregel bleiben dieselben.
Entscheidung vom 8. Oktober 2026
Latein bleibt bge-m3 (EXPECTED_EMBEDDING_MODEL, Collection {coll}_sentences). Jede andere Sprache nimmt EmbeddingGemma 2 (embeddinggemma-2:270m-bf16-text, bf16, mit den Suchpräfixen, Collection {coll}_sentences_gemma). GLiNER2.5 wird nicht mehr geladen. Ein fertiger bge-m3-Speicher wird nicht mit --rebuild neu gebaut; sonst gälte er als veraltet. Neue Sätze einer anderen Sprache schreibt der nächste Bau oder ein Seitendelta in die Gemma-Collection. Fehlt sie, bleibt die Anfrage bei bge-m3.