| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- # -*- coding: utf-8 -*-
- """
- JamSpell-Korrekturschicht.
- Neuronaler kontextueller Spellchecker (~0.2ms/Wort).
- """
- from pathlib import Path
- from trixy_core.stt.layers.base import CorrectionLayer
- from trixy_core.utils.debug import pdebug, pwarn
- try:
- import jamspell
- _HAS_JAMSPELL = True
- except ImportError:
- _HAS_JAMSPELL = False
- class JamSpellLayer(CorrectionLayer):
- """JamSpell neuronale kontextuelle Korrektur."""
- NAME = "jamspell"
- def __init__(self) -> None:
- self._corrector: "jamspell.TSpellCorrector | None" = None
- self._protected_words: set[str] = set()
- # Platzhalter fuer geschuetzte Woerter waehrend Korrektur
- self._placeholder_map: dict[str, str] = {}
- def is_available(self) -> bool:
- """Prueft ob jamspell installiert ist."""
- return _HAS_JAMSPELL
- def initialize(self, config: dict, language: str, protected_words: list[str]) -> bool:
- """Laedt vortrainiertes JamSpell-Modell."""
- if not _HAS_JAMSPELL:
- return False
- model_path = config.get("jamspell_model_path", "")
- if not model_path or not Path(model_path).exists():
- pdebug(f"[JamSpell] Modell nicht gefunden: {model_path}")
- return False
- try:
- self._corrector = jamspell.TSpellCorrector()
- if not self._corrector.LoadLangModel(str(model_path)):
- pwarn(f"[JamSpell] Modell konnte nicht geladen werden: {model_path}")
- self._corrector = None
- return False
- self._protected_words = {w.lower() for w in protected_words}
- # Platzhalter generieren (nicht im Woerterbuch vorkommend)
- for i, word in enumerate(protected_words):
- self._placeholder_map[word.lower()] = f"XPROTX{i:03d}X"
- pdebug(f"[JamSpell] Modell geladen: {model_path}")
- return True
- except Exception as e:
- pwarn(f"[JamSpell] Initialisierung fehlgeschlagen: {e}")
- self._corrector = None
- return False
- def correct(self, text: str) -> str:
- """Korrigiert Text mit JamSpell (kontextbasiert)."""
- if not self._corrector or not text.strip():
- return text
- try:
- # Geschuetzte Woerter durch Platzhalter ersetzen
- processed = text.lower()
- used_placeholders: dict[str, str] = {}
- for word, placeholder in self._placeholder_map.items():
- if word in processed.split():
- processed = " ".join(
- placeholder if w == word else w
- for w in processed.split()
- )
- used_placeholders[placeholder] = word
- # JamSpell korrigieren
- corrected = self._corrector.FixFragment(processed)
- # Platzhalter zurueckersetzen
- for placeholder, original in used_placeholders.items():
- corrected = corrected.replace(placeholder.lower(), original)
- corrected = corrected.replace(placeholder, original)
- if corrected != text.lower():
- pdebug(f"[JamSpell] '{text}' → '{corrected}'")
- return corrected
- return text
- except Exception as e:
- pdebug(f"[JamSpell] Fehler bei Korrektur: {e}")
- return text
- def shutdown(self) -> None:
- """Gibt Ressourcen frei."""
- self._corrector = None
|