File size: 6,491 Bytes
ffb5352 f47a29e ffb5352 24a79a8 ffb5352 | 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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | """Voice flips, coordinated-verb splitting, and per-request structure rotation."""
from __future__ import annotations
from app.engine import orchestrator
from app.engine.split import try_split_coordinated_verbs, try_split_long_sentence
from app.engine.variation import rotate
from app.engine.voice import active_to_passive, passive_to_active
def test_passive_to_active_recovers_the_agent():
text = (
"Areas for improvement can be identified by businesses that actively "
"listen to customer feedback."
)
assert passive_to_active(text) == (
"Businesses that actively listen to customer feedback can identify "
"areas for improvement."
)
def test_passive_to_active_keeps_perfect_and_past_tense():
assert passive_to_active("The budget has been approved by the committee.") == (
"The committee has approved the budget."
)
assert passive_to_active("The report was reviewed by readers yesterday.") == (
"Readers reviewed the report yesterday."
)
def test_passive_to_active_needs_an_explicit_agent():
assert passive_to_active("The window was broken.") is None
def test_passive_to_active_skips_negation_needing_do_support():
# "The editor did not correct mistakes" cannot be built by surface rebuild.
assert passive_to_active("Mistakes were not corrected by the editor.") is None
def test_active_to_passive_refuses_to_relocate_a_fronted_phrase():
"""Leftovers land after the agent, which would strip the opener's scope."""
text = (
"By consistently delivering high-quality service, organizations can "
"establish a strong reputation."
)
assert active_to_passive(text) is None
def test_active_to_passive_refuses_to_strand_a_preverbal_adverb():
assert active_to_passive(
"Organizations can also encourage positive recommendations."
) is None
assert active_to_passive("Maria carefully submitted the final report.") is None
def test_active_to_passive_keeps_hyphenated_compounds_intact():
result = active_to_passive("The team published the high-quality version last week.")
assert result == "The high-quality version was published by the team last week."
def test_active_and_passive_are_not_mutually_reachable():
text = "Readers reviewed the report yesterday."
passive = active_to_passive(text)
assert passive is not None
assert passive_to_active(passive) is not None
def test_active_to_passive_refuses_misattached_coordinate_tails():
"""spaCy may hang list verbs as advcl; rebuilding would strand them."""
text = (
"Customers appreciate companies that respond quickly to their questions, "
"resolve issues efficiently, and treat them with respect."
)
assert active_to_passive(text) is None
def test_unfront_opener_moves_prepositional_prefix():
from app.engine.templates import try_unfront_opener
assert try_unfront_opener(
"For the success of any business, supplying excellent customer service "
"is vital."
) == (
"Supplying excellent customer service is vital for the success of any "
"business."
)
assert try_unfront_opener(
"By consistently delivering high-quality service, organizations can "
"establish a strong reputation."
) == (
"Organizations can establish a strong reputation by consistently "
"delivering high-quality service."
)
# Discourse connectives must stay fronted.
assert try_unfront_opener(
"However, the committee approved the budget today."
) is None
def test_coordinated_split_repeats_subject_instead_of_stranding_a_verb():
text = (
"By consistently delivering high-quality service, organizations can "
"establish a strong reputation, gain customer retention, and encourage "
"positive word-of-mouth recommendations."
)
assert try_split_coordinated_verbs(text) == (
"By consistently delivering high-quality service, organizations can "
"establish a strong reputation and gain customer retention. "
"Organizations can also encourage positive word-of-mouth recommendations."
)
def test_coordinated_split_refuses_ambiguous_relative_clause():
"""The verb list belongs to "organizations", not to "Customers"."""
text = (
"Customers appreciate organizations that respond promptly to their "
"questions, resolve issues efficiently, and treat them with respect."
)
assert try_split_coordinated_verbs(text) is None
def test_plain_split_refuses_to_strand_a_bare_verb_phrase():
text = (
"By consistently delivering high-quality service, organizations can "
"establish a strong reputation, gain customer retention, and encourage "
"positive word-of-mouth recommendations."
)
result = try_split_long_sentence(text)
assert result is None or "Encourage positive" not in result
def test_rotation_keeps_weak_options_behind_the_band():
options = [("best", 0.90), ("near", 0.78), ("weak", 0.40)]
for seed in range(6):
ordered = rotate(
options, seed=seed, confidence_of=lambda item: item[1]
)
assert ordered[-1] == ("weak", 0.40)
assert set(ordered) == set(options)
def test_rotation_without_seed_preserves_order():
options = [("a", 0.9), ("b", 0.8)]
assert rotate(options, seed=None, confidence_of=lambda i: i[1]) == options
def test_same_sentence_takes_different_structures(structural_variation):
text = "The teacher graded the papers carefully yesterday."
outputs = {
orchestrator.rewrite_document(
text,
use_lexical_refinement=False,
use_paraphrase=False,
use_minilm_safety=False,
).text
for _ in range(12)
}
assert len(outputs) > 1
for candidate in outputs:
assert "teacher" in candidate
assert "papers" in candidate
def test_directional_place_is_not_fronted():
""""To school, Ram went" is marked; locative fronting stays available."""
outputs = {
orchestrator.rewrite_document(
"Ram went to school yesterday happily.",
use_lexical_refinement=False,
use_paraphrase=False,
use_minilm_safety=False,
variation_seed=seed,
).text
for seed in range(1, 10)
}
for candidate in outputs:
assert not candidate.lower().startswith("to school,")
|