textmachine/eval/editor_harness/verify_report.py

113 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Сверка НЕСУЩИХ ЧИСЕЛ отчёта `docs/experiments/20-editor-role.md` с сырьём.
Зачем отдельным скриптом: числа в отчёт попадают через мою же аналитику, и опечатка или устаревшая
цифра после пере-съёмки арма визуально неотличимы от факта. Здесь каждое заявленное число
пере-выводится из персистированных артефактов заново и сравнивается с тем, что написано в тексте.
Запуск: eval/.venv/bin/python eval/editor_harness/verify_report.py
Ненулевой код возврата = отчёт разошёлся с сырьём и его нельзя лендить.
"""
from __future__ import annotations
import difflib
import json
import statistics
import sys
from pathlib import Path
REPO = Path("/home/ubuntu/projects/textmachine")
sys.path.insert(0, str(REPO / "eval" / "bank_arbitration"))
RAW = Path.home() / "books" / "gu-zhenren" / "editor-harness"
import editor_wire_probe as P # noqa: E402
FAILS = 0
def g(tag: str):
f = RAW / f"{tag}.json"
return json.loads(f.read_text(encoding="utf-8")) if f.exists() else None
def ck(claim: str, ok: bool, got: str = "") -> None:
global FAILS
if not ok:
FAILS += 1
print(f"[{'OK ' if ok else 'ПРОВАЛ'}] {claim}" + ("" if ok else f" — сырьё даёт {got}"))
def cjk(s: str) -> int:
return sum(1 for ch in s if 0x3400 <= ord(ch) <= 0x9FFF)
def out_text(tag: str) -> str | None:
a = RAW / f"{tag}.applied.json"
if a.exists():
return json.loads(a.read_text(encoding="utf-8"))["text"]
r = g(tag)
return r["content"] if r else None
def main() -> None:
# §3.1 — отношение цены дифф/full по моделям и режимам
for ms, pre, claim in (("dp", "eh", 2.83), ("gl", "eh", 0.64), ("gl", "eht", 0.86),
("gr", "eh", 0.60), ("gr", "eht", 0.66),
("lu", "eh", 1.01), ("lu", "eht", 0.89)):
f = [g(f"{pre}-{ms}-full-w{k}") for k in range(6)]
d = [g(f"{pre}-{ms}-diff-harness-w{k}") for k in range(6)]
if any(x is None for x in f + d):
ck(f"§3.1 {ms}/{pre}", False, "нет артефактов")
continue
r = statistics.median(d[k]["cost_usd"] / f[k]["cost_usd"] for k in range(6))
ck(f"§3.1 {ms}/{pre} отношение дифф/full = {claim}", abs(r - claim) < 0.015, f"{r:.3f}")
# §3.3 — цена починки и полнота снятия дефектов
for ms, claim in (("dp", 0.000625), ("lu", 0.000173)):
f = RAW / f"repair-{ms}.json"
if not f.exists():
ck(f"§3.3 {ms}", False, "нет repair-*.json")
continue
rows = json.loads(f.read_text(encoding="utf-8"))
med = statistics.median(x["cost"] for x in rows)
ck(f"§3.3 {ms} цена одной починки = {claim}", abs(med - claim) < 1e-6, f"{med:.6f}")
snyat = sum(1 for x in rows if not x["still"])
ck(f"§3.3 {ms} дефект снят 12/12", snyat == 12, str(snyat))
inf = [x for x in rows if not x["degenerate"]]
strict = sum(1 for x in inf if not x["still"] and x["restored"])
ck(f"§3.3 {ms} восстановлен строго 7/8", (strict, len(inf)) == (7, 8),
f"{strict}/{len(inf)}")
# §4 — доля слов черновика, доживших до выхода
for ms, c, claim in (("dp", "full", 0.65), ("gl", "full", 0.83),
("dp", "diff-harness", 0.98)):
vals = []
for k in range(6):
o = g(f"eh-{ms}-{c}-w{k}")
if not o:
continue
dw = P.draft_of(k).split()
ow = (out_text(f"eh-{ms}-{c}-w{k}") or "").split()
sm = difflib.SequenceMatcher(None, dw, ow, autojunk=False)
vals.append(sum(b.size for b in sm.get_matching_blocks()) / len(dw))
ck(f"§4 {ms}/{c} слов дожило {claim:.0%}",
bool(vals) and abs(statistics.median(vals) - claim) < 0.015,
f"{statistics.median(vals):.3f}" if vals else "нет данных")
# §5.4 — утечка исходника в выход у luna
for c, w_claim, n_claim in (("full", 3, 19), ("diff-harness", 3, 16)):
outs = [cjk(out_text(f"eh-lu-{c}-w{k}") or "") for k in range(6)]
ck(f"§5.4 luna/{c}: окон с утечкой {w_claim}, знаков {n_claim}",
sum(1 for x in outs if x) == w_claim and sum(outs) == n_claim,
f"{sum(1 for x in outs if x)} окон, {sum(outs)} знаков")
# deepseek обязан быть чист по обоим контрактам — это утверждение отчёта
for c in ("full", "diff-harness"):
outs = [cjk(out_text(f"eh-dp-{c}-w{k}") or "") for k in range(6)]
ck(f"§5.4 deepseek/{c}: утечки нет", sum(outs) == 0, f"{sum(outs)} знаков")
print(f"\n{'ВСЕ ЧИСЛА ОТЧЁТА СХОДЯТСЯ' if not FAILS else f'РАСХОЖДЕНИЙ: {FAILS}'}")
sys.exit(1 if FAILS else 0)
if __name__ == "__main__":
main()