textmachine/eval/rerun2_judge/build_blind.py

105 lines
5.5 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
"""D39.8 blind-read package builder for the pere-run (rerun2).
3 editor arms (glm-5 / mistral / deepseek-pro) of 蛊真人 ch1-5, zh->ru. Per CHAPTER, the 3 versions are
shuffled to neutral labels A/B/C with a PER-CHAPTER salt (so the reader cannot accumulate "C = one model"
across chapters). Source at the top of each chapter for fidelity comparison. Auto-QA (CJK-in-ru residual)
runs before the human. Correspondence key -> a SEPARATE file, withheld from the owner until verdict (D39.8).
"""
import json, random, re
from pathlib import Path
RUN = Path("/home/ubuntu/books/gu-zhenren/rerun2")
OUT = RUN / "blind"
OUT.mkdir(exist_ok=True)
ARMS = ["glm", "mistral", "dspro"]
def load():
arms = {}
for a in ARMS:
d = json.load(open(RUN / f"export-{a}.json"))
arms[a] = d["chunks"]
return arms
def by_chapter(chunks):
ch = {}
for c in sorted(chunks, key=lambda c: (int(c["chapter"]), int(c["chunk_idx"]))):
ch.setdefault(c["chapter"], {"final": [], "source": [], "disp": []})
ch[c["chapter"]]["final"].append(c["final_text"])
ch[c["chapter"]]["source"].append(c["source"])
ch[c["chapter"]]["disp"].append(c["disposition"])
return {k: {"final": "\n\n".join(v["final"]), "source": "\n\n".join(v["source"]),
"disp": v["disp"]} for k, v in ch.items()}
CJK = re.compile(r"[㐀-鿿豈-﫿]")
def auto_qa(text):
flags = []
cjk = CJK.findall(text)
if cjk:
flags.append(f"CJK-in-ru residual: {len(cjk)} char(s) e.g. {''.join(cjk[:6])}")
# crude latin-word leak (>=3 latin letters run, excluding common ok tokens)
lat = re.findall(r"[A-Za-z]{3,}", text)
if lat:
flags.append(f"latin run(s): {lat[:5]}")
return flags
def main():
arms = load()
chap = {a: by_chapter(arms[a]) for a in ARMS}
chapters = sorted(chap["glm"].keys(), key=int)
key = {}
packet = []
packet.append("# Слепой пакет чтения — пере-прогон rerun2 (蛊真人, главы 15, zh→ru)\n")
packet.append(
"Три версии перевода каждой главы (**A / B / C**) — это три редакторских «руки» одного и того же "
"чернового перевода. Метки **перетасованы заново в каждой главе** (в гл.1 «A» и в гл.2 «A» — это, "
"скорее всего, РАЗНЫЕ руки). Соответствие меток и моделей — в отдельном файле "
"`blind_read_KEY.json`, **его не смотреть до вердикта**.\n")
packet.append(
"**Как читать (планка: ≤2 претензии на версию):** по каждой главе отметьте для A/B/C претензии "
"по ярусам — **критические** (искажение смысла / пропуск / неверный род / непереведённый "
"китайский / сломанное слово), **смысловые** (неточность, единицы времени, числа), "
"**редакторские** (стиль, ритм, канцелярит) — и назовите предпочтительную версию.\n")
packet.append("---\n")
for ch in chapters:
rng = random.Random(f"rerun2-blind-ch{ch}")
order = ARMS[:]
rng.shuffle(order)
labels = ["A", "B", "C"]
key[ch] = {labels[i]: order[i] for i in range(3)}
src = chap[order[0]][ch]["source"] # same source across arms
packet.append(f"## Глава {ch}\n")
packet.append(f"<details><summary>Китайский исходник (для сверки верности)</summary>\n\n```\n{src}\n```\n</details>\n")
for i, lab in enumerate(labels):
arm = order[i]
txt = chap[arm][ch]["final"]
qa = auto_qa(txt)
qa_note = f"\n> _(авто-QA: {'; '.join(qa)})_\n" if qa else ""
packet.append(f"### Глава {ch} — версия {lab}\n{qa_note}\n{txt}\n")
packet.append(f"\n**Ваши претензии по главе {ch}:**\n"
"- Версия A — критич.: … · смысл.: … · редакт.: …\n"
"- Версия B — критич.: … · смысл.: … · редакт.: …\n"
"- Версия C — критич.: … · смысл.: … · редакт.: …\n"
"- Предпочтение: …\n\n---\n")
(OUT / "blind_read_packet.md").write_text("\n".join(packet))
(OUT / "blind_read_KEY.json").write_text(json.dumps(
{"note": "WITHHELD from owner until verdict (D39.8). Per-chapter label->arm mapping.",
"arm_label": {"glm": "glm-5 (base)", "mistral": "mistral-large-2512", "dspro": "deepseek-v4-pro"},
"mapping": key}, ensure_ascii=False, indent=2))
# QA summary (mine, not owner-facing)
qa_summary = {}
for ch in chapters:
for arm in ARMS:
f = auto_qa(chap[arm][ch]["final"])
if f: qa_summary.setdefault(arm, {})[ch] = f
(OUT / "auto_qa.json").write_text(json.dumps(qa_summary, ensure_ascii=False, indent=2))
print("packet:", OUT / "blind_read_packet.md")
print("key (withheld):", OUT / "blind_read_KEY.json")
print("chapters:", chapters)
print("auto-QA hits by arm:", {a: list(v.keys()) for a, v in qa_summary.items()})
if __name__ == "__main__":
main()