"""Deterministic post-edits that push prose toward human statistical patterns. Detectors often score even sentence length, stock transitions, and Latinate diction. These transforms keep meaning while breaking that smoothness. """ from __future__ import annotations import random import re # Stable seed per process so the same text doesn't jitter wildly across identical runs # unless content changes. Still varies by text hash. def _rng_for(text: str) -> random.Random: return random.Random(hash(text) & 0xFFFFFFFF) PHRASE_SWAPS: list[tuple[re.Pattern[str], str]] = [ (re.compile(r"\bIt is important to note that\b", re.I), ""), (re.compile(r"\bIt is worth noting that\b", re.I), ""), (re.compile(r"\bIt should be noted that\b", re.I), ""), (re.compile(r"\bIn today's (?:fast-paced |ever-evolving )?world,?\s*", re.I), ""), (re.compile(r"\bIn conclusion,?\s*", re.I), ""), (re.compile(r"\bTo summarize,?\s*", re.I), ""), (re.compile(r"\bOverall,?\s*", re.I), ""), (re.compile(r"\bFurthermore,?\s*", re.I), ""), (re.compile(r"\bMoreover,?\s*", re.I), ""), (re.compile(r"\bAdditionally,?\s*", re.I), "Also, "), (re.compile(r"\bConsequently,?\s*", re.I), "So "), (re.compile(r"\bThus,?\s*", re.I), "So "), (re.compile(r"\bTherefore,?\s*", re.I), "So "), (re.compile(r"\bIn order to\b", re.I), "to"), (re.compile(r"\bdue to the fact that\b", re.I), "because"), (re.compile(r"\ba large number of\b", re.I), "many"), (re.compile(r"\ba myriad of\b", re.I), "many"), (re.compile(r"\butilize\b", re.I), "use"), (re.compile(r"\butilizes\b", re.I), "uses"), (re.compile(r"\butilized\b", re.I), "used"), (re.compile(r"\butilizing\b", re.I), "using"), (re.compile(r"\bfacilitate\b", re.I), "help"), (re.compile(r"\bfacilitates\b", re.I), "helps"), (re.compile(r"\bfacilitated\b", re.I), "helped"), (re.compile(r"\bfacilitating\b", re.I), "helping"), (re.compile(r"\bimplementation of\b", re.I), "putting in place "), (re.compile(r"\bimplementations\b", re.I), "rollouts"), (re.compile(r"\bimplementation\b", re.I), "rollout"), (re.compile(r"\bimplement\b", re.I), "roll out"), (re.compile(r"\bimplements\b", re.I), "rolls out"), (re.compile(r"\bimplemented\b", re.I), "rolled out"), (re.compile(r"\bimplementing\b", re.I), "rolling out"), (re.compile(r"\bleverage\b", re.I), "use"), (re.compile(r"\bleverages\b", re.I), "uses"), (re.compile(r"\bleveraged\b", re.I), "used"), (re.compile(r"\bleveraging\b", re.I), "using"), (re.compile(r"\bharness\b", re.I), "use"), (re.compile(r"\bharnesses\b", re.I), "uses"), (re.compile(r"\bharnessed\b", re.I), "used"), (re.compile(r"\bharnessing\b", re.I), "using"), (re.compile(r"\brobust\b", re.I), "solid"), (re.compile(r"\bseamless(?:ly)?\b", re.I), "smooth"), (re.compile(r"\bpivotal\b", re.I), "important"), (re.compile(r"\bcomprehensive\b", re.I), "full"), (re.compile(r"\bmultifaceted\b", re.I), "varied"), (re.compile(r"\bcutting-edge\b", re.I), "new"), (re.compile(r"\bgame-?changer\b", re.I), "big shift"), (re.compile(r"\bdelve(?:s|d)? into\b", re.I), "look at"), (re.compile(r"\bdive(?:s|d)? into\b", re.I), "look at"), (re.compile(r"\blandscape\b", re.I), "field"), (re.compile(r"\brealm\b", re.I), "area"), (re.compile(r"\btapestry\b", re.I), "mix"), (re.compile(r"\bembark(?:s|ed)? on\b", re.I), "start"), (re.compile(r"\bunderscores\b", re.I), "shows"), (re.compile(r"\bshowcases\b", re.I), "shows"), (re.compile(r"\bplays a crucial role in\b", re.I), "matters for"), (re.compile(r"\bserves as a testament to\b", re.I), "shows"), (re.compile(r"\bwhen it comes to\b", re.I), "for"), (re.compile(r"\bat the end of the day,?\s*", re.I), ""), (re.compile(r"\bin the ever-evolving\b", re.I), "in the changing"), (re.compile(r"\bnot only\s+(.+?)\s+but also\s+", re.I), r"\1 and "), ] CONTRACTIONS = [ (re.compile(r"\bdo not\b"), "don't"), (re.compile(r"\bdoes not\b"), "doesn't"), (re.compile(r"\bdid not\b"), "didn't"), (re.compile(r"\bis not\b"), "isn't"), (re.compile(r"\bare not\b"), "aren't"), (re.compile(r"\bwas not\b"), "wasn't"), (re.compile(r"\bwere not\b"), "weren't"), (re.compile(r"\bwill not\b"), "won't"), (re.compile(r"\bcannot\b"), "can't"), (re.compile(r"\bcould not\b"), "couldn't"), (re.compile(r"\bwould not\b"), "wouldn't"), (re.compile(r"\bshould not\b"), "shouldn't"), (re.compile(r"\bit is\b"), "it's"), (re.compile(r"\bthat is\b"), "that's"), (re.compile(r"\bthere is\b"), "there's"), (re.compile(r"\bwe are\b"), "we're"), (re.compile(r"\bwe have\b"), "we've"), (re.compile(r"\byou are\b"), "you're"), (re.compile(r"\bthey are\b"), "they're"), (re.compile(r"\bI am\b"), "I'm"), ] def apply_phrase_swaps(text: str) -> str: out = text for pattern, repl in PHRASE_SWAPS: out = pattern.sub(repl, out) # Clean doubled spaces / empty clause leftovers out = re.sub(r" {2,}", " ", out) out = re.sub(r"\s+([,.;:])", r"\1", out) out = re.sub(r"([.!?])\s*([a-z])", lambda m: f"{m.group(1)} {m.group(2).upper()}", out) return out def apply_contractions(text: str, tone: str) -> str: if tone == "Formal": # Light touch only pairs = CONTRACTIONS[:8] else: pairs = CONTRACTIONS out = text for pattern, repl in pairs: out = pattern.sub(repl, out) return out def _split_sentences(paragraph: str) -> list[str]: parts = re.split(r"(?<=[.!?])\s+", paragraph.strip()) return [p.strip() for p in parts if p.strip()] def burst_paragraph(paragraph: str, rng: random.Random) -> str: """Break uniform mid-length sentences; occasionally isolate a short line.""" sentences = _split_sentences(paragraph) if len(sentences) < 2: return paragraph.strip() rebuilt: list[str] = [] for sent in sentences: words = sent.split() # Split long even sentences into two when there's a natural comma/join if len(words) >= 22 and "," in sent and rng.random() < 0.55: left, right = sent.split(",", 1) left = left.strip() right = right.strip() if right and right[0].islower(): right = right[0].upper() + right[1:] if not left.endswith((".", "!", "?")): left = left + "." rebuilt.append(left) rebuilt.append(right if right.endswith((".", "!", "?")) else right + ".") else: rebuilt.append(sent) # Occasionally promote a short sentence to its own paragraph break marker pieces: list[str] = [] buf: list[str] = [] for sent in rebuilt: w = len(sent.split()) if w <= 8 and rng.random() < 0.35 and buf: pieces.append(" ".join(buf)) pieces.append(sent) buf = [] else: buf.append(sent) if buf: pieces.append(" ".join(buf)) return "\n\n".join(pieces) def stagger_openers(text: str, rng: random.Random) -> str: """Nudge a few paragraph openings away from tidy topic-sentence feel.""" openers = ["Still,", "And", "But", "Look,", "That said,", "Honestly,"] paras = [p.strip() for p in re.split(r"\n\s*\n", text) if p.strip()] if len(paras) < 2: return text out: list[str] = [] for i, para in enumerate(paras): if i == 0 or rng.random() > 0.28: out.append(para) continue first = para.split(" ", 1) # Don't double-prefix if para.split(",", 1)[0] in {o.rstrip(",") for o in openers}: out.append(para) continue if rng.random() < 0.5 and len(para.split()) > 6: opener = rng.choice(openers) rest = para[0].lower() + para[1:] if para and para[0].isupper() else para # "And" / "But" don't need comma always if opener in {"And", "But"}: out.append(f"{opener} {rest}") else: out.append(f"{opener} {rest}") else: out.append(para) return "\n\n".join(out) def tidy_artifacts(text: str) -> str: text = re.sub(r"\n{3,}", "\n\n", text) text = re.sub(r" {2,}", " ", text) # Fix "Also, ," style leftovers text = re.sub(r",\s*,", ",", text) text = re.sub(r"^\s*,\s*", "", text, flags=re.M) lines = [] for para in text.split("\n"): lines.append(para.strip() if para.strip() else "") return "\n".join(lines).strip() def mechanical_humanize(text: str, tone: str = "Neutral") -> str: """Apply non-LLM humanizing transforms.""" if not text.strip(): return text rng = _rng_for(text) out = apply_phrase_swaps(text) out = apply_contractions(out, tone) paras = [p.strip() for p in re.split(r"\n\s*\n", out) if p.strip()] bursted = [burst_paragraph(p, rng) for p in paras] # burst_paragraph may introduce new paragraph breaks flat = "\n\n".join(bursted) flat = stagger_openers(flat, rng) return tidy_artifacts(flat)