idnameraj commited on
Commit
bb7b252
·
verified ·
1 Parent(s): 7c28715

Upload 100 files

Browse files
app/pipeline/__pycache__/candidate_validator.cpython-311.pyc CHANGED
Binary files a/app/pipeline/__pycache__/candidate_validator.cpython-311.pyc and b/app/pipeline/__pycache__/candidate_validator.cpython-311.pyc differ
 
app/pipeline/__pycache__/generative.cpython-311.pyc CHANGED
Binary files a/app/pipeline/__pycache__/generative.cpython-311.pyc and b/app/pipeline/__pycache__/generative.cpython-311.pyc differ
 
app/pipeline/__pycache__/orchestrator.cpython-311.pyc CHANGED
Binary files a/app/pipeline/__pycache__/orchestrator.cpython-311.pyc and b/app/pipeline/__pycache__/orchestrator.cpython-311.pyc differ
 
app/pipeline/candidate_validator.py CHANGED
@@ -63,16 +63,78 @@ def _extract_propers(text: str) -> set[str]:
63
  return found
64
 
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  def _length_ok(original: str, candidate: str) -> bool:
67
  ow = max(1, len(original.split()))
68
  cw = len(candidate.split())
69
- if cw < max(3, ow // 3):
 
 
 
 
 
70
  return False
71
  if cw > int(ow * 2.2) + 8:
72
  return False
73
  return True
74
 
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  def _meaning_score(original: str, candidate: str) -> float | None:
77
  """MiniLM cosine if available; None if model missing."""
78
  try:
@@ -112,6 +174,9 @@ def validate_candidate(
112
  if not _length_ok(o, c):
113
  reasons.append("length")
114
 
 
 
 
115
  surf = _surface_sim(o, c)
116
  if surf >= max_surface:
117
  reasons.append("too_similar")
 
63
  return found
64
 
65
 
66
+ _STOP = frozenset(
67
+ """
68
+ a an the and or but if in on at to for of as by with from into over after
69
+ before about than then so too very more most such that this these those
70
+ it its they them their we our you your he she his her is are was were be
71
+ been being have has had do does did will would can could should may might
72
+ not no nor also just only own same other another each every both few many
73
+ much some any all because while when where how what which who whom
74
+ """.split()
75
+ )
76
+
77
+
78
+ def _content_tokens(text: str) -> set[str]:
79
+ """Lowercased content words (length ≥4) used for coverage checks."""
80
+ toks = re.findall(r"[a-zA-Z']+", text.lower())
81
+ out: set[str] = set()
82
+ for t in toks:
83
+ t = t.strip("'")
84
+ if len(t) < 4 or t in _STOP:
85
+ continue
86
+ # Light stem: drop trailing s/ed/ing for overlap
87
+ stem = t
88
+ if t.endswith("ing") and len(t) > 5:
89
+ stem = t[:-3]
90
+ elif t.endswith("ed") and len(t) > 4:
91
+ stem = t[:-2]
92
+ elif t.endswith("es") and len(t) > 4:
93
+ stem = t[:-2]
94
+ elif t.endswith("s") and len(t) > 4:
95
+ stem = t[:-1]
96
+ out.add(stem)
97
+ return out
98
+
99
+
100
+ def _sentence_count(text: str) -> int:
101
+ parts = re.split(r"[.!?]+", (text or "").strip())
102
+ return len([p for p in parts if p.strip()])
103
+
104
+
105
  def _length_ok(original: str, candidate: str) -> bool:
106
  ow = max(1, len(original.split()))
107
  cw = len(candidate.split())
108
+ # Reject half-dropped paraphrases (FLAN often keeps only the last sentence).
109
+ if ow <= 80:
110
+ min_words = max(3, int(ow * 0.72))
111
+ else:
112
+ min_words = max(3, int(ow * 0.55))
113
+ if cw < min_words:
114
  return False
115
  if cw > int(ow * 2.2) + 8:
116
  return False
117
  return True
118
 
119
 
120
+ def _coverage_ok(original: str, candidate: str) -> bool:
121
+ """Reject dropped sentences / severe content loss; allow normal paraphrases."""
122
+ o_sents = _sentence_count(original)
123
+ c_sents = _sentence_count(candidate)
124
+ # Short multi-sentence passages must keep every sentence (anti half-drop).
125
+ if 2 <= o_sents <= 5 and c_sents < o_sents:
126
+ return False
127
+
128
+ o_toks = _content_tokens(original)
129
+ if len(o_toks) >= 5:
130
+ c_toks = _content_tokens(candidate)
131
+ overlap = len(o_toks & c_toks) / max(1, len(o_toks))
132
+ # Only fail on severe stem loss (paraphrases often rewrite many content words).
133
+ if overlap < 0.32:
134
+ return False
135
+ return True
136
+
137
+
138
  def _meaning_score(original: str, candidate: str) -> float | None:
139
  """MiniLM cosine if available; None if model missing."""
140
  try:
 
174
  if not _length_ok(o, c):
175
  reasons.append("length")
176
 
177
+ if not _coverage_ok(o, c):
178
+ reasons.append("coverage")
179
+
180
  surf = _surface_sim(o, c)
181
  if surf >= max_surface:
182
  reasons.append("too_similar")
app/pipeline/generative.py CHANGED
@@ -35,6 +35,7 @@ _failed = False
35
  _backend: str | None = None
36
 
37
  _SHARED_RULES = (
 
38
  "Use different wording and vary sentence structure — do not copy phrases "
39
  "from the input almost verbatim.\n"
40
  "Keep every claim and the same polarity. Do not flip negatives or antonyms.\n"
 
35
  _backend: str | None = None
36
 
37
  _SHARED_RULES = (
38
+ "Keep ALL sentences and claims from the paragraph — do not drop or merge away ideas.\n"
39
  "Use different wording and vary sentence structure — do not copy phrases "
40
  "from the input almost verbatim.\n"
41
  "Keep every claim and the same polarity. Do not flip negatives or antonyms.\n"
app/pipeline/orchestrator.py CHANGED
@@ -146,7 +146,7 @@ def _accept_generative(source: str, draft: str) -> bool:
146
 
147
  def _hard_fail(reasons: list[str]) -> bool:
148
  for r in reasons:
149
- if r == "polarity" or r in {"numbers", "quotes"}:
150
  return True
151
  if r.startswith("meaning") or r.startswith("entity"):
152
  return True
 
146
 
147
  def _hard_fail(reasons: list[str]) -> bool:
148
  for r in reasons:
149
+ if r in {"polarity", "numbers", "quotes", "length", "coverage"}:
150
  return True
151
  if r.startswith("meaning") or r.startswith("entity"):
152
  return True
scripts/test_quality_pipeline.py CHANGED
@@ -31,6 +31,21 @@ def test_polarity() -> None:
31
  print("polarity OK")
32
 
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  def test_validator_rejects_flips() -> None:
35
  orig = (
36
  "Nowadays many people are living an unhealthy life because they don't have enough time. "
@@ -151,6 +166,7 @@ def test_classical_fallback() -> None:
151
  if __name__ == "__main__":
152
  test_polarity()
153
  test_validator_rejects_flips()
 
154
  test_validator_rejects_near_copy()
155
  test_ranker_rejects_near_copy_prefers_paraphrase()
156
  test_ranker_prefers_faithful()
 
31
  print("polarity OK")
32
 
33
 
34
+ def test_validator_rejects_truncated() -> None:
35
+ orig = (
36
+ "Nowadays many people are living an unhealthy life because they don't have enough time. "
37
+ "Eating fast foods is becoming very common and people don't realize how much it affects their health."
38
+ )
39
+ truncated = (
40
+ "Fast food is becoming very common because many people don't realize "
41
+ "how much it affects their health."
42
+ )
43
+ v = validate_candidate(orig, truncated, min_meaning=0.5)
44
+ assert not v.ok
45
+ assert "length" in v.reasons or "coverage" in v.reasons
46
+ print("validator rejects truncated OK:", v.reasons)
47
+
48
+
49
  def test_validator_rejects_flips() -> None:
50
  orig = (
51
  "Nowadays many people are living an unhealthy life because they don't have enough time. "
 
166
  if __name__ == "__main__":
167
  test_polarity()
168
  test_validator_rejects_flips()
169
+ test_validator_rejects_truncated()
170
  test_validator_rejects_near_copy()
171
  test_ranker_rejects_near_copy_prefers_paraphrase()
172
  test_ranker_prefers_faithful()