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

266 lines
8.9 KiB
Markdown
Raw Normal View History

# 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
```python
# 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:**
```python
# 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**
#### Szenario: Callout nur in Edge-Zone (kein Wikilink im Fließtext)
**Status:** ❌ **INFORMATIONSVERLUST**
**Beispiel:**
```markdown
---
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:**
```python
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