File size: 4,970 Bytes
d7b0955
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Regression tests for SmolLM2 / hybrid pipeline (no model download required)."""

from __future__ import annotations

import os
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))

from app.config import GENERATIVE_BACKEND, PIPELINE_MODE
from app.pipeline.alignment import align_documents, align_paragraph_sentences
from app.pipeline.candidate_validator import validate_candidate
from app.pipeline.generative import backend_kind, _clean_gen_text
from app.pipeline.grammar_fix import correct_text
from app.pipeline.orchestrator import rewrite_text


def test_backend_defaults() -> None:
    # Defaults come from env at import time; kind helper mirrors config
    assert backend_kind() in {"seq2seq", "causal"}
    assert GENERATIVE_BACKEND in {"seq2seq", "causal"}
    assert PIPELINE_MODE in {"hybrid", "generative", "classical"}
    print("backend defaults OK:", GENERATIVE_BACKEND, PIPELINE_MODE)


def test_clean_causal_wrappers() -> None:
    assert _clean_gen_text('Assistant: Hello there.') == "Hello there."
    assert _clean_gen_text('"Rewritten sentence."') == "Rewritten sentence."
    assert _clean_gen_text("Paraphrase: People live healthier lives.") == (
        "People live healthier lives."
    )
    print("clean wrappers OK")


def test_alignment_1to1() -> None:
    src = "Alpha is first. Beta is second."
    cand = "Alpha comes first. Beta comes second."
    units = align_paragraph_sentences(src, cand)
    assert len(units) == 2
    assert all(u.kind == "1:1" for u in units)
    print("alignment 1:1 OK")


def test_alignment_preserves_paragraphs() -> None:
    src = "One. Two.\n\nThree."
    cand = "Uno. Dos.\n\nTres."
    units = align_documents(src, cand)
    idxs = {u.paragraph_index for u in units}
    assert 0 in idxs and 1 in idxs
    print("alignment paragraphs OK:", len(units), "units")


def test_truncated_rejected() -> None:
    orig = (
        "Nowadays many people are living an unhealthy life because they don't have enough time. "
        "Eating fast foods is becoming very common and people don't realize how much it affects their health."
    )
    truncated = (
        "Fast food is becoming very common because many people don't realize "
        "how much it affects their health."
    )
    v = validate_candidate(orig, truncated, min_meaning=0.5)
    assert not v.ok
    assert "length" in v.reasons or "coverage" in v.reasons
    print("truncated rejected OK")


def test_hybrid_classical_without_ml() -> None:
    orig = (
        "Nowadays many peoples are living unhealthy life because they don't have enough times. "
        "Eating fast foods are becoming very common and peoples don't realizes how much it affect their health."
    )
    r = rewrite_text(
        orig,
        tone="Neutral",
        strength=1,
        preserve_length=True,
        ml_polish=False,
    )
    out = r.text.lower()
    assert "peoples" not in out
    assert "an unhealthy life" in out
    assert "affects" in out
    assert "enough time" in out
    # Both claims should survive classical path
    assert "unhealthy" in out
    assert "fast food" in out or "fast foods" in out
    assert r.pipeline_mode == "classical"
    print("hybrid classical-without-ml OK:", r.engine)


def test_hybrid_mode_with_ml_no_model() -> None:
    """When generative fails to load, hybrid still returns safe classical output."""
    orig = (
        "Nowadays many peoples are living unhealthy life because they don't have enough times. "
        "Eating fast foods are becoming very common and peoples don't realizes how much it affect their health."
    )
    # Force unavailable generative by not requiring it; hybrid runs classical+validate
    r = rewrite_text(
        orig,
        tone="Neutral",
        strength=1,
        preserve_length=True,
        ml_polish=True,
    )
    out = r.text.lower()
    assert "unhealthy" in out
    assert "health" in out
    # Must not collapse to single truncated claim only
    g = correct_text(orig).lower()
    assert "enough time" in out or "enough time" in g
    print("hybrid ml path OK mode=", r.pipeline_mode, "engine=", r.engine)
    if r.hybrid:
        print(
            "  units=",
            r.hybrid.units,
            "kept=",
            r.hybrid.classical_kept,
            "regen=",
            r.hybrid.regenerated,
            "accepted=",
            r.hybrid.gen_accepted,
            "reverted=",
            r.hybrid.reverted_source,
        )


if __name__ == "__main__":
    test_backend_defaults()
    test_clean_causal_wrappers()
    test_alignment_1to1()
    test_alignment_preserves_paragraphs()
    test_truncated_rejected()
    test_hybrid_classical_without_ml()
    test_hybrid_mode_with_ml_no_model()
    print("\nALL SMOLLM2 / HYBRID PIPELINE TESTS PASSED")