Skip to content

Commit 5a06d90

Browse files
committed
transformerless_lm: v79 refined self-awareness (#1 + #2 + #3)
v78 self-eval was binary + single-EMA + reactive only. v79 adds three layers of refined self-awareness: #1 Continuous insight scale [0, ~2]: insight = surprise_factor * real_word_factor * (1 - rep_factor) - surprise_factor: surprise / pi*log(phi), capped at 2 - real_word_factor: 1.0 if word, 0.3 if char - rep_factor: 1.0 if token in last F(7)=13 emissions, 0 if novel Replaces binary 0/1. #2 Two-tier momentum (tactical + strategic): momentum_short: 1/F(3)=0.5 weight EMA -- responds in 2 steps momentum_long: 1/F(7)=0.077 weight EMA -- responds in 13 steps Decisions split: short drives sharpen/flatten (per-token tactic), long drives reserve scaling (strategic frame). #3 Entropy override ("am I stuck?" signal): Local entropy of last F(5)=5 emissions. If H < log(2) ~ 0.69 -> force flatten regardless of momentum. The model detects its own repetition through entropy, not just momentum magnitude. Three layers of self-awareness: emission quality (continuous insight), temporal pattern (short + long momentum), and structural diversity (entropy override). All pure substrate (F-tier EMAs, log thresholds).
1 parent 2914105 commit 5a06d90

1 file changed

Lines changed: 81 additions & 34 deletions

File tree

experiments/transformerless_lm/train_self_recursive.py

Lines changed: 81 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,28 +1325,61 @@ def _omniweight_apply(base_probs: torch.Tensor,
13251325

13261326

13271327
def _self_eval_insight(base_probs: torch.Tensor, emitted_tid: int,
1328-
n_chars: int = 65) -> float:
1329-
"""Compute self-evaluation insight signal for a just-emitted token.
1328+
n_chars: int = 65,
1329+
recent_tokens: list = None) -> float:
1330+
"""Continuous insight score in [0, ~2].
13301331
1331-
insight = 1 if:
1332-
- emitted token is a real word (rank >= n_chars), AND
1333-
- surprise (-log p_emitted) >= pi*log(phi) ~ 1.51 (substrate threshold)
1334-
insight = 0 otherwise.
1332+
insight = surprise_factor * real_word_factor * (1 - repetition_factor)
13351333
1336-
Recursive substrate self-monitoring: model rates its own emissions
1337-
against its own distribution.
1334+
surprise_factor: surprise / (pi*log(phi)) capped at 2.
1335+
surprise = -log p_emitted under model's distribution.
1336+
real_word_factor: 1.0 if word-region (rank >= n_chars), 0.3 if char.
1337+
repetition_factor: 1.0 if token in last F(7)=13 emissions, 0 if novel.
1338+
1339+
Continuous scale (v79+) replaces binary insight (v77/v78).
1340+
Substrate-pure: phi/pi/F-tier thresholds.
13381341
"""
1339-
if emitted_tid < n_chars:
1340-
return 0.0
1341-
V = base_probs.shape[0]
1342-
if not (0 <= emitted_tid < V):
1342+
if emitted_tid < 0 or emitted_tid >= base_probs.shape[0]:
13431343
return 0.0
13441344
p = float(base_probs[emitted_tid].item())
13451345
if p <= 0.0:
13461346
return 0.0
13471347
surprise = -math.log(p + 1e-12)
13481348
threshold = math.pi * math.log(_PHI_FOR_SAMPLING)
1349-
return 1.0 if surprise >= threshold else 0.0
1349+
surprise_factor = min(surprise / threshold, 2.0)
1350+
real_word_factor = 1.0 if emitted_tid >= n_chars else 0.3
1351+
rep_factor = 0.0
1352+
if recent_tokens:
1353+
for tid in recent_tokens[-13:]:
1354+
if tid == emitted_tid:
1355+
rep_factor = 1.0
1356+
break
1357+
return surprise_factor * real_word_factor * (1.0 - rep_factor)
1358+
1359+
1360+
def _local_entropy(recent_tokens: list, window: int = 5) -> float:
1361+
"""Shannon entropy over last `window` (F(5)=5) emissions.
1362+
1363+
Low entropy = model is concentrating on few tokens (stuck).
1364+
High entropy = exploring diversity.
1365+
1366+
Returns H in nats; max for distinct tokens = log(window).
1367+
"""
1368+
if not recent_tokens:
1369+
return 0.0
1370+
last = recent_tokens[-window:]
1371+
counts = {}
1372+
for t in last:
1373+
counts[t] = counts.get(t, 0) + 1
1374+
total = sum(counts.values())
1375+
if total == 0:
1376+
return 0.0
1377+
H = 0.0
1378+
for c in counts.values():
1379+
p = c / total
1380+
if p > 0:
1381+
H -= p * math.log(p)
1382+
return H
13501383

13511384

13521385
def _omniweight_apply_split(base_probs: torch.Tensor,
@@ -1421,8 +1454,10 @@ def autoregressive_generate(model, prompt: torch.Tensor, n_new: int,
14211454
char_run = 0
14221455
recent_pairs = [] # (prev_tok, current_tok) bigram history
14231456
last_content_ends_s = False
1424-
creative_momentum = 0.0 # self-eval EMA register
1425-
momentum_history = [] # recent momentum values, F(7)=13 deep
1457+
# v79: two-tier momentum (refined self-awareness).
1458+
momentum_short = 0.0 # F(3)=2 step EMA -- tactical
1459+
momentum_long = 0.0 # F(7)=13 step EMA -- strategic
1460+
momentum_history = [] # recent momentum_short values
14261461
if vocab is not None:
14271462
prompt_list = seq[0].tolist()
14281463
for idx_pl, tid in enumerate(prompt_list):
@@ -1542,28 +1577,33 @@ def autoregressive_generate(model, prompt: torch.Tensor, n_new: int,
15421577
p = substrate_subject_threading(
15431578
seq_list, vocab, base, is_sentence_start=True)
15441579
lang_delta += _omniweight_delta(base, p)
1545-
# Apply split-brain mixer with momentum-modulated reserve.
1580+
# Apply split-brain mixer; STRATEGIC momentum (long) drives reserve.
15461581
probs = _omniweight_apply_split(
15471582
base, math_delta, lang_delta,
1548-
momentum=creative_momentum).unsqueeze(0)
1549-
# A. Three-mode behavior based on momentum sign.
1550-
if creative_momentum > 0.5:
1551-
# Exploit: sharpen distribution.
1583+
momentum=momentum_long).unsqueeze(0)
1584+
# Local entropy of last F(5)=5 emissions (refined self-awareness).
1585+
recent_emitted = seq[0, -_FIB_NUMS_FOR_BIGRAM[5]:].tolist()
1586+
local_H = _local_entropy(recent_emitted, window=_FIB_NUMS_FOR_BIGRAM[5])
1587+
entropy_threshold = math.log(2.0) # F(3)=2 distinct tokens
1588+
stuck = (local_H < entropy_threshold)
1589+
# A. TACTICAL momentum (short) drives sharpen/flatten.
1590+
if stuck:
1591+
# Entropy override: force flatten regardless of momentum.
1592+
p = probs[0] ** (1.0 / _PHI_FOR_SAMPLING)
1593+
probs[0] = p / (p.sum() + 1e-8)
1594+
elif momentum_short > 0.5:
15521595
p = probs[0] ** _PHI_FOR_SAMPLING
15531596
probs[0] = p / (p.sum() + 1e-8)
1554-
elif creative_momentum < -0.5:
1555-
# Escape: flatten distribution.
1597+
elif momentum_short < -0.5:
15561598
p = probs[0] ** (1.0 / _PHI_FOR_SAMPLING)
15571599
probs[0] = p / (p.sum() + 1e-8)
1558-
# B. Backtrack-on-collapse: if recent momentum dropped
1559-
# >F(3)=2 mass over last F(5)=5 steps AND current is
1560-
# negative, force newline boost (substrate reset).
1600+
# B. Backtrack-on-collapse on momentum_short history.
15611601
collapsed = False
15621602
if (len(momentum_history) >= _FIB_NUMS_FOR_BIGRAM[5]
15631603
and newline_mask is not None):
15641604
recent_window = momentum_history[-_FIB_NUMS_FOR_BIGRAM[5]:]
1565-
drop = max(recent_window) - creative_momentum
1566-
if drop > 0.3 and creative_momentum < -0.2:
1605+
drop = max(recent_window) - momentum_short
1606+
if drop > 0.3 and momentum_short < -0.2:
15671607
collapsed = True
15681608
if collapsed and newline_mask is not None:
15691609
nm = newline_mask.to(probs[0].device).to(probs[0].dtype)
@@ -1613,13 +1653,20 @@ def autoregressive_generate(model, prompt: torch.Tensor, n_new: int,
16131653
recent_pairs.append((prev_for_pair, nid))
16141654
if len(recent_pairs) > 13:
16151655
recent_pairs = recent_pairs[-13:]
1616-
# Self-evaluation: update creative momentum EMA.
1617-
insight = _self_eval_insight(base, nid, n_chars_local)
1618-
inv_phi = 1.0 / _PHI_FOR_SAMPLING
1619-
creative_momentum = (inv_phi * creative_momentum
1620-
+ (1.0 - inv_phi) * insight)
1621-
# Track momentum history for backtrack detection.
1622-
momentum_history.append(creative_momentum)
1656+
# Self-evaluation: continuous insight + two-tier momentum.
1657+
recent_emitted_list = seq[0, -13:].tolist()
1658+
insight = _self_eval_insight(
1659+
base, nid, n_chars_local,
1660+
recent_tokens=recent_emitted_list)
1661+
# Tactical short EMA: 1/F(3)=0.5 weight.
1662+
w_short = 1.0 / float(_FIB_NUMS_FOR_BIGRAM[3])
1663+
momentum_short = ((1.0 - w_short) * momentum_short
1664+
+ w_short * insight)
1665+
# Strategic long EMA: 1/F(7)=0.077 weight.
1666+
w_long = 1.0 / float(_FIB_NUMS_FOR_BIGRAM[7])
1667+
momentum_long = ((1.0 - w_long) * momentum_long
1668+
+ w_long * insight)
1669+
momentum_history.append(momentum_short)
16231670
if len(momentum_history) > 13:
16241671
momentum_history = momentum_history[-13:]
16251672
model.train()

0 commit comments

Comments
 (0)