CommunityBildgithub.com

claudejaune/gemma-embed-search

Indizieren Sie einen Ordner mit Bildern, Audiodateien oder Texten mit einem lokalen multimodalen Embedding-Modell und durchsuchen Sie ihn in natürlicher Sprache. Erstellt einen wiederaufnehmbaren Vektorindex über jeden OpenAI-kompatiblen /v1/embeddings-Server, der multimodale Inhalte akzeptiert, wie z. B. llama.cpp's llama-server mit EmbeddingGemma 2, und ordnet dann Dateien nach semantischer Ähnlichkeit mit Farbfilterung, Multi-Facetten-AND-Abfragen, JSON-Ausgabe und HTML-Kontaktbogen…

Was ist gemma-embed-search?

Gemma Embed Search ist ein Skill, der es ermöglicht, lokale Dateien (Bilder, Audio, Text) anhand ihrer Bedeutung zu durchsuchen. Er verwendet ein lokales multimodales Embedding-Modell, das auf der Hardware des Benutzers läuft, sodass keine Daten hochgeladen werden. Der Skill erstellt einen Vektorindex, der Dateien in einem einzigen Embedding-Raum repräsentiert und ermöglicht natürliche Sprachabfragen. Er unterstützt fortschrittliche Funktionen wie Farbfilterung (basierend auf Pixelfarben, nicht auf Textkontext), Multi-Facetten-AND-Verknüpfungen mit `--must` und `--also`, sowie die Ausgabe als JSON oder als HTML-Kontaktbogen mit eingebetteten Miniaturansichten. Der Skill ist für die Verwendung mit OpenAI-kompatiblen Servern konzipiert, insbesondere solchen, die das EmbeddingGemma 2-Modell ausführen (z. B. llama.cpp). Er bietet eine schrittweise Einrichtung, bei der zunächst die Serververbindung getestet (`doctor`), die Konfiguration gespeichert (`init`), der Index erstellt (`index`) und dann die Suche durchgeführt wird (`search`). Der Index ist inkrementell und wiederaufnehmbar, was ihn für große Dateimengen geeignet macht.

Funktioniert mit✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/claudejaune/gemma-embed-search/tree/HEAD

Installed? Explore more Bild skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Gemma Embed Search

Lokale Dateien nach ihrer Bedeutung finden. Ein einziger Embedding-Raum enthält Bilder, Audio und Text, sodass eine Texteingabe die passenden Bilder, Clips oder Dokumente zurückgibt. Das Modell läuft auf der Hardware des Benutzers über einen lokalen Server; es wird nichts hochgeladen.

scripts/embed_search.py erledigt vier Aufgaben: doctor prüft den Server, init speichert die Verbindung, index bettet Dateien in einen Cache ein und search ordnet sie nach einer Abfrage.

Lokale Konfiguration

Die Einstellungen befinden sich in config.json, niemals in dieser Datei:

  • Linux und macOS: ~/.config/gemma-embed-search/config.json
  • Windows: %USERPROFILE%\.config\gemma-embed-search\config.json

Lesen Sie diese Datei zuerst. Wenn sie url und model enthält, funktioniert jeder spätere Befehl ohne Verbindungsflags und Sie können Schritt 2 überspringen.

Wenn sie fehlt oder unvollständig ist, fragen Sie den Benutzer nach der Server-URL und dem zu indizierenden Ordner, führen Sie doctor aus, um die Modelle aufzulisten, die der Server tatsächlich anbietet, und führen Sie dann init aus, um die Datei zu schreiben. init führt eine Zusammenführung durch, daher ist das Hinzufügen einer Einstellung nach der anderen sicher. Raten Sie niemals einen Modellnamen.

Das Kopieren von config.example.json aus diesem Ordner in diesen Pfad und das Bearbeiten erledigt dieselbe Arbeit wie init, für einen Benutzer, der die Datei lieber direkt bearbeiten möchte. Fügen Sie "api_key" nur dort hinzu, wenn der Server einen benötigt.

Speichern Sie Einstellungen niemals im Skill-Ordner selbst. Ein Update des Skills ersetzt jede Datei darin, und alles, was dort geschrieben wurde, geht verloren.

Einrichtungs-Checkliste

Fortschritt:

  • Schritt 1: Server bestätigen und Modellnamen auswählen (doctor)
  • Schritt 2: Verbindung speichern (init)
  • Schritt 3: Einen Pilotdurchlauf mit 20 Dateien indizieren und eine Abfrage überprüfen
  • Schritt 4: Den gesamten Ordner indizieren
  • Schritt 5: Die eigentliche Abfrage des Benutzers beantworten, mit --html, damit er die Treffer sehen kann

Überspringen Sie Schritt 2, wenn config.json bereits url und model enthält.

Führen Sie das Skript mit uv run scripts/embed_search.py aus (installiert Pillow über die Inline-Metadaten des Skripts) oder python3 scripts/embed_search.py, wenn Pillow bereits importierbar ist.

Schritt 1 — Server und Modellname finden. Raten Sie niemals den Modellnamen; lesen Sie ihn vom Server ab.

uv run scripts/embed_search.py --url http://127.0.0.1:1235 doctor

doctor zeigt die Modelle an, die der Server anbietet, und testet ein Embedding. Wenn der Benutzer noch keinen Server gestartet hat, lesen Sie references/setup.md und geben Sie ihm den Befehl für sein Modell.

Schritt 2 — Speichern, damit spätere Aufrufe keine Flags benötigen. Übergeben Sie --api-key nur, wenn der Server einen benötigt; es wird mit Modus 0600 in die Konfigurationsdatei geschrieben. Übergeben Sie --root bei jedem späteren Befehl, um mit einem anderen Ordner zu arbeiten, ohne das Gespeicherte zu ändern.

uv run scripts/embed_search.py --url http://127.0.0.1:1235 --model <name-from-doctor> init --root <folder>
uv run scripts/embed_search.py index --limit 20

Schritt 3 — Pilot vor dem langen Lauf. Die Indizierung ist der teure Schritt: ungefähr 0,25 s pro Bild auf einer Desktop-GPU, also dauern 10.000 Dateien etwa 40 Minuten. Indizieren Sie 20 Dateien, führen Sie eine Abfrage aus und bestätigen Sie, dass die Ergebnisse richtig aussehen, bevor Sie sich auf den vollständigen Durchlauf festlegen.

Schritt 4 — Vollständige Indizierung. Ein erneuter Aufruf von index bettet nur neue oder geänderte Dateien ein, sodass ein unterbrochener Lauf von selbst fortgesetzt wird.

uv run scripts/embed_search.py index

Schritt 5 — Suchen.

uv run scripts/embed_search.py search "ein schwarzer Labrador am Strand" --top 20 --html hits.html

Abfragen-Kochbuch

AbsichtBefehl
Einfache semantische Suchesearch "ein belebter Nachtmarkt"
Zwei Facetten, die beide zutreffen müssensearch "eine Frau" --must "die Farbe Gelb"
Synonyme, damit eine Formulierung nicht dominiertsearch "eine Frau" --also "ein Mädchen" --also "weibliches Porträt"
Jedes Bild finden, das X enthältsearch "Charaktere mit roten Haaren" --top 60 --html hits.html
Subjekt plus eine echte Farbbeschränkungsearch "eine Frau" --color gelb --min-color 0.05
Hauptsächlich monochrome oder dunkle Bildersearch "beliebiges Bild" --max-color blau --modality image
Nur eine Dateiartsearch "Sirenengeräusche" --modality audio
Maschinenlesbar für weitere Arbeitsearch "..." --json --top 50
Schneller, etwas weniger genaue Bewertungsearch "..." --dims 256

--also mittelt Paraphrase-Vektoren zu einer Abfrage. --must behält die Punktzahl der schwächsten Facette bei, so drücken Sie UND aus. Verwenden Sie --also für Synonyme und --must für unabhängige Bedingungen.

Ausgabe lesen

Die normale Ausgabe ist score [modality] path, beste zuerst. Farbläufe fügen das Pixelverhältnis nach der Punktzahl ein. --json gibt {"query", "index", "total", "filtered_out", "results": [{"rank", "score", "color", "modality", "path"}]} auf stdout aus; alle Fortschrittsmeldungen gehen nach stderr, sodass stdout immer sauber in jq weitergeleitet werden kann.

Cosinus-Ähnlichkeitswerte dieser Modellfamilie liegen zwischen etwa 0,3 und 0,8. Die absolute Zahl bedeutet wenig; der Unterschied zwischen Treffern und Nicht-Treffern ist wichtig. Wenn die Spitze der Liste falsch ist, ist die Abfrage falsch — formulieren Sie sie neu, anstatt der Rangfolge zu vertrauen. Präsentieren Sie niemals eine lange Liste als gleich gut: nennen Sie, wo die sicheren Ergebnisse aufhören und das Raten beginnt.

Eine kurze Liste ist nicht die ganze Antwort. Jede indizierte Datei erhält eine Punktzahl, daher sagt die total in der Ausgabe die Größe des gesamten Korpus aus, sagt aber nie, wie viele Ergebnisse plausibel sind. Finden Sie stattdessen den Abgrund — den Punkt, an dem die Punktzahlen nicht mehr stark fallen. Wenn die Liste, die Sie gezeigt haben, vorher endet, sagen Sie, dass die Ergebnisse abgeschnitten sind, und bieten Sie einen längeren Durchlauf an: ein größeres --top kostet nur einen weiteren Kontaktbogen, keine erneute Indizierung. Respektieren Sie eine vom Benutzer genannte Anzahl und geben Sie immer noch den von Ihnen angewandten Grenzwert an. Behaupten Sie niemals "es gibt keine", ohne eine erweiterte Liste, --top 100 oder mehr, die tatsächlich jemand angesehen hat.

Für die visuelle Überprüfung bieten Sie immer --html an: es schreibt einen Kontaktbogen mit Miniaturansichten, Punktzahlen und Dateinamen, den der Benutzer in einem Browser öffnen kann. Ein bloßes --html schreibt hits.html im Arbeitsverzeichnis; --html FILE legt den Pfad fest. Miniaturansichten werden als Base64 eingebettet, sodass der Bogen in sich geschlossen ist und allein reisen kann. Der Bogen bettet echte Miniaturansichten der gefundenen Dateien ein, behandeln Sie ihn daher als Kopie dieses Teils der Bibliothek: halten Sie ihn aus der Versionskontrolle und allem, was Sie weiterleiten, heraus. Sie sind standardmäßig 512 Pixel breit; erhöhen Sie --thumb-width für eine genaue Untersuchung von Details.

Fallstricke

  • Ein Farbwort im Abfragetext ist ein weicher Hinweis, kein Filter. "eine Frau mit einem gelben Thema" ordnet eine Frau in einer orangefarbenen Jacke an erster Stelle. Verwenden Sie --color gelb --min-color 0.05 für eine echte Einschränkung; sie wird aus Pixeln berechnet, nicht aus dem Modell.
  • Ein Stilwort ist ebenfalls ein weicher Hinweis und ein noch schwächerer. "eine fotorealistische Frau mit roten Haaren" ordnet eine Tintenzeichnung einer rothaarigen Frau an erster Stelle, weil die Subjektnomen den Stil überwiegen. Verschieben Sie den Stil in --must, damit er als eigene Facette bewertet wird, und fixieren Sie das visuelle Attribut mit --color. Keines ist ein echter Filter: --must nimmt das Minimum über Facetten hinweg, daher wird durch starkes Drücken auf eine Facette die andere aufgegeben.
  • Mehrere Subjekte in einem Bild verschmelzen zu einem einzigen Vektor, daher schneidet das Bild bei einer Einzelsubjekt-Abfrage schlechter ab als ein Bild, das diesem Subjekt gewidmet ist: ein Porträt einer rothaarigen Frau neben einem Mann kann bei einer Suche nach "Frau mit roten Haaren" weit unten landen, während es bei "Charaktere mit roten Haaren" nahe der Spitze rangiert. Synonyme derselben einzelnen Idee helfen nicht; die Plural- oder Kollektivform hilft. Erweitern Sie --top, wenn die Frage "finde alles, was X enthält" lautet.
  • --color benötigt, dass der Index Farbstatistiken enthält, die nur index berechnet. Ein Index, der mit einer älteren Version erstellt wurde, meldet 0,0 für alles: Indizieren Sie mit --force neu, wenn die Farbfilterung stillschweigend jede Datei ausschließt.
  • Index und Abfrage müssen dasselbe Modell verwenden. Ein Wechsel von --model mischt stillschweigend inkompatible Vektoren; indizieren Sie nach jeder Modelländerung mit --force neu und notieren Sie das Modell in stats.
  • Der Server muss das Embedding-Modell mit Mean-Pooling und geladenem Vision-Projektor (--mmproj) ausführen. Ohne den Projektor schlagen Bildanforderungen fehl oder geben einen Vektor zurück, der das Bild ignoriert. doctor beweist, dass Text funktioniert; führen Sie eine Bildabfrage aus, um die Bildverarbeitung zu beweisen.
  • Bilder werden als JPEG mit einer längsten Seite von 1536 neu codiert, bevor sie gesendet werden. Die Neucodierung ist erforderlich, nicht kosmetisch: Server lehnen häufig WebP, 16-Bit oder falsch beschriftete Dateien ab, und Pillow liest diese stattdessen. Das Modell hat kein Pixel-Limit — der Server tastet jedes Bild auf ein festes Vision-Token-Budget um — daher tauscht --resize Upload-Größe gegen Genauigkeit, nicht Korrektheit. Gemessene Zahlen und die Details finden Sie in references/setup.md.
  • HEIC- und Raw-Kameraformate werden nicht gelesen, es sei denn, Pillow wurde mit dem entsprechenden Plugin erstellt. Das Skript protokolliert skip <file>: cannot identify image file und fährt fort; überprüfen Sie skipped_errors in der Indexzusammenfassung, anstatt von vollständiger Abdeckung auszugehen.
  • search in einem Ordner, der nie indiziert wurde, beendet sich mit Exit-Code 4 und einer Meldung. Behandeln Sie eine leere Ergebnisliste nicht als "keine Treffer", bis die Indexanzahl in stats korrekt aussieht.
  • Audio ist durch den Serverkontext begrenzt: etwa 5,5 Minuten pro Clip bei 25 Token pro Sekunde. Längere Dateien schlagen als Anforderungsfehler fehl, nicht als schlechter Treffer.
  • Punktzahlen sind nicht über verschiedene Korpora oder Quantisierungen hinweg vergleichbar. Versprechen Sie niemals einen Schwellenwert; stimmen Sie --min-color und --top auf das ab, was der Benutzer sieht.

Skript-Referenz

doctor                       Server prüfen, Modelle auflisten, ein Embedding testen
init [--root DIR]            url, model, key und Standard-Root in der Konfigurationsdatei speichern
index   --root DIR           Neue und geänderte Dateien einbetten (inkrementell, fortsetzbar)
        [--modality auto|image|audio|text] [--include '*.png,sub/*.jpg']
        [--exclude-dir node_modules,.git] [--limit N] [--batch 16] [--resize 1536]
        [--force] [--compact]
search  "Abfrage"            Indizierte Dateien bewerten; gibt Punktzahl, Modalität, Pfad aus
        [--also P]... [--must P]... [--color NAME --min-color F | --max-color F]
        [--modality image] [--dims 512|256|128] [--top 20] [--offset 0]
        [--json] [--html [FILE]] [--thumb-width 512]
stats                        Eintragsanzahl, Modalitätsmix, Modell, Indexgröße

Exit-Codes: 0 Erfolg, 2 Anwendungsfehler, 3 Server nicht erreichbar oder Authentifizierung abgelehnt, 4 Index fehlt, 5 nichts zu tun, 6 Serverfehler während des Laufs. Führen Sie scripts/embed_search.py <command> --help für die vollständige Flag-Dokumentation aus.

Die Konfigurationsauflösung ist Flag > Umgebung (EMBED_SEARCH_URL, EMBED_SEARCH_MODEL, EMBED_SEARCH_API_KEY, EMBED_SEARCH_ROOT) > Konfigurationsdatei unter ~/.config/gemma-embed-search/config.json. Der Index standardmäßig auf ~/.cache/gemma-embed-search/<folder>-<hash>.jsonl, ein JSON-Datensatz pro Datei, daher ist es sicher, mehrere Indizes für verschiedene Ordner zu führen.

Weitere Details

Verwandte Skills