Blog
EmbeddingGemma 2 lokale Suche: Finer als lokale Embedding-API auf dem Mac
- Embeddings
- Semantische Suche
- Lokale KI
- MCP
Ich suche auf Englisch. Viele Dokumente, die ich brauche, sind auf Deutsch, und manche Scans haben keine Textebene. Suche in der Cloud hieße, jede Datei hochzuladen. Darum habe ich Finer gebaut, eine lokale Suche für meinen Mac. Ihr Kern ist EmbeddingGemma 2, von Google am 6. Oktober 2026 veröffentlicht und hier genutzt als lokale Embeddings-API: Text hinein, 768 Zahlen hinaus, mit einem Kindprozess auf meinem Rechner als Endpunkt.
Bei 28 Fragen an meine eigenen Dateien erreichte die hybride Suche 0,90 MRR und ein Reranker mit Gate 0,95. Das sind README-Zahlen von meinem M4 Pro, auf einer kleinen Menge, auf der auch die Gewichte eingestellt wurden, also In-Sample-Werte, und das Repo nennt keinen Embedder-Namen bei diesen Werten (die Tabelle erklärt das). Finer entstand unter dem Arbeitsnamen MySearch, und Code, mse-Befehl und Repo nutzen diesen Namen noch.
Kernpunkte
- Ein Modell und ein 768-dimensionaler Raum decken Text, Bilder, PDF-Seiten, Audio und Video in über 100 Sprachen ab. Das ersetzt eine Text-Embedding-API plus eigene Bild- und Audiomodelle.
- README-Werte von meinem M4 Pro bei 28 Fragen, der Embedder vermutlich EmbeddingGemma 2 8-Bit: Keywords allein 0,63 MRR, hybride Suche 0,90, hybrid plus Reranker 0,95. Die Gewichte wurden auf diesen Fragen eingestellt, also sind die Zahlen In-Sample, und 0,82 bis 0,89 Hit@1 sind zwei Fragen.
- Der Reranker läuft nur bei knappen Entscheidungen. Meine erste Version brauchte etwa 3 Sekunden und erreichte 0,88 MRR. Die aktuelle fusioniert Ränge, kostet 0,25 bis 0,45 Sekunden extra und erreicht 0,95 auf denselben 28 Fragen.
- Finer ist nicht vollständig lokal. Suche, Embedding, Reranking, OCR und Transkription laufen auf dem Mac. Die optionale Ask-Funktion ist standardmäßig aus. Wenn sie an ist, schreibt ein Cloud-Modell die Antwort, außer du wählst das lokale Modell, und das Maskieren von Kennungen davor ist nur Regex.
- Gehostete Embeddings kosten pro Token fast nichts. Das Argument für lokal heißt: Dateien bleiben auf der Platte, die Suche geht offline, keine Rechnung pro Anfrage, kein Lock-in, und kein Anbieter schaltet eine Modellversion unter deinen Vektoren ab.
Warum ich Finer gebaut habe
Meine Dokumente sind auf die übliche Art ein Durcheinander: PDFs, Scans, Word-Dateien, E-Mails, Screenshots, Sprachnotizen, auf Englisch und Deutsch. Ich suche auf Englisch und brauche oft die deutsche Datei.
Finer beobachtet die Ordner, die ich wähle, und indexiert ihren Inhalt. Ich nutze es über eine Mac-App, die Kommandozeile, eine Webseite und über MCP aus Coding-Agenten. SQLite FTS5 übernimmt Keywords, EmbeddingGemma 2 die Bedeutung, eine kleine Brücke verbindet englisches und deutsches Vokabular, und gewichtete reziproke Rangfusion führt die Listen zusammen. Ein Qwen3-Reranker prüft knappe Entscheidungen, und ein Nachtjob stellt ein paar Einstellungen hinter Leitplanken neu ein.
Zwei Grenzen vorweg. Finer läuft nur auf dem Mac: Die Laufzeitumgebung des Modells ist Apples MLX, und OCR nutzt Apple Vision. Und es ist nicht vollständig lokal: Die optionale Ask-Funktion kann Passagen an ein Cloud-Modell schicken, Details weiter unten. Wo ein Teil nur auf dem Mac läuft, nenne ich, was du unter Linux oder Windows stattdessen probieren könntest. Das sind Vorschläge, Finer kann nichts davon.
Was EmbeddingGemma 2 für die lokale Suche ändert
Die Modellkarte nennt 740 Millionen Parameter, gebaut von Google DeepMind auf der Gemma-4-Architektur: ein 270-Millionen-Textmodell, ein 170-Millionen-Vision-Encoder und ein 300-Millionen-Audio-Encoder. Text, Code, Bilder, Video und Audio landen in einem 768-dimensionalen Raum, also findet eine Textanfrage ein Bild oder eine Aufnahme mit demselben Vektorvergleich wie einen Absatz. Ohne das bräuchte ich ein Textmodell, ein Bildmodell und ein Audiomodell, jedes mit eigenem Index.
Es deckt über 100 Sprachen ab (die Trainingsdaten enthalten über 140), das brauche ich für einen Ordner mit Englisch und Deutsch, und es hat 8.192 Token Kontext, viermal so viel wie die erste Version. Finer nutzt davon wenig: Es schneidet Text bei 2.048 Token ab und hält Chunks unter 1.600 Zeichen.
Googles Werte sind selbst berichtet, für den Checkpoint in voller Präzision. Auf mehrsprachigem MTEB v2 gibt die Version-2-Karte 61,36 gegen 61,15 für Version 1, auf MTEB Code 78,68 gegen 68,76. Auf englischem MTEB v2 läuft es andersherum: 68,46 gegen 69,67 auf der Version-1-Karte. Das vergleicht zwei Karten, und der Textgewinn steckt vor allem im Code. Stand 10. Oktober 2026 fand ich kein unabhängiges MTEB- oder Leaderboard-Ergebnis für Version 2.
Zur Lizenz nur Fakten. Googles Karte und Launch-Post sagen Apache 2.0. Die Karte sagt auch, Deployments müssen sich an die Gemma Prohibited Use Policy halten. Version 1 stand unter den Gemma Terms of Use. Ich fand keine Google-Seite, die erklärt, wie Lizenz und Policy zusammenpassen, also ziehe ich keinen Schluss daraus.
Warum eine lokale Embeddings-API in dieser Größe funktioniert
Die Größe hängt davon ab, welche Encoder du lädst: 270 Millionen Parameter für Text allein (die EmbeddingGemma-270m-Konfiguration), 440 Millionen mit Bildern, 570 Millionen mit Audio, 740 Millionen für alles. Ich nenne es lokale API, weil der Vertrag einem gehosteten Endpunkt entspricht. In Finer ist der Endpunkt ein Worker-Prozess, der JSON-Zeilen auf stdin liest und auf stdout antwortet, mit den Vektoren als base64-float32. Der aufrufende Code merkt nicht, dass kein Netz dazwischen ist.
Gehostete Embeddings kosten pro Token fast nichts. Das sind die Listenpreise auf den Anbieterseiten am 10. Oktober 2026, pro Million Text-Token:
- OpenAI: text-embedding-3-small $0.02, text-embedding-3-large $0.13.
- Google Gemini API: gemini-embedding-2 Text $0.20 oder $0.10 im Batch; zu Standardpreisen außerdem $0.00012 pro Bild, $0.00016 pro Sekunde Audio und $0.00079 pro Videoframe.
- Voyage AI: voyage-4-large $0.12, voyage-4 $0.06, voyage-4-lite $0.02.
Warum ich es trotzdem lokal betreibe
Bei $0.02 bis $0.20 pro Million Token ist der Preis nicht der Grund. Meine Gründe sind diese. Dateien bleiben auf der Platte, und der Index bleibt auf dem Rechner. Ask ist die Ausnahme: Wenn du es einschaltest, gehen Passagen standardmäßig an ein Cloud-Modell, wie unten beschrieben. Die Suche geht offline. Es gibt keine Rechnung pro Anfrage, und kein Anbieter kann eine Modellversion unter meinen Vektoren abschalten. Scans, Fotos und Aufnahmen werden durchsuchbar, ohne hochgeladen zu werden. Der Preis dafür ist Hardware, Einrichtungszeit und Platte: etwa 1,3 GB Modelle für eine minimale Installation, 4,4 GB für alle. Das Repo nennt keine Latenz für Query-Embeddings, also nenne ich keine.
EmbeddingGemma 2 mit MLX auf dem Mac betreiben
Ich nutze den mlx-community-8-Bit-Build, etwa 1,2 GB, über mlx-vlm. Sein Text-Encoder und die Audio-Projektion sind 8-Bit, Vision- und Audio-Türme bleiben in BF16. Die Karte sagt, Inferenz läuft in bfloat16 oder float32, nie in float16, weil die Aktivierungen den float16-Bereich sprengen. Mein README sagt 8-Bit gegen BF16: Kosinus 0,9996 und 99,6 % identische Top-10; kein Skript im Repo reproduziert das, und das README nennt keinen Korpus. Finer hält außerdem eine 320-MB-Textkopie für die Suche vor. Diese Größe ist keine Google-Zahl. Die Setup-Notizen sagen, die Kopie wurde aus dem vollen Ordner geschnitten, und die Methode ist nicht festgehalten.
Ein launchd-Dienst stellt eine lokale HTTP-API auf 127.0.0.1 hinter einem zufälligen Token bereit und betreibt Suche, Job-Queue und Dateiüberwachung. Er importiert nie MLX. Jedes Modell lebt in einem eigenen Worker-Prozess: Text-Embedding, volles multimodales Embedding, Sprache, Reranking und Ask. Ein Worker startet bei erster Nutzung, stoppt nach 10 Minuten ohne Arbeit (5 für Ask) und wird gekillt und neu gestartet, wenn er hängt.
Stoppt ein Prozess, wird sein Speicher frei, der Dienst bleibt klein (50 bis 170 MB laut meinem README), und ein festhängendes Modell kann die Suche nicht mitreißen. Das Repo misst keine der Alternativen: Modelle im Dienst laden oder ein HTTP-Modellserver. Ein festgehaltener Vergleich steht in einem Worker-Codekommentar: Der transformers-Tokenizer-Wrapper kostet etwa 575 MB für Gemmas 262.144-Token-Vokabular, die rohe tokenizers-Bibliothek etwa 260 MB. Leser unter Linux oder Windows könnten eine torch- oder llama.cpp-Laufzeit probieren. Das ist ein Vorschlag, Finer kann nichts davon.
So ist das System aufgebaut
Lies das Diagramm von oben nach unten. Die erste Hälfte läuft, wenn sich Dateien ändern. Die zweite Hälfte läuft, wenn ich suche.
files on disk
| file-system events (day) nightly job 02:30, on AC power
v
extract text layer, Office, e-mail | OCR, page images, Whisper (night)
v
chunk ~1100 characters, 150 overlap, plus one "title" item per file
|---> FTS5 table (name x4, heading x2, text x1)
v
embed EmbeddingGemma 2 worker, 768-d, cached by prompt hash
v
SQLite float16 vectors + 1-bit copy, one database per folder
query --> parse --> embed query --+--> keyword list (FTS5 bm25)
+--> bridge list (EN/DE terms, FTS5)
+--> meaning lists (1-bit shortlist x16, exact re-score)
weighted RRF (k = 60) --> files --> fold copies --> favourites
near-tie? yes --> Qwen3-Reranker, top 10 x 128 tokens --> rank fusion
results: app, CLI, web, MCP Ask: optional, off by defaultIngestion, OCR und Chunking: was eingebettet wird
Die Extraktion ist nach Kosten geteilt. Leichte Arbeit läuft tagsüber: Text, Office-Dateien, E-Mail, die PDF-Textebene. Schwere Arbeit läuft nachts oder per manuellem Sync, am Netzstrom: OCR, Seitenbilder, Audio, Video, Transkription. Bis zu fünf neue Scans oder Fotos bekommen OCR und Bildeinbettung auf einmal. Unveränderte Dateien werden nie geöffnet.
Eine PDF-Seite mit weniger als 40 Nicht-Leerzeichen zählt als Scan und geht durch Apple Vision OCR. Seite 1 und jede gescannte Seite werden zusätzlich als Bild gerendert und eingebettet, bis zu 30 pro Datei, also ist ein Scan über seinen OCR-Text und über das Aussehen der Seite findbar. Audio wird in 60-Sekunden-Segmente geschnitten und Video in 30-Sekunden-Clips, und Whisper large-v3-turbo transkribiert Sprache. Dateien, die nach Geheimnissen aussehen (Keys, .env-Dateien, Credential-Ordner), werden nie gelesen. Hier nur Mac: Apple Vision, PDFKit, textutil, File-System-Events und launchd. Leser unter Linux oder Windows könnten Tesseract oder EasyOCR mit pdfium, pandoc, watchdog, faster-whisper und systemd probieren. Das sind Vorschläge, das Repo hat keinen Benchmark von Tesseract gegen Vision.
Ich chunke nach Zeichen: etwa 1.100 pro Chunk, Texte bis 1.600 bleiben am Stück, 150 Überlappung. Markdown trennt nach Überschrift, PDFs nach Seite, Folien nach Folie, Tabellen nach Blatt. Zeichenzählen braucht keinen Tokenizer, und 1.600 Zeichen passen fast immer unter die 2.048-Token-Grenze, die Finer anlegt. Das Repo hält keinen Vergleich mit tokenbasiertem oder semantischem Chunking fest.
Dokumente werden in dem Format eingebettet, das die Karte vorschreibt, "title: {title} | text: {content}", und Anfragen als "task: search result | query: {query}". Die Karte sagt, ohne den Task-Präfix kann die Qualität sinken. Jede Datei bekommt zusätzlich ein Titel-Item aus ihren Pfadwörtern, also bleibt ein Scan mit schlechtem OCR über seinen Namen findbar. Ein Cache mit dem Hash des Prompts als Schlüssel nutzt Vektoren für identische Prompts wieder; mein README sagt, ein unveränderter Ordner braucht zum erneuten Einbetten 6 Sekunden statt 320, wieder ohne Skript dahinter. Kopien einer Datei werden alle indexiert und falten sich zur Anfragezeit in ein "N Versionen"-Ergebnis zusammen.
Hybride Suche: Keywords plus Embeddings, mit Zahlen
Die Keyword-Seite ist eine FTS5-Tabelle mit Namens-, Überschrifts- und Textspalte, ohne Diakritika, mit Präfix-Index und bm25-Gewichten 4, 2 und 1, also zählt ein Treffer im Dateinamen viermal so viel wie einer im Fließtext. Eine Anfrage wird ein ODER ihrer Wörter, und Wörter ab vier Buchstaben matchen auch als Präfix.
Die Tabelle nach diesen Notizen stammt aus meinem README: 28 handgeschriebene Fragen an einen privaten Ordner mit ein paar hundert Geschäftsunterlagen auf Englisch und Deutsch, ausgeführt mit mse eval auf meinem M4 Pro. Die Gewichte wurden auf genau diesen Fragen eingestellt, also ist jede Zeile In-Sample. Das Repo hält keinen Embedder-Namen und keine Revision bei der Tabelle fest. Ich ordne sie EmbeddingGemma 2 8-Bit per Zeitachse zu: Die Projektdateien stammen vom 7. Oktober 2026, dem Tag nach Modellrelease, und nennen keinen anderen Embedder. Lies sie mit vier Vorbehalten:
- Keywords allein erreichten 0,63 MRR. Dieser Lauf hatte keine Brücke, und die Gold-Set-Beschreibung selbst sagt, englische Fragen zielen meist auf deutsche Dokumente, also sagt das wenig über BM25 in einem einsprachigen Ordner.
- "Bedeutung allein" enthält die Brücke. Hybrid schlägt sie um 0,03 MRR bei gleichem Hit@1, ein kleiner Vorsprung bei 28 Fragen.
- Das README beschreibt die Standardeinstellung als eingestellte Gewichte, eine Strafe für Übersichtsdateien und Versionsgruppierung zusammen, also kann ich nicht sagen, was davon gearbeitet hat.
- Eine Frage sind 3,6 Punkte Hit@k. Von 0,82 auf 0,89 Hit@1 zu gehen sind zwei Fragen.
Setting Hit@1 Top 3 Top 10 MRR
First version, equal weights 0.68 0.89 0.96 0.81
Current default 0.82 0.96 1.00 0.90
Meaning only (vectors + bridge) 0.82 0.93 0.96 0.87
Keywords only (FTS5 bm25) 0.57 0.64 0.79 0.63
Current default + near-tie reranker 0.89 1.00 1.00 0.95
First reranker attempt (replaced) 0.79 0.96 1.00 0.88Listen zusammenführen mit Rangfusion
Keyword-Scores und Kosinuswerte leben auf verschiedenen Skalen, also fusioniere ich Ränge. Cormack, Clarke und Büttcher (SIGIR 2009) bewerten ein Dokument als Summe von 1 / (k + Rang) über die Listen, mit k = 60 fest in einem Piloten. Sie nennen 60 nahezu optimal und sagen, die Wahl war nicht kritisch. Ich habe das übernommen und ein Gewicht pro Liste ergänzt, also trägt jeder Treffer Gewicht / (60 + Rang) bei. Das ist gewichtete reziproke Rangfusion, und die Bauanleitung zeigt sie in Python. Die Standardgewichte sind Bedeutung 1,0, Keyword und Brücke 0,6, Titel 0,55, Bilder 0,75 und Audio 0,6, plus ein kleiner Bonus von 0,004 für den Top-Keyword- und Textvektortreffer.
Chunk-Scores rollen auf Dateien hoch als bester + 0,3 x zweiter + 0,1 x dritter. Dateien, deren Name nach Zusammenfassung, Readme, Index oder To-do-Liste klingt, werden mit 0,6 multipliziert, weil sie gern alles erwähnen. Das Repo hält keinen Vergleich von RRF mit einer linearen Mischung für die Retrieval-Listen fest, also berichte ich keinen. Der Nachtjob stellt die Keyword-, Brücken- und Titelgewichte, diese Strafe und zwei Reranker-Einstellungen neu ein. Der Rest, inklusive k, bleibt fest.
Deutsche Dateien mit englischen Fragen suchen
FTS5 kann keine Sprachen überqueren: Eine englische Anfrage hat keine deutschen Wörter zum Matchen. Die Brücke nutzt das Vokabular jedes Ordners selbst. Nachts bettet Finer bis zu 25.000 der häufigsten Begriffe des Ordners ein, mit dem Anfrage-Prompt, in eine Kosinustabelle. Zur Anfragezeit nimmt sie die 12 Begriffe nächst am Anfrage-Embedding, wirft alles unter Kosinus 0,62 und die Wörter der Anfrage selbst weg, behält höchstens fünf und fährt sie als zusätzliche FTS5-Anfrage mit Gewicht 0,6. Die Oberfläche zeigt sie als "auch gesucht". Für eine englische Anfrage wie "rental contract" ergänzt sie vielleicht "mietvertrag" oder "miete"; dieses Beispiel ist illustrativ und stammt aus keinem echten Index.
Das Vokabular trägt den Jargon des Ordners, Produktnamen und deutsche Komposita, ohne Übersetzungsmodell, Wörterbuch oder Netz. Die Anfrage mit einem Modell übersetzen, ein Wörterbuch nutzen oder ein LLM sie umschreiben lassen wären die Alternativen. Finer nutzt keine davon, und das Repo hat keinen Vergleich.
Die Belege sind dünn. Eine Testkonfiguration ohne Brücke existiert, aber ich habe keine veröffentlichte Zahl dazu, was die Brücke bringt. Ein Codekommentar vom 7. Oktober hält Anfrage-zu-Anfrage-Kosinuswerte von 0,75 bis 0,86 für die englische und deutsche Fassung einer Frage fest, gegen bis zu 0,889 für verschiedene Fragen; kein Skript reproduziert sie. Das misst Anfrageähnlichkeit und sagt nichts über Retrieval. Der Mechanismus sollte für jedes Sprachenpaar funktionieren, das das Modell abdeckt; die Stoppwortlisten decken nur Englisch und Deutsch ab.
1-Bit-Vektoren mit exaktem Nachbewerten: die Entscheidung
Vektoren leben in derselben SQLite-Datei wie der Text. Jeder Chunk speichert 768 Werte als float16 für exaktes Bewerten, plus eine Kopie, die nur das Vorzeichen jeder Dimension behält, gepackt in 96 Bytes in einer sqlite-vec-Tabelle. Eine Suche fragt diese Tabelle nach den k x 16 nächsten Chunks per Hamming-Distanz, 960 Kandidaten beim Standard-k von 60, und bewertet sie dann mit exaktem Kosinus auf den float16-Vektoren neu. Fertige Einheitsvektoren als float16 zu speichern ist in Ordnung: Der Cast passiert nach der Inferenz.
Das spart keine Platte, weil beide Kopien gespeichert werden, etwa 1,6 KB pro Chunk. Es kauft Tempo. Mein README sagt 99 % identische Top-10 gegen exakte Suche bei etwa 10-fachem Tempo, ohne Skript dahinter.
Qdrant hat Zahlen für EmbeddingGemma 2 veröffentlicht (Qdrant sagt, es hatte frühen Zugang von Google DeepMind). Auf fünf Text-Retrieval-Datensätzen hielt sein 1-Bit-TurboQuant auf allen 768 Dimensionen 99 % des float32-nDCG@10 bei 30-fach kleinerem Vektor-RAM, ohne Nachbewerten. Im Absatz über seinen separaten Quora-Lauf (523.000 Dokumente) ergänzt es, dass ohne Nachbewerten etwa 74 % der Top-10-Treffer der exakten Suche entsprachen. Kürzere 256-Dimensions-Vektoren mit Nachbewerten (4-faches Oversampling) hielten 94,5 % bei 77-fach kleinerem RAM. Das ist Qdrants Quantisierer auf Text-Benchmarks, und Finers Vorzeichenbits in einem hybriden System sind ein anderer Test. Es stützt die Idee, es beweist die README-Zahl nicht.
Ich nutze keine Matryoshka-Kürzung. Die Karte unterstützt 768, 512, 256 und 128 Dimensionen und nennt die Qualität bis 256 hinunter fast verlustfrei. Finer speichert alle 768, das ist ungenutzte Reserve, keine festgehaltene Entscheidung. 256 an den eigenen Dateien zu testen und nach dem Schneiden neu zu normieren wäre der erste Schritt.
Lohnt ein Reranker? Nur bei knappen Rennen
Rangfusion führt Retrieval-Listen zusammen. Ein Reranker macht einen anderen Job: Er liest die Top-Dokumente erneut. Qwen3-Reranker-0.6B steht unter Apache 2.0. Er liest die Anfrage und ein Dokument in einem Prompt und antwortet ja oder nein, und der Score ist die Wahrscheinlichkeit von Ja. Ich betreibe eine 8-Bit-MLX-Konvertierung mit eigener Instruktion.
Mein erster Versuch mischte diese Wahrscheinlichkeit in den Retrieval-Score, über 20 Dokumente zu je 640 Token. Er brauchte etwa 3 Sekunden pro Anfrage und erreichte 0,79 Hit@1 und 0,88 MRR, unter schlichtem Hybrid mit 0,90. Die Wahrscheinlichkeiten sättigen: Die meisten plausiblen Dateien landen zwischen 0,95 und 0,999, also fügt der Rohwert Rauschen hinzu. Die Reihenfolge trug trotzdem Signal: Allein setzte der Reranker die richtige Datei etwa so oft an erste Stelle wie die hybride Suche, bei anderen Anfragen.
Also fusioniert die aktuelle Version Ränge. Ein Dokument auf Retrieval-Rang i und Reranker-Rang j bekommt 0,75 / (10 + i) + 1 / (10 + j), also gewinnt der Reranker Gleichstände. Er liest nur die Top 10, zu je 128 Token, und nur wenn der Zweite mindestens 0,8 des Ersten erreicht. Ein Kommentar im Code sagt, dass das auf dem 28-Fragen-Gold-Set etwa die Hälfte aller Anfragen überspringt, und die hybride Suche lag bei jeder übersprungenen richtig.
Ergebnis: 0,89 Hit@1, 1,00 Top-3, 0,95 MRR, für 0,25 bis 0,45 Sekunden extra, wenn er läuft, gecacht bei Wiederholung. Das sind weiter zwei Fragen, auf einem Set, auf dem ich eingestellt habe. Die App zeigt die Hybridliste sofort und sortiert einen Moment später um, wenn sich die Reihenfolge geändert hat.
Favoriten, plus ein LoRA-Finetuning des Rerankers
Wenn ich die richtige Datei für eine Anfrage bestätige, gebe ich ihr einen Stern, und für genau diese Anfrage steht sie ab dann an erster Stelle. Eine ähnliche Anfrage bekommt einen Bonus nur, wenn das gespeicherte Anfrage-Embedding Kosinus 0,90 oder mehr mit der neuen hat und die Datei ohnehin gefunden wurde. Die 0,90 stammt aus Anfrage-zu-Anfrage-Kosinuswerten in einem Codekommentar, ohne Skript dahinter: Umformulierungen einer Frage liegen bei 0,94 bis 0,99, verschiedene Fragen reichen bis 0,889. Evaluationsläufe haben Favoriten aus, also können sie sich nicht selbst benoten.
Favoriten trainieren außerdem den Reranker, mit einem LoRA-Adapter (Rang 8, letzte 16 Layer), der aus jeder markierten Anfrage gegen harte Negative lernt. Er läuft am Netzstrom, erst nach 300 Favoriten über 100 verschiedene Anfragen, und trainiert nie auf Gold-Set-Fragen. Ein Adapter wird nur übernommen, wenn gehaltene Favoriten 0,02 MRR gewinnen, kein Gold-Set mehr als 0,01 verliert und die mittlere Rerank-Zeit um höchstens 10 % wächst. Finer stellt den Reranker neu ein und lässt den Embedder in Ruhe. Ein wahrscheinlicher Grund ist, dass ein neuer Embedder heißt, jede Datei neu einzubetten; das Repo nennt keinen Grund und hat keinen Vergleich.
Der einzige festgehaltene Lauf ist eine Test-Fixture: Gehaltene Favoriten-MRR stieg um 0,113, ein Gold-Set stieg um 0,015, das andere fiel um 0,049, und die Leitplanke lehnte ab. Betrachte das Finetuning als Mechanismus mit einer Test-Fixture. Das Repo zeigt nicht, ob ein Adapter aktiv ist.
Eine Nachtschleife, die sich selbst einstellt, hinter Leitplanken
Nach dem Nachtsync baut ein Lernjob Known-Item-Fragen aus dem Index (der bereinigte Titel oder Dateiname von bis zu 150 aktuellen Dateien pro Ordner), bewertet die aktuellen Einstellungen auf vier Sets (zwei handgeschriebene Gold-Sets, die Favoriten, die Known Items mit halbem Gewicht) und probiert bis zu 39 Einstellungen auf einem kleinen Raster über sechs Regler.
Ein Kandidat wird nur übernommen, wenn die gewichtete MRR um mindestens 0,01 steigt, kein handgeschriebenes Gold-Set mehr als 0,01 MRR verliert, kein Gold-Set den Rang-1-Treffer irgendeiner Frage verliert und die Favoriten nicht schlechter werden. Jeder Lauf schreibt eine JSON-Zeile, und ein Befehl rollt die letzte Änderung zurück.
Ein zweites Gold-Set wurde geschrieben, um Generalisierung zu prüfen, aber der Nachtjob bewertet es mit, also ist es kein sauberes Hold-out, und keine Zahl dazu ist veröffentlicht. Die Gold-Sets bleiben privat, also kann niemand sonst die Tabelle reproduzieren.
KI-Agenten Zugang geben über MCP
Finer spricht MCP mit acht Werkzeugen: search, get, multi_get, similar, collections, mark_best, sync und ask. Standardmäßig sucht ein Agent in dem Ordner, der sein Arbeitsverzeichnis enthält, und ein Befehl schreibt einen Servereintrag mit Ordnerbindung in die Konfigurationen von Claude Code, Cursor, Codex, Grok und OpenCode. Mit MSE_LOCK=1 darf die Sitzung nur diesen Ordner nutzen. Alles andere wird abgelehnt, und wenn der Ordner in keiner Collection ist, schlägt jeder Aufruf fehl. Ergebnisse werden auf dem Weg hinaus erneut geprüft, und Kennungen sind standardmäßig maskiert.
Die Grenzen: Der HTTP-/mcp-Endpunkt im Dienst hat ein Token-Gate, aber keine Bindung. mark_best, das Ranking ändert, und sync, das Re-Indexieren anstößt, sind Schreibzugriffe, die ein Agent in der Bindung aufrufen kann.
Ask: wo die Cloud ins Spiel kommt
Ask ist standardmäßig aus, und solange es aus ist, wird kein Modell aufgerufen oder geladen. Wenn es an ist, sucht Finer mit dem Reranker, nimmt die beste Passage aus jedem Top-Dokument (bis zu 8 Passagen, etwa 3.000 Token) und nummeriert sie. Der Prompt sagt, nur diese Passagen zu nutzen, jede Behauptung mit [n] zu belegen und einen festen Satz zu geben, wenn sie nicht antworten.
Standardmäßig schreibt ein Cloud-Modell die Antwort, Claude, außer du wählst ein anderes. Das lokale Qwen3-4B-Instruct-2507 in 4-Bit antwortet, wenn du Lokal wählst, wenn ein Ordner im Scope Cloud ausgeschaltet hat oder, wenn du local_fallback einschaltest (standardmäßig aus), wenn kein Cloud-Modell erreichbar ist. Mit den Standards bekommt ein offline Mac oder ein Cloud-Aufruf, der vor dem ersten Token scheitert, einen Fehler und keine lokale Antwort.
Bevor etwas hinausgeht, maskieren Regex IBANs, Pass-, Ausweis-, Aufenthalts-, Steuer- und Sozialversicherungsnummern, die ihren Labelwörtern folgen, Geburtsdaten und maschinenlesbare Passzeilen. Namen und Adressen werden nicht maskiert, und die Frage geht so hinaus, wie getippt. Dateien mit nur Metadaten werden nie gelesen. Auf einem 24-Fragen-Test nannte das lokale Modell das erwartete Dokument in 15 von 17 Antworten, wo es die Passagen erreichte, gegen 14 von 17 für Qwen3.5-4B, und gab den festen Verweigerungssatz 4 von 4 Mal, gegen 0 von 4 (es verweigerte in eigenen Worten). Das ist eine winzige Stichprobe, und der Cloud-Pfad ist gegen keine Live-API vermessen.
Bremst das meinen Mac? Was der Betrieb kostet
Das sind README-Zahlen von meinem M4 Pro, außer Asks lokalem Modell, das aus den Ask-Modellnotizen stammt. Kein Skript im Repo erzeugt die README-Zahlen. Speicher ist als physischer Footprint gemessen, weil ps GPU-Puffer verpasst. Das Repo hat keinen Vergleich von Finers Last mit Spotlight.
- Der Dienst: 50 bis 170 MB, etwa 0 % CPU im Leerlauf.
- Der Text-Embedding-Worker braucht geladen etwa 0,8 GB (mit der Textkopie), der Reranker etwa 0,9 GB, schwere Arbeit 1,5 bis 2 GB. Einbetten nutzt 30 bis 50 % eines CPU-Kerns. Asks lokales Modell, gemessen: 2,46 GB geladen, 3,76 GB Spitze beim Antworten.
- Eine geänderte Datei taucht nach etwa 3,6 Sekunden auf, 3,0 davon Beruhigungszeit. Modelle entladen nach 10 Minuten ohne Arbeit, und Nachtarbeit läuft am Netzstrom mit niedriger Priorität.
- Platte: etwa 1,3 GB Modelle für eine minimale Installation, 4,4 GB für alle.
EmbeddingGemma oder Qwen3-Embedding: welches für lokale Suche?
Die Qwen3-Embedding-0.6B-Karte berichtet 64,33 auf mehrsprachigem MTEB. Google berichtet 61,36 für EmbeddingGemma 2. Die Werte stammen aus verschiedenen Karten und Daten, also ist es kein direkter Vergleich. Qwen3-Embedding-0.6B steht unter Apache 2.0 und ist nur Text, mit 32K Kontext. EmbeddingGemma 2 legt Bilder, Audio und Video in denselben 768-dimensionalen Raum. Wenn deine Dateien nur Text sind und du den höheren veröffentlichten Wert willst, teste Qwen3-Embedding-0.6B. Das Repo hält keinen Lauf davon fest, also habe ich keine Zahlen dafür auf meinen Dateien.
Was rau oder offen ist
- Nur Mac: MLX, Apple Vision, File-System-Events, textutil und launchd.
- Ein Bug in der Keyword-Suche. Der Anfragecode faltet ß zu ss, aber der FTS5-Index behält ß, also findet eine Anfrage nach "Straße" nach diesem Code nur Dokumente, die "Strasse" schreiben. Die Indexseite lässt sich mit dem Schema aus der Bauanleitung reproduzieren; der volle Pfad wurde gegen keinen echten Finer-Index geprüft. "Mueller" matcht "Müller" auch nicht.
- Kein Stemming und kein Zerlegen von Komposita, und Stoppwörter plus Spracherkennung decken nur Englisch und Deutsch ab.
- Dünne Belege: 28 Fragen, ein privater Ordner, Gewichte auf demselben Set eingestellt, keine Hold-out-Zahl, Gold-Sets und Ergebnislogs privat, kein festgehaltener Embedder-Name und keine Revision bei der Tabelle, und keine Skripte hinter den 8-Bit-, 1-Bit-, Cache-, Live-Indexing- und Speicherzahlen.
- Zwei Teile lassen sich aus dem Repo nicht reproduzieren: Es hält weder fest, wie die 320-MB-Textkopie geschnitten wurde, noch den Befehl, der den 8-Bit-Reranker von Hand konvertierte, also kann ein frisches Setup den Reranker nicht herunterladen. Der minimale Installationspfad lief auf keinem frischen Mac.
- Asks Maskierung ist nur Regex, und die Cloud-Erlaubnis pro Ordner ist standardmäßig an, sobald Ask an ist. Die App ist ad-hoc signiert, nicht notarisiert.
Was du an deinen eigenen Dateien zuerst misst
Bevor du eine meiner Einstellungen kopierst, schreib etwa 30 echte Fragen aus deinen eigenen Dateien, jede mit der Datei, die antworten sollte, und bewerte Keyword-allein, Bedeutung-allein und Hybrid daran. Halte ein paar Fragen zurück, weil Einstellen auf allen In-Sample-Zahlen wie meine gibt. Die Bauanleitung hat den Code, inklusive MRR und Hit@k.
Der Quellcode ist unter Quellen verlinkt. Bekannte Lücken, wie das Repo sie festhält: kein Rezept für die 320-MB-Textkopie und den 8-Bit-Reranker, ein Installationspfad, der auf keinem frischen Mac lief, und keine Skripte hinter den Zahlen oben. KI-Arbeit für Gründer plane ich als Meilensteine mit Evals; sieh dir an, wie ich mit Gründern arbeite. Bei Parker AI habe ich die hybride Retrieval-Schicht entworfen, mit anfragebewusstem Re-Ranking.
Häufige Fragen
Ist EmbeddingGemma Open Source, und darf ich es kommerziell nutzen?
Nur Fakten, keine Rechtsberatung. Googles Modellkarte und Launch-Post sagen Apache 2.0 für Version 2, und die Karte sagt, Deployments müssen sich an die Gemma Prohibited Use Policy halten. Version 1 nutzte die Gemma Terms of Use. Ich fand keine Google-Seite, die erklärt, wie beides zusammenpasst, also frag Google oder einen Anwalt, wenn es dein Produkt betrifft.
Wie nutzt man EmbeddingGemma?
Lade es mit sentence-transformers oder transformers, setze "task: search result | query: " vor Anfragen und "title: {title} | text: {content}" vor Dokumente, und laufe in bfloat16 oder float32, nie float16. Googles Launch-Post nennt transformers, sentence-transformers, vLLM und llama.cpp unter den Laufzeiten, also ist es nicht nur Mac; ggml-org veröffentlicht einen GGUF-Build für llama.cpp. Die Bauanleitung hat Code.
Lohnt Reranking überhaupt?
Auf meinen 28 Fragen erreichte ein Reranker, der seine Wahrscheinlichkeit in jede Anfrage einmischte, 0,88 MRR gegen 0,90 für schlichtes Hybrid. Eine Version, die nur bei knappen Entscheidungen läuft und Ränge fusioniert, erreichte 0,95. Zwischen beiden änderte sich mehreres (das Gate, die Fusion, 10 Dokumente statt 20, 128 Token statt 640), also kann ich nicht sagen, was davon gearbeitet hat. Der Gewinn sind zwei Fragen auf einem Set, auf dem die Gewichte eingestellt wurden, also teste es auf deinem.
Ist EmbeddingGemma 2 dasselbe wie Gemma 2B oder Gemini Embedding 2?
Nein. EmbeddingGemma 2 (auch embedding gemma 2 oder gemma embedding 2 geschrieben) ist ein Google-DeepMind-Embedding-Modell mit offenen Gewichten, 740 Millionen Parameter, gebaut auf Gemma 4. Gemini Embedding 2 ist ein gehostetes Modell auf Googles Gemini-API-Preisseite.
Ist Finer vollständig lokal?
Nein. Suche, Embedding, Reranking, OCR und Transkription laufen auf dem Mac. Die optionale Ask-Funktion ist standardmäßig aus. Wenn sie an ist, schreibt ein Cloud-Modell (standardmäßig Claude) die Antwort aus den Top-Treffern, mit vorher maskierten persönlichen Kennungen. Ein lokales Qwen3-4B schreibt sie nur, wenn du Lokal wählst, ein Ordner im Scope Cloud ausgeschaltet hat oder du local_fallback einschaltest (standardmäßig aus); mit den Standards bekommt ein offline Mac einen Fehler. Die Maskierung ist nur Regex: Namen und Adressen werden nicht maskiert, und die Frage geht so hinaus, wie getippt.
Quellen
- EmbeddingGemma-2-Launch-Post (Google) blog.google
- EmbeddingGemma-2-Modellkarte (Hugging Face) huggingface.co
- EmbeddingGemma-2-Modellkarte (ai.google.dev) ai.google.dev
- EmbeddingGemma-1-Modellkarte (Hugging Face) huggingface.co
- Gemma Prohibited Use Policy ai.google.dev
- mlx-community-8-Bit-Konvertierung von EmbeddingGemma 2 huggingface.co
- GGUF-Build von EmbeddingGemma 2 für llama.cpp (ggml-org) huggingface.co
- Qdrant: Wie klein wird Googles neues EmbeddingGemma 2? qdrant.tech
- Qwen3-Reranker-0.6B-Modellkarte huggingface.co
- Qwen3-Embedding-0.6B-Modellkarte huggingface.co
- Cormack, Clarke, Büttcher: Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods (SIGIR 2009) research.google
- SQLite-FTS5-Dokumentation sqlite.org
- MLX, Apples Array-Framework für Apple Silicon github.com
- OpenAI-API-Preise (Embeddings) developers.openai.com
- Gemini-API-Preise (gemini-embedding-2) ai.google.dev
- Voyage-AI-Preise docs.voyageai.com
- Finer-Quellcode github.com
Sprich mich an
Baust du ein KI-Produkt und brauchst einen Senior für die technische Seite? Buche einen gratis 30-Minuten-Call.