| """Shared data models for the structural rewrite engine."""
|
|
|
| from __future__ import annotations
|
|
|
| from dataclasses import dataclass, field
|
| from typing import Any
|
|
|
|
|
| @dataclass
|
| class DocumentBlock:
|
| """A contiguous document region with rewrite policy."""
|
|
|
| text: str
|
| kind: str = "paragraph"
|
| rewriteable: bool = True
|
| index: int = 0
|
| meta: dict[str, Any] = field(default_factory=dict)
|
|
|
|
|
| @dataclass
|
| class SentenceSlots:
|
| """Constituent spans extracted for template fill."""
|
|
|
| text: str
|
| subject: str = ""
|
| verb: str = ""
|
| verb_phrase: str = ""
|
| object: str = ""
|
| place: str = ""
|
| time: str = ""
|
| manner: str = ""
|
| negation: str = ""
|
| leftover: str = ""
|
| entities: list[str] = field(default_factory=list)
|
| auxiliaries: list[str] = field(default_factory=list)
|
| subject_is_proper: bool = False
|
| verb_starts_with_aux: bool = False
|
| confidence: float = 0.0
|
| sentence_type: str = "unsupported"
|
| reasons: list[str] = field(default_factory=list)
|
|
|
|
|
| @dataclass
|
| class TemplateCandidate:
|
| template_id: str
|
| confidence: float
|
|
|
|
|
| @dataclass
|
| class LexicalChange:
|
| """One context-validated vocabulary substitution."""
|
|
|
| original: str
|
| replacement: str
|
| token_index: int
|
| lemma: str = ""
|
| synset_id: str = ""
|
| confidence: float = 0.0
|
|
|
|
|
| @dataclass
|
| class RewritePlan:
|
| """Decision object before generation."""
|
|
|
| safe: bool
|
| slots: SentenceSlots | None = None
|
| template_id: str = ""
|
| candidates: list[TemplateCandidate] = field(default_factory=list)
|
| fixed_spans: list[str] = field(default_factory=list)
|
| movable: list[str] = field(default_factory=list)
|
| skip_reason: str = ""
|
| confidence: float = 0.0
|
|
|
|
|
| @dataclass
|
| class SentenceRecord:
|
| """Per-sentence rewrite report."""
|
|
|
| index: int
|
| original: str
|
| rewritten: str
|
| confidence: float
|
| status: str
|
| template_id: str = ""
|
| sentence_type: str = ""
|
| reasons: list[str] = field(default_factory=list)
|
| block_index: int = 0
|
| lexical_changes: list[LexicalChange] = field(default_factory=list)
|
|
|
|
|
| @dataclass
|
| class EngineStats:
|
| batches: int = 0
|
| blocks: int = 0
|
| sentences: int = 0
|
| rewritten: int = 0
|
| skipped: int = 0
|
| reverted: int = 0
|
| passthrough: int = 0
|
| lexical_refined: int = 0
|
| forced_rewrites: int = 0
|
| paraphrased: int = 0
|
| seconds: float = 0.0
|
| reasons: dict[str, int] = field(default_factory=dict)
|
|
|
| def bump(self, reason: str) -> None:
|
| key = (reason or "other").split(":")[0]
|
| self.reasons[key] = self.reasons.get(key, 0) + 1
|
|
|
|
|
| @dataclass
|
| class EngineResult:
|
| text: str
|
| sentences: list[SentenceRecord] = field(default_factory=list)
|
| skipped: list[SentenceRecord] = field(default_factory=list)
|
| mapping: list[tuple[str, str]] = field(default_factory=list)
|
| stats: EngineStats = field(default_factory=EngineStats)
|
| notes: str = ""
|
| engine: str = "structural-reorder"
|
| input_words: int = 0
|
| output_words: int = 0
|
| changed: bool = False
|
| similarity: float = 1.0
|
|
|