62 lines
2.9 KiB
Python
62 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
||
"""exp13 — гейты на выходах армов (пре-рег §1.3): эхо-rate / refusal / объём-коридор / полнота.
|
||
Читает diag/arms13/<ARM>/<ch>_<ci>.txt + diag/chunks.json (исходники zh). $0 (детерминированно).
|
||
Выход: diag/arms13/gates.json + печать таблицы.
|
||
"""
|
||
from __future__ import annotations
|
||
import json, re
|
||
from pathlib import Path
|
||
|
||
DIAG = Path("/home/ubuntu/books/gu-zhenren/diag")
|
||
OUT = DIAG / "arms13"
|
||
TARGETS = [(5, 0), (5, 1), (7, 0), (7, 1), (14, 0), (14, 1)]
|
||
LEN_BOUNDS = (2.2, 4.2) # zh→ru приёмки
|
||
REFUSAL = re.compile(r"(?i)\b(я не могу|не буду переводить|as an ai|i cannot|i'm sorry|извините, но я|не могу выполнить|против правил)\b")
|
||
HAN = re.compile(r"[一-鿿㐀-䶿]")
|
||
|
||
|
||
def han_ratio(t: str) -> float:
|
||
ns = [c for c in t if not c.isspace()]
|
||
if not ns:
|
||
return 1.0
|
||
return sum(1 for c in ns if HAN.match(c)) / len(ns)
|
||
|
||
|
||
def main() -> None:
|
||
chunks = json.loads((DIAG / "chunks.json").read_text(encoding="utf-8"))
|
||
arms = sorted([p.name for p in OUT.iterdir() if p.is_dir()])
|
||
rows, per_arm = [], {}
|
||
for arm in arms:
|
||
agg = {"arm": arm, "n": 0, "echo": 0, "refusal": 0, "vol_bad": 0, "empty": 0,
|
||
"han_sum": 0.0, "vol_sum": 0.0}
|
||
for ch, ci in TARGETS:
|
||
key = f"{ch}/{ci}"
|
||
p = OUT / arm / f"{ch}_{ci}.txt"
|
||
src = chunks[key]["source"]
|
||
if not p.exists() or not p.read_text(encoding="utf-8").strip():
|
||
agg["empty"] += 1; agg["n"] += 1; continue
|
||
t = p.read_text(encoding="utf-8").strip()
|
||
hr = han_ratio(t)
|
||
vr = len(t) / max(1, len(src))
|
||
echo = hr > 0.10
|
||
ref = bool(REFUSAL.search(t))
|
||
volbad = not (LEN_BOUNDS[0] <= vr <= LEN_BOUNDS[1])
|
||
agg["n"] += 1; agg["han_sum"] += hr; agg["vol_sum"] += vr
|
||
agg["echo"] += echo; agg["refusal"] += ref; agg["vol_bad"] += volbad
|
||
rows.append({"arm": arm, "chunk": key, "han": round(hr, 4), "vol": round(vr, 2),
|
||
"echo": echo, "refusal": ref, "vol_bad": volbad, "chars": len(t)})
|
||
n = max(1, agg["n"] - agg["empty"])
|
||
agg["han_avg"] = round(agg["han_sum"] / n, 4)
|
||
agg["vol_avg"] = round(agg["vol_sum"] / n, 2)
|
||
agg["echo_rate"] = round(agg["echo"] / max(1, agg["n"]), 3)
|
||
per_arm[arm] = agg
|
||
|
||
(OUT / "gates.json").write_text(json.dumps({"per_arm": per_arm, "rows": rows}, ensure_ascii=False, indent=1), encoding="utf-8")
|
||
print(f"{'arm':<5} {'n':>2} {'echo':>5} {'refus':>5} {'volBad':>6} {'empty':>5} {'han_avg':>8} {'vol_avg':>7}")
|
||
for arm in arms:
|
||
a = per_arm[arm]
|
||
print(f"{arm:<5} {a['n']:>2} {a['echo']:>5} {a['refusal']:>5} {a['vol_bad']:>6} {a['empty']:>5} {a['han_avg']:>8} {a['vol_avg']:>7} echo_rate={a['echo_rate']}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|