WP24c - Agentic Edge Validation & Chunk-Aware Multigraph-System (v4.5.8) #22
|
|
@ -13,6 +13,7 @@ class RawBlock:
|
|||
level: Optional[int]
|
||||
section_path: str
|
||||
section_title: Optional[str]
|
||||
exclude_from_chunking: bool = False # WP-24c v4.2.0: Flag für Edge-Zonen, die nicht gechunkt werden sollen
|
||||
|
||||
@dataclass
|
||||
class Chunk:
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ FILE: app/core/chunking/chunking_parser.py
|
|||
DESCRIPTION: Zerlegt Markdown in logische Einheiten (RawBlocks).
|
||||
Hält alle Überschriftenebenen (H1-H6) im Stream.
|
||||
Stellt die Funktion parse_edges_robust zur Verfügung.
|
||||
WP-24c v4.2.0: Identifiziert Edge-Zonen und markiert sie für Chunking-Ausschluss.
|
||||
"""
|
||||
import re
|
||||
import os
|
||||
from typing import List, Tuple, Set
|
||||
from .chunking_models import RawBlock
|
||||
from .chunking_utils import extract_frontmatter_from_text
|
||||
|
|
@ -20,7 +22,10 @@ def split_sentences(text: str) -> list[str]:
|
|||
return [p.strip() for p in _SENT_SPLIT.split(text) if p.strip()]
|
||||
|
||||
def parse_blocks(md_text: str) -> Tuple[List[RawBlock], str]:
|
||||
"""Zerlegt Text in logische Einheiten (RawBlocks), inklusive H1-H6."""
|
||||
"""
|
||||
Zerlegt Text in logische Einheiten (RawBlocks), inklusive H1-H6.
|
||||
WP-24c v4.2.0: Identifiziert Edge-Zonen (LLM-Validierung & Note-Scope) und markiert sie für Chunking-Ausschluss.
|
||||
"""
|
||||
blocks = []
|
||||
h1_title = "Dokument"
|
||||
section_path = "/"
|
||||
|
|
@ -29,6 +34,31 @@ def parse_blocks(md_text: str) -> Tuple[List[RawBlock], str]:
|
|||
# Frontmatter entfernen
|
||||
fm, text_without_fm = extract_frontmatter_from_text(md_text)
|
||||
|
||||
# WP-24c v4.2.0: Konfigurierbare Header-Namen und -Ebenen
|
||||
llm_validation_headers = os.getenv(
|
||||
"MINDNET_LLM_VALIDATION_HEADERS",
|
||||
"Unzugeordnete Kanten,Edge Pool,Candidates"
|
||||
)
|
||||
llm_validation_header_list = [h.strip() for h in llm_validation_headers.split(",") if h.strip()]
|
||||
if not llm_validation_header_list:
|
||||
llm_validation_header_list = ["Unzugeordnete Kanten", "Edge Pool", "Candidates"]
|
||||
|
||||
note_scope_headers = os.getenv(
|
||||
"MINDNET_NOTE_SCOPE_ZONE_HEADERS",
|
||||
"Smart Edges,Relationen,Global Links,Note-Level Relations,Globale Verbindungen"
|
||||
)
|
||||
note_scope_header_list = [h.strip() for h in note_scope_headers.split(",") if h.strip()]
|
||||
if not note_scope_header_list:
|
||||
note_scope_header_list = ["Smart Edges", "Relationen", "Global Links", "Note-Level Relations", "Globale Verbindungen"]
|
||||
|
||||
# Header-Ebenen konfigurierbar (Default: LLM=3, Note-Scope=2)
|
||||
llm_validation_level = int(os.getenv("MINDNET_LLM_VALIDATION_HEADER_LEVEL", "3"))
|
||||
note_scope_level = int(os.getenv("MINDNET_NOTE_SCOPE_HEADER_LEVEL", "2"))
|
||||
|
||||
# Status-Tracking für Edge-Zonen
|
||||
in_exclusion_zone = False
|
||||
exclusion_zone_type = None # "llm_validation" oder "note_scope"
|
||||
|
||||
# H1 für Note-Titel extrahieren (Metadaten-Zweck)
|
||||
h1_match = re.search(r'^#\s+(.*)', text_without_fm, re.MULTILINE)
|
||||
if h1_match:
|
||||
|
|
@ -47,20 +77,47 @@ def parse_blocks(md_text: str) -> Tuple[List[RawBlock], str]:
|
|||
if buffer:
|
||||
content = "\n".join(buffer).strip()
|
||||
if content:
|
||||
blocks.append(RawBlock("paragraph", content, None, section_path, current_section_title))
|
||||
blocks.append(RawBlock(
|
||||
"paragraph", content, None, section_path, current_section_title,
|
||||
exclude_from_chunking=in_exclusion_zone
|
||||
))
|
||||
buffer = []
|
||||
|
||||
level = len(heading_match.group(1))
|
||||
title = heading_match.group(2).strip()
|
||||
|
||||
# WP-24c v4.2.0: Prüfe, ob dieser Header eine Edge-Zone startet
|
||||
is_llm_validation_zone = (
|
||||
level == llm_validation_level and
|
||||
any(title.lower() == h.lower() for h in llm_validation_header_list)
|
||||
)
|
||||
is_note_scope_zone = (
|
||||
level == note_scope_level and
|
||||
any(title.lower() == h.lower() for h in note_scope_header_list)
|
||||
)
|
||||
|
||||
if is_llm_validation_zone:
|
||||
in_exclusion_zone = True
|
||||
exclusion_zone_type = "llm_validation"
|
||||
elif is_note_scope_zone:
|
||||
in_exclusion_zone = True
|
||||
exclusion_zone_type = "note_scope"
|
||||
elif in_exclusion_zone:
|
||||
# Neuer Header gefunden, der keine Edge-Zone ist -> Zone beendet
|
||||
in_exclusion_zone = False
|
||||
exclusion_zone_type = None
|
||||
|
||||
# Pfad- und Titel-Update für die Metadaten der folgenden Blöcke
|
||||
if level == 1:
|
||||
current_section_title = title; section_path = "/"
|
||||
elif level == 2:
|
||||
current_section_title = title; section_path = f"/{current_section_title}"
|
||||
|
||||
# Die Überschrift selbst als regulären Block hinzufügen
|
||||
blocks.append(RawBlock("heading", stripped, level, section_path, current_section_title))
|
||||
# Die Überschrift selbst als regulären Block hinzufügen (auch markiert, wenn in Zone)
|
||||
blocks.append(RawBlock(
|
||||
"heading", stripped, level, section_path, current_section_title,
|
||||
exclude_from_chunking=in_exclusion_zone
|
||||
))
|
||||
continue
|
||||
|
||||
# Trenner (---) oder Leerzeilen beenden Blöcke, außer innerhalb von Callouts
|
||||
|
|
@ -68,17 +125,26 @@ def parse_blocks(md_text: str) -> Tuple[List[RawBlock], str]:
|
|||
if buffer:
|
||||
content = "\n".join(buffer).strip()
|
||||
if content:
|
||||
blocks.append(RawBlock("paragraph", content, None, section_path, current_section_title))
|
||||
blocks.append(RawBlock(
|
||||
"paragraph", content, None, section_path, current_section_title,
|
||||
exclude_from_chunking=in_exclusion_zone
|
||||
))
|
||||
buffer = []
|
||||
if stripped == "---":
|
||||
blocks.append(RawBlock("separator", "---", None, section_path, current_section_title))
|
||||
blocks.append(RawBlock(
|
||||
"separator", "---", None, section_path, current_section_title,
|
||||
exclude_from_chunking=in_exclusion_zone
|
||||
))
|
||||
else:
|
||||
buffer.append(line)
|
||||
|
||||
if buffer:
|
||||
content = "\n".join(buffer).strip()
|
||||
if content:
|
||||
blocks.append(RawBlock("paragraph", content, None, section_path, current_section_title))
|
||||
blocks.append(RawBlock(
|
||||
"paragraph", content, None, section_path, current_section_title,
|
||||
exclude_from_chunking=in_exclusion_zone
|
||||
))
|
||||
|
||||
return blocks, h1_title
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ DESCRIPTION: Der zentrale Orchestrator für das Chunking-System.
|
|||
- Integriert physikalische Kanten-Injektion (Propagierung).
|
||||
- Stellt H1-Kontext-Fenster sicher.
|
||||
- Baut den Candidate-Pool für die WP-15b Ingestion auf.
|
||||
WP-24c v4.2.0: Konfigurierbare Header-Namen für LLM-Validierung.
|
||||
"""
|
||||
import asyncio
|
||||
import re
|
||||
import os
|
||||
import logging
|
||||
from typing import List, Dict, Optional
|
||||
from .chunking_models import Chunk
|
||||
|
|
@ -31,6 +33,10 @@ async def assemble_chunks(note_id: str, md_text: str, note_type: str, config: Op
|
|||
fm, body_text = extract_frontmatter_from_text(md_text)
|
||||
blocks, doc_title = parse_blocks(md_text)
|
||||
|
||||
# WP-24c v4.2.0: Filtere Blöcke aus Edge-Zonen (LLM-Validierung & Note-Scope)
|
||||
# Diese Bereiche sollen nicht als Chunks angelegt werden, sondern nur die Kanten extrahiert werden
|
||||
blocks_for_chunking = [b for b in blocks if not getattr(b, 'exclude_from_chunking', False)]
|
||||
|
||||
# Vorbereitung des H1-Präfix für die Embedding-Fenster (Breadcrumbs)
|
||||
h1_prefix = f"# {doc_title}" if doc_title else ""
|
||||
|
||||
|
|
@ -38,11 +44,11 @@ async def assemble_chunks(note_id: str, md_text: str, note_type: str, config: Op
|
|||
# Alle Strategien nutzen nun einheitlich context_prefix für die Window-Bildung.
|
||||
if config.get("strategy") == "by_heading":
|
||||
chunks = await asyncio.to_thread(
|
||||
strategy_by_heading, blocks, config, note_id, context_prefix=h1_prefix
|
||||
strategy_by_heading, blocks_for_chunking, config, note_id, context_prefix=h1_prefix
|
||||
)
|
||||
else:
|
||||
chunks = await asyncio.to_thread(
|
||||
strategy_sliding_window, blocks, config, note_id, context_prefix=h1_prefix
|
||||
strategy_sliding_window, blocks_for_chunking, config, note_id, context_prefix=h1_prefix
|
||||
)
|
||||
|
||||
if not chunks:
|
||||
|
|
@ -63,14 +69,29 @@ async def assemble_chunks(note_id: str, md_text: str, note_type: str, config: Op
|
|||
k, t = parts
|
||||
ch.candidate_pool.append({"kind": k, "to": t, "provenance": "explicit"})
|
||||
|
||||
# 5. Global Pool (Unzugeordnete Kanten aus dem Dokument-Ende)
|
||||
# Sucht nach dem Edge-Pool Block im Original-Markdown.
|
||||
pool_match = re.search(
|
||||
r'###?\s*(?:Unzugeordnete Kanten|Edge Pool|Candidates)\s*\n(.*?)(?:\n#|$)',
|
||||
body_text,
|
||||
re.DOTALL | re.IGNORECASE
|
||||
# 5. Global Pool (Unzugeordnete Kanten - kann mitten im Dokument oder am Ende stehen)
|
||||
# WP-24c v4.2.0: Konfigurierbare Header-Namen und -Ebene via .env
|
||||
# Sucht nach ALLEN Edge-Pool Blöcken im Original-Markdown (nicht nur am Ende).
|
||||
llm_validation_headers = os.getenv(
|
||||
"MINDNET_LLM_VALIDATION_HEADERS",
|
||||
"Unzugeordnete Kanten,Edge Pool,Candidates"
|
||||
)
|
||||
if pool_match:
|
||||
header_list = [h.strip() for h in llm_validation_headers.split(",") if h.strip()]
|
||||
# Fallback auf Defaults, falls leer
|
||||
if not header_list:
|
||||
header_list = ["Unzugeordnete Kanten", "Edge Pool", "Candidates"]
|
||||
|
||||
# Header-Ebene konfigurierbar (Default: 3 für ###)
|
||||
llm_validation_level = int(os.getenv("MINDNET_LLM_VALIDATION_HEADER_LEVEL", "3"))
|
||||
header_level_pattern = "#" * llm_validation_level
|
||||
|
||||
# Regex-Pattern mit konfigurierbaren Headern und Ebene
|
||||
# WP-24c v4.2.0: finditer statt search, um ALLE Zonen zu finden (auch mitten im Dokument)
|
||||
# Zone endet bei einem neuen Header (jeder Ebene) oder am Dokument-Ende
|
||||
header_pattern = "|".join(re.escape(h) for h in header_list)
|
||||
zone_pattern = rf'^{re.escape(header_level_pattern)}\s*(?:{header_pattern})\s*\n(.*?)(?=\n#|$)'
|
||||
|
||||
for pool_match in re.finditer(zone_pattern, body_text, re.DOTALL | re.IGNORECASE | re.MULTILINE):
|
||||
global_edges = parse_edges_robust(pool_match.group(1))
|
||||
for e_str in global_edges:
|
||||
parts = e_str.split(':', 1)
|
||||
|
|
|
|||
|
|
@ -23,19 +23,34 @@ from .graph_extractors import (
|
|||
)
|
||||
|
||||
# WP-24c v4.2.0: Header-basierte Identifikation von Note-Scope Zonen
|
||||
NOTE_SCOPE_ZONE_HEADERS = [
|
||||
"Smart Edges",
|
||||
"Relationen",
|
||||
"Global Links",
|
||||
"Note-Level Relations",
|
||||
"Globale Verbindungen"
|
||||
]
|
||||
# Konfigurierbar via MINDNET_NOTE_SCOPE_ZONE_HEADERS (komma-separiert)
|
||||
def get_note_scope_zone_headers() -> List[str]:
|
||||
"""
|
||||
Lädt die konfigurierten Header-Namen für Note-Scope Zonen.
|
||||
Fallback auf Defaults, falls nicht konfiguriert.
|
||||
"""
|
||||
import os
|
||||
headers_env = os.getenv(
|
||||
"MINDNET_NOTE_SCOPE_ZONE_HEADERS",
|
||||
"Smart Edges,Relationen,Global Links,Note-Level Relations,Globale Verbindungen"
|
||||
)
|
||||
header_list = [h.strip() for h in headers_env.split(",") if h.strip()]
|
||||
# Fallback auf Defaults, falls leer
|
||||
if not header_list:
|
||||
header_list = [
|
||||
"Smart Edges",
|
||||
"Relationen",
|
||||
"Global Links",
|
||||
"Note-Level Relations",
|
||||
"Globale Verbindungen"
|
||||
]
|
||||
return header_list
|
||||
|
||||
def extract_note_scope_zones(markdown_body: str) -> List[Tuple[str, str]]:
|
||||
"""
|
||||
WP-24c v4.2.0: Extrahiert Note-Scope Zonen aus Markdown.
|
||||
|
||||
Identifiziert Sektionen mit spezifischen Headern (z.B. "## Smart Edges")
|
||||
Identifiziert Sektionen mit spezifischen Headern (konfigurierbar via .env)
|
||||
und extrahiert alle darin enthaltenen Links.
|
||||
|
||||
Returns:
|
||||
|
|
@ -46,8 +61,14 @@ def extract_note_scope_zones(markdown_body: str) -> List[Tuple[str, str]]:
|
|||
|
||||
edges: List[Tuple[str, str]] = []
|
||||
|
||||
# Regex für Header-Erkennung (## oder ###)
|
||||
header_pattern = r'^#{2,3}\s+(.+?)$'
|
||||
# WP-24c v4.2.0: Konfigurierbare Header-Ebene
|
||||
import os
|
||||
import re
|
||||
note_scope_level = int(os.getenv("MINDNET_NOTE_SCOPE_HEADER_LEVEL", "2"))
|
||||
header_level_pattern = "#" * note_scope_level
|
||||
|
||||
# Regex für Header-Erkennung (konfigurierbare Ebene)
|
||||
header_pattern = rf'^{re.escape(header_level_pattern)}\s+(.+?)$'
|
||||
|
||||
lines = markdown_body.split('\n')
|
||||
in_zone = False
|
||||
|
|
@ -60,9 +81,11 @@ def extract_note_scope_zones(markdown_body: str) -> List[Tuple[str, str]]:
|
|||
header_text = header_match.group(1).strip()
|
||||
|
||||
# Prüfe, ob dieser Header eine Note-Scope Zone ist
|
||||
# WP-24c v4.2.0: Dynamisches Laden der konfigurierten Header
|
||||
zone_headers = get_note_scope_zone_headers()
|
||||
is_zone_header = any(
|
||||
header_text.lower() == zone_header.lower()
|
||||
for zone_header in NOTE_SCOPE_ZONE_HEADERS
|
||||
for zone_header in zone_headers
|
||||
)
|
||||
|
||||
if is_zone_header:
|
||||
|
|
|
|||
|
|
@ -45,4 +45,19 @@ MINDNET_VAULT_ROOT=./vault_prod
|
|||
MINDNET_VOCAB_PATH=/mindnet/vault/mindnet/_system/dictionary/edge_vocabulary.md
|
||||
|
||||
# Change Detection für effiziente Re-Imports
|
||||
MINDNET_CHANGE_DETECTION_MODE=full
|
||||
MINDNET_CHANGE_DETECTION_MODE=full
|
||||
|
||||
# --- WP-24c v4.2.0: Konfigurierbare Markdown-Header für Edge-Zonen ---
|
||||
# Komma-separierte Liste von Headern für LLM-Validierung
|
||||
# Format: Header1,Header2,Header3
|
||||
MINDNET_LLM_VALIDATION_HEADERS=Unzugeordnete Kanten,Edge Pool,Candidates
|
||||
|
||||
# Header-Ebene für LLM-Validierung (1-6, Default: 3 für ###)
|
||||
MINDNET_LLM_VALIDATION_HEADER_LEVEL=3
|
||||
|
||||
# Komma-separierte Liste von Headern für Note-Scope Zonen
|
||||
# Format: Header1,Header2,Header3
|
||||
MINDNET_NOTE_SCOPE_ZONE_HEADERS=Smart Edges,Relationen,Global Links,Note-Level Relations,Globale Verbindungen
|
||||
|
||||
# Header-Ebene für Note-Scope Zonen (1-6, Default: 2 für ##)
|
||||
MINDNET_NOTE_SCOPE_HEADER_LEVEL=2
|
||||
|
|
@ -50,6 +50,11 @@ Diese Variablen steuern die Infrastruktur, Pfade und globale Timeouts. Seit der
|
|||
| `MINDNET_LL_BACKGROUND_LIMIT`| `2` | **Traffic Control:** Max. parallele Hintergrund-Tasks (Semaphore). |
|
||||
| `MINDNET_CHANGE_DETECTION_MODE` | `full` | `full` (Text + Meta) oder `body` (nur Text). |
|
||||
| `MINDNET_DEFAULT_RETRIEVER_WEIGHT` | `1.0` | **Neu (WP-22):** Systemweiter Standard für das Retriever-Gewicht einer Notiz. |
|
||||
| `MINDNET_LLM_VALIDATION_HEADERS` | `Unzugeordnete Kanten,Edge Pool,Candidates` | **Neu (v4.2.0):** Komma-separierte Header-Namen für LLM-Validierung. |
|
||||
| `MINDNET_LLM_VALIDATION_HEADER_LEVEL` | `3` | **Neu (v4.2.0):** Header-Ebene für LLM-Validierung (1-6, Default: 3 für ###). |
|
||||
| `MINDNET_NOTE_SCOPE_ZONE_HEADERS` | `Smart Edges,Relationen,Global Links,Note-Level Relations,Globale Verbindungen` | **Neu (v4.2.0):** Komma-separierte Header-Namen für Note-Scope Zonen. |
|
||||
| `MINDNET_NOTE_SCOPE_HEADER_LEVEL` | `2` | **Neu (v4.2.0):** Header-Ebene für Note-Scope Zonen (1-6, Default: 2 für ##). |
|
||||
| `MINDNET_IGNORE_FOLDERS` | *(leer)* | **Neu (v4.1.0):** Komma-separierte Liste von Ordnernamen, die beim Import ignoriert werden. |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
242
docs/03_Technical_References/KONFIGURATION_EDGE_ZONEN.md
Normal file
242
docs/03_Technical_References/KONFIGURATION_EDGE_ZONEN.md
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
# Konfiguration von Edge-Zonen Headern (v4.2.0)
|
||||
|
||||
**Version:** v4.2.0
|
||||
**Status:** Aktiv
|
||||
|
||||
## Übersicht
|
||||
|
||||
Das Mindnet-System unterstützt zwei Arten von speziellen Markdown-Sektionen für Kanten:
|
||||
|
||||
1. **LLM-Validierung Zonen** - Links, die vom LLM validiert werden
|
||||
2. **Note-Scope Zonen** - Links, die der gesamten Note zugeordnet werden
|
||||
|
||||
Die Header-Namen für beide Zonen-Typen sind über Umgebungsvariablen konfigurierbar.
|
||||
|
||||
## Konfiguration via .env
|
||||
|
||||
### LLM-Validierung Header
|
||||
|
||||
**Umgebungsvariablen:**
|
||||
- `MINDNET_LLM_VALIDATION_HEADERS` - Komma-separierte Liste von Header-Namen
|
||||
- `MINDNET_LLM_VALIDATION_HEADER_LEVEL` - Header-Ebene (1-6, Default: 3 für `###`)
|
||||
|
||||
**Format:** Komma-separierte Liste von Header-Namen
|
||||
|
||||
**Default:**
|
||||
```
|
||||
MINDNET_LLM_VALIDATION_HEADERS=Unzugeordnete Kanten,Edge Pool,Candidates
|
||||
MINDNET_LLM_VALIDATION_HEADER_LEVEL=3
|
||||
```
|
||||
|
||||
**Beispiel:**
|
||||
```env
|
||||
MINDNET_LLM_VALIDATION_HEADERS=Unzugeordnete Kanten,Edge Pool,Candidates,Zu prüfende Links
|
||||
MINDNET_LLM_VALIDATION_HEADER_LEVEL=3
|
||||
```
|
||||
|
||||
**Verwendung in Markdown:**
|
||||
```markdown
|
||||
### Unzugeordnete Kanten
|
||||
|
||||
related_to:Ziel-Notiz
|
||||
depends_on:Andere Notiz
|
||||
```
|
||||
|
||||
**Wichtig:** Diese Bereiche werden **nicht als Chunks angelegt**, sondern nur die Kanten extrahiert.
|
||||
|
||||
### Note-Scope Zone Header
|
||||
|
||||
**Umgebungsvariablen:**
|
||||
- `MINDNET_NOTE_SCOPE_ZONE_HEADERS` - Komma-separierte Liste von Header-Namen
|
||||
- `MINDNET_NOTE_SCOPE_HEADER_LEVEL` - Header-Ebene (1-6, Default: 2 für `##`)
|
||||
|
||||
**Format:** Komma-separierte Liste von Header-Namen
|
||||
|
||||
**Default:**
|
||||
```
|
||||
MINDNET_NOTE_SCOPE_ZONE_HEADERS=Smart Edges,Relationen,Global Links,Note-Level Relations,Globale Verbindungen
|
||||
MINDNET_NOTE_SCOPE_HEADER_LEVEL=2
|
||||
```
|
||||
|
||||
**Beispiel:**
|
||||
```env
|
||||
MINDNET_NOTE_SCOPE_ZONE_HEADERS=Smart Edges,Relationen,Globale Verbindungen,Note-Level Links
|
||||
MINDNET_NOTE_SCOPE_HEADER_LEVEL=2
|
||||
```
|
||||
|
||||
**Verwendung in Markdown:**
|
||||
```markdown
|
||||
## Smart Edges
|
||||
|
||||
[[rel:depends_on|Globale Notiz]]
|
||||
[[rel:part_of|System-Übersicht]]
|
||||
```
|
||||
|
||||
**Wichtig:** Diese Bereiche werden **nicht als Chunks angelegt**, sondern nur die Kanten extrahiert.
|
||||
|
||||
## Konfiguration in prod.env
|
||||
|
||||
Fügen Sie die folgenden Zeilen zu Ihrer `.env` oder `config/prod.env` hinzu:
|
||||
|
||||
```env
|
||||
# --- WP-24c v4.2.0: Konfigurierbare Markdown-Header für Edge-Zonen ---
|
||||
# Komma-separierte Liste von Headern für LLM-Validierung
|
||||
MINDNET_LLM_VALIDATION_HEADERS=Unzugeordnete Kanten,Edge Pool,Candidates
|
||||
|
||||
# Header-Ebene für LLM-Validierung (1-6, Default: 3 für ###)
|
||||
MINDNET_LLM_VALIDATION_HEADER_LEVEL=3
|
||||
|
||||
# Komma-separierte Liste von Headern für Note-Scope Zonen
|
||||
MINDNET_NOTE_SCOPE_ZONE_HEADERS=Smart Edges,Relationen,Global Links,Note-Level Relations,Globale Verbindungen
|
||||
|
||||
# Header-Ebene für Note-Scope Zonen (1-6, Default: 2 für ##)
|
||||
MINDNET_NOTE_SCOPE_HEADER_LEVEL=2
|
||||
```
|
||||
|
||||
**Wichtig:** Beide Zonen-Typen werden **nicht als Chunks angelegt**. Nur die Kanten werden extrahiert, der Text selbst wird vom Chunking ausgeschlossen.
|
||||
|
||||
## Unterschiede
|
||||
|
||||
### LLM-Validierung Zonen
|
||||
|
||||
- **Header-Ebene:** Konfigurierbar via `MINDNET_LLM_VALIDATION_HEADER_LEVEL` (Default: 3 = `###`)
|
||||
- **Zweck:** Links werden vom LLM validiert
|
||||
- **Provenance:** `global_pool`
|
||||
- **Scope:** `chunk` (wird Chunks zugeordnet)
|
||||
- **Aktivierung:** Nur wenn `enable_smart_edge_allocation: true`
|
||||
- **Chunking:** ❌ **Diese Bereiche werden NICHT als Chunks angelegt** - nur Kanten werden extrahiert
|
||||
|
||||
**Beispiel:**
|
||||
```markdown
|
||||
### Unzugeordnete Kanten
|
||||
|
||||
related_to:Mögliche Verbindung
|
||||
depends_on:Unsichere Notiz
|
||||
```
|
||||
|
||||
### Note-Scope Zonen
|
||||
|
||||
- **Header-Ebene:** Konfigurierbar via `MINDNET_NOTE_SCOPE_HEADER_LEVEL` (Default: 2 = `##`)
|
||||
- **Zweck:** Links werden der gesamten Note zugeordnet
|
||||
- **Provenance:** `explicit:note_zone`
|
||||
- **Scope:** `note` (Note-weite Verbindung)
|
||||
- **Aktivierung:** Immer aktiv
|
||||
- **Chunking:** ❌ **Diese Bereiche werden NICHT als Chunks angelegt** - nur Kanten werden extrahiert
|
||||
|
||||
**Beispiel:**
|
||||
```markdown
|
||||
## Smart Edges
|
||||
|
||||
[[rel:depends_on|Globale Notiz]]
|
||||
[[rel:part_of|System-Übersicht]]
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### ✅ Empfohlen
|
||||
|
||||
1. **Konsistente Header-Namen:**
|
||||
- Nutzen Sie aussagekräftige Namen
|
||||
- Dokumentieren Sie die verwendeten Header in Ihrem Team
|
||||
|
||||
2. **Minimale Konfiguration:**
|
||||
- Nutzen Sie die Defaults, wenn möglich
|
||||
- Nur bei Bedarf anpassen
|
||||
|
||||
3. **Dokumentation:**
|
||||
- Dokumentieren Sie benutzerdefinierte Header in Ihrer Projekt-Dokumentation
|
||||
|
||||
### ❌ Vermeiden
|
||||
|
||||
1. **Zu viele Header:**
|
||||
- Zu viele Optionen können verwirrend sein
|
||||
- Beschränken Sie sich auf 3-5 Header pro Typ
|
||||
|
||||
2. **Ähnliche Namen:**
|
||||
- Vermeiden Sie Header, die sich zu ähnlich sind
|
||||
- Klare Unterscheidung zwischen LLM-Validierung und Note-Scope
|
||||
|
||||
## Technische Details
|
||||
|
||||
### Code-Referenzen
|
||||
|
||||
- **LLM-Validierung:** `app/core/chunking/chunking_processor.py` (Zeile 66-72)
|
||||
- **Note-Scope Zonen:** `app/core/graph/graph_derive_edges.py` → `get_note_scope_zone_headers()`
|
||||
|
||||
### Fallback-Verhalten
|
||||
|
||||
- Wenn die Umgebungsvariable nicht gesetzt ist, werden die Defaults verwendet
|
||||
- Wenn die Variable leer ist, werden ebenfalls die Defaults verwendet
|
||||
- Header-Namen werden case-insensitive verglichen
|
||||
|
||||
### Regex-Escape
|
||||
|
||||
- Header-Namen werden automatisch für Regex escaped
|
||||
- Sonderzeichen in Header-Namen sind sicher
|
||||
|
||||
## Beispiel-Konfiguration
|
||||
|
||||
```env
|
||||
# Eigene Header-Namen für LLM-Validierung (H3)
|
||||
MINDNET_LLM_VALIDATION_HEADERS=Zu prüfende Links,Kandidaten,Edge Pool
|
||||
MINDNET_LLM_VALIDATION_HEADER_LEVEL=3
|
||||
|
||||
# Eigene Header-Namen für Note-Scope Zonen (H2)
|
||||
MINDNET_NOTE_SCOPE_ZONE_HEADERS=Globale Relationen,Note-Verbindungen,Smart Links
|
||||
MINDNET_NOTE_SCOPE_HEADER_LEVEL=2
|
||||
```
|
||||
|
||||
**Alternative:** Beide auf H2 setzen:
|
||||
```env
|
||||
MINDNET_LLM_VALIDATION_HEADER_LEVEL=2
|
||||
MINDNET_NOTE_SCOPE_HEADER_LEVEL=2
|
||||
```
|
||||
|
||||
**Verwendung:**
|
||||
```markdown
|
||||
---
|
||||
type: decision
|
||||
title: Meine Notiz
|
||||
---
|
||||
|
||||
# Inhalt
|
||||
|
||||
## Globale Relationen
|
||||
|
||||
[[rel:depends_on|System-Architektur]]
|
||||
|
||||
### Zu prüfende Links
|
||||
|
||||
related_to:Mögliche Verbindung
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: Kann ich beide Zonen-Typen in einer Notiz verwenden?**
|
||||
A: Ja, beide können gleichzeitig verwendet werden.
|
||||
|
||||
**Q: Was passiert, wenn ein Header in beiden Listen steht?**
|
||||
A: Die Note-Scope Zone hat Vorrang (wird als Note-Scope behandelt).
|
||||
|
||||
**Q: Können Header-Namen Leerzeichen enthalten?**
|
||||
A: Ja, Leerzeichen werden beibehalten.
|
||||
|
||||
**Q: Werden Header-Namen case-sensitive verglichen?**
|
||||
A: Nein, der Vergleich ist case-insensitive.
|
||||
|
||||
**Q: Kann ich Header-Namen mit Sonderzeichen verwenden?**
|
||||
A: Ja, Sonderzeichen werden automatisch für Regex escaped.
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
- ✅ **LLM-Validierung:**
|
||||
- `MINDNET_LLM_VALIDATION_HEADERS` (Header-Namen, komma-separiert)
|
||||
- `MINDNET_LLM_VALIDATION_HEADER_LEVEL` (Header-Ebene 1-6, Default: 3)
|
||||
- ❌ **Nicht als Chunks angelegt** - nur Kanten werden extrahiert
|
||||
- ✅ **Note-Scope Zonen:**
|
||||
- `MINDNET_NOTE_SCOPE_ZONE_HEADERS` (Header-Namen, komma-separiert)
|
||||
- `MINDNET_NOTE_SCOPE_HEADER_LEVEL` (Header-Ebene 1-6, Default: 2)
|
||||
- ❌ **Nicht als Chunks angelegt** - nur Kanten werden extrahiert
|
||||
- ✅ **Format:** Komma-separierte Liste für Header-Namen
|
||||
- ✅ **Fallback:** Defaults werden verwendet, falls nicht konfiguriert
|
||||
- ✅ **Case-insensitive:** Header-Namen werden case-insensitive verglichen
|
||||
Loading…
Reference in New Issue
Block a user