Semantische Suche unvollständig: Vektorindex (ChromaDB) nur zu ~14 % / ~58 % gefüllt — mtime-Skip verhindert Nachholung #196

Closed
opened 2026-10-27 12:34:42 +00:00 by alf · 2 comments
Owner

Verschoben aus alf/2ndbrain#119 (falsches Repo — die Index-Skripte gehören zu Iris).

Problem

Die semantische Suche (RAG) im Vault und in der Chat-Historie liefert nur einen Bruchteil der möglichen Treffer, weil der Vektorindex (ChromaDB) deutlich kleiner ist als der Volltextindex (SQLite/FTS5). Gemessen am 2026-10-27 auf dem Produktivsystem:

Index SQLite (Volltext) ChromaDB (Vektoren) Abdeckung
Vault (RAG) 7.022 Notizen 1.001 Notizen / 3.136 Chunks ~14 %
Chats + Workspaces (Memory) 31.493 Einträge 18.192 Chunks ~58 %

Auswirkungen im Live-Test

  • Vault: semantische Suche nach «flash-attn CUDA-Mismatch Dockerfile Build Abbruch» liefert thematisch falsche Treffer (Wing-Commander-III-Anleitungen, Patreon-Mails) mit für semantische Treffer untypisch hohen Abständen (0.14–0.17) — die tatsächlich passende Notiz (CLAUDE.md im Vault-Root) ist in SQLite indiziert, aber nicht im Vektorindex.
  • Chat: funktioniert subjektiv, aber ~42 % der Einträge sind für die semantische Suche unsichtbar.
  • Embedding-Modell ist korrekt konfiguriert und aktiv (mlx-community/multilingual-e5-large, lokal, MLX).

Wahrscheinliche Ursache

Der inkrementelle Index-Lauf ueberschreibt die SQLite-Zeile neu, ueberspringt das Embedding aber, wenn sich die Datei seit dem letzten Lauf nicht geaendert hat (mtime-Vergleich). Damit war der Vektorindex einmal weg (geloescht bzw. ein --full-Lauf abgebrochen), bauen sich die Vektoren fuer alle unveraenderten Notizen nie wieder auf.

Bestaetigt im Test: index --area "00 Kontext" meldet indexed: 1, unchanged: 9 — die Vektorabdeckung in dem Ordner bleibt danach bei 2 von 12 Notizen.

Der GUI-Button «Neu aufbauen» (Einstellungen -> Vault Wartung -> RAG-Index / Memory-Index) ruft korrekt index --full auf — er ist als Workaround geeignet, aber nicht die Wurzelbehebung.

Erwartetes Verhalten

Ein inkrementeller Index-Lauf erkennt, wenn zu einer als indiziert gefuehrten Datei kein Vektor im ChromaDB-Store existiert, und holt das Embedding nach — unabhaengig vom mtime-Status. Der Index heilt sich also selbst, statt dauerhaft unvollstaendig zu bleiben.

Reproduction

  1. ChromaDB-Store loeschen (oder die Situation eines abgebrochenen --full-Laufs nachstellen).
  2. Inkrementellen Index-Lauf ausloesen (Vault-Wartung oder index ohne --full).
  3. Chunk-Zahl im Vektorstore mit der Notiz-/Eintragszahl in SQLite vergleichen — sie bleibt weit darunter.

Vorschlag

  • Beim inkrementellen Laufen die vorhandenen Vektor-IDs gegen die SQLite-Eintraege pruefen und fehlende Embeddings nachziehen (Selbstheilung).
  • Optional: In den Stats (Einstellungen -> Vault Wartung) Abdeckung als Verhaeltnis anzeigen (Vektor-Chunks vs. erwartete Chunks), damit eine solche Drift sofort sichtbar ist — eine Notiz erzeugt mehrere Chunks, die Chunk-Zahl muss also ueber der Notiz-Zahl liegen.
> Verschoben aus https://forgejo.lewerken.duckdns.org/alf/2ndbrain/issues/119 (falsches Repo — die Index-Skripte gehören zu Iris). ## Problem Die semantische Suche (RAG) im Vault und in der Chat-Historie liefert nur einen Bruchteil der möglichen Treffer, weil der Vektorindex (ChromaDB) deutlich kleiner ist als der Volltextindex (SQLite/FTS5). Gemessen am 2026-10-27 auf dem Produktivsystem: | Index | SQLite (Volltext) | ChromaDB (Vektoren) | Abdeckung | |---|---|---|---| | Vault (RAG) | 7.022 Notizen | 1.001 Notizen / 3.136 Chunks | ~14 % | | Chats + Workspaces (Memory) | 31.493 Einträge | 18.192 Chunks | ~58 % | ## Auswirkungen im Live-Test - Vault: semantische Suche nach «flash-attn CUDA-Mismatch Dockerfile Build Abbruch» liefert thematisch falsche Treffer (Wing-Commander-III-Anleitungen, Patreon-Mails) mit für semantische Treffer untypisch hohen Abständen (0.14–0.17) — die tatsächlich passende Notiz (CLAUDE.md im Vault-Root) ist in SQLite indiziert, aber nicht im Vektorindex. - Chat: funktioniert subjektiv, aber ~42 % der Einträge sind für die semantische Suche unsichtbar. - Embedding-Modell ist korrekt konfiguriert und aktiv (mlx-community/multilingual-e5-large, lokal, MLX). ## Wahrscheinliche Ursache Der inkrementelle Index-Lauf ueberschreibt die SQLite-Zeile neu, ueberspringt das Embedding aber, wenn sich die Datei seit dem letzten Lauf nicht geaendert hat (mtime-Vergleich). Damit war der Vektorindex einmal weg (geloescht bzw. ein --full-Lauf abgebrochen), bauen sich die Vektoren fuer alle unveraenderten Notizen nie wieder auf. Bestaetigt im Test: index --area "00 Kontext" meldet indexed: 1, unchanged: 9 — die Vektorabdeckung in dem Ordner bleibt danach bei 2 von 12 Notizen. Der GUI-Button «Neu aufbauen» (Einstellungen -> Vault Wartung -> RAG-Index / Memory-Index) ruft korrekt index --full auf — er ist als Workaround geeignet, aber nicht die Wurzelbehebung. ## Erwartetes Verhalten Ein inkrementeller Index-Lauf erkennt, wenn zu einer als indiziert gefuehrten Datei kein Vektor im ChromaDB-Store existiert, und holt das Embedding nach — unabhaengig vom mtime-Status. Der Index heilt sich also selbst, statt dauerhaft unvollstaendig zu bleiben. ## Reproduction 1. ChromaDB-Store loeschen (oder die Situation eines abgebrochenen --full-Laufs nachstellen). 2. Inkrementellen Index-Lauf ausloesen (Vault-Wartung oder index ohne --full). 3. Chunk-Zahl im Vektorstore mit der Notiz-/Eintragszahl in SQLite vergleichen — sie bleibt weit darunter. ## Vorschlag - Beim inkrementellen Laufen die vorhandenen Vektor-IDs gegen die SQLite-Eintraege pruefen und fehlende Embeddings nachziehen (Selbstheilung). - Optional: In den Stats (Einstellungen -> Vault Wartung) Abdeckung als Verhaeltnis anzeigen (Vektor-Chunks vs. erwartete Chunks), damit eine solche Drift sofort sichtbar ist — eine Notiz erzeugt mehrere Chunks, die Chunk-Zahl muss also ueber der Notiz-Zahl liegen.
Author
Owner

PR #120 gemergt: fix(rag): Index heilt sich selbst — unveränderte Dateien ohne Vektor werden nachgebettet (iris/Iris#196)
alf/2ndbrain#120

Commits:

  • fix(rag): Index heilt sich selbst — unveränderte Dateien ohne Vektor werden nachgebettet (iris/Iris#196)

Stand: Selbstheilung des Vektorindex

Befund: Bestätigt im Code. cmd_index übersprang unveränderte Dateien allein per mtime-Vergleich gegen SQLite, ohne zu prüfen, ob ChromaDB Chunks dazu hält.

Geändert:

  • skills/obsidian-rag/obsidian.py: Der inkrementelle Lauf liest vorab die Notiz-IDs aus ChromaDB (_vectorised_ids). Eine Notiz mit unveränderter mtime wird nur übersprungen, wenn sie dort vorkommt; sonst wird sie neu eingebettet. Die Antwort enthält healed.
  • skills/memory/memory.py: gleiche Prüfung für Kernquellen (Chats, Workspaces) und Plugin-Quellen.
  • --full und der Fall ohne ChromaDB / mit nicht lesbarem Store verhalten sich wie vorher.

Geprüft:

  • index --area "00 Kontext" auf dem Produktivvault: erster Lauf healed: 8, 15 Chunks; zweiter Lauf healed: 0, chunks_embedded: 0. Das passt zum Befund (vorher 2 von 12 Notizen im Ordner mit Vektoren).
  • _vectorised_ids gegen eine Attrappe mit 12.000 Einträgen (Seitenweise Lesen) und mit None.
  • Beide Dateien kompilieren.

Nicht geprüft:

  • memory.py mit echten Daten (nur Syntax).
  • Ein voller inkrementeller Lauf über den ganzen Vault (~6.000 Notizen) und über Chats/Workspaces; Laufzeit unbekannt.
  • Notizen ohne Text erzeugen keine Chunks und werden bei jedem Lauf neu geparst (nicht eingebettet).

Offen: Optionale Abdeckungsanzeige (Vektor-Chunks gegen erwartete Chunks) in den Stats der Vault-Wartung ist nicht gebaut.

PR #120 gemergt: fix(rag): Index heilt sich selbst — unveränderte Dateien ohne Vektor werden nachgebettet (iris/Iris#196) https://forgejo.lewerken.duckdns.org/alf/2ndbrain/pulls/120 Commits: - fix(rag): Index heilt sich selbst — unveränderte Dateien ohne Vektor werden nachgebettet (iris/Iris#196) --- ## Stand: Selbstheilung des Vektorindex **Befund:** Bestätigt im Code. `cmd_index` übersprang unveränderte Dateien allein per mtime-Vergleich gegen SQLite, ohne zu prüfen, ob ChromaDB Chunks dazu hält. **Geändert:** - `skills/obsidian-rag/obsidian.py`: Der inkrementelle Lauf liest vorab die Notiz-IDs aus ChromaDB (`_vectorised_ids`). Eine Notiz mit unveränderter mtime wird nur übersprungen, wenn sie dort vorkommt; sonst wird sie neu eingebettet. Die Antwort enthält `healed`. - `skills/memory/memory.py`: gleiche Prüfung für Kernquellen (Chats, Workspaces) und Plugin-Quellen. - `--full` und der Fall ohne ChromaDB / mit nicht lesbarem Store verhalten sich wie vorher. **Geprüft:** - `index --area "00 Kontext"` auf dem Produktivvault: erster Lauf `healed: 8`, 15 Chunks; zweiter Lauf `healed: 0`, `chunks_embedded: 0`. Das passt zum Befund (vorher 2 von 12 Notizen im Ordner mit Vektoren). - `_vectorised_ids` gegen eine Attrappe mit 12.000 Einträgen (Seitenweise Lesen) und mit `None`. - Beide Dateien kompilieren. **Nicht geprüft:** - `memory.py` mit echten Daten (nur Syntax). - Ein voller inkrementeller Lauf über den ganzen Vault (~6.000 Notizen) und über Chats/Workspaces; Laufzeit unbekannt. - Notizen ohne Text erzeugen keine Chunks und werden bei jedem Lauf neu geparst (nicht eingebettet). **Offen:** Optionale Abdeckungsanzeige (Vektor-Chunks gegen erwartete Chunks) in den Stats der Vault-Wartung ist nicht gebaut.
alf closed this issue 2026-10-27 16:37:04 +00:00
Author
Owner

PR #210 gemergt: chore(skills): memory (Plugin-Quellen) und obsidian-rag (Selbstheilung, #196) aus dem Quellbaum übernommen
#210

Commits:

  • chore(skills): memory (Plugin-Quellen) und obsidian-rag (Selbstheilung, #196) aus dem Quellbaum übernommen
PR #210 gemergt: chore(skills): memory (Plugin-Quellen) und obsidian-rag (Selbstheilung, #196) aus dem Quellbaum übernommen https://forgejo.lewerken.duckdns.org/iris/Iris/pulls/210 Commits: - chore(skills): memory (Plugin-Quellen) und obsidian-rag (Selbstheilung, #196) aus dem Quellbaum übernommen
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
iris/Iris#196
No description provided.