File size: 4,962 Bytes
8f6d79d 7ea9869 7b67b50 8f6d79d 31bce5e 7ea9869 31bce5e 7ea9869 8f6d79d 7b67b50 8f6d79d 7b67b50 8f6d79d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | """Rewrite planning — decide safety and ranked template candidates."""
from __future__ import annotations
from app.engine.classify import classify_sentence, is_rewriteable_type
from app.engine.models import RewritePlan, SentenceSlots, TemplateCandidate
from app.engine.parse import extract_slots
from app.engine.templates import can_swap_initial_subordinate, rank_templates
from app.engine.voice import active_to_passive
def build_plan(text: str, *, min_confidence: float = 0.55) -> RewritePlan:
"""Create a rewrite plan without generating text yet."""
raw = (text or "").strip()
if not raw:
return RewritePlan(safe=False, skip_reason="empty")
kind = classify_sentence(raw)
if kind == "because_clause":
return RewritePlan(
safe=True,
template_id="because_front",
candidates=[TemplateCandidate("because_front", 0.85)],
confidence=0.85,
slots=SentenceSlots(text=raw, sentence_type=kind, confidence=0.85),
movable=["because_clause"],
fixed_spans=[],
)
if kind == "complex":
if can_swap_initial_subordinate(raw):
slots = extract_slots(raw)
slots.confidence = 0.76
return RewritePlan(
safe=True,
template_id="complex_clause_swap",
candidates=[TemplateCandidate("complex_clause_swap", 0.76)],
confidence=0.76,
slots=slots,
movable=["subordinate_clause"],
fixed_spans=list(slots.entities),
)
# Other complex prose still reaches paraphrase/lexical/ensure via finalize.
passive_candidate = active_to_passive(raw)
if passive_candidate:
slots = extract_slots(raw)
slots.confidence = 0.7
return RewritePlan(
safe=True,
template_id="active_to_passive",
candidates=[TemplateCandidate("active_to_passive", 0.7)],
confidence=0.7,
slots=slots,
movable=["subject", "object"],
fixed_spans=list(slots.entities),
)
return RewritePlan(
safe=False,
skip_reason="complex",
confidence=0.0,
slots=SentenceSlots(text=raw, sentence_type=kind),
)
if not is_rewriteable_type(kind):
passive_candidate = active_to_passive(raw)
if passive_candidate:
slots = extract_slots(raw)
slots.confidence = 0.7
return RewritePlan(
safe=True,
template_id="active_to_passive",
candidates=[TemplateCandidate("active_to_passive", 0.7)],
confidence=0.7,
slots=slots,
movable=["subject", "object"],
fixed_spans=list(slots.entities),
)
return RewritePlan(
safe=False,
skip_reason=kind,
confidence=0.0,
slots=SentenceSlots(text=raw, sentence_type=kind),
)
slots = extract_slots(raw)
if "low_confidence" in slots.reasons or slots.confidence < min_confidence:
return RewritePlan(
safe=False,
skip_reason="low_confidence",
confidence=slots.confidence,
slots=slots,
)
if any(r.startswith("skip:") for r in slots.reasons):
return RewritePlan(
safe=False,
skip_reason=slots.reasons[0],
confidence=slots.confidence,
slots=slots,
)
candidates = rank_templates(slots)
structural_ids = {candidate.template_id for candidate in candidates}
if not structural_ids or structural_ids <= {"subj_verb_object"}:
if active_to_passive(raw):
candidates.append(TemplateCandidate("active_to_passive", 0.7))
if not candidates:
return RewritePlan(
safe=False,
skip_reason="no_template",
confidence=slots.confidence,
slots=slots,
)
# Filter by min confidence
candidates = [c for c in candidates if c.confidence >= min_confidence]
if not candidates:
return RewritePlan(
safe=False,
skip_reason="low_template_confidence",
confidence=slots.confidence,
slots=slots,
)
fixed = list(slots.entities)
if slots.negation:
fixed.append(slots.negation)
movable = [x for x in ("time", "manner", "place") if getattr(slots, x, "")]
return RewritePlan(
safe=True,
slots=slots,
template_id=candidates[0].template_id,
candidates=candidates,
fixed_spans=fixed,
movable=movable,
confidence=candidates[0].confidence,
)
|