moritz conjé
Projektmanagement
Kommunikation & Konzeption
T-Shaped Professional

Notizblog

Homelab: Beiträge rund um Aufbau und Betrieb meines eigenen Homelabs:
von Hardware und Netzwerk bis zu selbst gehosteten Diensten und smarter Haussteuerung.
Eigene Lösungen statt fertiger Anbieter, mit allem Basteln und Lernen, das dazugehört.

Remote Claude nutzt LiteLLM
Im Beitrag über das Gateway habe ich einen zentralen Zugang gebaut, über den KI-Werkzeuge die Suche und das Regelwerk meines Second Brains erreichen. Zwei Wochen später fiel mir auf, dass ihn noch niemand benutzte. Den Anstoß gab etwas ganz anderes: ...
Eine eigene Statuszeile fürs Terminal: mehr Überblick bei der Arbeit mit Claude Code
Wer täglich mit einer KI im Terminal arbeitet, kennt das Problem: Wie ausgelastet die laufende Sitzung gerade ist, wie nah man an ein Nutzungslimit kommt oder was sie bereits gekostet hat, bleibt normalerweise unsichtbar. Man merkt es meist erst, wen ...
Fähigkeiten ergänzen: passende Skills für die Rollen und Aufgaben finden
Ein KI-Assistent kann schon ohne Erweiterungen erstaunlich viel. Für ein konkretes Projekt reicht „erstaunlich viel" aber selten als Arbeitsweise. Beim Aufbau des Second Brain kamen zuletzt drei sehr unterschiedliche, eigenständige Projekte zusammen: ...
Mehr Zusammenhang für die Suche: Wie Wikilinks und Arbeitssitzungen zu Graph-Signalen werden

Mit der Freigabe war die Suche nach Bedeutung fertig, und inzwischen läuft sie auch im Alltag über das Gateway. Offen blieb ein Gedanke, der seit dem Projektstart im Raum stand: Eine Suche nach Ähnlichkeit erkennt, welche Notizen sich inhaltlich ähneln. Sie weiß aber nicht, welche Notizen zusammengehören. Dieser Teil beschreibt, wie ich der Suche drei zusätzliche Signale für den Zusammenhang gegeben habe. Zwei davon sind heute fest im Ablauf der KI-Rollen verankert, das dritte läuft bewusst noch ungenutzt mit. Unterwegs hat mich ein Filter, den ich selbst eingeführt hatte, fast um das beste Ergebnis gebracht.

Kurz zur Erinnerung

Mein Second Brain ist eine Sammlung von Notizen zu Links, Artikeln, Videos und Büchern. KI-Agenten mit festen Rollen arbeiten darin, allen voran ein Redakteur, der neue Notizen einordnet und mir Vorschläge zur Freigabe macht.

Damit er dafür nicht jedes Mal alles neu lesen muss, gibt es VectorSearch, eine Bedeutungssuche: Sie sucht nicht nach übereinstimmenden Stichwörtern, sondern nach inhaltlicher Ähnlichkeit. Dafür wird jede Notiz in eine Zahlenreihe übersetzt, einen Vektor oder auch Embedding, und ähnliche Themen liegen rechnerisch nah beieinander. Im Review-Gate habe ich diese Suche freigegeben.

Warum ein Graph?

Ein Graph ist in der Informatik ein Netz aus Knoten und Kanten. Die Knoten sind hier die Notizen, die Kanten die Verbindungen zwischen ihnen. Der Unterschied zu VectorSearch lässt sich an einem Beispiel zeigen: Eine Notiz über ein Video zur Heimautomation und die Projektnotiz, in der ich daraus etwas umgesetzt habe, klingen oft völlig verschieden. Die eine beschreibt ein Konzept, die andere Konfigurationsschritte. Rechnerisch liegen sie weit auseinander. Trotzdem gehören sie zusammen, und das weiß ich, weil ich sie verknüpft habe.

Solche Verbindungen hinterlassen Spuren, die sich auswerten lassen. Drei davon habe ich nacheinander als eigene Signale aufgebaut:

  • Verweise: Welche Notiz zeigt per Link auf welche andere? Das ist die Vaultmap.
  • Arbeitssitzungen: Welche Notizen wurden in derselben Sitzung gemeinsam bearbeitet? Das ist der Change-Graph.
  • Suchverhalten: Welche Notizen tauchen immer wieder gemeinsam in denselben Suchergebnissen auf? Das ist der Search-Graph.

Die ersten beiden bilden ab, was ich selbst getan habe. Das dritte entsteht aus der Nutzung des Systems.

Signal 1: Die Verweise im Wiki

Das Wiki arbeitet mit Wikilinks, also Verweisen, mit denen eine Notiz direkt auf eine andere zeigt. Die naheliegende Idee: Jeder Verweis wird eine Kante. Bevor ich das umsetzte, stand eine Designfrage im Raum. Sollen Kanten zu jedem Verweisziel entstehen oder nur zu Zielen, die auch selbst im Suchbestand liegen?

Statt zu schätzen, habe ich nachgezählt. Im Suchbestand fanden sich 9.735 Verweise. Fast die Hälfte davon, 4.979, zeigte gar nicht auf Inhalte, sondern auf zwei Kategorienlisten aus der Zeit vor dem Umzug aus Notion. Dort dienten Verweise als Ersatz für Schlagwörter, einzelne Kategorien wurden über 300-mal angesteuert. Ein Graph mit diesen Kanten hätte riesige Knotenpunkte erzeugt, die fast alles mit fast allem verbinden und damit nichts aussagen.

Die Lösung war eine einfache Regel: Eine Kante entsteht nur, wenn das Ziel selbst im Suchbestand liegt. Damit fallen die Kategorienlisten automatisch heraus, ohne sie einzeln ausschließen zu müssen. Übrig blieben 3.174 Kanten. Technisch ist das deutlich günstiger als der Rest der Suche: Die Verweise werden einfach aus dem Text gelesen, ein Embedding ist nicht nötig. Die Auswertung läuft im bestehenden nächtlichen Aktualisierungslauf mit, und ein neues Werkzeug für die Agenten liefert zu jeder Notiz ihre Nachbarn. Eine Stichprobe bestätigte das Ergebnis: Eine bekannte Themen-Notiz lieferte genau ihre sechs dokumentierten Quellnotizen zurück.

Signal 2: Was gemeinsam bearbeitet wurde

Für das zweite Signal gibt es eine naheliegende Quelle. Jede Arbeitssitzung im Wiki endet mit einem Eintrag im Arbeitsprotokoll, einer Tabelle, in der steht, was getan wurde und welche Notizen betroffen waren. Tauchen zwei Notizen im selben Eintrag auf, liegt eine Verbindung nahe.

Die erste Auswertung war ernüchternd: nur 23 brauchbare Kanten aus 3 von 88 Sitzungen. Als Ergänzung prüfte ich Zeitstempel als zweite Quelle, also die Frage, welche Notizen am selben Tag geändert wurden. Auch das führte ins Leere. Das Datenfeld für das Änderungsdatum fehlt in 96 Prozent des Bestands, und die Zeitstempel des Dateisystems zeigten über 1.100 Dateien, die an einem einzigen Tag verändert wurden. Das war erkennbar ein technischer Massenvorgang und keine echte Arbeitssitzung. Das Signal schien nicht zu tragen.

Der eigene Filter als blinder Fleck

Der Fehler lag nicht in den Zeitstempeln, sondern schon in den 23 Kanten. Die Auswertung hatte die Verweise im Arbeitsprotokoll auf den Suchbestand beschränkt, also auf dieselbe Regel, die bei den Wiki-Verweisen richtig gewesen war. Der KI-Assistent, mit dem ich das umsetze, hatte sie unbemerkt auf eine andere Datenquelle mit einem anderen Zweck übertragen. Mir fiel es erst bei einer Rückfrage auf: Das Arbeitsprotokoll dokumentiert vor allem Arbeit an Infrastruktur und Projekten, kaum an den gesammelten Notizen selbst. Der Filter hatte also fast die gesamte Substanz der Quelle entfernt, bevor sie überhaupt geprüft wurde.

Ohne die übernommene Einschränkung, über das ganze Wiki mit rund 12.600 Dateien gerechnet, wurden aus 23 Kanten 367 Kanten aus 65 von 88 Sitzungen. Die Knotenpunkte waren plausibel: Die am häufigsten gemeinsam bearbeitete Notiz ist eine konkrete Rollendefinition eines Agenten, kein Sammelbegriff. Auch dieses Signal läuft seitdem im nächtlichen Lauf mit und hat ein eigenes Werkzeug. Die Zeitstempel blieben ungenutzt, das Protokoll allein trägt bereits.

Die Lehre daraus ist für mich die wichtigste der ganzen Graph-Erweiterung: Ein Filter, der an einer Stelle die richtige Entscheidung war, kann an der nächsten zur unbemerkten Fehlerquelle werden. Er muss für jeden neuen Zusammenhang neu begründet werden. Mit einem KI-Assistenten passiert so etwas leicht, weil er gute Entscheidungen konsequent weiterverwendet. Die Rückfrage, warum eine Einschränkung hier gilt, bleibt meine Aufgabe.

Vom Bereitstehen zum Benutzen

Zwei Tage lang liefen beide Signale im Hintergrund, ohne dass eine Rolle sie aufrief. Technisch hätte jede Sitzung die Werkzeuge nutzen können, verlässlich tat es keine. Für die Anbindung gab es zwei Wege:

  • Verschmelzen mit der Suche: Die Suche würde ihre Treffer bei jeder Anfrage automatisch mit den Graph-Nachbarn kombinieren. Das wirkt überall, greift aber tief in ein gerade erst freigegebenes System ein.
  • Gezielter Einsatz pro Rolle: Einzelne Rollen bekommen in ihrer Beschreibung einen zusätzlichen Arbeitsschritt, der das passende Werkzeug aufruft. Das ist risikoarm, wirkt aber nur dort, wo es eingetragen ist.

Vor der Entscheidung stand wieder ein Test, diesmal mit umgekehrtem Vorzeichen. Beim Test der Stichwortsuche im Review-Gate war die Frage, ob ein vermutetes Problem wirklich auftritt. Jetzt ging es darum, ob eine echte Chance verpasst wird. Ich nahm acht zufällige Paare aus Notiz und verlinktem Ziel, genau den Fall, den der Redakteur beim Einordnen braucht, und stellte die Notiz als Anfrage an VectorSearch. In sechs von acht Fällen tauchte das verlinkte Ziel nicht unter den ersten zehn Treffern auf, auch nicht, als ich statt des Titels den vollen Notizinhalt als Anfrage verwendete. Die Verweise enthalten also Wissen, das VectorSearch allein nicht findet.

Beim Vorbereiten desselben Tests für die Arbeitssitzungen dann die nächste Überraschung: Die Tabelle enthielt nur noch 6 statt 367 Kanten. Ursache war ein stiller Fehler beim Einlesen des Arbeitsprotokolls. Das Programm las eine feste Spaltenposition, und seit die Tabelle eine Spalte mehr hatte, griff es auf eine meist leere Reservespalte zu. Nur wenige Zeilen lieferten zufällig noch etwas, deshalb gab es nie einen Totalausfall und keine Fehlermeldung, nur einen leisen Schwund. Nach der Korrektur liest das Programm die Spalten über die Überschriftenzeile aus und ist damit robust gegen künftige Änderungen. Die Tabelle kam auf 372 Kanten, nahe am ursprünglichen Wert. Der anschließende Test ergab ein gemischtes, aber positives Bild: klare, nicht offensichtliche Treffer bei Projekten, daneben Rauschen durch Notizen, die nur zufällig am selben Tag mitbearbeitet wurden.

Die Entscheidung fiel auf den gezielten Einsatz pro Rolle. Der Redakteur nutzt beim Einordnen neuer Notizen zusätzlich die Wiki-Verweise, der Prozess-Agent kann vor einer Entscheidung nachsehen, was in der Vergangenheit gemeinsam mit einer Notiz bearbeitet wurde. Beides ist als Kann-Schritt formuliert, nicht als Pflicht, und führt zu Vorschlägen, nicht zu automatischen Entscheidungen. Das Verschmelzen mit der Suche war für die Arbeitssitzungen ohnehin ausgeschlossen: Deren Kanten reichen ins ganze Wiki, VectorSearch kennt aber nur den Second-Brain-Bereich.

Ein drittes Signal: der Search-Graph

Mit zwei Signalen im Einsatz lag die Anschlussfrage nahe: Gibt es eines, das nicht aus meinem eigenen Handeln stammt? Die Idee kommt von Suchmaschinen, die aus dem Klickverhalten ihrer Nutzer lernen. Übertragen heißt das: Notizen, die bei vielen verschiedenen Anfragen immer wieder gemeinsam unter den Treffern auftauchen, gehören vermutlich zusammen, auch wenn niemand sie verknüpft hat.

Anders als bei den ersten beiden Signalen gibt es dafür keine Vergangenheit, die sich auswerten ließe, denn frühere Suchanfragen wurden nicht gespeichert. Der Graph muss bei null anfangen. Der Aufwand war dafür gering: Bei jeder Suche werden alle Paare aus den Treffern gespeichert, und jedes erneute gemeinsame Auftauchen erhöht das Gewicht der Kante. Schlägt das Speichern fehl, läuft die Suche trotzdem normal weiter. Zwei identische Testanfragen bestätigten die Logik: Der erste Lauf erzeugte 28 Kanten aus acht Treffern, der zweite erhöhte alle Gewichte korrekt. Die Testkanten habe ich danach wieder gelöscht, damit der Graph nur aus echter Nutzung wächst.

Gebaut, aber bewusst nicht verdrahtet

Die Reihenfolge ist diesmal umgekehrt: erst bauen, dann den Bedarf prüfen. Der Bau war billig genug, und ohne ihn entsteht nie eine Datenbasis. Die Anbindung an die Rollen habe ich dagegen zurückgehalten, aus zwei Gründen:

  • Die bisherige Testfrage passt nicht. Bei den Wiki-Verweisen war der Test einfach: Findet VectorSearch eine verlinkte Notiz von allein? Wenn nicht, liefert der Verweis etwas Neues. Beim Search-Graph funktioniert dieser Test nicht, denn eine Kante entsteht dort nur, wenn VectorSearch beide Notizen bereits gemeinsam gefunden hat. Der Test würde also immer bestätigen, dass VectorSearch die Verbindung schon kennt, und damit nichts über den Nutzen aussagen. Es braucht eine andere Prüffrage, und die ist noch offen.
  • Eine zu frühe Anbindung verfälscht die Daten. Die ersten Kanten stammen sonst aus Test- und Entwicklungsanfragen statt aus echter Arbeit.

Beim Schreiben dieses Beitrags umfasst der Search-Graph 66 Kanten, nur 4 davon wurden mehr als einmal bestätigt. Als Arbeitsschwelle für einen sinnvollen Test habe ich rund 15 mehrfach bestätigte Kanten festgelegt. Das Wachstum ist langsam, weil nicht jede Arbeitsumgebung die Suche bisher überhaupt aufrufen konnte. Diese Lücke ist inzwischen geschlossen.

Fazit

VectorSearch findet Ähnliches, die drei Graph-Signale ergänzen sie um Zusammenhang: was ich verknüpft habe, was ich gemeinsam bearbeitet habe und was die Suche selbst immer wieder zusammen findet. Zwei davon sind durch Tests belegt und fest in den Rollen verankert, das dritte sammelt noch Daten.

Über die ganze Serie zieht sich eine Arbeitsweise, die auch hier jede Entscheidung geprägt hat: erst nachzählen, dann entscheiden. Das Nachzählen hat die Kategorienlisten aus den Wiki-Verweisen gefiltert, den stillen Einlesefehler aufgedeckt und gezeigt, dass Verweise Wissen enthalten, das VectorSearch allein nicht findet. Die Graph-Erweiterung fügt eine zweite Lehre hinzu: Auch eine gute Regel muss für jeden neuen Zusammenhang neu begründet werden.

Ausblick

Mit diesem Teil endet die Serie über den Aufbau der VectorSearch erst einmal. Offen bleibt die neue Prüffrage für den Search-Graph, die nicht darauf beruht, ob VectorSearch eine Verbindung verpasst. Sie steht an, sobald genug echte Nutzung gesammelt ist, und mit ihr die Entscheidung, ob das dritte Signal einen festen Platz in den Rollen bekommt.