254 lines
15 KiB
Python
254 lines
15 KiB
Python
#!/usr/bin/env python3
|
||
"""Счёт четырёх фальсификаций СТРОГО по критериям, замороженным в 19-editor-contract-q4b §3.
|
||
|
||
Критерии не мои и после прогона не меняются:
|
||
L — §2.7 падает, если медианное отношение цены дифф/full ≤1.0. Плюс ОБЯЗАТЕЛЬНЫЙ эхо-контроль:
|
||
ненулевая доля ханьцзы в выходе делает `low` непригодным независимо от цены.
|
||
G — §2.1 падает, если формат-комплаенс (applied/ops_total) на боевой единице <0.90.
|
||
E — §2.7 падает, если на английской цели отношение цены ≤1.0. Точность перевода НЕ скорится.
|
||
N — §2.2 падает, если доля NO_CHANGE на fidelity-only промпте >0.
|
||
|
||
Средние исходы печатаются как «неопределённо». Ничего не абсорбируется молча: недостающие
|
||
клетки печатаются поимённо, а не выпадают из знаменателя.
|
||
"""
|
||
from __future__ import annotations
|
||
import json
|
||
import statistics
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
RAW = Path.home() / "books" / "gu-zhenren" / "bank-arbitration"
|
||
|
||
|
||
def rec(tag: str):
|
||
f = RAW / f"{tag}.json"
|
||
return json.loads(f.read_text(encoding="utf-8")) if f.exists() else None
|
||
|
||
|
||
def app(tag: str):
|
||
f = RAW / f"{tag}.applied.json"
|
||
return json.loads(f.read_text(encoding="utf-8")) if f.exists() else None
|
||
|
||
|
||
def hanzi_share(s: str) -> float:
|
||
if not s:
|
||
return 0.0
|
||
h = sum(1 for c in s if 0x3400 <= ord(c) <= 0x9FFF)
|
||
return h / len(s)
|
||
|
||
|
||
def money_block(tags: list[str], label: str) -> dict:
|
||
rs = [r for r in (rec(t) for t in tags) if r]
|
||
if not rs:
|
||
return {}
|
||
return {"label": label, "n": len(rs),
|
||
"usd": sum(r["cost_usd"] for r in rs),
|
||
"out": sum(r["completion_tokens"] for r in rs),
|
||
"finish": {r["finish"] for r in rs}}
|
||
|
||
|
||
def pair_ratios(dtag, ftag, cells) -> tuple[list[tuple], list[str]]:
|
||
"""[(клетка, отношение цены дифф/full)] + пропуски поимённо.
|
||
|
||
⚠ Возвращается ИМЕННО пара с клеткой: ранняя версия отдавала голый список отношений, и
|
||
группировка по окнам делалась `zip` с пере-фильтрованным списком клеток — при любом пропуске
|
||
отношения съезжали на чужие окна, а медиана считалась бы по перепутанным данным.
|
||
"""
|
||
out, missing = [], []
|
||
for c in cells:
|
||
d, f = rec(dtag(c)), rec(ftag(c))
|
||
if not d or not f:
|
||
missing.append(f"{dtag(c)}|{ftag(c)}")
|
||
continue
|
||
out.append((c, d["cost_usd"] / f["cost_usd"]))
|
||
return out, missing
|
||
|
||
|
||
def compliance(tags: list[str]) -> tuple[int, int, dict, list[str]]:
|
||
ops = ap = 0
|
||
reasons = {"notfound": 0, "ambiguous": 0, "overlap": 0, "empty": 0,
|
||
"malformed": 0, "no_change": 0}
|
||
missing = []
|
||
for t in tags:
|
||
a = app(t)
|
||
if not a:
|
||
missing.append(t)
|
||
continue
|
||
ops += a["ops_total"]
|
||
ap += a["applied"]
|
||
reasons["notfound"] += a["rejected_notfound"]
|
||
reasons["ambiguous"] += a["rejected_ambiguous"]
|
||
reasons["overlap"] += a["rejected_overlap"]
|
||
reasons["empty"] += a["rejected_empty"]
|
||
reasons["malformed"] += a["malformed"]
|
||
reasons["no_change"] += a["no_change"]
|
||
return ops, ap, reasons, missing
|
||
|
||
|
||
def verdict(name: str, falls: bool | None, detail: str) -> None:
|
||
mark = {True: "ВЫВОД §ПАДАЕТ", False: "вывод устоял", None: "НЕОПРЕДЕЛЁННО"}[falls]
|
||
print(f" ⇒ {name}: {mark} — {detail}")
|
||
|
||
|
||
def arm_L():
|
||
print("\n=== АРМ L: «дифф дороже» — артефакт несъёмного thinking? (reasoning_effort=low) ===")
|
||
cells = [(k, r) for k in range(6) for r in (1, 2, 3)]
|
||
pairs, missing = pair_ratios(lambda c: f"fp-LD-w{c[0]}-r{c[1]}",
|
||
lambda c: f"fp-LF-w{c[0]}-r{c[1]}", cells)
|
||
if missing:
|
||
print(f" ⚠ нет пары для {len(missing)} клеток: {', '.join(missing[:6])}")
|
||
if not pairs:
|
||
return verdict("L", None, "нет ни одной полной пары")
|
||
# медиана ПО ОКНАМ: сперва медиана розыгрышей внутри окна, затем медиана окон
|
||
ratios = [r for _, r in pairs]
|
||
by_win = {}
|
||
for (k, _rep), ratio in pairs:
|
||
by_win.setdefault(k, []).append(ratio)
|
||
win_med = {k: statistics.median(v) for k, v in sorted(by_win.items())}
|
||
med = statistics.median(win_med.values())
|
||
print(" отношение цены дифф/full по окнам: "
|
||
+ " ".join(f"w{k}={v:.2f}" for k, v in win_med.items()))
|
||
print(f" медиана окон = {med:.3f} (всех клеток {len(ratios)}, медиана клеток "
|
||
f"{statistics.median(ratios):.3f})")
|
||
|
||
d = money_block([f"fp-LD-w{k}-r{r}" for k, r in cells], "дифф low")
|
||
f = money_block([f"fp-LF-w{k}-r{r}" for k, r in cells], "full low")
|
||
for b in (d, f):
|
||
if b:
|
||
print(f" {b['label']}: n={b['n']} ${b['usd']:.6f} выход {b['out']} ток. finish={b['finish']}")
|
||
|
||
# ЭХО-КОНТРОЛЬ. Пре-рег §3 сказан буквально: «ненулевое эхо делает low непригодным».
|
||
# ⚠ ИСПРАВЛЕНО по адверсариальному ревью 05.08. Прежний комментарий утверждал, что все
|
||
# найденные знаки — «цитаты в сносках»; это было ЛОЖНО и опиралось на разбор ОДНОГО случая
|
||
# из двух. Сырьё: `fp-LD-w4-r1` (修行) — дословный SEARCH-якорь по сноске САМОГО черновика,
|
||
# REPLACE пуст, операция сноску удаляет ⇒ модель знаков не порождала; `fp-LF-w3-r2` (潜能) —
|
||
# сносок в выходе нет вообще, знаки стоят внутри повествования («символом жизненной潜能»),
|
||
# а черновик в этом месте несёт корректное «жизненного потенциала» ⇒ это ПОРОЖДЁННАЯ
|
||
# моделью микро-утечка исходника. Порог 5% ниже боевого гейта (`disposition.go`
|
||
# cjkEchoThreshold = 0.15) и на два порядка выше наблюдённого; явление quirks §4 (выход
|
||
# исходником целиком, доля 0.83–0.999) не наблюдалось. Low-специфичность НЕ показана:
|
||
# на дефолтном эффорте ханьцзы тоже есть (ec-D1 2/18, ec-D2 1/18 — та же сноска черновика).
|
||
from collections import Counter
|
||
chars, per_call = Counter(), {}
|
||
for k, r in cells:
|
||
for t in (f"fp-LD-w{k}-r{r}", f"fp-LF-w{k}-r{r}"):
|
||
rr = rec(t)
|
||
if not rr:
|
||
continue
|
||
hz = [c for c in rr["content"] if 0x3400 <= ord(c) <= 0x9FFF]
|
||
if hz:
|
||
chars.update(hz)
|
||
per_call[t] = hanzi_share(rr["content"])
|
||
literal_nonzero = bool(per_call)
|
||
worst = max(per_call.values()) if per_call else 0.0
|
||
print(f" эхо-контроль, БУКВА пре-рега (ханьцзы > 0): "
|
||
f"{'есть' if literal_nonzero else 'нет'} — вызовов с ханьцзы {len(per_call)}, "
|
||
f"всего знаков {sum(chars.values())}, худшая доля {worst:.4%}")
|
||
if chars:
|
||
print(f" какие знаки: {dict(chars)} ⇒ разбор глазами обязателен")
|
||
if worst >= 0.05:
|
||
print(" ⛔ ЭХО-МИНА: доля исходника в выходе ≥5% — это не цитата")
|
||
verdict("L", None, "цена нерелевантна: `low` пере-вооружил эхо-мину ⇒ режим непригоден")
|
||
else:
|
||
if literal_nonzero:
|
||
print(" ⚠ ДЕВИАЦИЯ ОТ БУКВЫ пре-рега: порог 5% вместо «ненулевого». Разбор сырья: "
|
||
"часть знаков — SEARCH-якорь по сноске ЧЕРНОВИКА (модель их не порождала), "
|
||
"часть — настоящая микро-утечка исходника в повествование. Сплошного эха "
|
||
"(quirks §4, доля 0.83+) нет. По БУКВЕ пре-рега рекомендация «редактору low» "
|
||
"закрыта независимо от цены; на медианный вердикт ниже это не влияет")
|
||
# ⚠ НЕ печатаем «вывод устоял»: по адверсариальному ревью 05.08 (отчёт 19 §6.2) арм L —
|
||
# НЕ исполненная фальсификация. Его посылка («ручка low на pro работает», quirks §3б)
|
||
# не выдержала пере-счёта: решающее правило n=3/3 воспроизводится НУЛЕВЫМ вмешательством,
|
||
# на побайтно одном входе дефолт и low пересекаются (MW p=0.589). Число верно, статус — нет.
|
||
print(f" ⇒ L: НЕ ФАЛЬСИФИКАЦИЯ — отличимость `low` от дефолта не установлена (§6.2). "
|
||
f"Медиана {med:.3f} > 1.0 засчитывается как ВТОРАЯ РЕПЛИКАЦИЯ вывода «дифф дороже», "
|
||
f"а не как выдержанная проверка гипотезы про несъёмный thinking")
|
||
|
||
ops, ap, reasons, miss = compliance([f"fp-LD-w{k}-r{r}" for k, r in cells])
|
||
if ops:
|
||
print(f" побочно, комплаенс диффа на low: {ap}/{ops} = {ap / ops:.3f}; {reasons}")
|
||
|
||
|
||
def arm_N():
|
||
print("\n=== АРМ N: покупается ли do-nothing узким fidelity-промптом? ===")
|
||
tags = [f"fp-N-w{k}-r{r}" for k in range(6) for r in (1, 2, 3)]
|
||
ops, ap, reasons, missing = compliance(tags)
|
||
present = len(tags) - len(missing)
|
||
if missing:
|
||
print(f" ⚠ нет выхода для {len(missing)}: {', '.join(missing[:6])}")
|
||
if not present:
|
||
return verdict("N", None, "нет данных")
|
||
nc = reasons["no_change"]
|
||
print(f" вызовов {present}/{len(tags)} · операций {ops} · применено {ap} "
|
||
f"· NO_CHANGE {nc} · малформед {reasons['malformed']}")
|
||
print(f" комплаенс {ap / ops:.3f}" if ops else " операций 0")
|
||
b = money_block(tags, "fidelity-дифф")
|
||
if b:
|
||
print(f" {b['label']}: ${b['usd']:.6f} выход {b['out']} ток. finish={b['finish']}")
|
||
verdict("N", nc > 0, f"NO_CHANGE {nc} из {present} вызовов (в §2 было 0 из 36)")
|
||
|
||
|
||
def arm_G():
|
||
print("\n=== АРМ G: держится ли комплаенс на БОЕВОЙ единице (~3200 ру-ток.)? ===")
|
||
cells = [(u, r) for u in range(2) for r in (1, 2, 3)]
|
||
dtags = [f"fp-GD-u{u}-r{r}" for u, r in cells]
|
||
ops, ap, reasons, missing = compliance(dtags)
|
||
if missing:
|
||
print(f" ⚠ нет apply для {len(missing)}: {', '.join(missing)}")
|
||
if not ops:
|
||
return verdict("G", None, "операций 0 — считать нечего")
|
||
comp = ap / ops
|
||
print(f" операций {ops} · применено {ap} · комплаенс {comp:.3f}")
|
||
print(f" причины reject: {reasons}")
|
||
gpairs, miss2 = pair_ratios(lambda c: f"fp-GD-u{c[0]}-r{c[1]}",
|
||
lambda c: f"fp-GF-u{c[0]}-r{c[1]}", cells)
|
||
ratios = [r for _, r in gpairs]
|
||
if ratios:
|
||
print(f" отношение цены дифф/full на длинной единице: медиана "
|
||
f"{statistics.median(ratios):.3f} ({len(ratios)} пар)")
|
||
for b in (money_block(dtags, "дифф длинный"),
|
||
money_block([f"fp-GF-u{u}-r{r}" for u, r in cells], "full длинный")):
|
||
if b:
|
||
print(f" {b['label']}: n={b['n']} ${b['usd']:.6f} выход {b['out']} ток. finish={b['finish']}")
|
||
verdict("G", comp < 0.90, f"комплаенс {comp:.3f} против порога 0.90")
|
||
|
||
|
||
def arm_E():
|
||
print("\n=== АРМ E: «дифф дороже» — артефакт РУССКОЙ фертильности? (английская цель) ===")
|
||
cells = [(k, r) for k in range(6) for r in (1, 2)]
|
||
epairs, missing = pair_ratios(lambda c: f"fp-ED-w{c[0]}-r{c[1]}",
|
||
lambda c: f"fp-EF-w{c[0]}-r{c[1]}", cells)
|
||
ratios = [r for _, r in epairs]
|
||
if missing:
|
||
print(f" ⚠ нет пары для {len(missing)}: {', '.join(missing[:6])}")
|
||
if not ratios:
|
||
return verdict("E", None, "нет ни одной полной пары")
|
||
med = statistics.median(ratios)
|
||
print(f" отношение цены дифф/full: медиана {med:.3f} по {len(ratios)} парам "
|
||
f"({' '.join(f'{r:.2f}' for r in ratios)})")
|
||
dt = [f"fp-ED-w{k}-r{r}" for k, r in cells]
|
||
ops, ap, reasons, miss = compliance(dt)
|
||
if ops:
|
||
print(f" формат-комплаенс на английском: {ap}/{ops} = {ap / ops:.3f}; {reasons}")
|
||
for b in (money_block(dt, "дифф en"),
|
||
money_block([f"fp-EF-w{k}-r{r}" for k, r in cells], "full en")):
|
||
if b:
|
||
print(f" {b['label']}: n={b['n']} ${b['usd']:.6f} выход {b['out']} ток. finish={b['finish']}")
|
||
print(" ⚠ точность перевода этим армом НЕ измеряется: en-голда в проекте нет (пре-рег §3)")
|
||
verdict("E", med <= 1.0, f"медиана {med:.3f} против порога 1.0")
|
||
|
||
|
||
def main():
|
||
spent = sum(json.loads(f.read_text(encoding="utf-8"))["cost_usd"]
|
||
for f in RAW.glob("fp-*.json") if not f.name.endswith(".applied.json"))
|
||
for fn in (arm_L, arm_N, arm_G, arm_E):
|
||
try:
|
||
fn()
|
||
except Exception as e: # noqa: BLE001 — арм не должен ронять счёт остальных
|
||
print(f" ⛔ счёт арма упал: {type(e).__name__}: {e}")
|
||
print(f"\nПОТРАЧЕНО на фальсификации: ${spent:.6f} (потолок пре-рега $0.50)")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
sys.exit(0)
|