#!/usr/bin/env python3 """$0 детерминированная батарея верности на ГОТОВЫХ парах база↔митигация P4 (09.07). Это тот источник, на который промт сессии указывал прямо: `~/books/gu-zhenren/research15-probes/`. Генерация за них уже оплачена 09.07 — здесь не тратится ни цента. Судья отвечает на «исказила ли митигация СМЫСЛ». Половина этого вопроса — про ПРОПУСКИ и обрывы — решается детерминированно и бесплатно: митигация, которая режет текст, видна по длине и по числу предложений относительно ОДНОГО И ТОГО ЖЕ исходника. Оставшаяся половина (искажение при сохранённом объёме) без судьи не берётся, и это здесь честно помечено, а не замазано. """ from __future__ import annotations import collections import json import re import statistics import sys import unicodedata from pathlib import Path REPO = Path("/home/ubuntu/projects/textmachine") sys.path.insert(0, str(REPO / "eval")) from refusal_bench import split_sentences RAW = Path.home() / "books" / "gu-zhenren" / "research15-probes" / "probes" / "raw" ARM_NAME = {"G0": "база", "G1": "инстр.ПОСЛЕ", "G2": "few-shot", "G3": "яз.констрейнт", "G4": "комбо", "D0": "база", "D1": "инстр.ПОСЛЕ", "D2": "few-shot", "DP": "префилл"} def cjk_share(s: str) -> float: if not s: return 1.0 return sum(1 for c in s if "CJK UNIFIED" in (unicodedata.name(c, "") or "")) / len(s) def load(): out = {} for f in sorted(RAW.glob("echo-*.json")): d = json.load(open(f)) t = d.get("text") or "" # исходник фрагмента лежит в user-сообщении между шапкой и (для арма G1) постинструкцией u = d.get("user") or "" src = u.split("Переведи следующий фрагмент:\n\n", 1)[-1] src = src.split("\n\nНапоминание:")[0] out[d["tag"]] = dict(tag=d["tag"], text=t, src=src, cjk=cjk_share(t), echo=cjk_share(t) > 0.15) return out def metrics(src: str, out: str) -> dict: src_ns = len(re.sub(r"\s", "", src)) out_ns = len(re.sub(r"\s", "", out)) return dict(chars=len(out), len_ratio=round(out_ns / src_ns, 3) if src_ns else None, sent_src=len(split_sentences(src)), sent_out=len(split_sentences(out)), cjk=round(cjk_share(out), 4)) def main() -> int: d = load() groups = collections.defaultdict(dict) for tag, r in d.items(): m = re.match(r"echo-grok-(gu-\d+)-(G\d)$", tag) if m: groups[("grok", m.group(1))][m.group(2)] = r continue m = re.match(r"echo-ds-gu008-(D\w+)-s(\d)$", tag) if m: groups[("deepseek", "gu-008-s" + m.group(2))][m.group(1)] = r print("=== ПАРЫ база↔митигация из P4 (генерация оплачена 09.07; здесь $0) ===\n") print(f"{'семейство':<9}{'фрагмент':<14}{'арм':<14}{'len_ratio':>10}{'предл. вых/исх':>16}" f"{'симв':>7}{'Δlen_ratio к базе':>19}") rows = [] for (fam, frag), arms in sorted(groups.items()): base_key = "G0" if fam == "grok" else "D0" base = arms.get(base_key) if not base or base["echo"] or not base["text"]: continue bm = metrics(base["src"], base["text"]) print(f"{fam:<9}{frag:<14}{ARM_NAME[base_key]:<14}{bm['len_ratio']:>10}" f"{str(bm['sent_out']) + '/' + str(bm['sent_src']):>16}{bm['chars']:>7}{'—':>19}") for a in ("G1", "G2", "G4", "D1", "D2", "DP"): m = arms.get(a) if not m or m["echo"] or not m["text"]: continue mm = metrics(base["src"], m["text"]) delta = mm["len_ratio"] - bm["len_ratio"] rows.append(dict(fam=fam, frag=frag, arm=a, d_len=delta, d_sent=mm["sent_out"] - bm["sent_out"], base_lr=bm["len_ratio"], mit_lr=mm["len_ratio"])) print(f"{'':<9}{'':<14}{ARM_NAME[a]:<14}{mm['len_ratio']:>10}" f"{str(mm['sent_out']) + '/' + str(mm['sent_src']):>16}{mm['chars']:>7}{delta:>+19.3f}") print() print(f"ВСЕГО ПАР: {len(rows)}\n") print("=== СВОДКА ПО МИТИГАЦИИ: режет ли она текст относительно базы на ТОМ ЖЕ исходнике ===") print(f"{'митигация':<16}{'пар':>5}{'медиана Δlen_ratio':>21}{'пар с Δ<-0.15':>15}" f"{'пар с Δ>+0.15':>15}{'медиана Δпредл.':>17}") for a in ("G1", "G2", "G4", "D1", "D2", "DP"): rs = [r for r in rows if r["arm"] == a] if not rs: continue dl = [r["d_len"] for r in rs] ds = [r["d_sent"] for r in rs] print(f"{ARM_NAME[a]:<16}{len(rs):>5}{statistics.median(dl):>+21.3f}" f"{sum(1 for x in dl if x < -0.15):>15}{sum(1 for x in dl if x > 0.15):>15}" f"{statistics.median(ds):>+17.1f}") print("\nЧТЕНИЕ: Δlen_ratio < −0.15 = митигированный перевод заметно КОРОЧЕ базы на том же") print("исходнике — подпись пропуска. Δ > +0.15 — многословнее (отсебятина или развёрнутость).") print("⚠ Ось «искажение при сохранённом объёме» этим прибором НЕ берётся — только судьёй.") return 0 if __name__ == "__main__": raise SystemExit(main())