#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ FILE: scripts/debug_edge_loss.py VERSION: 2.1.0 (2025-12-15) STATUS: Active (Debug-Tool) COMPATIBILITY: v2.9.1 (Post-WP14/WP-15b) Zweck: ------- Debug-Tool zur Analyse von Edge-Verlust-Problemen bei der Chunk-Verarbeitung. Hilft zu verstehen, warum bestimmte Edges nicht erkannt oder verloren gehen. Funktionsweise: --------------- 1. Analysiert eine einzelne Markdown-Datei 2. Führt zwei Analyseschritte durch: a) Pre-Scan: Extrahiert alle Edge-Kandidaten aus dem rohen Text - Wikilinks - Typed Relations - Callout Relations b) Chunk-Analyse: - Erstellt Chunks mit konfigurierbarem Profil - Prüft, welche Edges in jedem Chunk gefunden werden - Vergleicht mit Pre-Scan-Ergebnissen 3. Gibt detaillierte Analyse pro Chunk aus Ergebnis-Interpretation: ------------------------ - [1] Globale Kandidaten: Alle Edge-Kandidaten, die im Text vorhanden sind - [2] Chunk-Struktur: Für jeden Chunk: * Section-Pfad * Text-Snippet * Gefundene explizite Kanten (callout:edge, inline:rel) * Warnung, falls Callout im Text vorhanden, aber nicht erkannt Verwendung: ----------- - Debugging von Edge-Verlust bei Chunk-Grenzen - Validierung der Edge-Extraktion in verschiedenen Chunk-Kontexten - Analyse von Problemen mit Callout-Erkennung Hinweise: --------- - Asynchrones Skript (nutzt assemble_chunks async API) - Konfigurierbares Chunking-Profil (Standard: sliding_window, 400/600 chars) - Smart Edge Allocation ist standardmäßig deaktiviert für klare Analyse Aufruf: ------- python3 scripts/debug_edge_loss.py [PFAD_ZUR_DATEI.md] Parameter: ---------- Keine CLI-Parameter. Dateipfad als erstes Argument oder Standard-Pfad. Änderungen: ----------- v2.1.0 (2025-12-15): Kompatibilität mit WP-14 Modularisierung - Entfernt: _extract_all_edges_from_md (nicht mehr vorhanden) - Ersetzt durch: extract_wikilinks, extract_typed_relations, extract_callout_relations - Chunk-Payload-Struktur angepasst (window, type hinzugefügt) v1.0.0: Erster Release """ import asyncio import os import sys from pathlib import Path # Pfad-Setup sys.path.insert(0, os.path.abspath(".")) from app.core.chunking import assemble_chunks from app.core.graph.graph_derive_edges import build_edges_for_note from app.core.parser import extract_wikilinks from app.core.graph.graph_extractors import extract_typed_relations, extract_callout_relations # Mock für Settings, falls nötig os.environ["MINDNET_LLM_MODEL"] = "phi3:mini" async def analyze_file(file_path: str): print(f"\n=== ANALYSE: {file_path} ===") with open(file_path, "r", encoding="utf-8") as f: text = f.read() # 1. Globale Kandidaten (Was sieht der Pre-Scan?) # Wir extrahieren alle Edge-Kandidaten aus dem Text note_id = Path(file_path).stem candidates = [] # Wikilinks extrahieren wikilinks = extract_wikilinks(text) for wl in wikilinks: candidates.append(f"wikilink:{wl}") # Typed Relations extrahieren typed_rels, _ = extract_typed_relations(text) for kind, target in typed_rels: candidates.append(f"typed:{kind}:{target}") # Callout Relations extrahieren callout_rels, _ = extract_callout_relations(text) for kind, target in callout_rels: candidates.append(f"callout:{kind}:{target}") print(f"\n[1] Globale Kandidaten (Pre-Scan):") for c in candidates: print(f" - {c}") # 2. Chunking (Ohne Smart Edges erstmal, um die physische Integrität zu prüfen) # Wir nutzen ein Profil, das dem User-Setup entspricht config = { "strategy": "sliding_window", "target": 400, "max": 600, "overlap": 50, "enable_smart_edge_allocation": False # Erstmal aus } chunks = await assemble_chunks(note_id, text, "concept", config=config) print(f"\n[2] Chunk-Struktur & Physische Kanten:") for i, chunk in enumerate(chunks): print(f"\n--- Chunk {i} (Section: {chunk.section_path}) ---") print(f"Snippet: {chunk.text[:50]}...") # Was findet derive_edges in diesem rohen Chunk? # Wir simulieren das Payload-Dict, das derive_edges erwartet chunk_pl = { "text": chunk.text, "window": chunk.window or chunk.text, "chunk_id": chunk.id, "type": "concept" } # WP-24c v4.2.0: Übergabe des Markdown-Bodys für Note-Scope Zonen edges = build_edges_for_note(note_id, [chunk_pl], markdown_body=text) found_explicitly = [f"{e['kind']}:{e.get('target_id')}" for e in edges if e['rule_id'] in ['callout:edge', 'inline:rel']] if found_explicitly: print(f" ✅ Gefundene Explizite Kanten: {found_explicitly}") else: print(f" ❌ Keine expliziten Kanten gefunden (trotz Callout im Text?)") # Check auf Callout im Text if "> [!edge]" in chunk.text: print(" ℹ️ HINWEIS: '> [!edge]' String ist im Text vorhanden!") if __name__ == "__main__": # Pfad zu deiner problematischen Datei hier anpassen! target_file = "./vault_master/Dein_Problematisches_File.md" if len(sys.argv) > 1: target_file = sys.argv[1] asyncio.run(analyze_file(target_file))