@@ -667,6 +667,89 @@ def build_vowel_start_mask(vocab: list) -> torch.Tensor:
667667 return mask
668668
669669
670+ def build_unpronounceable_mask (vocab : list ) -> torch .Tensor :
671+ """Mask = 1 for tokens with impossible-shape lettering:
672+ - max consonant cluster > F(4)=3
673+ - same letter triple (F(3)=2 repetitions of same char in a row)
674+ - vowel ratio < 1/phi^2 ~ 0.382 (too few vowels to be syllabic)
675+ Char tokens (len=1) are exempt. Pure substrate (char-class
676+ arithmetic + Fibonacci-tier thresholds).
677+ """
678+ V = len (vocab )
679+ mask = torch .zeros (V )
680+ F = _FIB_NUMS_FOR_BIGRAM
681+ inv_phi2 = 1.0 / (_PHI_FOR_SAMPLING ** 2 )
682+ for i , tok in enumerate (vocab ):
683+ if not tok or len (tok ) <= 1 :
684+ continue
685+ # Skip if not all alphabetic (punctuation/contractions).
686+ if not all (c .isalpha () for c in tok ):
687+ continue
688+ # Max consonant cluster.
689+ max_cluster = 0
690+ cur = 0
691+ for ch in tok :
692+ if ch in _IAMBIC_VOWELS :
693+ cur = 0
694+ else :
695+ cur += 1
696+ if cur > max_cluster :
697+ max_cluster = cur
698+ # Same-letter triple.
699+ triple = False
700+ for j in range (len (tok ) - 2 ):
701+ if tok [j ] == tok [j + 1 ] == tok [j + 2 ]:
702+ triple = True
703+ break
704+ # Vowel ratio.
705+ n_vowel = sum (1 for c in tok if c in _IAMBIC_VOWELS )
706+ vowel_ratio = n_vowel / len (tok )
707+ if max_cluster > F [4 ] or triple or vowel_ratio < inv_phi2 :
708+ mask [i ] = 1.0
709+ return mask
710+
711+
712+ def substrate_word_spacing (prev_tid : int , probs : torch .Tensor ,
713+ vocab : list , n_chars : int = 65 ) -> torch .Tensor :
714+ """After a word-token (rank >= n_chars), boost the space token to
715+ encourage word-boundary spacing. Prevents adjacent-word
716+ concatenation ("naygrumio", "thouA"). Pure substrate (rank tier +
717+ char-class identification of space).
718+
719+ Boost = phi (substrate-canonical). Penalty for other chars stays
720+ flat (no suppression to avoid breaking punctuation flow).
721+ """
722+ if prev_tid < n_chars or not vocab :
723+ return probs
724+ space_idx = None
725+ for i in range (min (n_chars , len (vocab ))):
726+ if vocab [i ] == ' ' :
727+ space_idx = i
728+ break
729+ if space_idx is None :
730+ return probs
731+ out = probs .clone ()
732+ out [space_idx ] = out [space_idx ] * _PHI_FOR_SAMPLING
733+ return out / (out .sum () + 1e-8 )
734+
735+
736+ def substrate_pronounceability (probs : torch .Tensor ,
737+ unpronounceable_mask : torch .Tensor
738+ ) -> torch .Tensor :
739+ """Suppress tokens flagged as un-pronounceable (impossible shape).
740+ Multiplicative penalty by 1/phi^pi ~ 0.221.
741+ Pure substrate (precomputed shape filter).
742+ """
743+ if unpronounceable_mask is None :
744+ return probs
745+ upm = unpronounceable_mask .to (probs .device ).to (probs .dtype )
746+ penalty = 1.0 / (_PHI_FOR_SAMPLING ** math .pi )
747+ multiplier = 1.0 - upm * (1.0 - penalty )
748+ out = probs * multiplier
749+ return out / (out .sum () + 1e-8 )
750+ return mask
751+
752+
670753def substrate_phonotactics (cluster_len : int , probs : torch .Tensor ,
671754 vowel_start_mask : torch .Tensor ) -> torch .Tensor :
672755 """When recent consonant cluster >= 2, boost vowel-starting tokens.
@@ -1124,7 +1207,8 @@ def autoregressive_generate(model, prompt: torch.Tensor, n_new: int,
11241207 vowel_start_mask : torch .Tensor = None ,
11251208 end_vowels : list = None ,
11261209 punct_mask : torch .Tensor = None ,
1127- newline_mask : torch .Tensor = None ):
1210+ newline_mask : torch .Tensor = None ,
1211+ unpronounceable_mask : torch .Tensor = None ):
11281212 """Sample n_new tokens autoregressively with substrate sampling AND
11291213 a substrate-canonical recency penalty.
11301214
@@ -1206,6 +1290,15 @@ def autoregressive_generate(model, prompt: torch.Tensor, n_new: int,
12061290 recent_list = seq [0 , - 13 :].tolist ()
12071291 probs [0 ] = substrate_rhyme_resonance (
12081292 recent_list , end_vowels , probs [0 ])
1293+ # Word spacing (post-word space pressure).
1294+ if vocab is not None and seq .shape [1 ] >= 1 :
1295+ probs [0 ] = substrate_word_spacing (
1296+ int (seq [0 , - 1 ]), probs [0 ], vocab ,
1297+ n_chars = n_chars_local )
1298+ # Pronounceability filter (suppress impossible shapes).
1299+ if unpronounceable_mask is not None :
1300+ probs [0 ] = substrate_pronounceability (
1301+ probs [0 ], unpronounceable_mask )
12091302 # Theme momentum (subject-matter coherence).
12101303 if token_signatures is not None and seq .shape [1 ] >= 1 :
12111304 recent_list = seq [0 , - 13 :].tolist ()
@@ -1369,11 +1462,20 @@ def _single_stage_refine(model, draft, vocab_size, scorer, mode: str,
13691462 if vowel_start_mask is not None and cl_len >= 2 :
13701463 pos_probs = substrate_phonotactics (
13711464 cl_len , pos_probs , vowel_start_mask )
1465+ # Word spacing (post-word space pressure).
1466+ pos_probs = substrate_word_spacing (
1467+ int (new [0 , t_draft - 1 ]), pos_probs , vocab ,
1468+ n_chars = n_chars_r )
1469+ # Pronounceability filter.
1470+ if unpronounceable_mask is not None :
1471+ pos_probs = substrate_pronounceability (
1472+ pos_probs , unpronounceable_mask )
1473+ # Rhyme resonance.
13721474 if end_vowels is not None :
1373- recent_start = max (0 , t_draft - 13 )
1374- recent_list = new [0 , recent_start :t_draft ].tolist ()
1475+ recent_start_ev = max (0 , t_draft - 13 )
1476+ recent_list_ev = new [0 , recent_start_ev :t_draft ].tolist ()
13751477 pos_probs = substrate_rhyme_resonance (
1376- recent_list , end_vowels , pos_probs )
1478+ recent_list_ev , end_vowels , pos_probs )
13771479 # Theme momentum (subject-matter coherence).
13781480 if token_signatures is not None and t_draft >= 1 :
13791481 recent_start = max (0 , t_draft - 13 )
@@ -1454,7 +1556,7 @@ def staged_refine(model, prompt, n_new, vocab_size,
14541556 with torch .no_grad ():
14551557 draft = autoregressive_generate (model , prompt , n_new = n_new ,
14561558 vocab_size = vocab_size ,
1457- temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask )
1559+ temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask , unpronounceable_mask = unpronounceable_mask )
14581560 stages_out = {}
14591561 stages_out ["initial" ] = {"seq" : draft .clone (),
14601562 "harmony" : harmony_scorer (draft ),
@@ -1467,7 +1569,7 @@ def staged_refine(model, prompt, n_new, vocab_size,
14671569 n_iters = n_iters_per_stage ,
14681570 resample_frac = resample_frac ,
14691571 prompt_len = prompt_len ,
1470- temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask )
1572+ temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask , unpronounceable_mask = unpronounceable_mask )
14711573 stages_out ["after_harmony" ] = {"seq" : draft .clone (),
14721574 "trajectory" : h_traj ,
14731575 "harmony" : harmony_scorer (draft ),
@@ -1480,7 +1582,7 @@ def staged_refine(model, prompt, n_new, vocab_size,
14801582 n_iters = n_iters_per_stage ,
14811583 resample_frac = resample_frac ,
14821584 prompt_len = prompt_len ,
1483- temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask )
1585+ temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask , unpronounceable_mask = unpronounceable_mask )
14841586 stages_out ["after_quality" ] = {"seq" : draft .clone (),
14851587 "trajectory" : q_traj ,
14861588 "harmony" : harmony_scorer (draft ),
@@ -1494,7 +1596,7 @@ def staged_refine(model, prompt, n_new, vocab_size,
14941596 n_iters = n_iters_per_stage ,
14951597 resample_frac = resample_frac ,
14961598 prompt_len = prompt_len ,
1497- temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask )
1599+ temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask , unpronounceable_mask = unpronounceable_mask )
14981600 stages_out ["after_creativity" ] = {"seq" : draft .clone (),
14991601 "trajectory" : c_traj ,
15001602 "harmony" : harmony_scorer (draft ),
@@ -1528,7 +1630,7 @@ def iterative_refine(model, prompt, n_new, vocab_size,
15281630 # Step 1: initial draft.
15291631 draft = autoregressive_generate (model , prompt , n_new = n_new ,
15301632 vocab_size = vocab_size ,
1531- temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask )
1633+ temperature = temperature , bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask , unpronounceable_mask = unpronounceable_mask )
15321634 history = []
15331635 h0 = harmony_scorer (draft ) if harmony_scorer is not None else None
15341636 q0 = quality_scorer (draft ) if quality_scorer is not None else None
@@ -1936,13 +2038,15 @@ def quality_fn(seq_tokens):
19362038 end_vowels = build_end_vowel_per_token (vocab_for_bigram )
19372039 punct_mask = build_punct_mask (vocab_for_bigram )
19382040 newline_mask = build_newline_mask (vocab_for_bigram )
2041+ unpronounceable_mask = build_unpronounceable_mask (vocab_for_bigram )
19392042 print (f" symbol classes: { n_classes } | "
19402043 f"pronoun cand: { int (pronoun_mask .sum ().item ())} | "
19412044 f"vowel-start: { int (vowel_start_mask .sum ().item ())} | "
19422045 f"punct: { int (punct_mask .sum ().item ())} | "
19432046 f"newline: { int (newline_mask .sum ().item ())} | "
1944- f"end-vowel toks: "
1945- f"{ sum (1 for v in end_vowels if v )} " )
2047+ f"unpronounceable: "
2048+ f"{ int (unpronounceable_mask .sum ().item ())} | "
2049+ f"end-vowel: { sum (1 for v in end_vowels if v )} " )
19462050 else :
19472051 class_id_tensor = None
19482052 n_classes = 0
@@ -1951,6 +2055,7 @@ def quality_fn(seq_tokens):
19512055 end_vowels = None
19522056 punct_mask = None
19532057 newline_mask = None
2058+ unpronounceable_mask = None
19542059
19552060 # Active training base: starts as tiny_seed, GROWS by appending each
19562061 # cycle's best refined output -- only if (a) creativity > corpus
@@ -2018,14 +2123,14 @@ def quality_fn(seq_tokens):
20182123 draft = autoregressive_generate (
20192124 model , prompt_s , n_new = growth_n_new ,
20202125 vocab_size = vocab_size , temperature = 0.8 ,
2021- bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask )
2126+ bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask , unpronounceable_mask = unpronounceable_mask )
20222127 refined_s , _ = staged_refine (
20232128 model , prompt_s , n_new = growth_n_new , vocab_size = vocab_size ,
20242129 harmony_scorer = harmony_fn , quality_scorer = quality_fn ,
20252130 creativity_scorer = creativity_fn ,
20262131 n_iters_per_stage = 30 , resample_frac = 0.35 ,
20272132 prompt_len = 16 , temperature = 0.5 ,
2028- bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask )
2133+ bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask , unpronounceable_mask = unpronounceable_mask )
20292134 samples .append ((refined_s .squeeze (0 ).clone (),
20302135 creativity_fn (refined_s )))
20312136 # Sort by creativity desc, keep top K.
@@ -2095,14 +2200,14 @@ def quality_fn(seq_tokens):
20952200 final_gen = autoregressive_generate (model , prompt , n_new = n_new ,
20962201 vocab_size = vocab_size ,
20972202 temperature = 0.8 ,
2098- bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask )
2203+ bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask , unpronounceable_mask = unpronounceable_mask )
20992204 final_refined , _ = staged_refine (
21002205 model , prompt , n_new = n_new , vocab_size = vocab_size ,
21012206 harmony_scorer = harmony_fn , quality_scorer = quality_fn ,
21022207 creativity_scorer = creativity_fn ,
21032208 n_iters_per_stage = 200 , resample_frac = 0.35 ,
21042209 prompt_len = 16 , temperature = 0.5 ,
2105- bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask )
2210+ bigram_prior = bigram_prior , vocab = vocab , token_signatures = token_signatures , active_vocab_size = active_vocab_size , class_id_tensor = class_id_tensor , n_classes = n_classes , pronoun_mask = pronoun_mask , vowel_start_mask = vowel_start_mask , end_vowels = end_vowels , punct_mask = punct_mask , newline_mask = newline_mask , unpronounceable_mask = unpronounceable_mask )
21062211
21072212 return {"name" : name , "mode" : "self_distillation" ,
21082213 "n_params" : n_params ,
0 commit comments