Amend the drift freeze before reading its numbers: add the same editor with the term bank, because the first arm set confounded topology with bank presence
This commit is contained in:
parent
3bc01c6d69
commit
059c681c9e
1 changed files with 92 additions and 15 deletions
|
|
@ -45,7 +45,12 @@ OUT = Path.home() / "books" / "role-topology"
|
|||
CORP = Path.home() / "books" / "gu-zhenren" / "labels" / "raw" / "corpus.jsonl"
|
||||
|
||||
N_CHAPTERS = 10 # заказ промта: 8–10
|
||||
DRIFT_ARMS = ("F3", "A", "D_") # черновик · связка · однопроходка
|
||||
# ⚠ ПОПРАВКА К ФРИЗУ 07.08, внесена ДО чтения боевых чисел дрейфа и с объявленной причиной.
|
||||
# Первый состав ("F3","A","D_") нёс КОНФАУНД, найденный проверкой сообщений: банк терминов
|
||||
# подаётся черновику и `D_` (block="law"), а арму `A` — НЕТ (block=None, это боевой бейзлайн
|
||||
# без банкноты). На оси «консистентность термина» это означало бы замер БАНКА под видом замера
|
||||
# топологии. `A_law` — тот же редактор С банком — делает сравнение честным.
|
||||
DRIFT_ARMS = ("F3", "A", "A_law", "D_") # черновик · связка без банка · связка с банком · однопроходка
|
||||
CEIL_DRIFT = 0.60
|
||||
# ⚠ Глоб покрывает ТОТ ЖЕ тег, которым идут покупки. Правило заведено после того, как касса
|
||||
# армов глобила `bo2-*`, а покупки шли тегом `bo4-*`, и $0.29309 прошли мимо потолка.
|
||||
|
|
@ -181,25 +186,97 @@ def terms(ch: list[dict], min_ch: int = 3) -> list[str]:
|
|||
return sorted(t for t, s in seen.items() if len(s) >= min_ch)
|
||||
|
||||
|
||||
def variants(arm: str, ch: list[dict]) -> dict:
|
||||
"""Какую из ДВУХ конкурирующих русских форм термина арм выбрал в каждой главе.
|
||||
|
||||
Банк `inject_probe.TERMS` держит на каждый zh-термин пару соперничающих форм и регулярки для
|
||||
их опознания. Дрейф — это когда арм в главе k пишет одну форму, а в главе k+1 другую, при
|
||||
том что zh-термин тот же. Считается детерминированно, судья не нужен.
|
||||
"""
|
||||
out: dict[str, dict[int, set]] = {}
|
||||
for zh, (_v1, _v2, r1, r2) in BO.IP.TERMS.items():
|
||||
for c in ch:
|
||||
if zh not in c["source"]:
|
||||
continue
|
||||
txt = text(arm, c["uid"])
|
||||
if not txt.strip():
|
||||
continue
|
||||
got = set()
|
||||
if re.search(r1, txt, re.I):
|
||||
got.add(0)
|
||||
if re.search(r2, txt, re.I):
|
||||
got.add(1)
|
||||
if got:
|
||||
out.setdefault(zh, {})[c["no"]] = got
|
||||
return out
|
||||
|
||||
|
||||
def cmd_score() -> None:
|
||||
ch = chapters()
|
||||
have = [c for c in ch if text("F3", c["uid"]).strip()]
|
||||
if not have:
|
||||
print("текстов нет — сначала --arms")
|
||||
return
|
||||
print(f"ДРЕЙФ на {len(have)} подряд идущих главах ({have[0]['no']}…{have[-1]['no']})\n")
|
||||
print(f"{'арм':6s}{'ты/вы смеш.':>13s}{'новых вариантов/гл.':>21s}{'знаков':>9s}")
|
||||
for arm in DRIFT_ARMS:
|
||||
ts = [text(arm, c["uid"]) for c in have]
|
||||
ty = sum(1 for t in ts if re.search(r"\bты\b", t) and re.search(r"\bвы\b", t, re.I))
|
||||
print(f"ДРЕЙФ НА СВЯЗНОМ ОТРЕЗКЕ: главы {ch[0]['no']}…{ch[-1]['no']}\n")
|
||||
have = {a: [c for c in ch if text(a, c["uid"]).strip()] for a in DRIFT_ARMS}
|
||||
print("покрытие отрезка армами:")
|
||||
for a in DRIFT_ARMS:
|
||||
miss = [c["no"] for c in ch if c not in have[a]]
|
||||
print(f" {a:4s} {len(have[a])}/{len(ch)} глав" + (f" · нет: {miss}" if miss else ""))
|
||||
print("\n⚠ у связки нога черновика: глава без годного черновика выпадает целиком.")
|
||||
print(" Однопроходка этого отказного режима не имеет ПО ПОСТРОЕНИЮ.\n")
|
||||
|
||||
# ⚠ МЕТРИКА ИСПРАВЛЕНА ИСПОЛНЕНИЕМ. Первая версия считала, какую из ДВУХ форм банка выбрал
|
||||
# арм, и давала «расхождений нет» у всех троих. Проверка показала, что ВТОРАЯ форма не
|
||||
# срабатывает НИ РАЗУ (0 попаданий на 8 терминах × 3 армах × 10 главах), то есть ноль был
|
||||
# тривиален. При этом у арма есть ТРЕТЬЯ форма, банку неизвестная: 蛊师 передаётся то как
|
||||
# «гу-мастер», то «Мастер Гу», то просто «мастер». Здесь считается то, что видно без
|
||||
# выравнивания и сравнимо МЕЖДУ АРМАМИ на одних главах: держит ли арм канонную форму там,
|
||||
# где zh-термин стоит в исходнике, и сколько раз этот признак ПЕРЕКЛЮЧАЕТСЯ между соседними
|
||||
# главами. Переключение и есть дрейф; удержание — консистентность.
|
||||
print(f"{'арм':5s}{'клеток':>8s}{'канон держится':>16s}{'ПЕРЕКЛЮЧЕНИЙ':>14s}{'на переход':>12s}"
|
||||
f"{'ты/вы смеш.':>13s}")
|
||||
common = [c for c in ch if all(text(a, c["uid"]).strip() for a in DRIFT_ARMS)]
|
||||
print(f" (общих глав у всех армов: {len(common)})")
|
||||
per_arm = {}
|
||||
for a in DRIFT_ARMS:
|
||||
cells = hold = flips = trans = 0
|
||||
detail: dict[str, list] = {}
|
||||
for zh, (_v1, _v2, r1, _r2) in BO.IP.TERMS.items():
|
||||
seq = []
|
||||
for c in common:
|
||||
if zh not in c["source"]:
|
||||
continue
|
||||
cells += 1
|
||||
ok = bool(re.search(r1, text(a, c["uid"]), re.I))
|
||||
hold += ok
|
||||
seq.append((c["no"], ok))
|
||||
for (_n1, o1), (_n2, o2) in zip(seq, seq[1:]):
|
||||
trans += 1
|
||||
flips += o1 != o2
|
||||
if len(seq) > 1:
|
||||
detail[zh] = seq
|
||||
per_arm[a] = detail
|
||||
ty = sum(1 for c in common
|
||||
if re.search(r"(?<![а-яё])ты(?![а-яё])", text(a, c["uid"]), re.I)
|
||||
and re.search(r"(?<![а-яё])вы(?![а-яё])", text(a, c["uid"]), re.I))
|
||||
print(f"{a:5s}{cells:>8d}{hold:>13d}/{cells}{flips:>14d}"
|
||||
f"{(flips / trans if trans else 0):>12.2f}{ty:>10d}/{len(common)}")
|
||||
|
||||
print("\nПОТЕРМИННО (+ канон держится, − арм написал что-то другое):")
|
||||
for a in DRIFT_ARMS:
|
||||
print(f" {a}:")
|
||||
for zh, seq in sorted(per_arm[a].items()):
|
||||
line = " ".join(f"{n}{'+' if o else '−'}" for n, o in seq)
|
||||
fl = sum(1 for x, y in zip(seq, seq[1:]) if x[1] != y[1])
|
||||
print(f" {zh:6s} {line} переключений {fl}")
|
||||
|
||||
print("\nРОСТ СЛОВАРЯ (новых слов на главу; растущая кривая = арм не помнит решений):")
|
||||
for a in DRIFT_ARMS:
|
||||
vocab, new = set(), []
|
||||
for t in ts:
|
||||
w = set(re.findall(r"[а-яё]{4,}", t.lower()))
|
||||
for c in have[a]:
|
||||
w = set(re.findall(r"[а-яё]{4,}", text(a, c["uid"]).lower()))
|
||||
new.append(len(w - vocab))
|
||||
vocab |= w
|
||||
print(f"{arm:6s}{ty:>10d}/{len(ts)}{st.mean(new):>21.0f}{sum(len(t) for t in ts):>9d}")
|
||||
print("\n⚠ полные метрики консистентности термина и шва — после закупки, здесь только то,")
|
||||
print(" что считается из одного текста; терминные требуют выравнивания zh↔ru по главам.")
|
||||
half = len(new) // 2
|
||||
print(f" {a:5s} первая половина {st.mean(new[:half]):.0f}/гл · "
|
||||
f"вторая {st.mean(new[half:]):.0f}/гл · всего уникальных {len(vocab)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue