textmachine/eval/editor_tier/panel.py

252 lines
13 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
"""ФАЗЫ B и C. Платные, идут через кассу пака.
ФАЗА B — граница `glm-5`. 16 НОВЫХ единиц (`material.units_new`), на каждой покупается ровно то,
что нужно контрасту границы: якорный черновик · боевой редактор `deepseek-v4-pro` (R0) ·
пограничный `glm-5` (R2). n контраста R0/R2 растёт 16 → 32.
ФАЗА C — панель сильного тира. Прошедшие фазу A идут редакторами поверх ТОЙ ЖЕ якорной базы
эксп-22 на его 16 единицах. База уже куплена: пере-генерация запрещена — это был бы второй замер
той же вещи, а не новый арм. Клетка R0 над этой базой тоже куплена эксп-22 и переиспользуется.
⚠ ПОТОЛОК ФАЗЫ C ПОДНЯТ $1.80 → $2.30 ИЗ ОБЪЯВЛЕННОГО РЕЗЕРВА ПАКА (см. `money.CEILINGS`),
объявляется ДО покупок фазы. Две причины, обе замерные: пре-рег-критерий пропустил ТРОИХ, и
панель по замеренным ценам фазы A стоит $1.844 вместо сметы на двоих; плюс плану нужен СВОЙ
шумовой пол — вторая независимая генерация самого дешёвого арма, ещё $0.29. Пакетный потолок
$4.00 (санкция владельца) НЕ двигается: смета пака $2.93. Фазовый потолок — моя разбивка внутри
санкции; тихо пробить его было бы нечестно, тихо срезать панель — тем более.
"""
from __future__ import annotations
import sys
from pathlib import Path
REPO = Path("/home/ubuntu/projects/textmachine")
ZONE = Path(__file__).resolve().parent
sys.path.insert(0, str(REPO / "eval" / "tenant_panel"))
sys.path.insert(0, str(REPO / "eval" / "role_topology"))
def _load(name: str, path: Path):
"""Чужое — только явной загрузкой (см. `screen._load`)."""
import importlib.util # noqa: PLC0415
spec = importlib.util.spec_from_file_location(name, path)
mod = importlib.util.module_from_spec(spec)
sys.modules[name] = mod
spec.loader.exec_module(mod)
return mod
TP = REPO / "eval" / "tenant_panel"
PR = _load("prompts22", TP / "prompts.py")
P22 = _load("panel22", TP / "panel.py")
MAT = _load("material_et", ZONE / "material.py")
SCR = _load("screen_et", ZONE / "screen.py")
import bakeoff as BO # noqa: E402
MONEY = SCR.MONEY
ROSTER = SCR.ROSTER
ANCHOR = "deepseek-v4-flash" # черновик боевой пары
BATTLE = "deepseek-v4-pro" # R0
BORDER = "glm-5" # R2 — пограничный контраст эксп-22
FLOOR_ARM = None # заполняется survivors()[0] — самый дешёвый прошедший
def survivors() -> list[str]:
"""Прошедшие фазу A по ПРЕ-РЕГ-критерию пака, по возрастанию замеренной цены."""
r = SCR.result()
ok = [m for m, v in r.items() if v["verdict"] == "прошёл"]
return sorted(ok, key=lambda m: r[m]["price_editor"] or 9)
# ── ФАЗА B ────────────────────────────────────────────────────────────────────────────────────
def tag_b(kind: str, model: str, uid: str) -> str:
return f"et-unit-{kind}-{model}-{uid}"
def cmd_b_plan() -> None:
us = MAT.units_new()
r22 = ROSTER.R22
exp = {ANCHOR: 0.00130, BATTLE: 0.00545, BORDER: 0.01303} # замеры эксп-22, $/ед
tot = sum(exp.values()) * len(us)
print(f"фаза B: {len(us)} новых единиц × (черновик + {BATTLE} + {BORDER}) = "
f"{len(us) * 3} клеток · ожидание ${tot:.3f} · потолок {MONEY.CEILINGS['ФB']:.2f}")
_ = r22
if tot > MONEY.CEILINGS["ФB"]:
print("⛔ смета выше потолка фазы — СТОП")
raise SystemExit(1)
def cmd_b_run() -> None:
led = MONEY.Guarded("ФB")
for u in MAT.units_new():
blk = PR.glossary_block(PR.terms_in(u["source"]))
t = tag_b("draft", ANCHOR, u["uid"])
if not (MONEY.OUT / f"{t}.json").exists():
MONEY.purchase(led, t, ANCHOR, SCR.client(ANCHOR),
ROSTER.call_kwargs(ANCHOR, PR.translator_msgs(u["source"], blk)),
role="draft", uid=u["uid"])
d = draft_b(u["uid"])
if not d.strip():
print(f" {u['uid']}: черновика нет — редактуры пропущены")
continue
# ⚠ ГЕЙТ БРАКА ЧЕРНОВИКА БЫЛ НАПИСАН И НЕ ПОДКЛЮЧЁН. Фаза проверяла только «строка пуста»,
# поэтому эхо-мина прошла на боевую базу: `63ab55ac5c` — 1798 ханьцзы и НОЛЬ кириллицы при
# `finish=stop`. Отчёт из-за этого объявлял класс «не ловится ни одним гейтом» — неверно:
# `draft_reject_reason` его ловит, звать было некому. Поймано аудитом закрытия заказа.
if (why := BO.draft_reject_reason(d)):
print(f" {u['uid']}: черновик забракован ({why}) — редактуры НЕ покупаются")
continue
law = PR.law_block(PR.terms_in(u["source"]))
for m in (BATTLE, BORDER):
te = tag_b("edit", m, u["uid"])
if (MONEY.OUT / f"{te}.json").exists():
continue
MONEY.purchase(led, te, m, SCR.client(m),
ROSTER.call_kwargs(m, PR.editor_msgs(u["source"], d, law)),
role="edit", uid=u["uid"])
MONEY.report()
def draft_b(uid: str) -> str:
import json # noqa: PLC0415
f = MONEY.OUT / f"{tag_b('draft', ANCHOR, uid)}.json"
return (json.loads(f.read_text(encoding="utf-8")).get("content") or "") if f.exists() else ""
def text_b(arm: str, uid: str) -> str:
import json # noqa: PLC0415
m = {"R0": BATTLE, "R2": BORDER}[arm]
f = MONEY.OUT / f"{tag_b('edit', m, uid)}.json"
return (json.loads(f.read_text(encoding="utf-8")).get("content") or "") if f.exists() else ""
# ── ФАЗА C ────────────────────────────────────────────────────────────────────────────────────
def tag_c(model: str, uid: str) -> str:
return f"et-ed-{model}-{uid}"
def cmd_c_plan() -> None:
ok, us = survivors(), P22.M.units_zh()
r = SCR.result()
tot = sum((r[m]["price_editor"] or 0) * len(us) for m in ok)
print(f"{'арм':6s}{'модель':16s}{'$/ед':>10s}{'×16':>10s}")
for i, m in enumerate(ok, start=1):
pe = r[m]["price_editor"] or 0
print(f"{'T' + str(i):6s}{m:16s}{pe:10.5f}{pe * len(us):10.3f}")
print(f"{'ИТОГО':22s}{'':10s}{tot:10.3f} потолок {MONEY.CEILINGS['ФC']:.2f}")
print(f"база R0 ({BATTLE} над якорным черновиком) — уже куплена эксп-22, $0")
if tot > MONEY.CEILINGS["ФC"]:
print("⛔ смета выше потолка фазы — СТОП")
raise SystemExit(1)
def cmd_c_run() -> None:
led = MONEY.Guarded("ФC")
for u in P22.M.units_zh():
base = P22.draft_text(ANCHOR, u["uid"])
if not base.strip():
print(f" {u['uid']}: якорной базы нет — пропуск")
continue
law = PR.law_block(PR.terms_in(u["source"]))
for m in survivors():
t = tag_c(m, u["uid"])
if (MONEY.OUT / f"{t}.json").exists():
continue
MONEY.purchase(led, t, m, SCR.client(m),
ROSTER.call_kwargs(m, PR.editor_msgs(u["source"], base, law)),
role="edit", uid=u["uid"])
MONEY.report()
def tag_floor(uid: str, gen: int) -> str:
return f"et-floor-p{gen}-{survivors()[0]}-{uid}"
def cmd_floor_run() -> None:
"""ШУМОВОЙ ПОЛ прохода: ДВЕ независимые генерации ОДНОГО арма на одном входе.
Истинная разница между ними — ноль, поэтому разброс их перевесов и есть шум одного вызова.
Первая генерация уже куплена фазой C (клетка панели), докупается только вторая: пол обязан
быть СВОИМ для прохода, а не заимствованным у эксп-22 — там другая панель и другой прайс.
"""
m = survivors()[0]
led = MONEY.Guarded("ФC")
for u in P22.M.units_zh():
base = P22.draft_text(ANCHOR, u["uid"])
if not base.strip():
continue
t = tag_floor(u["uid"], 2)
if (MONEY.OUT / f"{t}.json").exists():
continue
law = PR.law_block(PR.terms_in(u["source"]))
MONEY.purchase(led, t, m, SCR.client(m),
ROSTER.call_kwargs(m, PR.editor_msgs(u["source"], base, law)),
role="floor2", uid=u["uid"])
MONEY.report()
def floor_pair(uid: str):
"""(генерация 1, генерация 2) самого дешёвого арма панели.
⚠ ДЕФЕКТ, ОБЪЯВЛЕННЫЙ И НЕ ПОЧИНЕННЫЙ В ЭТОМ ПАКЕ: первая половина пары — это САМА боевая
клетка `T1`, а не отдельная генерация. Следствие ровно одно, и оно не в числах пола (пол
считается по РАЗНОСТИ двух генераций и остаётся честным), а в контроле «БЛИЗНЕЦ»: он ловит
побайтные дубли, и здесь единственным дублем оказывается пара `CTRLfloorA`≡`T1` в 16/16 —
то есть контроль сравнивает `T1` с самим собой и ничего не проверяет. Чинить надо ПОКУПКОЙ
отдельной первой генерации, поэтому в этом паке дефект только объявлен (отчёт §12).
"""
import json # noqa: PLC0415
a = text_c("T1", uid)
f = MONEY.OUT / f"{tag_floor(uid, 2)}.json"
b = (json.loads(f.read_text(encoding="utf-8")).get("content") or "") if f.exists() else ""
return (a, b) if a.strip() and b.strip() else None
def text_c(arm: str, uid: str) -> str:
"""Тексты армов Ф C. R0 — клетка эксп-22, переиспользуется без покупки."""
import json # noqa: PLC0415
if arm == "R0":
return P22.edit_text(ANCHOR, uid)
ok = survivors()
m = ok[int(arm[1:]) - 1]
f = MONEY.OUT / f"{tag_c(m, uid)}.json"
return (json.loads(f.read_text(encoding="utf-8")).get("content") or "") if f.exists() else ""
def selfcheck() -> int:
bad = 0
ok = survivors()
if not ok:
print("[ПРОВАЛ] фазу A не прошёл никто — панели нет")
bad += 1
us_b, us_c = MAT.units_new(), P22.M.units_zh()
if set(u["uid"] for u in us_b) & set(u["uid"] for u in us_c):
print("[ПРОВАЛ] единицы фаз B и C пересекаются")
bad += 1
tags = [tag_b("draft", ANCHOR, u["uid"]) for u in us_b] + \
[tag_b("edit", m, u["uid"]) for u in us_b for m in (BATTLE, BORDER)] + \
[tag_c(m, u["uid"]) for u in us_c for m in ok]
if len(tags) != len(set(tags)):
print("[ПРОВАЛ] теги не уникальны")
bad += 1
if not all(t.startswith(("et-unit-", "et-ed-")) for t in tags):
print("[ПРОВАЛ] тег вне глобов фаз")
bad += 1
if sum(MONEY.CEILINGS.values()) > MONEY.PACK_CEILING + 1e-9:
print("[ПРОВАЛ] сумма фазовых потолков выше пакетного")
bad += 1
print(f"панель: армов {len(ok)} ({ok}) · клеток в плане {len(tags)} · провалов {bad}")
return bad
if __name__ == "__main__":
a = sys.argv[1:] or ["--selfcheck"]
fn = {"--b-plan": cmd_b_plan, "--b-run": cmd_b_run, "--c-plan": cmd_c_plan,
"--c-run": cmd_c_run, "--floor-run": cmd_floor_run,
"--selfcheck": lambda: sys.exit(1 if selfcheck() else 0)}.get(a[0])
if fn:
fn()
else:
print(__doc__)