110 lines
3.7 KiB
Python
110 lines
3.7 KiB
Python
# tests/test_final_wp15_validation.py
|
|
|
|
import asyncio
|
|
import unittest
|
|
from typing import List, Dict, Any
|
|
import re
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
# --- PFAD-KORREKTUR ---
|
|
ROOT_DIR = Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(ROOT_DIR))
|
|
|
|
from app.core import chunker
|
|
from app.services.semantic_analyzer import SemanticAnalyzer
|
|
|
|
def get_config_for_test(strategy: str, enable_smart_edge: bool) -> Dict[str, Any]:
|
|
cfg = chunker.get_chunk_config("concept")
|
|
cfg['strategy'] = strategy
|
|
cfg['enable_smart_edge_allocation'] = enable_smart_edge
|
|
# WICHTIG: Setze sehr kleine Werte, um Split bei kurzem Text zu erzwingen
|
|
cfg['target'] = 50
|
|
cfg['max'] = 100
|
|
return cfg
|
|
|
|
TEST_NOTE_ID_SMART = "20251212-test-smart"
|
|
TEST_NOTE_ID_LEGACY = "20251212-test-legacy"
|
|
|
|
TEST_MARKDOWN_SMART = """
|
|
---
|
|
id: 20251212-test-smart
|
|
title: Integrationstest - Smart Edges
|
|
type: concept
|
|
status: active
|
|
---
|
|
# Teil 1: Wichtige Definition
|
|
Die Mission ist: präsent sein.
|
|
Dies entspricht unseren Werten [[leitbild-werte#Integrität]].
|
|
|
|
## Teil 2: Konflikt
|
|
Der Konflikt zwischen [[leitbild-rollen#Vater]] und [[leitbild-rollen#Beruf]].
|
|
Lösung: [[rel:depends_on leitbild-review#Weekly Review]].
|
|
"""
|
|
|
|
# Verlängerter Text, um Split > 1 zu erzwingen (bei Target 50)
|
|
TEST_MARKDOWN_SLIDING = """
|
|
---
|
|
id: 20251212-test-legacy
|
|
title: Fließtext Protokoll
|
|
type: journal
|
|
status: active
|
|
---
|
|
Dies ist der erste Absatz. Er muss lang genug sein, damit der Chunker ihn schneidet.
|
|
Wir schreiben hier über Rituale wie [[leitbild-rituale-system]] und viele andere Dinge.
|
|
Das Wetter ist schön und die Programmierung läuft gut. Dies sind Füllsätze für Länge.
|
|
|
|
Dies ist der zweite Absatz. Er ist durch eine Leerzeile getrennt und sollte einen neuen Kontext bilden.
|
|
Auch hier schreiben wir viel Text, damit die Token-Anzahl die Grenze von 50 Tokens überschreitet.
|
|
Das System muss hier splitten.
|
|
"""
|
|
|
|
class TestFinalWP15Integration(unittest.TestCase):
|
|
|
|
_analyzer_instance = None
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls._analyzer_instance = SemanticAnalyzer()
|
|
chunker._semantic_analyzer_instance = cls._analyzer_instance
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
# FIX: Kein explizites Loop-Closing hier, um RuntimeError zu vermeiden
|
|
pass
|
|
|
|
def test_a_smart_edge_allocation(self):
|
|
"""A: Prüft Smart Edge Allocation (LLM-Filter)."""
|
|
config = get_config_for_test('by_heading', enable_smart_edge=True)
|
|
|
|
chunks = asyncio.run(chunker.assemble_chunks(
|
|
note_id=TEST_NOTE_ID_SMART,
|
|
md_text=TEST_MARKDOWN_SMART,
|
|
note_type='concept',
|
|
config=config
|
|
))
|
|
|
|
self.assertTrue(len(chunks) >= 2, f"A1 Fehler: Erwartete >= 2 Chunks, bekam {len(chunks)}")
|
|
print(f" -> Chunks generiert (Smart): {len(chunks)}")
|
|
|
|
def test_b_backward_compatibility(self):
|
|
"""B: Prüft Sliding Window (Legacy)."""
|
|
config = get_config_for_test('sliding_window', enable_smart_edge=False)
|
|
|
|
chunks = asyncio.run(chunker.assemble_chunks(
|
|
note_id=TEST_NOTE_ID_LEGACY,
|
|
md_text=TEST_MARKDOWN_SLIDING,
|
|
note_type='journal',
|
|
config=config
|
|
))
|
|
|
|
# Sliding Window muss bei diesem langen Text > 1 Chunk liefern
|
|
self.assertTrue(len(chunks) >= 2, f"B1 Fehler: Sliding Window lieferte nur {len(chunks)} Chunk(s). Split defekt.")
|
|
|
|
# Check: Keine LLM Kanten (da deaktiviert)
|
|
injected = re.search(r'\[\[rel:', chunks[0].text)
|
|
self.assertIsNone(injected, "B2 Fehler: LLM-Kanten trotz Deaktivierung gefunden!")
|
|
print(f" -> Chunks generiert (Legacy): {len(chunks)}")
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main() |