textmachine/eval/exp15/blind_packets.py

95 lines
5.1 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
"""exp15 — BLIND reading packets for the owner (§D3 human endpoint: metrics NOMINATE, blind read RATIFIES,
planка = <=2 claims/chapter). Presents the SAME opening source passage translated 3 ways — flat-A0-30
(blind-greedy baseline), oracle-30 (seam-aligned), q3a-src (source-carryover arm) — under SHUFFLED neutral
labels (V1/V2/V3), with a separate key. The owner reads without knowing which is which and counts claims.
Deterministic shuffle (fixed seed). Outputs to exp15/monitor/ (blind packet + key, key kept separate).
Run: python blind_packets.py
"""
from __future__ import annotations
import json
import random
import sqlite3
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from chunker import greedy_chunks
SD = Path("/home/ubuntu/books/gu-zhenren/exp15")
AH = SD / "anchors"
MON = SD / "monitor"
N_CHUNKS = 6 # ~first 3-4 节 of the opening (readable passage)
def db_finals(db):
con = sqlite3.connect(db)
out = {}
for ck, txt in con.execute("SELECT chunk_idx, response_text FROM checkpoints WHERE stage='edit' ORDER BY chunk_idx, attempt"):
out[ck] = txt
con.close()
return out
def main():
MON.mkdir(parents=True, exist_ok=True)
flat_src = greedy_chunks((SD / "S2prime_big_flat.txt").read_text(encoding="utf-8"))
oracle_src = greedy_chunks((SD / "S2prime_big_blanklines.txt").read_text(encoding="utf-8"))
flat_fin = db_finals(AH / "flat_a0_30.db")
oracle_fin = db_finals(AH / "oracle_30.db")
# source span covered by the first N flat chunks (used for oracle coverage matching AND now shown as
# the fidelity reference — the reader compares each version against this original for omissions/errors)
src_span = "".join(flat_src[:N_CHUNKS])
src_display = "\n\n".join(flat_src[:N_CHUNKS]) # paragraph-joined for readability
# flat + q3a-src share flat chunking; oracle differs -> take oracle chunks until it covers ~the same source len
flat_text = "\n\n".join(flat_fin[i] for i in range(N_CHUNKS) if i in flat_fin)
arm_dir = SD / "arms" / "q3a-src"
src_arm = "\n\n".join((arm_dir / f"{i:02d}.final.txt").read_text(encoding="utf-8")
for i in range(N_CHUNKS) if (arm_dir / f"{i:02d}.final.txt").exists())
# oracle: chunks whose cumulative source length ~covers src_span
cov, oi, otexts = 0, 0, []
target = len(src_span)
while oi < len(oracle_src) and cov < target:
if oi in oracle_fin:
otexts.append(oracle_fin[oi])
cov += len(oracle_src[oi]); oi += 1
oracle_text = "\n\n".join(otexts)
arms = {"flat-A0-30 (blind greedy baseline)": flat_text,
"oracle-30 (seam-aligned)": oracle_text,
"q3a-src (source-carryover)": src_arm}
labels = ["V1", "V2", "V3"]
keys = list(arms.keys())
rnd = random.Random("exp15-blind-2026-07-18")
rnd.shuffle(keys)
mapping = dict(zip(labels, keys)) # V1->arm, ...
# blind packet (no arm names) — original source at top for FIDELITY comparison, then the 3 versions
pkt = [f"# exp15 — СЛЕПОЙ ПАКЕТ для чтения (открывающий фрагмент 蛊真人, ~{N_CHUNKS} чанков)",
"",
"Три версии перевода ОДНОГО фрагмента под нейтральными метками (V1/V2/V3, перемешаны; ключ отдельно).",
"Оцени: (а) художественность/связность и (б) ВЕРНОСТЬ — сверяя каждую версию с китайским ОРИГИНАЛОМ",
"ниже (ничего не потеряно; смысл/род/референт/порядок событий переданы). Планка: ≤2 претензии на главу.",
"Примечание: V1/V2/V3 переводились с разной нарезкой на чанки, поэтому у одной из версий хвост",
"фрагмента может слегка отличаться по границе — это часть эксперимента, не ошибка перевода.",
"", "---", "",
"## ОРИГИНАЛ — китайский исходник (эталон для сверки верности)",
"",
src_display,
"", "---", ""]
for lab in labels:
pkt += [f"## {lab}", "", arms[mapping[lab]], "", "---", ""]
(MON / "blind_read_packet.md").write_text("\n".join(pkt), encoding="utf-8")
(MON / "blind_read_KEY.json").write_text(json.dumps(
{"_warning": "KEY — не показывать читающему до вынесения вердикта",
"mapping_label_to_arm": mapping, "n_chunks": N_CHUNKS,
"source_span_runes": len(src_span)}, ensure_ascii=False, indent=2), encoding="utf-8")
print(f"blind packet -> {MON}/blind_read_packet.md (key -> blind_read_KEY.json)")
print(f" labels: {mapping}")
print(f" lengths: flat {len(flat_text)}c, oracle {len(oracle_text)}c, q3a-src {len(src_arm)}c")
if __name__ == "__main__":
main()