Freeze two ablation variants with the verification tail cut from both and opt-in trace capture
This commit is contained in:
parent
eb49b651d4
commit
3075566104
2 changed files with 102 additions and 5 deletions
|
|
@ -119,8 +119,84 @@ PAIRS["zh"]["restore"] = None
|
|||
# первую клетку второй раз.
|
||||
ARMS = {"RN": ("deepseek-v4-pro", 1), "RN2": ("deepseek-v4-pro", 2),
|
||||
"RG": ("glm-5", 1), "RK": ("grok-4.3", 1),
|
||||
"RA": ("deepseek-v4-pro", 1)} # тот же промт, ВОССТАНОВЛЕННЫЕ абзацы исходника
|
||||
"RA": ("deepseek-v4-pro", 1), # тот же промт, ВОССТАНОВЛЕННЫЕ абзацы исходника
|
||||
"RC": ("deepseek-v4-pro", 1), # промт МИНУС рамка оценки, см. CUT
|
||||
"RB": ("deepseek-v4-pro", 1)} # рамка оценки ПЕРЕВЁРНУТА: брак = чужой язык
|
||||
RESTORE_ARMS = ("RA",)
|
||||
|
||||
# ⚠ РЕЗАНЫЕ ВАРИАНТЫ ПРОМТА. Замер `RN` дал ТРИ независимых показания одного сдвига: размышление
|
||||
# ×28 против прежней склейки при входе ×1.17, слепое чтение — «самый точный по деталям, но проза
|
||||
# самая серая: гладкопись подстрочника», перевёрстка 1.60 против 1.77–1.79 у обеих старых схем.
|
||||
# Модель стала аккуратнее и трусливее по всем осям сразу.
|
||||
# Гипотеза: пять напечатанных осей, «по которым проверят результат», заставляют оптимизировать
|
||||
# ЧЕК-ЛИСТ, а не текст — держаться ближе к букве есть самый дешёвый способ не нарушить пять
|
||||
# критериев разом. Ровно этот отказ предсказывали и приёмка Fable-5, и документация Anthropic
|
||||
# (перенесённые инструкции самопроверки дают избыточную проверку).
|
||||
# ⚠ РЕЖЕТСЯ РОВНО ОДИН БЛОК, остальное побайтно то же — иначе замер не скажет, что подействовало.
|
||||
# Селфтест это ПРОВЕРЯЕТ: разница промтов обязана быть равна вырезанному куску и ничему больше.
|
||||
# ⚠ ПЕРВАЯ РЕДАКЦИЯ РЕЗА БЫЛА НЕГОДНОЙ, и поймала её проверка исполнением ДО покупки: вырезание
|
||||
# блока целиком уносило 1871 знак — вместе с ним исчезали ВСЕ запреты и рамка РЕГИСТРА, лучшая
|
||||
# часть промта по мнению приёмки. Это был бы замер «промт без правил», а не «промт без чек-листа».
|
||||
# ⇒ Режется РОВНО РАМКА ОЦЕНКИ, содержание остаётся побайтно: «по чему будет проверен результат,
|
||||
# это же и есть список ошибок» → «чего нельзя». Одна переменная: знает ли модель, что её ОЦЕНЯТ
|
||||
# по перечню. Убирается и мета-строка про «вольность ошибкой не считается» — она сама ссылается
|
||||
# на оценку и без рамки повисает.
|
||||
# ⚠ RB — ВТОРАЯ ФОРМУЛИРОВКА, И ОНА ОТ ВЛАДЕЛЬЦА. Разбор Fable-5 показал, ПОЧЕМУ экзамен
|
||||
# переиграл свободы: все пять осей сформулированы как оси ИЗБЕГАНИЯ, и серая проза проходит все
|
||||
# пять — «ни кальки, ни канцелярита» гладкий подстрочник проходит, факт/полноту/канон проходит
|
||||
# лучше всех. Весь риск объявленного экзамена лежал на смелости и ни грамма на осторожности,
|
||||
# значит держаться буквы было доминантной стратегией.
|
||||
# Лечение — не убрать экзамен, а ПЕРЕВЕРНУТЬ его риск. Формулировка владельца 20.08 дословно:
|
||||
# «не прям серость, я бы сказал присутствие одного языка в другом. То есть полное отсутствие
|
||||
# художественности и родного звучания текста. Машинный перевод грубо говоря. Всё же перевод это
|
||||
# отчасти какое-то но творчество, без перевирания смысла нужно написать текст, чтоб он звучал
|
||||
# естественно». Это уточняет его же решение 16.08 («штрафовать только за перевирание смысла»):
|
||||
# вторым браком объявляется не вольность, а ПРОСВЕЧИВАЮЩИЙ ИСХОДНЫЙ ЯЗЫК.
|
||||
_BRAK = (
|
||||
"БРАКУЮТСЯ ДВА ИСХОДА, и второй так же строго, как первый.\n"
|
||||
"Первый — перевранный смысл: факт, смысловой ход, канон.\n"
|
||||
"Второй — текст, сквозь который просвечивает исходный язык: чужой синтаксис, переведённо\n"
|
||||
"звучащая фраза, отсутствие живого русского. Машинный перевод бракуется наравне с враньём.\n"
|
||||
"Перевод — отчасти творчество: не переврав смысла, напиши так, чтобы звучало по-русски\n"
|
||||
"естественно. Вольность не проверяет никто.\n\n"
|
||||
"Ниже — то, что относится к первому браку и к границам второго:")
|
||||
# ⚠⚠ ХВОСТ РЕЖЕТСЯ В ОБОИХ АРМАХ, И ЭТО ПОЧИНКА ДИЗАЙНА, А НЕ ФОРМУЛИРОВКИ. Приёмка Fable-5
|
||||
# поймала: после того как императив самопроверки оправдан замером (его не было на момент покупки),
|
||||
# ведущим подозреваемым становится ХВОСТОВАЯ СТРОКА «не нарушает ни одной из осей» — единственное
|
||||
# оставшееся место, где смелость ОБУСЛОВЛЕНА полной верификацией пяти осей. В первой редакции
|
||||
# обоих резов она стояла НЕТРОНУТОЙ, то есть при исходе «оба не сработали» вывод «рамка ни при
|
||||
# чём» был бы неинтерпретируем: ведущий подозреваемый не вырезан нигде.
|
||||
_TAIL_OLD = ("Вольность в пределах этих пяти ошибкой НЕ СЧИТАЕТСЯ. Текст, который читается лучше "
|
||||
"и не нарушает\nни одной из осей, лучше текста, который следует за буквой.")
|
||||
# ⚠ Формулировка второго брака — СЛОВА ВЛАДЕЛЬЦА 20.08: «присутствие одного языка в другом …
|
||||
# полное отсутствие художественности и родного звучания … машинный перевод грубо говоря … перевод
|
||||
# это отчасти какое-то но творчество, без перевирания смысла нужно написать текст, чтоб он звучал
|
||||
# естественно». Правки по приёмке: убран дубль «так же строго»/«наравне с враньём»; «отсутствие
|
||||
# живого русского» → «мёртвый русский» (проверка СВОЙСТВА, а не отсутствия — последняя глобальна
|
||||
# по построению); строка-мост исправлена (ЯЗЫК и РЕГИСТР — СУЩЕСТВО второго брака, а не «границы»).
|
||||
_BRAK = (
|
||||
"БРАКУЮТСЯ ДВА ИСХОДА, и второй так же строго, как первый.\n"
|
||||
"Первый — перевранный смысл: факт, смысловой ход, канон.\n"
|
||||
"Второй — текст, сквозь который просвечивает исходный язык: чужой синтаксис, переведённо\n"
|
||||
"звучащая фраза, мёртвый русский. Машинный перевод — брак, даже когда в нём всё верно.\n"
|
||||
"Перевод — отчасти творчество: не переврав смысла, напиши так, чтобы звучало по-русски\n"
|
||||
"естественно. Вольность не проверяет никто.\n\n"
|
||||
"Первому браку служат СМЫСЛ, ПОЛНОТА и КАНОН; второму — ЯЗЫК и РЕГИСТР:")
|
||||
CUT = {
|
||||
# RB: риск ПЕРЕВЁРНУТ. Хвост заменён не условием, а ПЕРЕОПРЕДЕЛЕНИЕМ: смелость перестаёт быть
|
||||
# разрешённым исключением и становится проверяемым требованием.
|
||||
"RB": [("ПО ЧЕМУ БУДЕТ ПРОВЕРЕН РЕЗУЛЬТАТ. Это же и есть полный список того, что считается "
|
||||
"ошибкой —\nдругих запретов нет:", _BRAK),
|
||||
(_TAIL_OLD,
|
||||
"Живая фраза вместо буквы — не вольность, а исполнение второго требования.")],
|
||||
# RC: экзамена нет вовсе. Хвост тоже без условия верификации и без слова «оси», которое в RC
|
||||
# повисало бы без референта — выше ни одна вещь осью не названа.
|
||||
"RC": [("ПО ЧЕМУ БУДЕТ ПРОВЕРЕН РЕЗУЛЬТАТ. Это же и есть полный список того, что считается "
|
||||
"ошибкой —\nдругих запретов нет:", "ЧЕГО НЕЛЬЗЯ:"),
|
||||
(_TAIL_OLD,
|
||||
"Всё, что за пределами этих пяти, — твоя воля; живая фраза вместо буквы — норма, "
|
||||
"а не риск.")],
|
||||
}
|
||||
FREE = ("ZD", "Z0", "ZP")
|
||||
PRIMARY = ("RN", "ZP") # единственный несущий контраст, см. шапку
|
||||
|
||||
|
|
@ -155,7 +231,7 @@ def pair_blocks(p: str) -> tuple[str, str]:
|
|||
return _block(tr_core, UNITS_HEAD), _block(ed_core, REFLOW_HEAD)
|
||||
|
||||
|
||||
def rol_msgs(p: str, src: str) -> list[dict]:
|
||||
def rol_msgs(p: str, src: str, arm: str = "RN") -> list[dict]:
|
||||
"""Однопроходка НОВЫМ промтом: роль, рамки, регистр, критерии проверки, пар-блоки, глоссарий."""
|
||||
cfg = PAIRS[p]
|
||||
cfg["wire"]()
|
||||
|
|
@ -165,6 +241,11 @@ def rol_msgs(p: str, src: str) -> list[dict]:
|
|||
raise SystemExit(f"⛔ у пары {p} нет блока «{UNITS_HEAD}» либо «{REFLOW_HEAD}» — "
|
||||
"промт собрать нечем, арм не строится")
|
||||
core, _few, user = PR.load_template(CORE)
|
||||
for was, now in CUT.get(arm, []):
|
||||
if was not in core:
|
||||
raise SystemExit(f"⛔ у арма {arm} не найден заменяемый кусок «{was[:40]}…» — "
|
||||
"промт изменился под замером, СТОП")
|
||||
core = core.replace(was, now)
|
||||
core = (core.replace("{{ПАР_ЕДИНИЦЫ}}", units_blk)
|
||||
.replace("{{ПАР_ПЕРЕВЁРСТКА}}", reflow_blk))
|
||||
brief = getattr(PR, PR.PAIR_BRIEF[key])
|
||||
|
|
@ -359,12 +440,19 @@ def call_kwargs(model: str, msgs: list[dict]) -> dict:
|
|||
|
||||
|
||||
# ── ПОКУПКА ──────────────────────────────────────────────────────────────────────────────────
|
||||
# ⚠ АБЛЯЦИИ НЕ НУЖНА ВСЯ ПАНЕЛЬ. Эффект, который ищется, огромен (×28 размышления), и виден он
|
||||
# на трёх главах; тратить на него шестнадцать значит выбрать между двумя вариантами вместо того,
|
||||
# чтобы купить оба. Ограничитель берёт ПЕРВЫЕ N глав отбора — тот же детерминированный порядок,
|
||||
# значит абляция сравнима с уже купленным `RN` глава в главу.
|
||||
N_LIMIT = next((int(a.split("=", 1)[1]) for a in sys.argv if a.startswith("--n=")), 0)
|
||||
|
||||
|
||||
def buy(p: str, which: list[str]) -> None:
|
||||
ZK.price_gate()
|
||||
cfg = PAIRS[p]
|
||||
cfg["wire"]()
|
||||
ZK.preflight([ARMS[a][0] for a in which], cfg["phase"], cfg["letter"])
|
||||
us = chosen(p)
|
||||
us = chosen(p)[:N_LIMIT] if N_LIMIT else chosen(p)
|
||||
led = MONEY.Guarded(cfg["phase"], default_expect=0.03)
|
||||
print(f"\nпара {p} · глав {len(us)} · армы {' '.join(which)} · касса {cfg['phase']}")
|
||||
for arm in which:
|
||||
|
|
@ -380,7 +468,7 @@ def buy(p: str, which: list[str]) -> None:
|
|||
# часами, и пересёкший 16:00 UTC цикл писал бы вызовы по вчерашнему прайсу.
|
||||
ZK.price_gate(quiet=True)
|
||||
rec = MONEY.purchase(led, tg, model, ED22.client(model),
|
||||
call_kwargs(model, rol_msgs(p, src_of(p, arm, u))),
|
||||
call_kwargs(model, rol_msgs(p, src_of(p, arm, u), arm)),
|
||||
role="onepass", uid=u["uid"], arm=arm, gen=gen, pair=p,
|
||||
podacha="абзацы" if arm in RESTORE_ARMS else "плоско")
|
||||
if rec.get("skipped"):
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from __future__ import annotations
|
|||
|
||||
import json
|
||||
import time
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from prices import cost
|
||||
|
|
@ -78,7 +79,15 @@ def usage_of(u, ch) -> dict:
|
|||
return dict(prompt_tokens=u.prompt_tokens or 0, cached_tokens=cached,
|
||||
completion_tokens=u.completion_tokens or 0, reasoning_tokens=reasoning,
|
||||
total_tokens=getattr(u, "total_tokens", 0) or 0,
|
||||
reasoning_chars=len(getattr(msg, "reasoning_content", None) or ""))
|
||||
reasoning_chars=len(getattr(msg, "reasoning_content", None) or ""),
|
||||
# ⚠ САМ ТРЕЙС РАЗМЫШЛЕНИЯ — ТОЛЬКО ПО ЯВНОМУ ФЛАГУ, и это не осторожность, а вес:
|
||||
# у dspro он бывает 30+ тыс. знаков на клетку, то есть удваивает файл сырья, а
|
||||
# нужен он редко. Провайдер отдаёт его в ответе БЕСПЛАТНО, но `usage_of` до 20.08
|
||||
# сохранял одну ДЛИНУ — и когда замер промта дал ×28 размышления, прочитать,
|
||||
# на что оно потрачено, оказалось нечем: пришлось бы пере-покупать клетки.
|
||||
# Флаг `TM_KEEP_TRACE=1` включает сохранение для абляционных прогонов.
|
||||
**({"reasoning_text": getattr(msg, "reasoning_content", None) or ""}
|
||||
if os.environ.get("TM_KEEP_TRACE") == "1" else {}))
|
||||
|
||||
|
||||
def priced(model: str, us: dict) -> float:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue