749 lines
47 KiB
Plaintext
749 lines
47 KiB
Plaintext
---
|
||
tags:
|
||
- Writing
|
||
aliases:
|
||
- "RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze"
|
||
cssclasses:
|
||
- table-wide
|
||
- table-wrap
|
||
authors:
|
||
- name: GPT-4.5
|
||
url: https://chatgpt.com
|
||
affiliation:
|
||
- name: OpenAI
|
||
url: https://openai.com
|
||
- name: cogito-v1-preview
|
||
url: https://www.deepcogito.com/research/cogito-v1-preview
|
||
affiliation:
|
||
- name: DeepCogito
|
||
url: https://www.deepcogito.com
|
||
- name: Claude 3.7 Sonnet
|
||
url: https://claude.ai
|
||
affiliation:
|
||
- name: Antrhopic
|
||
url: https://www.anthropic.com
|
||
- name: Nicole Dresselhaus
|
||
affiliation:
|
||
- name: Humboldt-Universität zu Berlin
|
||
url: https://hu-berlin.de
|
||
orcid: 0009-0008-8850-3679
|
||
date: 2025-04-24
|
||
categories:
|
||
- Article
|
||
- RAG
|
||
- ML
|
||
fileClass: authored
|
||
lang: de
|
||
linter-yaml-title-alias:
|
||
"RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze"
|
||
title: "RAG für eine Obsidian-Wissensdatenbank: Technische Ansätze"
|
||
bibliography:
|
||
- obsidian-rag.bib
|
||
citation-style: springer-humanities-brackets
|
||
image: ../thumbs/writing_obsidian-rag.png
|
||
---
|
||
|
||
## Hintergrund und Zielsetzung
|
||
|
||
Der Nutzer verfügt über eine Obsidian-Wissensdatenbank, in der Markdown-Dateien
|
||
mit **typisierten** Inhalten (FileClasses wie `Person`, `Projekt`, `Deliverable`
|
||
etc.) verwaltet werden. Die Notizen enthalten strukturierte **YAML-Metadaten**
|
||
(unterstützt durch Plugins wie _Metadata Menu_) und sind durch viele
|
||
**Wiki-Links** miteinander vernetzt. Standardisierte Templates (via _Templater_)
|
||
sorgen dafür, dass z.B. Personenseiten immer ähnliche Felder (Name, ORCID, etc.)
|
||
aufweisen.
|
||
|
||
**Ziel** ist es, mithilfe eines Language Models (LLM) wiederkehrende Aufgaben zu
|
||
erleichtern, zum Beispiel: automatisch YAML-Felder ausfüllen (etwa fehlende
|
||
ORCID iDs bei Personen ergänzen), neue Entitätsseiten anhand von Templates
|
||
befüllen oder sinnvolle Verlinkungen zwischen Notizen vorschlagen. Dabei reicht
|
||
ein tägliches Neu-Einlesen der Obsidian-Daten (via Cronjob o.Ä.) aus – eine
|
||
Echtzeit-Synchronisation ist optional. Die Obsidian-internen Wikilinks
|
||
(`[[...]]`) müssen im LLM-Ausgabeformat nicht unbedingt klickbar sein (es
|
||
genügt, wenn sie referenziert werden).
|
||
|
||
Um diese Funktionen umzusetzen, bieten sich verschiedene **technische Ansätze**
|
||
an. Im Folgenden werden fünf Optionen untersucht: (1) Nutzung eines
|
||
**Vektorspeichers** für semantische Suche, (2) Aufbau eines **Knowledge Graph**
|
||
aus den Notizen, (3) eine **Hybrid-Lösung** aus Graph und Vektor, (4) Extraktion
|
||
& Normalisierung der **YAML-Metadaten** und (5) existierende **Tools/Workflows**
|
||
zur Automatisierung. Jede Option wird mit Funktionsweise, Vorund Nachteilen,
|
||
Aufwand, Integrationsmöglichkeiten (insb. mit lokalen LLMs wie LLaMA, Deepseek,
|
||
Cogito etc.) sowie konkreten Tool-Empfehlungen dargestellt.
|
||
|
||
## 1. Vektorbasierter Ansatz: Semantic Search mit Embeddings
|
||
|
||
### Prinzip
|
||
|
||
Alle Markdown-Notizen (bzw. deren Inhalt) werden in kleinere Chunks zerlegt und
|
||
durch einen Embedding-Modell in hochdimensionale Vektoren umgewandelt. Diese
|
||
Vektoren werden in einem **Vektorstore** (wie ChromaDB oder Weaviate)
|
||
gespeichert. Bei Anfragen des LLM (z.B. _"Welche Projekte hat Person X?"_ oder
|
||
_"Erstelle eine neue Organisation XYZ basierend auf ähnlichen Einträgen"_),
|
||
können mittels **ähnlichkeitssuche** semantisch passende Notiz-Abschnitte
|
||
abgerufen und dem LLM als Kontext mitgegeben werden (Retrieval-Augmented
|
||
Generation).
|
||
|
||
### Implementierung
|
||
|
||
In der Praxis ließe sich z.B. ein Workflow mit **Ollama** + **Nomic
|
||
Embeddings** + **Chroma**^[Alle diese Teile laufen bereits individuell in der
|
||
Arbeitsgruppe bzw. werden schon genutzt.] aufbauen. Ollama stellt ein lokales
|
||
LLM-Serving bereit und bietet auch eine API für Embeddins
|
||
[@ollama_chroma_cookbook]. Man könnte ein spezialisiertes Embeddin-Modell wie
|
||
`nomic-embed-text` verwenden, welches kompakte 1024-dimensionale Textvektoren
|
||
liefert [@ollama_chroma_cookbook]. Die Notizen des Obsidian Vault würden per
|
||
Skript täglich eingelesen, in Sinnabschnitte (Chunks) aufgeteilt (z.B. nach
|
||
Überschriften oder einer festen Token-Länge) und über Ollamas Embedding-API in
|
||
Vektoren umgewandelt [@ollama_chroma_cookbook]. Diese Vektoren speichert man in
|
||
einer lokalen DB wie Chroma. Anfragen an das LLM werden dann zunächst an den
|
||
Vektorstore gestellt, um die relevantesten Notiz-Abschnitte zu finden, welche
|
||
dann zusammen mit der eigentlichen Frage an das LLM gegeben werden (klassischer
|
||
RAG-Pipeline). Dieses Verfahren ist vergleichbar mit dem _Smart Connections_
|
||
Obsidian-Plugin: Dort wird ebenfalls ein "Text Embedding Model" auf den Vault
|
||
angewendet, um zu einer Nutzerfrage automatisch thematisch passende Notizen zu
|
||
finden und dem LLM bereitzustellen [@smart_connections_plugin]. So konnte im
|
||
Beispiel ein lokales LLaMA-basiertes Modell Fragen zum eigenen Vault korrekt
|
||
beantworten, indem es zuvor den passenden Ausschnitt (hier: eine
|
||
Styleguide-Notiz) über Embeddings gefunden hatte [@smart_connections_plugin].
|
||
|
||
### Integration mit lokalen LLMs
|
||
|
||
Ein Vorteil dieses Ansatzes ist, dass er schon heute mit lokalen
|
||
Open-Source-LLMs funktioniert. Beispielsweise ließ sich in _Smart Connections_
|
||
ein lokal gehostetes LLaMA-Model (3B Instruct) via text-generation-webui
|
||
einbinden [@smart_connections_plugin]. Alternativ kann man auch
|
||
_LLM-as-a-service_ Tools wie **Ollama** nutzen, um ein Modell wie Llama 2
|
||
bereitzustellen. Die Open-Source-Tools **LangChain** oder **LlamaIndex** bieten
|
||
Module, um Vektorstores anzubinden und mit LLM-Abfragen zu kombinieren – dies
|
||
kann man auch mit lokal eingebundenen Modellen (z.B. über LlamaCpp oder GPT4All)
|
||
verwenden. Zahlreiche fertige Projekte demonstrieren dieses Vorgehen: z.B.
|
||
_privateGPT_ kombiniert LangChain, GPT4All (lokales LLM) und Chroma, um komplett
|
||
offline Fragen über lokale Dateien zu beantworten
|
||
[@second_brain_assistant_with_obsidian]. Auch **Khoj** verfolgt einen ähnlichen
|
||
Pfad: Es indexiert den Vault und erlaubt semantische **Natürliche Sprache
|
||
Suche** über Markdown-Inhalte sowie _"ähnliche Notizen finden"_ [@khoj_plugin].
|
||
|
||
### Leistung
|
||
|
||
Dank moderner Embedding-Modelle können semantisch ähnliche Inhalte gefunden
|
||
werden, selbst wenn die Schlagwörter nicht exakt übereinstimmen. Das löst das in
|
||
Obsidian bekannte Problem, dass die eingebaute Suche nur exakte Worttreffer
|
||
findet [@supercharging_obsidian_search]. Der Ansatz skaliert auch auf größere
|
||
Wissensbasen; Vektordatenbanken wie Weaviate oder Chroma sind für zehntausende
|
||
Einträge ausgelegt. Eine tägliche Aktualisierung ist machbar, da nur
|
||
neue/geänderte Notizen re-embedded werden müssen.
|
||
|
||
### Nachteile und Aufwand
|
||
|
||
Die Einrichtung erfordert mehrere Komponenten. Man benötigt Pipeline-Schritte
|
||
für das Chunking, Embedding und das Handling des Vektorstores – dies bedeutet
|
||
anfängliche Komplexität und Rechenaufwand [@supercharging_obsidian_search].
|
||
Insbesondere das Generieren der Embeddings kann bei großen Vaults zeitund
|
||
speicherintensiv sein (je nach Modell und Hardware)
|
||
[@supercharging_obsidian_search]. Laufende Kosten sind bei rein lokaler
|
||
Verarbeitung allerdings kein Thema außer CPU/GPU-Last. Ein potenzieller Nachteil
|
||
ist, dass rein embeddings-basierte Suche keine **strukturierte** Abfrage erlaubt
|
||
– das Modell findet zwar thematisch passende Textpassagen, aber um z.B. **eine
|
||
bestimmte Eigenschaft** (wie eine fehlende ORCID) gezielt abzufragen, müsste man
|
||
dennoch im Text suchen oder zusätzliche Logik anwenden. Das LLM kann aus den
|
||
gefundenen Texten zwar implizit Fakten entnehmen, hat aber kein explizites
|
||
Wissen über die Datenstruktur. Zudem können irrelevante Kontextstücke
|
||
eingebunden werden, wenn das semantische Matching fehlerhaft ist (dies erfordert
|
||
ggf. Feintuning der Chunk-Größe oder Filtern per Dateityp/-klasse)^[Und diese
|
||
Nachteile machen dies zu einem Deal-Breaker. Gerade in Tabellen oder
|
||
Auflistungen kann der Attention-Mechanismus der LLM schnell zu einem Mischen
|
||
oder Verwechseln von präsentierten Informationen führen. Besonders kleine Netze
|
||
(meist bis ~7b) sind hier anfällig.].
|
||
|
||
### Zusammenfassung – Ansatz 1: Vektordatenbank (Embeddings)
|
||
|
||
| | **Details** |
|
||
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| **Vorgehen** | Inhalte aller Markdown-Dateien in semantische Vektoren kodieren (z.B. mit `nomic-embed-text` ([@ollama_chroma_cookbook])) und in einer Vektor-DB speichern. LLM-Anfragen per Similarity Search mit relevantem Kontext anreichern. |
|
||
| **Stärken** | _Semantische Suche_ (findet thematisch passende Infos, nicht nur exakte Worttreffer) [@supercharging_obsidian_search]. Skaliert auf große Textmengen. Bereits heute mit lokalen LLMs erprobt (z.B. _Smart Connections_ Plugin) [@smart_connections_plugin]. Gut geeignet für Q&A, Textzusammenfassungen und Link-Vorschläge basierend auf Ähnlichkeit. |
|
||
| **Schwächen** | Komplexeres Setup (Embedding-Model + DB + Pipeline) [@supercharging_obsidian_search]. Hoher Rechenaufwand für Embeddings bei großen Vaults. Kein explizites Modell von Beziehungen/Metadaten – strukturierte Abfragen (z.B. _"zeige alle Personen ohne ORCID"_) nur mit Zusatzlogik. Kontexttreffer können ungenau sein (erfordert ggf. Feinjustierung). |
|
||
| **Integrations-Optionen** | Lokale LLM-Einbindung möglich (z.B. LLaMA 2 über Ollama-API). Tools: **ChromaDB**, **Weaviate** oder **FAISS** als Vektorstore; **LangChain/LlamaIndex** für Pipeline-Management. Obsidian-Plugins: _Smart Connections_ (komplett integriert mit lokalem Embedder+LLM) [@smart_connections_plugin]; _Khoj_ (separater Suchassistent mit Embeddings) [@khoj_plugin]. |
|
||
|
||
```{mermaid}
|
||
%%| column: screen-inset-right
|
||
graph LR
|
||
A[Obsidian Vault] --> B[Chunking]
|
||
B --> C[Embedding Model]
|
||
C --> D[(Vector Database)]
|
||
E[User Query] --> F[Query Embedding]
|
||
F --> G[Similarity Search]
|
||
D --> G
|
||
G --> H[Relevant Chunks]
|
||
H --> I[LLM]
|
||
E --> I
|
||
I --> J[Response]
|
||
```
|
||
|
||
## 2. Knowledge-Graph-Ansatz: Strukturierte Graphdatenbank
|
||
|
||
### Prinzip
|
||
|
||
Statt (oder zusätzlich zu) freiem Text wird der Informationsgehalt des Vaults
|
||
als **Graph** modelliert. Jede Notiz entspricht einem **Knoten** im Graphen (mit
|
||
Typ-Label gemäß FileClass, z.B. `Person`, `Projekt` etc.). Relationen zwischen
|
||
Notizen – implizit durch Obsidian-Wikilinks gegeben – werden zu expliziten
|
||
**Kanten** im Graph (z.B. eine Person "arbeitet in" Organisation, ein Projekt
|
||
"liefert" ein Deliverable). Auch Metadaten aus YAML können als Knoten oder
|
||
Properties modelliert werden (z.B. ORCID als Attribut eines Person-Knotens, Tags
|
||
als Relationen _"hat Schlagwort"_ usw.). Das Ergebnis ist ein **Wissensgraph**,
|
||
der ähnlich einem klassischen RDF-Triple-Store oder Neo4j-Property-Graph
|
||
komplexe Abfragen und Analysen ermöglicht.
|
||
|
||
### Erstellung des Graphen
|
||
|
||
Eine Möglichkeit ist die Obsidian-Daten nach RDF zu exportieren. So beschreibt
|
||
Pavlyshyn (2023) ein Verfahren, einen Vault ins RDF-Format zu überführen, um
|
||
"komplexe Abfragen mit klassischen Semantic-Tools" zu ermöglichen
|
||
[@export_obsidian_to_rdf]. Alternativ kann man direkt in einer Graphdatenbank
|
||
wie **Neo4j** modellieren. Ein Community-Plugin (_obsidian-neo4j-stream_) hat
|
||
beispielsweise versucht, den Obsidian-Linkgraph in Neo4j importierbar zu machen
|
||
[@export_to_common_graph_formats]. Konkret würde man pro Markdown-Datei einen
|
||
Node mit dessen YAML-Feldern als Properties anlegen. Bestehende Wiki-Links
|
||
zwischen Dateien werden als ungerichtete oder gerichtete Edges abgebildet (hier
|
||
kann man, sofern man mehr Semantik will, Link-Typen einführen – z.B. im Text
|
||
`[[Albert Einstein|Autor]]` könnte der Alias "Autor" als Kanten-Label genutzt
|
||
werden). Da Obsidian standardmäßig keine typisierten Kanten unterstützt, bleiben
|
||
Relationstypen begrenzt – Plugins wie _Juggl_ oder _Graph-Link-Types_ erlauben
|
||
allerdings das Hinzufügen von Link-Metadaten, was für eine genauere
|
||
Graph-Modellierung hilfreich sein könnte
|
||
[@personal_knowledge_graphs_in_obsidian]. YAML-Inhalte, die auf andere Notizen
|
||
referenzieren, können ebenfalls als Kanten kodiert werden (Beispiel: In einer
|
||
Projekt-Notiz listet das YAML-Feld `team:` mehrere Personen – diese Verweise
|
||
werden im Graph als Kanten _Projekt —hatTeam→ Person_ umgesetzt). Nicht
|
||
referenzielle Metadaten (etwa ein ORCID-Wert) bleiben einfach als Datenfeld am
|
||
Knoten.
|
||
|
||
### Nutzung für LLM-Aufgaben
|
||
|
||
Ein solcher Graph erlaubt **strukturierte Abfragen** und **Schlussfolgerungen**.
|
||
Für wiederkehrende Aufgaben kann man den Graph gezielt auswerten. Beispielsweise
|
||
ließen sich _"alle Personen ohne ORCID"_ mittels einer einfachen Graph-Query
|
||
ermitteln. Das LLM könnte diese Liste als Input erhalten und dann (ggf. mittels
|
||
Tools oder Wissensbasis) die fehlenden IDs ergänzen. Auch _Link-Vorschläge_
|
||
können aus dem Graph gezogen werden: Durch Graph-Analysen wie das Finden von
|
||
gemeinsamen Nachbarn oder kürzesten Pfaden entdeckt man Verbindungen, die im
|
||
Vault noch nicht als direkte Links existieren. So könnte man z.B. feststellen,
|
||
dass zwei Personen an vielen gleichen Meetings teilgenommen
|
||
haben und dem Nutzer vorschlagen, diese Personen direkt miteinander zu
|
||
verknüpfen. Oder man erkennt durch _link prediction_ Algorithmen neue mögliche
|
||
Beziehungen. Forschung und Community sehen hier großes Potential: Eine
|
||
AI-gestützte Graphanalyse kann helfen, verborgene Zusammenhänge im eigenen
|
||
Zettelkasten zu finden [@ai_empowered_zettelkasten_with_ner_and_graph_llm]. Mit
|
||
Graph-basiertem Reasoning ließe sich sogar **neues Wissen entdecken** oder
|
||
logisch konsistente Antworten generieren
|
||
[@ai_empowered_zettelkasten_with_ner_and_graph_llm,
|
||
@personal_knowledge_graphs_in_obsidian] – etwas, das rein embeddings-basierte
|
||
Ansätze so nicht leisten.
|
||
|
||
### Integration mit LLMs
|
||
|
||
Die Integration eines Graphen erfordert meist eine **Zwischenschicht**. Ein LLM
|
||
kann nicht direkt "in" einer Neo4j-Datenbank suchen, aber man kann ihm eine
|
||
Schnittstelle anbieten. Zwei Strategien sind denkbar:
|
||
|
||
1. **Verbalize & Prompt:** Informationen aus dem Graph gezielt ins Prompt
|
||
einbetten. Z.B. könnte man bei einer Frage wie "In welcher Organisation
|
||
arbeitet Alice?" erst eine Graphdatenbank-Anfrage (z.B. in Cypher oder
|
||
SPARQL) ausführen und das Ergebnis (etwa: "Alice – arbeitetBei → AcmeCorp")
|
||
in Textform dem Modell vorgeben, bevor es antwortet. Solche Abfragen könnte
|
||
ein LLM theoretisch sogar selbst generieren (LangChain bietet z.B. Agents,
|
||
die Cypher-Queries formulieren und ausführen können). Für definierte
|
||
Use-Cases kann man aber auch feste Query-Vorlagen
|
||
verwenden.
|
||
1. **LLM-in-the-Loop Graph Reasoning:** Neuere Libraries wie LlamaIndex
|
||
ermöglichen es, LLMs als Reasoner über Graphen einzusetzen. Der Graph wird
|
||
dabei intern z.B. als Tripel-Liste gehalten, und das LLM kann mittels
|
||
promptbasierter Logik Kettenschlüsse durchführen. Allerdings muss der Graph
|
||
dafür in das Prompt passen (bei sehr vielen Knoten unrealistisch) – es ist
|
||
also eher für Teilgraphen oder summarische Beziehungen geeignet^[Via 'Tool
|
||
Use' in Modernen LLM könnte das LLM selbst eine Suche auslösen und so den
|
||
Teilgraphen wählen. Aber alleine die formulierung der Suche führt dann direkt
|
||
zu dem hybriden Ansatz unten.].
|
||
|
||
Eine andere interessante Möglichkeit ist die Nutzung **graphbasierter
|
||
KI-Modelle** (Graph Neural Networks o.ä.), die aber in unserem Kontext
|
||
(persönlicher Vault) noch experimentell sind. Erwähnenswert ist z.B. MyKin.ai,
|
||
ein Projekt, das einen privaten KI-Assistenten baut, der gemeinsam mit dem
|
||
Nutzer einen persönlichen Wissensgraphen aufbaut und nutzt
|
||
[@personal_knowledge_graphs_in_obsidian]. Hier übernimmt die KI das "heavy
|
||
lifting" der Graph-Pflege, während der Nutzer chattet – ein hybrider Ansatz aus
|
||
Conversation und Graphaufbau. Für unseren Anwendungsfall wäre jedoch eher ein
|
||
statischer Graph sinnvoll, den wir periodisch aktualisieren.
|
||
|
||
### Zusammenfassung - Ansatz 2: Graphdatenbank
|
||
|
||
| | **Details** |
|
||
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| **Vorgehen** | Konvertiere Vault-Inhalte in einen strukturierten Graphen (Knoten = Notizen/Entitäten; Kanten = Obsidian-Links oder abgeleitete Relationen). Nutzen von Graph-DB (Neo4j, RDF-Store) für Abfragen und Analysen. |
|
||
| **Stärken** | Explizite **Struktur**: ermöglicht genaue Abfragen, z.B. Finde fehlende Werte oder alle Verknüpfungen eines Knotens auf einen Blick. **Logische Inferenzen** möglich (Graph Reasoning) – unterstützt Link-Empfehlungen und Konsistenzprüfungen [@ai_empowered_zettelkasten_with_ner_and_graph_llm, @personal_knowledge_graphs_in_obsidian]. Gute Ergänzung zu YAML-Typisierung: FileClass-Struktur wird vollständig nutzbar. Persistenz: Graph kann unabhängig von Obsidian analysiert, versioniert, mit anderen Daten gemappt werden (z.B. ORCID-Abgleich via externen Datensatz). |
|
||
| **Schwächen** | Erheblicher **Initialaufwand**: Datenmodell entwerfen, Export-Skripte schreiben oder Tools einrichten [@export_to_common_graph_formats]. Keine fertige Out-of-the-box-Lösung für Obsidian↔Graph (bislang nur Ansätze in der Community). Laufende Synchronisation nötig (Vault-Änderungen -> Graph-Update). Die LLM-Integration ist komplexer – erfordert Query-Tool oder das Einbetten von Graph-Daten ins Prompt. Für offene Fragen (Freitext) allein nicht ausreichend, da der Graph primär Fakten repräsentiert, nicht Fließtext. |
|
||
| **Integrations-Optionen** | **Neo4j** (mit APOC/Neosemantics für RDF-Unterstützung) eignet sich für Property-Graph-Modell; **Apache Jena** oder GraphDB für RDF-Triple-Store. _LangChain_ bietet Memory/Agent, um Wissensgraphen abzufragen (z.B. ConversationKGMemory). _LlamaIndex_ hat einen KnowledgeGraphIndex, der Tripel extrahieren und durchs LLM traversieren kann. Diese Lösungen sind aber noch experimentell. Evtl. Kombination mit Obsidian-Plugin: Ein früher Plugin-Prototyp streamte Obsidian-Daten nach Neo4j [@export_to_common_graph_formats] – dieser könnte als Ausgangspunkt dienen. |
|
||
|
||
```{mermaid}
|
||
%%| column: screen-inset-right
|
||
graph LR
|
||
A[Obsidian Vault] --> B[Entity Extraction]
|
||
A --> C[Relationship Extraction]
|
||
B --> D[Graph Construction]
|
||
C --> D
|
||
D --> E[(Graph Database)]
|
||
F[User Query] --> G[Query Parser]
|
||
G --> H[Graph Traversal]
|
||
E --> H
|
||
H --> I[Structured Facts]
|
||
I --> J[LLM]
|
||
F --> J
|
||
J --> K[Response]
|
||
```
|
||
|
||
### Fazit Graphdatenbank
|
||
|
||
Ein Wissensgraph spielt seine Stärken vor allem bei **strukturbezogenen
|
||
Aufgaben** aus. Für das automatische Ausfüllen von YAML-Feldern oder das Prüfen
|
||
von Verlinkungen ist er ideal, da solche Fragen direkte Graphabfragen
|
||
ermöglichen. Auch für neuartige Verknüpfungen (Link-Vorschläge) lässt sich ein
|
||
Graph analytisch nutzen (z.B. "Link Prediction" auf Basis von
|
||
Graph-Nachbarschaft). Allerdings ist die Umsetzung deutlich komplexer als beim
|
||
Vektorstore, und viele RAG-Anwendungsfälle (Zusammenfassungen, inhaltliche Q&A)
|
||
erfordern trotzdem den Rückgriff auf die eigentlichen Texte – was wiederum den
|
||
Vektoransatz benötigt. Daher bietet sich oft eine Kombination beider Methoden
|
||
an.
|
||
|
||
## 3. Hybrid-Ansatz: Kombination aus Graph und Vektor-RAG
|
||
|
||
Dieser Ansatz versucht, **semantische Textsuche** und **strukturierte
|
||
Graph-Abfragen** zu vereinen, um die Vorteile beider Welten auszuschöpfen. In
|
||
der Praxis gibt es mehrere Möglichkeiten, wie ein hybrides System ausgestaltet
|
||
sein kann:
|
||
|
||
- **Parallelbetrieb mit separaten Pipelines:** Vektorstore und Knowledge Graph
|
||
werden beide gepflegt. Je nach Anfrage oder Teilaufgabe wird das eine oder
|
||
andere genutzt. Beispiel: Für eine Q&A-Frage holt das System erst relevante
|
||
Text-Passagen via Vektorstore, **und** prüft zusätzlich im Graph, welche
|
||
Entitäten darin vorkommen und ruft deren Beziehungen ab. Das LLM bekäme dann
|
||
sowohl inhaltliche Ausschnitte als Kontext als auch strukturierte Fakten (z.B.
|
||
_"Alice arbeitetBei AcmeCorp"_) als Knowledge-Panel. Für die Aufgabe
|
||
_Link-Vorschläge_ könnte das System sowohl einen Embedding-Vergleich zwischen
|
||
Notizen nutzen (um thematisch ähnliche Notes zu finden), als auch den Graphen
|
||
auswerten (um strukturell nahe, aber unverbundene Knoten zu entdecken). Die
|
||
finalen Vorschläge wären die **Schnittmenge** bzw. **Union** beider Methoden –
|
||
das erhöht Präzision und Reichweite der Empfehlungen.
|
||
- **Integration innerhalb einer Datenplattform:** Moderne Vector-Datenbanken wie
|
||
_Weaviate_ erlauben es, semantische Vektorsuche mit symbolischen Filtern zu
|
||
kombinieren. Man kann Objekte (hier: Notizen) mit ihren strukturierten Feldern
|
||
in Weaviate speichern und neben dem Vektorindex auch die Metadaten abfragen.
|
||
Z.B. könnte man eine Query formulieren: _"Gib mir die 5 ähnlichsten Notizen zu
|
||
`[Text]`, die vom Typ Projekt sind und nach 2020 erstellt wurden."_ – Weaviate
|
||
würde erst nach Ähnlichkeit filtern, dann die Metadaten-Bedingungen anwenden.
|
||
So eine **hybride Suche** könnte man nutzen, um etwa bei Template-Befüllung
|
||
**nur vergleichbare Objekte** zum Prompt hinzuzufügen (z.B. nur andere
|
||
Organisationen, keine Meeting-Notizen). Auch ChromaDB arbeitet an
|
||
Feature-Filterfunktionen, die so etwas erlauben würden. Alternativ kann man
|
||
den Graphen selbst mit Vektor-Embeddings anreichern: Man könnte jedem
|
||
Knotentyp einen eigenen Vektor zuordnen, der den gesamten Inhalt der
|
||
zugehörigen Notiz(en) repräsentiert. Diese Vektoren ließen sich im Graphen als
|
||
Attribut halten und für Ähnlichkeitssuchen zwischen Knoten verwenden
|
||
(_knowledge graph embeddings_). Allerdings ist das experimentell – man müsste
|
||
z.B. bei Kanten-Traversierung dynamisch Nachbarschaftsvektoren kombinieren,
|
||
was nicht trivial ist.
|
||
- **LLM als Orchestrator:** Hier steuert das LLM, wann welcher Ansatz gezogen
|
||
wird. Beispielsweise könnte man ein System bauen, in dem das LLM zunächst
|
||
entscheidet: _"Brauche ich strukturiertes Wissen?"_ Wenn ja, könnte es per
|
||
Tool-Use einen Graph-Query durchführen (z.B. via Cypher) – eine Technik, die
|
||
mit LangChain Agents umsetzbar wäre. Danach würde es ggf. einen zweiten
|
||
Schritt machen: _"Benötige ich noch Detailinformationen oder Zitate?"_ – dann
|
||
die Vektor-Datenbank abfragen, relevante Textstücke holen, und schließlich
|
||
alles in einer konsolidierten Antwort formulieren. Dieser agentenbasierte
|
||
Ansatz ist sehr flexibel, aber auch am anspruchsvollsten in der
|
||
Implementierung (er erfordert zuverlässig trainierte/verfeinerte LLM-Prompts,
|
||
die wissen, wann und wie die jeweiligen Werkzeuge zu benutzen sind).
|
||
|
||
### Vor-/Nachteile
|
||
|
||
Die Hybridlösung verspricht **maximale Abdeckung** der Anwendungsfälle.
|
||
Strukturierte Fakten und unstrukturierte Inhalte können gemeinsam dem LLM
|
||
präsentiert werden, was sowohl präzise Faktenkenntnis als auch reichhaltigen
|
||
Kontext ermöglicht. Gerade für komplexe Aufgaben – etwa das automatisierte
|
||
Erstellen einer neuen Entitätenseite – wären wohl beide Aspekte wichtig: das LLM
|
||
müsste sich an vorhandenen ähnlichen Seiten **inhaltlich** orientieren
|
||
(Vektorsuche nach ähnlichen Organisations-Beschreibungen) und zugleich
|
||
**korrekte Verknüpfungen** setzen (Graph checken, ob z.B. die neue Organisation
|
||
bereits Personen im Vault hat, die als Mitarbeiter verknüpft werden sollten).
|
||
Ein solches System könnte also dem Nutzer sehr viel Arbeit abnehmen und dabei
|
||
konsistente, vernetzte Notizen erzeugen.
|
||
|
||
Dem steht jedoch ein hoher **Architekturund Wartungsaufwand** gegenüber. Man
|
||
muss im Grunde zwei Systeme aufbauen und aktuell halten. Zudem ist die Logik,
|
||
wie die Ergebnisse zusammenfließen, nicht trivial. Ohne gutes Design kann es
|
||
passieren, dass der Graph-Teil und der Vektor-Teil widersprüchliche oder
|
||
redundante Informationen liefern. Auch muss man Performance beachten – doppelte
|
||
Abfragen kosten mehr Zeit. In vielen Fällen mag auch ein einzelner Ansatz
|
||
ausreichen, sodass die Zusatzkomplexität nicht immer gerechtfertigt ist.
|
||
|
||
### Integrationsmöglichkeiten
|
||
|
||
Auf technischer Seite ist so ein hybrides System durchaus machbar.
|
||
Beispielsweise ließe sich **LlamaIndex** verwenden, um unterschiedliche Indexe
|
||
(VectorIndex, KnowledgeGraphIndex) zu kombinieren – es gibt Konzepte wie
|
||
"Composable Indices", mit denen man hierarchische Abfragen bauen kann. So könnte
|
||
man erst den Graph nach relevanten Knoten filtern und dann nur die zugehörigen
|
||
Dokumente vektor-suchen (oder umgekehrt). Weaviate als All-in-one-Lösung wurde
|
||
bereits erwähnt. In kleineren Umgebungen kann man auch pragmatisch vorgehen: Ein
|
||
Python-Skript, das bei bestimmten Fragen zuerst einen Neo4j-Query absetzt und
|
||
dessen Ergebnis dem LLM als Teil des Prompts voranstellt, während es parallel
|
||
eine Chroma-Query macht, wäre eine einfache implementierbare Variante.
|
||
|
||
### Zusammenfassung – Ansatz 3: Hybrid-Lösung
|
||
|
||
| | **Details** |
|
||
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| **Vorgehen** | Kombination beider Ansätze: Pflege einer Graph-Struktur **und** eines Vektorindex. Nutzung je nach Bedarf – entweder separat oder durch orchestrierte Abfragen, um sowohl strukturiertes Wissen als auch relevante Texte bereitzustellen. |
|
||
| **Stärken** | Sehr **leistungsfähig** – deckt sowohl faktische als auch kontextuelle Fragen ab. Kann die **höchste Antwortqualität** liefern (Konsistenz durch Graph-Fakten, Detail durch Textauszüge). Hilft, sowohl "Known-item" Suchen (explizite Werte) als auch "Open-ended" Suchen (Texte) zu bedienen. Für Link-Vorschläge ideal: Kombination aus semantischer Ähnlichkeit und Graph-Nachbarschaft erhöht Trefferquote sinnvoll. |
|
||
| **Schwächen** | **Sehr komplex** in Umsetzung und Wartung. Erfordert doppelte Infrastruktur. Koordination zwischen Graph und Vectorstore nötig – potenziell fehleranfällig. Höhere Latenz durch Mehrfach-Abfragen. Nur lohnend, wenn wirklich vielfältige Aufgaben automatisiert werden sollen; für rein textliche Q&A overkill. |
|
||
| **Integrations-Optionen** | Weaviate (Vectors + strukturierte Class-Properties in einem System), oder Kombination aus Neo4j + Chroma. LangChain Agents könnten Graphund Vektor-Tools parallel nutzen. **LlamaIndex** bietet experimentell kombinierbare Indizes. Workflows müssen sorgfältig entworfen werden (z.B. zuerst Graph-Query, dann Vector-Query auf Untermenge). |
|
||
|
||
```{mermaid}
|
||
%%| column: screen-inset-right
|
||
graph LR
|
||
A[Obsidian Vault] --> B[Chunking]
|
||
A --> C[Entity Extraction]
|
||
B --> D[Embedding Model]
|
||
C --> E[Graph Construction]
|
||
D --> F[(Vector Database)]
|
||
E --> G[(Graph Database)]
|
||
H[User Query] --> I[Query Embedding]
|
||
H --> J[Graph Query]
|
||
I --> K[Vector Search]
|
||
J --> L[Graph Traversal]
|
||
F --> K
|
||
G --> L
|
||
K --> M[Text Context]
|
||
L --> N[Structured Facts]
|
||
M --> O[Combined Context]
|
||
N --> O
|
||
H --> P[LLM]
|
||
O --> P
|
||
P --> Q[Enriched Response]
|
||
```
|
||
|
||
### Fazit Hybrid-Lösung
|
||
|
||
Die Hybrid-Lösung ist die **ambitionierteste**, aber auch zukunftsträchtigste
|
||
Option. Sie empfiehlt sich, wenn sowohl inhaltliche Assistenz (Texte
|
||
zusammenfassen, beantworten) als auch datenbankartige Operationen (Felder
|
||
validieren, Beziehungen auswerten) gefragt sind – was hier der Fall ist. Oft
|
||
kann man auch schrittweise vorgehen: zunächst mit einem Vektor-RAG starten
|
||
(geringerer Aufwand) und dann gezielt Graph-Features ergänzen, sobald z.B.
|
||
Link-Empfehlungen oder Konsistenzprüfungen wichtiger werden.
|
||
|
||
## 4. Datenaufbereitung: YAML-Metadaten extrahieren und normalisieren
|
||
|
||
Unabhängig vom gewählten Retrieval-Ansatz ist es essenziell, die in YAML front
|
||
matter steckenden strukturierten Informationen effektiv zu nutzen. Die
|
||
Obsidian-Plugins _Metadata Menu_ und _Templater_ stellen sicher, dass viele
|
||
wichtige Daten bereits sauber in den Notizen vorliegen (z.B. hat eine
|
||
Personenseite Felder wie `fullname`, `birthdate`, `ORCID` usw.). Ein LLM könnte
|
||
zwar theoretisch auch direkt im Markdown nach diesen Mustern suchen, aber es ist
|
||
deutlich effizienter, die Daten einmalig zu **extrahieren** und in einer
|
||
leichter nutzbaren Form vorzuhalten.
|
||
|
||
### Extraktion
|
||
|
||
Ein möglicher Schritt im täglichen Refresh ist ein Skript, das alle Dateien
|
||
durchläuft und die YAML-Blöcke parst (z.B. mit einem YAML-Parser in Python oder
|
||
JavaScript). Die extrahierten Felder können dann in eine **normale Datenbank**
|
||
(SQLite/CSV/JSON) oder direkt als Knoten/Properties in den Knowledge Graph
|
||
überführt werden. Damit erhält man z.B. eine Tabelle aller Personen mit ihren
|
||
ORCID-IDs, eine Liste aller Projekte mit Start-/Enddatum etc.
|
||
|
||
### Normalisierung
|
||
|
||
Oft müssen die Rohwerte etwas vereinheitlicht werden. Beispielsweise sollten
|
||
Datumsangaben ein konsistentes Format haben, Personennamen evtl. in
|
||
Vor-/Nachname zerlegt, und fehlende Felder explizit als `null` markiert werden.
|
||
Außerdem kann man hier foreign-key-Bezüge auflösen: Wenn z.B. im YAML einer
|
||
Publikation `author: "[[Doe, John]]"` steht, könnte das Skript erkennen, dass
|
||
dies die Person mit UID XYZ ist, und entsprechend in der extrahierten Struktur
|
||
statt des Link-Codes einen eindeutigen Verweis (auf die Person John Doe)
|
||
speichern. Diese Normalisierung erleichtert nachfolgende Analysen enorm –
|
||
insbesondere kann man einfache Regeln ableiten, die dann vom LLM geprüft oder
|
||
genutzt werden. Zum Beispiel: _"Wenn `person.ORCID` leer ist, schlage vor, ihn
|
||
zu ergänzen"_ – das kann das LLM dann direkt als Aufforderung bekommen. Oder:
|
||
_"Beim Erstellen einer neuen Person fülle Felder X,Y nach Vorlage aus"_ – hier
|
||
weiß man aus der YAML-Definition bereits, welche Felder existieren müssen.
|
||
|
||
### Nutzung durch LLM
|
||
|
||
Der aufbereitete YAML-Datensatz kann auf zwei Weisen eingebunden werden:
|
||
|
||
- **Inline im Prompt:** Für bestimmte Aufgaben kann man dem LLM direkt
|
||
Ausschnitte aus dieser strukturierten Sammlung geben. Etwa: _"In unserer
|
||
Datenbank fehlt für `Person[42]` der ORCID. Hier ist eine Liste aller
|
||
Personennamen mit ORCID, finde anhand des Namens den passenden ORCID und trage
|
||
ihn ein."_ – Falls die Person woanders erwähnt wurde, könnte das Modell es
|
||
herausfinden. (Eher unwahrscheinlich ohne Internetzugriff – ORCID erfordert
|
||
eher einen API-Call, aber zumindest könnte das LLM erkennen, _dass_ es fehlt
|
||
und ggf. den Nutzer nach der ID fragen). Für Link-Empfehlungen könnte man dem
|
||
LLM eine Liste aller Titel geben – oder besser direkt die Graph-Info wie
|
||
_"Person A und Person B haben 3 gemeinsame Projekte"_ – siehe Hybrid-Ansatz.
|
||
- **Programmatisch außerhalb des LLMs:** Viele Routineaufgaben lassen sich
|
||
erkennen, ohne das LLM zu bemühen. Man könnte einen Teil der Automatisierung
|
||
rein mit Skripten vorab erledigen. Z.B. neue Links: Ein Skript könnte alle
|
||
Personennamen im Fließtext durchsuchen und prüfen, ob sie bereits als
|
||
`[[Link]]` markiert sind; wenn nicht, die Stelle hervorheben und dem LLM als
|
||
_"Kandidat für Verlinkung"_ präsentieren. Oder bei einer neuen Organisation
|
||
könnten automatisch Felder aus externen APIs gezogen und ins Template
|
||
eingetragen werden (sofern erlaubt). Das LLM hätte dann eher die Rolle, die
|
||
zusammengestellten Infos in schönen Prosa-Text zu gießen, anstatt die Fakten
|
||
selbst zu suchen.
|
||
|
||
### Beispiel-Workflows
|
||
|
||
- YAML-Exports lassen sich mit vorhandenen Tools unterstützen. Es gibt z.B. das
|
||
Obsidian-Plugin _Dataview_, welches Abfragen auf YAML ermöglichen kann –
|
||
allerdings nur innerhalb Obsidian. Man könnte aber ein Dataview
|
||
JS-Skript^[oder Plugins wie _Dataview-Publisher_ benutzen, die die Ergebnisse
|
||
als Markdown-Tabell in ein Dokument schreiben] schreiben, das alle Einträge
|
||
eines Typs ausgibt, und diese Output-Datei dann weiterverarbeiten. Alternativ
|
||
direkt auf Dateisystemebene arbeiten: Python mit `os` und `pyyaml` kann alle
|
||
`.md` Files scannen.
|
||
- Die extrahierten Daten kann man mit dem Graph-Ansatz koppeln: etwa alle
|
||
Personen ohne ORCID als Cypher-Query generieren lassen und automatisch in eine
|
||
"ToDo"-Liste (Obsidian Note) schreiben, die vom LLM oder Nutzer geprüft wird.
|
||
- Durch Templates sind die Felder pro FileClass ja bekannt. Diese Knowledge kann
|
||
ins Prompt fließen: _"Eine Organisation hat die Felder Name, Typ,
|
||
Beschreibung, Mitarbeiter, etc. Fülle basierend auf den folgenden Infos…"_ Das
|
||
Modell weiß dann genau, welche YAML-Spalten es ausgeben soll.
|
||
|
||
### Vor- & Nachteile
|
||
|
||
Die **Vorteile** der strukturierten Extraktion liegen auf der Hand – Performance
|
||
und Präzision. Man muss nicht jedes Mal den gesamten Markdown-Text durchsuchen,
|
||
um z.B. den Wert eines bestimmten Feldes zu finden; man hat ihn direkt. Außerdem
|
||
reduziert es die Abhängigkeit vom LLM für einfache Aufgaben (Daten finden,
|
||
vergleichen). Für die meisten Menschen ist es auch leichter zu verstehen und zu
|
||
prüfen, wenn man z.B. eine CSV mit allen ORCIDs hat, als wenn man dem LLM blind
|
||
glauben muss.
|
||
Als **Nachteil** kann gesehen werden, dass es zusätzlicher
|
||
Implementierungsaufwand ist und eine gewisse Duplizierung der Daten (die
|
||
YAML-Inhalte leben dann in zwei Formen: im Markdown und in der extrahierten
|
||
Sammlung). Die Synchronisation muss bei Änderungen immer gewährleistet sein
|
||
(Cronjob). Allerdings ist das, verglichen mit dem Aufwand der LLM-Integration,
|
||
relativ gering und gut automatisierbar.
|
||
|
||
```{mermaid}
|
||
%%| column: screen-inset-right
|
||
graph LR
|
||
A[Obsidian Vault] --> B[FileClass Detection]
|
||
B --> C[Type-Specific Extraction]
|
||
C --> D[YAML Parser]
|
||
D --> E[Data Validation]
|
||
E --> F[Type Normalization]
|
||
F --> G[(Typed Collections)]
|
||
H[Task Request] --> I[Schema Lookup]
|
||
I --> J[Targeted Data Fetch]
|
||
G --> J
|
||
J --> K[Context Assembly]
|
||
H --> K
|
||
K --> L[LLM Processing]
|
||
L --> M[Schema-Aware Output]
|
||
```
|
||
|
||
### Zusammenfassung – Ansatz 4: Extraktion
|
||
|
||
In jedem Fall sollte man eine Pipeline vorsehen, die die YAML-**Metadaten
|
||
extrahiert** und in eine strukturierte Form bringt. Diese bildet das Rückgrat
|
||
für den Knowledge-Graph-Ansatz (ohne diese wären die Knoten nackte Titel ohne
|
||
Attribute) und ist auch für Vektor-RAG nützlich (z.B. als Filter oder zur
|
||
post-processing der LLM-Antworten). Insbesondere dank der FileClass-Typisierung
|
||
im Vault kann man hier sehr **zielgerichtet** vorgehen – etwa nur definierte
|
||
Entitätstypen verarbeiten. In Community-Diskussionen wurde vorgeschlagen,
|
||
YAML-Metadaten zu nutzen, um AI-Aufgaben einzuschränken: z.B. NER-Modelle nur
|
||
auf bestimmten Notizen laufen zu lassen, die laut YAML einen bestimmten Typ
|
||
haben [@ai_empowered_zettelkasten_with_ner_and_graph_llm]. Solche Optimierungen
|
||
werden durch saubere strukturelle Aufbereitung erst möglich.
|
||
|
||
## 5. Automatisierungstools und Workflows
|
||
|
||
Für die Umsetzung der oben beschriebenen Ansätze gibt es bereits einige Tools,
|
||
Projekte und Best Practices, die man nutzen oder von denen man lernen kann. Hier
|
||
eine strukturierte Übersicht samt Empfehlungen:
|
||
|
||
### Obsidian-Plugins (In-App KI-Features)
|
||
|
||
- _Smart Connections:_ Plugin, das innerhalb Obsidian mit lokalen Embeddings
|
||
arbeitet, um **ähnliche Notizen** zu finden, und einen Chatbot bereitstellt.
|
||
Es kann ein lokales LLM (oder OpenAI API) einbinden und versorgt es
|
||
automatisch mit Kontext aus dem Vault [@smart_connections_plugin]. Vorteil:
|
||
einfache Installation, enge Vault-Integration (Antworten können direkt als
|
||
Notiz eingefügt werden). Nachteil: begrenzt anpassbar – der Workflow ist
|
||
vordefiniert (hauptsächlich Q&A Chat). Für den Start aber exzellent, um ein
|
||
Gefühl für RAG im eigenen Vault zu bekommen.
|
||
- _Khoj:_ Ein Open-Source Projekt, bestehend aus einem lokalen Backend
|
||
[@khoj_plugin] und Obsidian-Plugin. Ermöglicht **natürliche Sprachsuche** und
|
||
Chat über die eigenen Notizen [@khoj_plugin]. Es kann sowohl online-Modelle
|
||
(GPT-4 etc.) als auch lokale Modelle nutzen
|
||
[@build_your_second_brain_with_khoj_ai]. Khoj fokussiert auf schnelle
|
||
semantische Suche; der Chat-Teil ist vor allem QA-orientiert. Als persönlicher
|
||
Suchassistent ist es sehr interessant – etwa um via Obsidian Command Palette
|
||
Fragen ans Vault zu stellen. Es ist weniger darauf ausgelegt, automatisch
|
||
Links zu erzeugen oder YAML zu verändern (dafür wäre wiederum ein LLM mit
|
||
Schreibrechten nötig).
|
||
- _Obsidian Copilot / GPT-Assistant:_ Es existieren mehrere Plugins, die GPT-3/4
|
||
in Obsidian integrieren (teils auch lokal via LLaMA). Diese sind im Prinzip
|
||
UI-Verbesserungen, um das LLM "im Editor" zu nutzen. Für RAG kann man sie
|
||
einsetzen, indem man manuell Kontext reinkopiert, aber automatisches Retrieval
|
||
bieten sie nicht ohne weiteres.
|
||
- _Obsidian Neo4j Plugin (Experimentell):_ Das erwähnte _obsidian-neo4j-stream_
|
||
von \@HEmile [@export_to_common_graph_formats] könnte als Ausgangspunkt
|
||
dienen, falls man die Graph-Route ausprobieren will. Es war dazu gedacht, den
|
||
Vault als kontinuierlichen Stream in Neo4j zu spiegeln. Leider wurde es nicht
|
||
fertiggestellt/maintained. Dennoch ließe sich der Code evtl. anpassen, um
|
||
zumindest einmalig einen Export durchzuführen. Alternativ: Im Obsidian-Forum
|
||
gibt es auch Beispiele, wie man mit ein paar Skriptzeilen alle Links
|
||
extrahieren kann. Zusammen mit den YAML-Daten könnte man so einen
|
||
Basic-Graphen schon bekommen.
|
||
|
||
### Externe Anwendungen / Skripte
|
||
|
||
- _LlamaIndex (GPT Index):_ Diese Python-Bibliothek ist eine **Schweizer
|
||
Taschenmesser** für RAG. Man kann Dokumente laden (Markdown wird unterstützt),
|
||
unterschiedliche Indizes erstellen (Vector, List, KnowledgeGraph etc.) und
|
||
Abfragen mit LLM orchestrieren. Sie eignet sich, um schnell Prototypen zu
|
||
bauen. Beispielsweise könnte man einen **KnowledgeGraphIndex** erstellen, der
|
||
mittels Instruct-LLM Tripel aus den Notizen extrahiert (z.B. "Person X –
|
||
arbeitet für – Organisation Y"). Anschließend kann man Abfragen in natürlicher
|
||
Sprache stellen, die vom LLM in Graph-Traversals übersetzt werden. Oder man
|
||
nutzt den simpleren VectorIndex auf Markdown-Chunks. LlamaIndex kann auch
|
||
**Komposition**: man könnte pro FileClass einen Index bauen (z.B. alle
|
||
Personen in einem VectorIndex, alle Projekte in einem anderen) und dann einen
|
||
übergeordneten Query laufen lassen. Diese Flexibilität ist mächtig – aber es
|
||
erfordert eben etwas Programmierung. Für einen produktiven Workflow (täglicher
|
||
Cronjob) müsste man ein eigenes Python-Skript schreiben, das die Indizes
|
||
aktualisiert.
|
||
- _LangChain:_ Ein Framework v.a. für komplexere Chains und Agenten. Es liefert
|
||
Bausteine, um z.B. eine Tool-using Agent zu bauen, die mit einer **Vector DB
|
||
Suche** und einer **Graph-DB Abfrage** als Tools ausgestattet ist. Damit ließe
|
||
sich ein Dialogsystem kreieren, das je nach Frage entscheidet, ob es den
|
||
Neo4j-Graph oder den Chroma-Vektorindex konsultiert. Allerdings setzt dies
|
||
einiges an Prompt Engineering voraus, damit der Agent zuverlässig
|
||
funktioniert. Alternativ kann man LangChain auch einfach nutzen, um entweder
|
||
Vector-search oder Graph-DB-Queries einzeln bequemer zu machen (es gibt z.B.
|
||
vorgefertigte Neo4j Retriever-Klassen etc.).
|
||
- _Haystack:_ Das von deepset (evtl. in der Frage mit "Deepseek" gemeint)
|
||
entwickelte Open-Source-Toolkit **Haystack** ist ebenfalls auf Dokumenten-QA
|
||
spezialisiert. Es unterstützt das Indexieren von Markdown, verschiedene
|
||
Vector-Backends und kann auch Knowledge-Graph-Komponenten integrieren. Zudem
|
||
hat es Pipeline-Knoten zum z.B. Fragenklassifizieren, dass bestimmte Fragen an
|
||
bestimmte Reader geleitet werden. Für einen produktiven Einsatz mit lokalem UI
|
||
ggf. eine Option. Allerdings eher heavy-weight und auf QA fokussiert, weniger
|
||
auf Wissensbasis-Pflege.
|
||
- _privateGPT / llama.cpp based scripts:_ Für einfache Frage-Antwort-Systeme auf
|
||
dem eigenen Vault kann man vorhandene Lösungen wie _privateGPT_ oder _GPT4All_
|
||
(mit UI) verwenden [@second_brain_assistant_with_obsidian]. Diese bringen
|
||
einen Großteil der Vector+LLM Pipeline schon fertig mit. Sie indexieren Ordner
|
||
voller Dokumente (auch Markdown) und erlauben dann Queries an ein lokales
|
||
Modell. Der Anpassungsspielraum (z.B. andere Tasks als reines QA) ist aber
|
||
gering. Als **Baseline** sind sie nützlich – man könnte damit z.B. testen, wie
|
||
gut ein LLM mit den eingebetteten Obsidian-Notizen Fragen beantwortet, und
|
||
daraus Anforderungen ableiten.
|
||
- _Basic Memory (basicmachines):_ Ein innovativer Ansatz ist hier zu erwähnen:
|
||
**Basic Memory** speichert AI-Konversationen als Markdown in Obsidian und baut
|
||
daraus sukzessive einen semantischen Wissensgraph
|
||
[@basic_memory_ai_conversations_that_build_knowledge]. D.h. wenn man mit dem
|
||
LLM chatbasiert arbeitet, erstellt das Tool automatisch Notizen und verbindet
|
||
sie (z.B. werden erkannte Entitäten verlinkt). Es ist quasi das Gegenstück zu
|
||
unserem Problem – statt einen bestehenden Vault zu nutzen, erzeugt es einen
|
||
Vault. Dennoch kann man sich dort Konzepte abschauen: z.B. wie strukturierte
|
||
Notizen aus LLM-Ausgaben generiert werden können, oder wie man
|
||
_bi-direktional_ arbeitet (User editiert Notiz, KI liest Änderungen beim
|
||
nächsten Mal). Basic Memory setzt auf lokale Dateien und betont Privatsphäre,
|
||
was dem hiesigen Anforderungsprofil ähnelt. Für die konkreten Aufgaben
|
||
(ORCID-Suche, Link-Vorschlag) liefert es zwar keine fertige Lösung, aber die
|
||
**Idee, KI beim Nutzer Notizen anlegen/ändern zu lassen,** ist hier praktisch
|
||
umgesetzt.
|
||
- **Externe APIs / Datenquellen:**
|
||
Für bestimmte Felder wie ORCID wird ein rein lokales LLM kaum die Werte
|
||
erraten können, sofern sie nicht schon irgendwo im Vault stehen. Falls
|
||
Internetzugriff eine Option ist, könnte man ein Plugin oder einen Workflow
|
||
integrieren, der **ORCID API** Abfragen durchführt (z.B. über den Namen der
|
||
Person) und die ID zurückliefert. Ein LLM-Agent könnte auch so einen API-Call
|
||
ausführen (via Tools in LangChain). Alternativ: Alle bekannten ORCID-IDs der
|
||
eigenen Personen könnte man in einer Datei sammeln; wenn das LLM eine Lücke
|
||
findet, bittet es den Nutzer um Input. Hier muss man die Limitierungen eines
|
||
LLM realistisch sehen und ggf. klassische Automatisierung (API-Skripte)
|
||
kombinieren.
|
||
|
||
```{mermaid}
|
||
%%| column: screen-inset-right
|
||
graph LR
|
||
subgraph Obsidian
|
||
A[Vault] --> B[Plugins]
|
||
B --> C[Templater]
|
||
B --> D[Metadata Menu]
|
||
B --> E[AI Assistant]
|
||
end
|
||
|
||
subgraph External Processing
|
||
A --> F[Daily Export]
|
||
F --> G[Data Processing]
|
||
G --> H[LLM Analysis]
|
||
H --> I[Automation Scripts]
|
||
end
|
||
|
||
subgraph Integration
|
||
I --> J[Change Proposals]
|
||
J --> K[User Review]
|
||
K --> L[Accepted Changes]
|
||
L --> M[Vault Updates]
|
||
M --> A
|
||
end
|
||
```
|
||
|
||
## Zusammenfassende Empfehlung
|
||
|
||
Für einen ersten Prototypen empfiehlt es sich, mit dem **Vektorstore-Ansatz
|
||
(1)** zu beginnen, da dieser am schnellsten sichtbare Erfolge bringt. Man kann
|
||
z.B. mit ChromaDB + einem lokalen LLM experimentieren, oder direkt das
|
||
Smart-Connections-Plugin ausprobieren, um ein Gefühl für semantische Suche im
|
||
Vault zu bekommen. Die YAML-Daten sollte man von Anfang an **mit-extrahieren
|
||
(4)**, da sie die Grundlage für weitere Strukturierungsmaßnahmen bilden.
|
||
Anschließend kann man gezielt **Graph-Features (2)** ergänzen: etwa den
|
||
exportierten Vault in Neo4j laden und ein paar Abfragen formulieren, um Missing
|
||
Links oder fehlende Felder aufzuspüren. Mittelfristig dürfte eine **Kombination
|
||
(3)** notwendig sein, um sowohl Inhalt als auch Struktur abzudecken – dies kann
|
||
man Schritt für Schritt angehen (z.B. zunächst Vector-RAG für inhaltliche
|
||
Fragen, und separate Tools/Reports für strukturierte Checks; später dann
|
||
Integration zu einem einheitlichen KI-Assistenten). Unterstützend sollte man
|
||
vorhandene **Tools (5)** nutzen, wo möglich – z.B. Khoj für ad-hoc Fragen, oder
|
||
LlamaIndex für schnelle Implementierung von Prototypen. Generell gilt: lokale
|
||
LLMs sind inzwischen leistungsfähig genug für solche Aufgaben, wie die genannten
|
||
Beispiele zeigen (Chat mit Vault über LLaMA etc.). Wichtig ist es, die
|
||
**Vault-Organisation** konsequent weiterzuführen (FileClasses, Templates), da
|
||
ein sauber strukturiertes Wissen die Grundlage für jede erfolgreiche RAG-Lösung
|
||
ist – egal ob Vektor, Graph oder hybrid.
|
||
|
||
## Quellen
|
||
|
||
Die Analyse basiert auf aktuellen Erkenntnissen aus der Obsidian-Community und
|
||
KI-Fachwelt, u.a. Erfahrungen mit semantischer Suche
|
||
[@smart_connections_plugin], Diskussionen zu Knowledge Graphs in PKM
|
||
[@ai_empowered_zettelkasten_with_ner_and_graph_llm] und Berichten über lokale
|
||
RAG-Implementierungen [@local_free_rag_with_question_generation,
|
||
@smart_connections_plugin].
|
||
|
||
## Methodik / LLMs als 'Autoren' {.appendix}
|
||
|
||
Erstellt wurde der initial draft mittels Websuche und "Deep-Research" von
|
||
`gpt-4.5 (preview)`. Systematische Überarbeitungen (Extraktion Bibliographie,
|
||
Überarbeitung Metadaten) mittels `cogito-v0.1` im Editor. Übernahme nach
|
||
manueller Prüfung. Erstellung der Mermaid-Diagramme mittels `Claude 3.7 Sonnet`.
|
||
Abschließendes Korrekturlesen/inhaltliche Prüfung/Layouting
|
||
durch Nicole Dresselhaus.
|