textmachine/eval/dovodka/d7_self.py

143 lines
7.4 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
"""Д7 — МИКРО-ПРОБА САМООЦЕНКИ ЖИЛЬЦОВ (идея владельца). Платный, ≤$0.05.
⚠ РЕШЕНИЙ НЕ НЕСЁТ, и это записано ДО покупки. Заказ формулирует прямо: «печатается как
любопытство с оговоркой „самооценка моделей ненадёжна“; никакие решения на ней не стоят».
Ценность в СВЕРКЕ: модель говорит, что ей будет трудно, а фаза уже знает, что вышло на самом
деле — и расхождение между предсказанием модели о себе и фактом само по себе любопытно.
Спрашиваются ОБА жильца обеих ролей по ТРЁМ книгам фазы. Вопрос один и тот же, чтобы ответы
сравнивались между парами: «сможешь ли перевести эту книгу на издательском уровне; что будет
трудным?» Отрывок даётся настоящий — из тех же приколотых единиц, что покупала фаза.
Запуск: d7_self.py --dry | --run | --show | --selftest
"""
from __future__ import annotations
import importlib.util
import json
import sys
from pathlib import Path
REPO = Path("/home/ubuntu/projects/textmachine")
ZONE = Path(__file__).resolve().parent
for d in ("dovodka", "editor_tier", "tenant_panel", "role_topology", "bank_arbitration"):
sys.path.insert(0, str(REPO / "eval" / d))
def _load(name: str, path: Path):
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
C = _load("contour_d7", ZONE / "contour.py")
PE = _load("pair_en_d7", REPO / "eval" / "role_topology" / "pair_en.py")
MJ = _load("mat_ja_d7", ZONE / "material_ja.py")
MONEY, ROSTER, ED22 = C.MONEY, C.ROSTER, C.ED22
RESIDENTS = ("deepseek-v4-flash", "deepseek-v4-pro")
PHASE, PFX = "ФД-D", "dv-d"
MAX_OUT = 8000
SYS = ("Ты — переводчик художественной литературы. Тебе дают отрывок книги. Ответь ЧЕСТНО и "
"коротко, двумя абзацами:\n"
"1) Сможешь ли ты перевести ЭТУ книгу на русский на ИЗДАТЕЛЬСКОМ уровне (так, чтобы "
"текст читался как написанный по-русски, а не переведённый)? Ответь прямо: да, нет или "
"с оговорками — и какими.\n"
"2) Что в ЭТОЙ книге будет для тебя самым трудным? Назови конкретные места и явления, "
"а не общие слова про «культурные различия».")
def books() -> dict[str, tuple[str, str]]:
"""{ключ: (язык, отрывок)} — из ПРИКОЛОТЫХ единиц фазы, а не из случайного места книги."""
zh = C.units_ok()[0]["source"]
en = PE.units(8)[0]["source"]
ja = MJ.units()[0]["source"]
return {"zh": ("китайская вебновелла", zh), "en": ("английское тёмное фэнтези", en),
"ja": ("японская веб-новелла", ja)}
def tag(res: str, book: str) -> str:
return f"{PFX}-self-{res.replace('.', '')}-{book}"
def text_of(res: str, book: str) -> str:
f = MONEY.OUT / f"{tag(res, book)}.json"
if not f.exists():
return ""
return json.loads(f.read_text(encoding="utf-8")).get("content") or ""
def cmd_run() -> None:
led = MONEY.Guarded(PHASE, default_expect=0.004)
for res in RESIDENTS:
for book, (what, src) in books().items():
tg = tag(res, book)
if text_of(res, book).strip():
continue
msgs = [{"role": "system", "content": SYS},
{"role": "user", "content": f"Книга: {what}.\n\nОтрывок:\n{src[:2500]}"}]
rec = MONEY.purchase(led, tg, res, ED22.client(res),
ROSTER.call_kwargs(res, msgs, max_out=MAX_OUT),
role="selfassess", book=book, arm="SELF")
if rec.get("skipped"):
raise SystemExit(f"⛔ ГАРД ОТКАЗАЛ на {tg} — СТОП")
MONEY.report()
def cmd_show() -> None:
print("Д7 — САМООЦЕНКА ЖИЛЬЦОВ\n")
print("⚠ САМООЦЕНКА МОДЕЛЕЙ НЕНАДЁЖНА. Печатается как любопытство; никакие решения фазы на "
"этих ответах НЕ стоят — так объявлено ДО покупки.\n")
fact = {"zh": "факт фазы: связка 4.00 ошибок/ед., черновик хуже",
"en": "факт фазы: черновик 2.78 → связка 1.22 ошибок/ед.",
"ja": "факт фазы: черновик 5.44 → связка 2.22 ошибок/ед. (ХУДШИЙ черновик фазы)"}
for res in RESIDENTS:
for book in books():
t = text_of(res, book)
if not t.strip():
continue
print(f"### {res} · {book}{fact[book]}")
print(" " + t.strip().replace("\n", "\n ")[:900] + "\n")
def cmd_dry() -> None:
have = sum(1 for r in RESIDENTS for b in books() if text_of(r, b).strip())
n = len(RESIDENTS) * len(books())
sp = MONEY.Guarded(PHASE).spent()
print(f"Д7 · клеток {have}/{n} · жильцы {' · '.join(RESIDENTS)} · книги zh/en/ja")
print(f" {PHASE}: потрачено ${sp:.4f} · потолок ${MONEY.CEILINGS[PHASE]:.2f} · "
f"смета ${(n - have) * 0.004:.4f}")
def cmd_selftest() -> int:
bad = 0
def ck(n: str, ok: bool, d: str = "") -> None:
nonlocal bad
bad += not ok
print(f"[{'OK ' if ok else 'ПРОВАЛ'}] {n}" + (f" {d}" if d else ""))
bk = books()
ck("три книги фазы", len(bk) == 3, " ".join(bk))
ck("отрывки — из приколотых единиц, непустые",
all(len(v[1]) > 500 for v in bk.values()))
ck("тег покрыт глобом кассы ФД-D", tag("m", "zh").startswith("dv-d-"))
ck("вопрос НЕ подсказывает ответ (нет слов «трудно»/«не сможешь» в постановке)",
"не сможешь" not in SYS)
# Оговорка обязана быть в САМОЙ печати, а не в моей памяти: иначе при чтении отчёта
# «любопытство» незаметно превратится в довод.
src = Path(__file__).read_text(encoding="utf-8")
ck("оговорка о ненадёжности зашита в печать", "САМООЦЕНКА МОДЕЛЕЙ НЕНАДЁЖНА" in src)
print(f"\n{'Д7 ГОТОВ' if not bad else f'ПРОВАЛОВ: {bad}'}")
return bad
if __name__ == "__main__":
a = sys.argv[1] if len(sys.argv) > 1 else "--dry"
fn = {"--dry": cmd_dry, "--run": cmd_run, "--show": cmd_show,
"--selftest": lambda: sys.exit(1 if cmd_selftest() else 0)}.get(a)
fn() if fn else print(__doc__)