"""Smart Humanize on one sample per subject (real models + Groq), with an independent audit of every sentence: python devtools/batch.py [--passes 3] [--only medicine,law] [--out devtools/logs/batch.md] Per subject: AI score before -> after, sentences rewritten, lost numbers / citations / terms, meaning similarity, publication-rule violations, time. The full before/after text of every sentence goes to the --out file.""" import argparse import os import sys import time from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) sys.path.insert(0, str(Path(__file__).resolve().parent)) import env # noqa: E402 env.load() os.environ.setdefault("LT_MODE", "off") import e2e # noqa: E402 from samples_domains import DOMAINS # noqa: E402 def main(): ap = argparse.ArgumentParser() ap.add_argument("--passes", type=int, default=3) ap.add_argument("--only", default="") ap.add_argument("--out", default=str(ROOT / "devtools" / "logs" / "batch.md")) a = ap.parse_args() import humanizer as H import meaning as M import pubrules as PR import smart as S import textparse as TP want = [x.strip() for x in a.only.split(",") if x.strip()] names = [n for n in DOMAINS if not want or any(w in n for w in want)] rows, md = [], ["# Smart Humanize by subject\n"] quiet = lambda frac, desc=None: None for name in names: text = DOMAINS[name] t = time.time() try: r = S.smart_text(text, 0, a.passes, 0.9, "Auto", 0.80, 0.50, quiet) except Exception as err: # one subject failing must not hide the others print(f"{name}: FAILED {type(err).__name__}: {err}", flush=True) rows.append((name, "FAILED", str(err)[:60])) continue secs = time.time() - t so, sn = H.split_sentences(r["orig"]), H.split_sentences(r["new"]) lost = e2e.integrity(r["orig"], r["new"]) n_lost = sum(len(v) for v in lost.values()) md.append(f"\n## {name}: {r['before']['pct']}% -> {r['after']['pct']}% ({secs:.0f}s)\n") md += [f"- {line}" for line in r["log"]] md.append(f"- {r['note'].strip()}") issues, sims, changed = [], [], 0 if len(so) != len(sn): issues.append(f"sentence count {len(so)} -> {len(sn)}") md.append(f"\n**Sentence count changed.** Output:\n\n{r['new']}\n") else: sm = M.similarities(list(zip(so, sn))) for k, (o, n, s) in enumerate(zip(so, sn, sm), 1): if o.strip() == n.strip(): md.append(f"\n{k}. (unchanged) {o}") continue changed += 1 sims.append(s) v = PR.violations(o, n) + ([TP.symbol_issue(o, n)] if TP.symbol_issue(o, n) else []) if v: issues.append(f"s{k}: " + "; ".join(v)) md.append(f"\n{k}. meaning {s:.2f}" + (f" | RULES: {'; '.join(v)}" if v else "") + f"\n - {o}\n + {n}") if n_lost: issues.append(f"lost {lost}") rows.append((name, r["before"]["pct"], r["after"]["pct"], f"{changed}/{len(so)}", n_lost, f"{min(sims):.2f}" if sims else "-", f"{sum(sims) / len(sims):.2f}" if sims else "-", len([i for i in issues if i.startswith('s')]), f"{secs:.0f}s", issues)) print(f"{name:26} AI {r['before']['pct']:3}% -> {r['after']['pct']:3}% | rewritten {changed}/{len(so)} | " f"lost {n_lost} | min sim {rows[-1][5]} | {secs:.0f}s" + (f" | {issues}" if issues else ""), flush=True) md.insert(1, "\n| Subject | AI before | AI after | Rewritten | Lost items | Min meaning | Mean meaning | Rule flags | Time |" "\n|---|---|---|---|---|---|---|---|---|\n" + "\n".join("| " + " | ".join(str(x) for x in row[:9]) + " |" for row in rows if len(row) > 3) + "\n") Path(a.out).parent.mkdir(parents=True, exist_ok=True) Path(a.out).write_text("\n".join(md), encoding="utf-8") import groqai as G print("groq:", G.status()) print("report:", a.out) if __name__ == "__main__": main()