mindnet/docs/03_Technical_References/AUDIT_CLEAN_CONTEXT_V4.2.0.md

8.9 KiB

Audit: Informations-Integrität (Clean-Context v4.2.0)

Datum: 2026-01-10
Version: v4.2.0
Status: Audit abgeschlossen - KRITISCHES PROBLEM IDENTIFIZIERT

Kontext

Das System wurde auf den Gold-Standard v4.2.0 optimiert. Ziel ist der "Clean-Context"-Ansatz: Strukturelle Metadaten (speziell > [!edge] Callouts und definierte Note-Scope Zonen) werden aus den Text-Chunks entfernt, um das semantische Rauschen im Vektor-Index zu reduzieren. Diese Informationen müssen stattdessen exklusiv über den Graphen (Feld explanation im QueryHit) an das LLM geliefert werden.

Audit-Ergebnisse

1. Extraktion vor Filterung (Temporal Integrity) ⚠️ TEILWEISE

✅ Note-Scope Zonen: FUNKTIONIERT

Status: ✅ KORREKT

  • build_edges_for_note() erhält markdown_body (Original-Markdown) als Parameter
  • extract_note_scope_zones() analysiert den unbearbeiteten Markdown-Text
  • Extraktion erfolgt VOR dem Chunking-Filter
  • Code-Referenz: app/core/graph/graph_derive_edges.py Zeile 152-177
# WP-24c v4.2.0: Note-Scope Zonen Extraktion (VOR Chunk-Verarbeitung)
note_scope_edges: List[dict] = []
if markdown_body:
    zone_links = extract_note_scope_zones(markdown_body)  # ← Original-Markdown

❌ Callouts in Edge-Zonen: KRITISCHES PROBLEM

Status: ❌ FEHLT

Problem:

  • build_edges_for_note() extrahiert Callouts aus gefilterten Chunks (Zeile 217-265)
  • Chunks wurden bereits gefiltert (Edge-Zonen entfernt) in chunking_processor.py Zeile 38
  • Callouts in Edge-Zonen werden NICHT extrahiert!

Code-Referenz:

# app/core/graph/graph_derive_edges.py Zeile 217-265
for ch in chunks:  # ← chunks sind bereits gefiltert!
    raw = _get(ch, "window") or _get(ch, "text") or ""
    # ...
    # C. Callouts (> [!edge])
    call_pairs, rem2 = extract_callout_relations(rem)  # ← rem kommt aus gefilterten chunks

Konsequenz:

  • Callouts in Edge-Zonen (z.B. ### Unzugeordnete Kanten oder ## Smart Edges) werden nicht in den Graph geschrieben
  • Informationsverlust: Diese Kanten existieren nicht im Graph und können nicht über explanation an das LLM geliefert werden

Empfehlung:

  • Callouts müssen auch aus dem Original-Markdown (markdown_body) extrahiert werden
  • Ähnlich wie extract_note_scope_zones() sollte eine Funktion extract_callouts_from_markdown() erstellt werden
  • Diese sollte vor der Chunk-Verarbeitung aufgerufen werden

2. Payload-Vollständigkeit (Explanation-Mapping) ✅ FUNKTIONIERT

Status: ✅ KORREKT (wenn Edges im Graph sind)

Code-Referenz: app/core/retrieval/retriever.py Zeile 188-238

Verifizierung:

  • ✅ _build_explanation() sammelt alle Edges aus dem Subgraph (Zeile 189-215)
  • ✅ Edges werden in EdgeDTO-Objekte konvertiert (Zeile 205-214)
  • ✅ related_edges werden im Explanation-Objekt gespeichert (Zeile 236)
  • ✅ Top 3 Edges werden als Reason-Objekte formuliert (Zeile 217-228)

Einschränkung:

  • Funktioniert nur, wenn Edges im Graph sind
  • Da Callouts in Edge-Zonen nicht extrahiert werden (siehe Punkt 1), fehlen sie auch in der Explanation

3. Prompt-Sichtbarkeit (RAG-Interface) ⚠️ UNKLAR

Status: ⚠️ TEILWEISE DOKUMENTIERT

Code-Referenz: app/routers/chat.py Zeile 178-274

Verifizierung:

  • ✅ explain=True wird in QueryRequest gesetzt (Zeile 211 in decision_engine.py)
  • ✅ explanation wird im QueryHit gespeichert (Zeile 334 in retriever.py)
  • ⚠️ Unklar: Wie wird explanation.related_edges im LLM-Prompt verwendet?

Untersuchung:

  • chat.py verwendet interview_template Prompt (Zeile 212-222)
  • Prompt-Variablen werden aus QueryHit extrahiert
  • Fehlend: Explizite Verwendung von explanation.related_edges im Prompt

Empfehlung:

  • Prüfen Sie config/prompts.yaml für interview_template
  • Stellen Sie sicher, dass {related_edges} oder ähnliche Variablen im Prompt verwendet werden
  • Dokumentieren Sie die Prompt-Struktur für RAG-Kontext

4. Edge-Case Analyse ⚠️ KRITISCH

Status: ❌ INFORMATIONSVERLUST

Beispiel:

---
type: decision
title: Meine Notiz
---

# Hauptinhalt

Dieser Text wird gechunkt.

## Smart Edges

> [!edge] depends_on
> [[Projekt Alpha]]

## Weiterer Inhalt

Mehr Text...

Aktuelles Verhalten:

  1. ✅ ## Smart Edges wird als Edge-Zone erkannt
  2. ✅ Zone wird vom Chunking ausgeschlossen
  3. ❌ Callout wird NICHT extrahiert (weil aus gefilterten Chunks extrahiert wird)
  4. ❌ Kante fehlt im Graph
  5. ❌ Kante fehlt in Explanation
  6. ❌ LLM erhält keine Information über diese Verbindung

Konsequenz:

  • Wissens-Vakuum: Die Information existiert weder im Chunk-Text noch im Graph
  • Semantische Verbindung verloren: Das LLM kann diese Verbindung nicht berücksichtigen

Zusammenfassung der Probleme

❌ KRITISCH: Callout-Extraktion aus Edge-Zonen fehlt

Problem:

  • Callouts werden nur aus gefilterten Chunks extrahiert
  • Callouts in Edge-Zonen werden nicht erfasst
  • Informationsverlust: Diese Kanten fehlen im Graph

Lösung:

  1. Erstellen Sie extract_callouts_from_markdown(markdown_body: str) Funktion
  2. Rufen Sie diese vor der Chunk-Verarbeitung auf
  3. Integrieren Sie die extrahierten Callouts in build_edges_for_note()

⚠️ WARNUNG: Prompt-Integration unklar

Problem:

  • Unklar, ob explanation.related_edges im LLM-Prompt verwendet werden
  • Keine explizite Dokumentation der Prompt-Struktur

Empfehlung:

  • Prüfen Sie config/prompts.yaml für interview_template
  • Dokumentieren Sie die Verwendung von related_edges im Prompt

Empfohlene Fixes

Fix 1: Callout-Extraktion aus Original-Markdown

Datei: app/core/graph/graph_derive_edges.py

Änderung:

def extract_callouts_from_markdown(markdown_body: str, note_id: str) -> List[dict]:
    """
    WP-24c v4.2.0: Extrahiert Callouts aus dem Original-Markdown.
    Wird verwendet, um Callouts in Edge-Zonen zu erfassen, die nicht in Chunks sind.
    """
    if not markdown_body:
        return []
    
    edges: List[dict] = []
    
    # Extrahiere alle Callouts aus dem gesamten Markdown
    call_pairs, _ = extract_callout_relations(markdown_body)
    
    for k, raw_t in call_pairs:
        t, sec = parse_link_target(raw_t, note_id)
        if not t:
            continue
        
        # Bestimme scope: "note" wenn in Note-Scope Zone, sonst "chunk"
        # (Für jetzt: scope="note" für alle Callouts aus Markdown)
        payload = {
            "edge_id": _mk_edge_id(k, note_id, t, "note", target_section=sec),
            "provenance": "explicit:callout",
            "rule_id": "callout:edge",
            "confidence": PROVENANCE_PRIORITY.get("callout:edge", 1.0)
        }
        if sec:
            payload["target_section"] = sec
        
        edges.append(_edge(
            kind=k,
            scope="note",
            source_id=note_id,
            target_id=t,
            note_id=note_id,
            payload=payload
        ))
    
    return edges

def build_edges_for_note(
    note_id: str,
    chunks: List[dict],
    note_level_references: Optional[List[str]] = None,
    include_note_scope_refs: bool = False,
    markdown_body: Optional[str] = None,
) -> List[dict]:
    # ... existing code ...
    
    # WP-24c v4.2.0: Callout-Extraktion aus Original-Markdown (VOR Chunk-Verarbeitung)
    if markdown_body:
        callout_edges = extract_callouts_from_markdown(markdown_body, note_id)
        edges.extend(callout_edges)
    
    # ... rest of function ...

Fix 2: Prompt-Dokumentation

Datei: config/prompts.yaml und Dokumentation

Empfehlung:

  • Prüfen Sie, ob interview_template {related_edges} verwendet
  • Falls nicht: Erweitern Sie den Prompt um Graph-Kontext
  • Dokumentieren Sie die Prompt-Struktur

Validierung nach Fix

Nach Implementierung der Fixes sollte folgendes verifiziert werden:

  1. ✅ Callouts in Edge-Zonen werden extrahiert

    • Test: Erstellen Sie eine Notiz mit Callout in ## Smart Edges
    • Verifizieren: Edge existiert in Qdrant _edges Collection
  2. ✅ Edges erscheinen in Explanation

    • Test: Query mit explain=True
    • Verifizieren: explanation.related_edges enthält die Callout-Edge
  3. ✅ LLM erhält Graph-Kontext

    • Test: Chat-Query mit Edge-Information
    • Verifizieren: LLM-Antwort berücksichtigt die Graph-Verbindung

Fazit

Aktueller Status: ⚠️ INFORMATIONSVERLUST BEI CALLOUTS IN EDGE-ZONEN

Hauptproblem:

  • Callouts in Edge-Zonen werden nicht extrahiert
  • Diese Information geht vollständig verloren

Lösung:

  • Implementierung von extract_callouts_from_markdown() erforderlich
  • Integration in build_edges_for_note() vor Chunk-Verarbeitung

Nach Fix:

  • ✅ Alle Callouts werden erfasst (auch in Edge-Zonen)
  • ✅ Graph-Vollständigkeit gewährleistet
  • ✅ Explanation enthält alle relevanten Edges
  • ✅ LLM erhält vollständigen Kontext