252 lines
13 KiB
Python
252 lines
13 KiB
Python
#!/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__)
|