--- doc_type: concept audience: architect, developer scope: architecture, design_patterns, modularization status: active version: 2.9.1 context: "Architektur-Patterns, Design-Entscheidungen und modulare Struktur von Mindnet. Basis für Verständnis und Erweiterungen." --- # Architektur-Patterns & Design-Entscheidungen Dieses Dokument beschreibt die zentralen Architektur-Patterns und Design-Entscheidungen, die Mindnet prägen. Es dient als Referenz für Entwickler und Architekten, um das System zu verstehen und konsistent zu erweitern. ## 1. Kern-Paradigmen ### 1.1 Filesystem First (Source of Truth) **Prinzip:** Markdown-Dateien im Vault sind die einzige Quelle der Wahrheit. Die Datenbank (Qdrant) ist ein abgeleiteter Index. **Implikationen:** - Dateien werden immer direkt von der Festplatte gelesen (z.B. im Editor) - Datenbank-Inhalte können aus Markdown rekonstruiert werden - Änderungen erfolgen primär im Vault, nicht in der DB - Die Datenbank ist ein Cache, kein primärer Speicher **Code-Beispiele:** - `ui_callbacks.py`: Liest Dateien direkt von Disk - `ingestion_processor.py`: Schreibt zuerst auf Disk, dann in DB ### 1.2 Late Binding (Späte Semantik) **Prinzip:** Struktur und Interpretation werden in Konfigurationen definiert, nicht im Code. **Implikationen:** - Neue Note-Typen werden in `types.yaml` definiert, nicht im Code - Prompt-Templates sind in `prompts.yaml` konfigurierbar - Edge-Typen werden in `edge_vocabulary.md` verwaltet - Die "Persönlichkeit" ist Config, kein Code **Vorteile:** - Erweiterbarkeit ohne Code-Änderungen - A/B-Testing von Prompt-Strategien - Anpassung an verschiedene Use-Cases ### 1.3 Virtual Schema Layer **Prinzip:** Markdown-Dateien benötigen nur minimale Frontmatter-Angaben. Komplexität wird zur Laufzeit injiziert. **Beispiel:** ```yaml # Minimal im Frontmatter --- id: 20250101-test title: Test type: project --- # Im Code wird zur Laufzeit ergänzt: # - chunking_profile aus types.yaml # - retriever_weight aus types.yaml # - edge_defaults aus types.yaml ``` **Vorteile:** - Robuste Markdown-Dateien (weniger Breaking Changes) - Zentrale Verwaltung von Logik - Einfache Migration zwischen Versionen --- ## 2. Modulare Architektur (WP-14) ### 2.1 Paket-Struktur Seit WP-14 ist die Core-Logik in spezialisierte Pakete unterteilt: ``` app/core/ ├── chunking/ # Text-Segmentierung │ ├── chunking_strategies.py # Sliding/Heading-Strategien │ ├── chunking_processor.py # Orchestrierung │ └── chunking_propagation.py # Edge-Vererbung ├── database/ # Qdrant-Infrastruktur │ ├── qdrant.py # Client & Config │ └── qdrant_points.py # Point-Mapping ├── graph/ # Graph-Logik │ ├── graph_subgraph.py # Expansion │ └── graph_weights.py # Scoring ├── ingestion/ # Import-Pipeline │ ├── ingestion_processor.py # Two-Pass Workflow │ └── ingestion_validation.py # Mistral-safe Parsing ├── parser/ # Markdown-Parsing │ ├── parsing_markdown.py # Frontmatter/Body │ └── parsing_scanner.py # File-Scan └── retrieval/ # Suche & Scoring ├── retriever.py # Orchestrator └── retriever_scoring.py # Mathematik ``` ### 2.2 Design-Pattern: Proxy-Adapter (Abwärtskompatibilität) **Problem:** Nach WP-14 Modularisierung müssen alte Import-Pfade weiter funktionieren. **Lösung:** Proxy-Module leiten Anfragen an neue Pakete weiter. **Beispiel:** ```python # app/core/retriever.py (Proxy) from .retrieval.retriever import ( Retriever, hybrid_retrieve, semantic_retrieve ) __all__ = ["Retriever", "hybrid_retrieve", "semantic_retrieve"] ``` **Vorteile:** - Keine Breaking Changes für bestehenden Code - Graduelle Migration möglich - Alte Scripts funktionieren weiter ### 2.3 Design-Pattern: Singleton (Edge Registry) **Problem:** Edge Registry muss konsistent über alle Services sein. **Lösung:** Singleton-Pattern mit Lazy Loading. **Code:** ```python # app/services/edge_registry.py class EdgeRegistry: _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance ``` **Vorteile:** - Einheitliche Validierung - Keine Duplikation von Vokabular-Daten - Thread-safe Initialisierung --- ## 3. Asynchrone Verarbeitung ### 3.1 Background Tasks Pattern **Problem:** Ingestion kann lange dauern (LLM-Calls, Embeddings). Blockiert API nicht. **Lösung:** FastAPI Background Tasks für non-blocking Verarbeitung. **Flow:** 1. API empfängt Request (`/ingest/save`) 2. Datei wird sofort auf Disk geschrieben 3. API antwortet mit `status: "queued"` 4. Background Task startet Ingestion asynchron 5. User kann weiterarbeiten **Code:** ```python @router.post("/save") async def save_note(req: SaveRequest, background_tasks: BackgroundTasks): # Sofortige Persistenz write_to_disk(req.markdown_content) # Async Processing background_tasks.add_task(run_ingestion_task, ...) return SaveResponse(status="queued", ...) ``` **Vorteile:** - Keine Timeouts bei großen Dateien - Bessere User Experience - System bleibt responsiv ### 3.2 Traffic Control (Semaphore Pattern) **Problem:** Parallele LLM-Calls können System überlasten. **Lösung:** Semaphore begrenzt parallele Hintergrund-Tasks. **Code:** ```python # app/services/llm_service.py background_semaphore = asyncio.Semaphore( settings.BACKGROUND_LIMIT # Default: 2 ) async def generate(...): if priority == "background": async with background_semaphore: return await _call_llm(...) else: # realtime return await _call_llm(...) # Keine Limitierung ``` **Vorteile:** - Schutz vor API-Quoten-Überschreitung - Stabiler Betrieb bei hoher Last - Priorisierung von Echtzeit-Anfragen --- ## 4. Resilienz-Patterns ### 4.1 Provider-Kaskade (Fallback-Kette) **Problem:** Cloud-Provider können ausfallen oder Quoten überschreiten. **Lösung:** Dreistufige Kaskade mit intelligentem Fallback. **Stufen:** 1. **Cloud (OpenRouter/Gemini):** Schnell, aber abhängig von Provider 2. **Rate-Limit-Handling:** Automatische Retries bei HTTP 429 3. **Lokaler Fallback (Ollama):** Langsam, aber immer verfügbar **Code:** ```python # app/services/llm_service.py async def generate(...): try: return await _call_cloud(...) except RateLimitError: await asyncio.sleep(LLM_RATE_LIMIT_WAIT) return await _call_cloud(...) # Retry except Exception: return await _call_ollama(...) # Fallback ``` **Vorteile:** - Hohe Verfügbarkeit - Kostenoptimierung (Cloud für Speed, Lokal für Fallback) - Resilienz gegen Provider-Ausfälle ### 4.2 Deep Fallback (Kognitiver Fallback) **Problem:** Cloud liefert technisch erfolgreiche, aber inhaltlich leere Antworten (Silent Refusal). **Lösung:** Validierung der Antwort-Qualität, nicht nur HTTP-Status. **Code:** ```python response = await _call_cloud(...) if is_valid_json(response): return response else: # Deep Fallback: Cloud hat blockiert, lokaler Fallback return await _call_ollama(...) ``` **Vorteile:** - Erkennung von Policy-Violations - Datenintegrität trotz Cloud-Filter - Lokale Souveränität --- ## 5. Datenfluss-Patterns ### 5.1 Two-Pass Workflow (WP-15b) **Problem:** Smart Edge Validation benötigt globalen Kontext (alle Notizen). **Lösung:** Zwei-Phasen-Import mit Pre-Scan. **Pass 1: Pre-Scan** - Schnelles Scannen aller Dateien - Aufbau von `LocalBatchCache` (IDs, Titel, Summaries) - Keine LLM-Calls **Pass 2: Semantic Processing** - Nur für geänderte Dateien - Binäre Validierung gegen Cache - Effiziente Nutzung von LLM-Quoten **Vorteile:** - Reduktion von LLM-Calls (nur Validierung, keine Extraktion) - Konsistente Validierung (globaler Kontext) - Schnellerer Import ### 5.2 Idempotenz-Pattern **Prinzip:** Mehrfache Imports derselben Datei führen zum gleichen Ergebnis. **Mechanismen:** - **Deterministische IDs:** UUIDv5 basierend auf Datei-Inhalt - **Hash-basierte Change Detection:** Multi-Hash für `body` und `full` - **Deduplizierung:** Kanten werden anhand Identität erkannt **Code:** ```python # Deterministische ID note_id = uuid.uuid5(NAMESPACE_URL, f"{file_path}#{content_hash}") # Change Detection if current_hash == stored_hash: skip_processing() # Idempotent ``` **Vorteile:** - Sicherheit bei Re-Imports - Keine Duplikate - Konsistente Datenbank --- ## 6. Frontend-Patterns ### 6.1 Active Inspector Pattern **Problem:** Graph-Re-Renders bei Knoten-Selektion führen zu Flackern. **Lösung:** CSS-Klassen statt State-Änderungen für Selektion. **Code:** ```python # ui_graph_cytoscape.py stylesheet = [ { "selector": ".inspected", "style": {"border-width": 6, "border-color": "#FFC300"} } ] # Selektion ändert nur CSS-Klasse, nicht React-Key ``` **Vorteile:** - Stabiles UI (kein Re-Render) - Bessere Performance - Smooth User Experience ### 6.2 Resurrection Pattern **Problem:** Streamlit vergisst Eingaben bei Re-Runs. **Lösung:** Aggressive Synchronisation in `session_state`. **Code:** ```python # ui_editor.py if widget_key not in st.session_state: st.session_state[widget_key] = restore_from_data_key() ``` **Vorteile:** - Texteingaben überleben Tab-Wechsel - Keine Datenverluste - Bessere UX --- ## 7. Erweiterbarkeit: "Teach-the-AI" Paradigma Mindnet lernt durch **Konfiguration**, nicht durch Training. ### 7.1 Drei-Ebenen-Erweiterung **1. Daten-Ebene (`types.yaml`):** ```yaml risk: retriever_weight: 0.90 edge_defaults: ["blocks"] ``` **2. Strategie-Ebene (`decision_engine.yaml`):** ```yaml DECISION: inject_types: ["value", "risk"] ``` **3. Kognitive Ebene (`prompts.yaml`):** ```yaml risk_definition: ollama: "Ein Risiko ist eine potenzielle Gefahr..." ``` **Vorteile:** - Keine Code-Änderungen nötig - Schnelle Iteration - A/B-Testing möglich --- ## 8. Design-Entscheidungen & Trade-offs ### 8.1 Qdrant als Vektor-DB **Entscheidung:** Qdrant statt Pinecone/Weaviate **Gründe:** - Self-hosted (Privacy First) - Open Source - Gute Performance bei lokaler Installation **Trade-off:** Mehr Wartungsaufwand als Managed Service ### 8.2 Hybrid Retrieval (Semantik + Graph) **Entscheidung:** Kombination von Vektor-Suche und Graph-Expansion **Gründe:** - Semantik findet ähnliche Inhalte - Graph findet strukturelle Verbindungen - Kombination liefert bessere Relevanz **Trade-off:** Höhere Komplexität, mehr Berechnungsaufwand ### 8.3 Background Tasks statt Queue-System **Entscheidung:** FastAPI Background Tasks statt Redis/RabbitMQ **Gründe:** - Einfacher Setup (keine zusätzliche Infrastruktur) - Ausreichend für Single-User-Szenario - Weniger Moving Parts **Trade-off:** Keine Persistenz bei Server-Neustart (Tasks gehen verloren) --- ## 9. Konsistenz-Garantien ### 9.1 Deterministische IDs **Prinzip:** UUIDv5 basierend auf Datei-Inhalt **Vorteile:** - Reproduzierbare IDs - Keine Duplikate bei Re-Import - Graph ist aus Markdown rekonstruierbar ### 9.2 Provenance-Hierarchie **Prinzip:** Kanten haben Qualitätsstufen (explicit > smart > rule) **Vorteile:** - Menschliche Intention hat Vorrang - System-Heuristiken können überschrieben werden - Transparente Gewichtung --- ## 10. Weitere Informationen - **Vision & Strategie:** Siehe [Vision & Strategie](../00_General/00_vision_and_strategy.md) - **Graph-Logik:** Siehe [Graph-Logik](02_concept_graph_logic.md) - **KI-Persönlichkeit:** Siehe [KI-Persönlichkeit](02_concept_ai_personality.md) - **Developer Guide:** Siehe [Developer Guide](../05_Development/05_developer_guide.md) --- **Letzte Aktualisierung:** 2025-01-XX **Version:** 2.9.1