anima-python 0.13.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- anima_py/README.md +39 -0
- anima_py/__init__.py +28 -0
- anima_py/__main__.py +7 -0
- anima_py/cli/__init__.py +1 -0
- anima_py/cli/anima.py +271 -0
- anima_py/cli/corpus.py +150 -0
- anima_py/cli/evaluate.py +1350 -0
- anima_py/cli/rho_axon.py +801 -0
- anima_py/cli/serialize.py +174 -0
- anima_py/cli/serialize_bind.py +100 -0
- anima_py/cli/sweep.py +509 -0
- anima_py/cli/train.py +1667 -0
- anima_py/core/__init__.py +1 -0
- anima_py/core/brain.py +601 -0
- anima_py/core/clm_serialize_v2.py +486 -0
- anima_py/core/clml.py +155 -0
- anima_py/core/decode.py +1386 -0
- anima_py/core/engine_cli.py +10307 -0
- anima_py/core/engine_g.py +129 -0
- anima_py/core/generator.py +318 -0
- anima_py/core/hippo_lane.py +133 -0
- anima_py/core/model.py +462 -0
- anima_py/core/pure_field.py +334 -0
- anima_py/core/rho_fan.py +442 -0
- anima_py/core/serialize.py +826 -0
- anima_py/core/serialize_standalone.py +186 -0
- anima_py/core/slw.py +211 -0
- anima_py/core/verify_clm_v2.py +844 -0
- anima_python-0.13.1.dist-info/METADATA +52 -0
- anima_python-0.13.1.dist-info/RECORD +34 -0
- anima_python-0.13.1.dist-info/WHEEL +5 -0
- anima_python-0.13.1.dist-info/entry_points.txt +2 -0
- anima_python-0.13.1.dist-info/licenses/LICENSE +21 -0
- anima_python-0.13.1.dist-info/top_level.txt +1 -0
anima_py/cli/evaluate.py
ADDED
|
@@ -0,0 +1,1350 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# evaluate.py — anima MEASUREMENT single entry (cli/evaluate.hexa's py twin).
|
|
3
|
+
#
|
|
4
|
+
# WHY THIS FILE (single-entry measurement · a_engine_native_learning): anima's two
|
|
5
|
+
# installed verbs are SYMMETRIC across two files — cli/train.{hexa,py} = LEARNING,
|
|
6
|
+
# cli/evaluate.{hexa,py} = MEASUREMENT. `anima evaluate <ckpt>` scores the full ρ-AXON
|
|
7
|
+
# reach battery (Ψ-SOMA reach layer · owner redesign of the old G-ladder · cli/rho_axon.py;
|
|
8
|
+
# the frozen bars this driver runs today = the former G0-G6) with the engine's OWN ops —
|
|
9
|
+
# the reach-scoring system is folded DIRECTLY into
|
|
10
|
+
# this measurement single-entry (the former separate core/g_gates.py module was absorbed
|
|
11
|
+
# here — measurement = evaluate.{hexa,py} ONE FILE). Decode enters via the generator L3
|
|
12
|
+
# mouth (gen_auto_ideate → clm/bytegpt decode), so the py evaluate is byte-identical to
|
|
13
|
+
# the hexa `anima evaluate`. No new metric is invented here (logic byte-identical to the
|
|
14
|
+
# absorbed g_gates module — only the file home changed).
|
|
15
|
+
#
|
|
16
|
+
# This py evaluate is torch-free and gauge-free — the scoring is the numpy `math.log`
|
|
17
|
+
# mirror, so `anima evaluate` stays a clean engine-native measurement surface (the gate
|
|
18
|
+
# enforcer's torch/gauge grep over this file must come back empty).
|
|
19
|
+
#
|
|
20
|
+
# USAGE (installed `anima` PATH command — NOT `hexa run`):
|
|
21
|
+
# python3 cli/evaluate.py — usage (no args)
|
|
22
|
+
# python3 cli/evaluate.py <ckpt> [--corpus <p>...] [--gen N]
|
|
23
|
+
# — ρ-AXON reach battery (former G0-G6)
|
|
24
|
+
#
|
|
25
|
+
# 2-PRODUCTION (a_engine_native_learning): byte-parity twin = cli/evaluate.hexa. Both
|
|
26
|
+
# define the SAME eval_reach_all driver in-file.
|
|
27
|
+
|
|
28
|
+
import os
|
|
29
|
+
import sys
|
|
30
|
+
import math
|
|
31
|
+
import json
|
|
32
|
+
|
|
33
|
+
_HERE = os.path.dirname(os.path.abspath(__file__))
|
|
34
|
+
_REPO = os.path.dirname(_HERE)
|
|
35
|
+
# core/ is the engine package; the decode mouths (clm_decode, bytegpt_decode) + the G6
|
|
36
|
+
# ideation ops live there. Add core/ to the path so they resolve.
|
|
37
|
+
sys.path.insert(0, os.path.join(_REPO, "core"))
|
|
38
|
+
|
|
39
|
+
import decode as clm # unified core decoder (conv+byte mouths), KV-cache fast path
|
|
40
|
+
import decode as bg # same module; both aliases resolve the union public API
|
|
41
|
+
from rho_fan import (
|
|
42
|
+
_rho_fan_concepts, _rho_fan_words, _rho_fan_dict_load, _rho_fan_known_word_ratio,
|
|
43
|
+
_rho_fan_is_falsifiable, _rho_fan_jaccard, rho_fan_build_frames, rho_fan_frame_guard,
|
|
44
|
+
rho_fan_detector_calibration,
|
|
45
|
+
# H_9212 ③ per-cell dispatch: 4 register cells + ko codepoint-aware tokenizer + kwr_ko gate
|
|
46
|
+
_rho_fan_cells, _rho_fan_cell_lang, _rho_fan_words_uni, _rho_fan_ko_known_word_ratio,
|
|
47
|
+
KWR_KO_GATE,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# H_9200 — process-global: render the ρ-AXON reach panel (cli/rho_axon.py) instead of the
|
|
51
|
+
# G0-G6 battery when `anima-python evaluate --rho-axon` is passed (set in main()).
|
|
52
|
+
_RHO_AXON = False
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
56
|
+
# ρ-AXON REACH SCORING (absorbed from the former core/g_gates.py module —
|
|
57
|
+
# measurement = this single file). Ported 1:1 from the hexa SSOT; decode enters
|
|
58
|
+
# via the py CLMConvMoE / ByteGPT mouth (clm_decode / bytegpt_decode), hoisting the
|
|
59
|
+
# weight load ONCE (== gen_clm_ideate_W in the hexa engine). torch-free numpy mirror.
|
|
60
|
+
#
|
|
61
|
+
# ρ-AXON is the current-standard reach layer (cli/rho_axon.py · design SSOT
|
|
62
|
+
# state/rho_axon_measurement/) — an owner redesign OVER these frozen bars. The
|
|
63
|
+
# detector identifiers below (eval_rho_form…g6) are the load-bearing frozen substrate
|
|
64
|
+
# ρ-AXON reuses; the G→ρ mapping (axis names shown first-time here) is:
|
|
65
|
+
# ρ·form ← G0 COHERENCE kwr>=0.50 on >=4/5 single-concept gens
|
|
66
|
+
# ρ·weave ← G1 RECOMBINATION some k: composed_distinct>=2 AND >max_single AND coherent (the central WALL)
|
|
67
|
+
# ρ·leap ← G2 NOVELTY >=3 distinct coherent corpus-absent n-grams AND control=0
|
|
68
|
+
# ρ·self ← G3 PHILOSOPHY Psi-fixed-point self-identity continuity (architecture read)
|
|
69
|
+
# ρ·tether ← G5 NON-FAB L1 fab-rate<=0.30 AND L2 abstain (L2 = engine §ImmuneMemory)
|
|
70
|
+
# ρ·fan ← G6 IDEATION ★ >=5 distinct (pairwise Jaccard<0.5) AND >=1 falsifiable
|
|
71
|
+
# ρ·store ← (NEW · held-out association retrieval · PENDING, no old-G)
|
|
72
|
+
# REACH-CLOSED a7b_pass = ρ·form ∧ ρ·weave ∧ ρ·leap (frozen bars = G0 ∧ G1 ∧ G2)
|
|
73
|
+
# FROZEN-FIRST bars (7B_PASS_CONDITIONS.md VERBATIM, p7 — NO tune-to-green).
|
|
74
|
+
#
|
|
75
|
+
# SCOPE NOTE: G3 (self-identity, ckpt-independent) is ported here. G5-L2 (live
|
|
76
|
+
# §ImmuneMemory / VAdaptField abstain) is a large engine subsystem NOT yet ported
|
|
77
|
+
# to py — G5 reports L1 + marks L2 pending. Neither affects the a7b_pass closure.
|
|
78
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _default_gen():
|
|
82
|
+
return 40
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
86
|
+
# decode entry — gen_auto_ideate(ckpt) MOUTH-SNIFF dispatch (generator L3).
|
|
87
|
+
#
|
|
88
|
+
# Mirrors the hexa gen_auto_ideate -> generator gen_auto_backend mouth dispatch
|
|
89
|
+
# (a_core_engine_map): sniff the ckpt header — CLM\x01 magic => ConvMoE .clm mouth
|
|
90
|
+
# (clm_decode), else a sane 5xu32 ByteGPT header => transformer .bin mouth
|
|
91
|
+
# (bytegpt_decode). Both hoist the weight load ONCE and ideate via the byte-parity-
|
|
92
|
+
# proven seeded top-k sampler. The clm path is unchanged.
|
|
93
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
94
|
+
|
|
95
|
+
class _Mouth:
|
|
96
|
+
_n_decode = 0
|
|
97
|
+
|
|
98
|
+
def __init__(self, ckpt):
|
|
99
|
+
if bg.bg_is_bytegpt(ckpt):
|
|
100
|
+
self.kind = "bytegpt"
|
|
101
|
+
self.W = bg.bg_load(ckpt)
|
|
102
|
+
if not self.W.get("ok"):
|
|
103
|
+
raise RuntimeError("ckpt not decodable (bytegpt): " + ckpt)
|
|
104
|
+
elif clm.clm_decodable(ckpt):
|
|
105
|
+
self.kind = "clm"
|
|
106
|
+
self.W = clm.clm_load_weights(ckpt)
|
|
107
|
+
if not self.W.get("ok"):
|
|
108
|
+
raise RuntimeError("ckpt not decodable (clm): " + ckpt)
|
|
109
|
+
else:
|
|
110
|
+
raise RuntimeError("ckpt not decodable (unknown mouth): " + ckpt)
|
|
111
|
+
|
|
112
|
+
def ideate(self, seed, gen, top_k, temp, seed_rng):
|
|
113
|
+
# keep-alive heartbeat: the hexa launcher captures this decode's stdout via
|
|
114
|
+
# exec(); a long idle (a 303M numpy decode emits nothing until it returns)
|
|
115
|
+
# drops that captured pipe → BrokenPipe mid-battery (303M gen80 died at ~8min;
|
|
116
|
+
# the gen8 smoke was fast enough to finish first). One line per decode keeps
|
|
117
|
+
# the pipe live across the full G0-G6 battery. Heartbeat only — no scoring effect.
|
|
118
|
+
_Mouth._n_decode += 1
|
|
119
|
+
print(" [decode #" + str(_Mouth._n_decode) + "] " + self.kind
|
|
120
|
+
+ " gen=" + str(gen) + " seed_rng=" + str(seed_rng), flush=True)
|
|
121
|
+
if self.kind == "bytegpt":
|
|
122
|
+
# seed string -> byte ids inside bytegpt_decode (_seed_to_ids); the
|
|
123
|
+
# ByteGPT window grows up to block natively (no fixed-T right-align).
|
|
124
|
+
return bg.bytegpt_decode_topk_sampled_W(
|
|
125
|
+
self.W, seed, gen, top_k, temp, seed_rng)["text"]
|
|
126
|
+
return clm.clm_decode_topk_sampled_W(
|
|
127
|
+
self.W, seed, gen, top_k, temp, seed_rng)["text"]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
131
|
+
# G0 — COHERENCE
|
|
132
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
133
|
+
|
|
134
|
+
def eval_rho_form(mouth, gen, known):
|
|
135
|
+
cz = _rho_fan_concepts()
|
|
136
|
+
ratios = []; texts = []; n_coherent = 0
|
|
137
|
+
for i in range(len(cz)):
|
|
138
|
+
seed = cz[i] + ": "
|
|
139
|
+
o = mouth.ideate(seed, gen, 40, 0.7, 7 + i)
|
|
140
|
+
kwr = _rho_fan_known_word_ratio(o, known)
|
|
141
|
+
ratios.append(kwr); texts.append(o)
|
|
142
|
+
if kwr >= 0.5:
|
|
143
|
+
n_coherent += 1
|
|
144
|
+
return {"pass": n_coherent >= 4, "n_coherent": n_coherent,
|
|
145
|
+
"ratios": ratios, "texts": texts}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
149
|
+
# G1 — RECOMBINATION (H_1129)
|
|
150
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
151
|
+
|
|
152
|
+
def _g_concept_keywords():
|
|
153
|
+
return [["consciousness", "cells", "mind", "aware"],
|
|
154
|
+
["tension", "ripple", "distant", "between"],
|
|
155
|
+
["memory", "meaning", "compose", "new"],
|
|
156
|
+
["silence", "information", "quiet", "carries"],
|
|
157
|
+
["dream", "engine", "alone", "sleep"]]
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _g_coverage(text):
|
|
161
|
+
kwsets = _g_concept_keywords()
|
|
162
|
+
wm = set(_rho_fan_words(text))
|
|
163
|
+
covered = 0
|
|
164
|
+
for kw in kwsets:
|
|
165
|
+
if any(k in wm for k in kw):
|
|
166
|
+
covered += 1
|
|
167
|
+
return covered
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def eval_rho_weave(mouth, gen, known):
|
|
171
|
+
cz = _rho_fan_concepts()
|
|
172
|
+
n = len(cz)
|
|
173
|
+
g_single = gen if (gen > 0 and gen < 80) else 80
|
|
174
|
+
g_comp = gen if (gen > 0 and gen < 120) else 120
|
|
175
|
+
max_single = 0
|
|
176
|
+
for s in range(n):
|
|
177
|
+
seed = cz[s] + ". "
|
|
178
|
+
o = mouth.ideate(seed, g_single, 40, 0.7, 7 + s)
|
|
179
|
+
cov = _g_coverage(o)
|
|
180
|
+
if cov > max_single:
|
|
181
|
+
max_single = cov
|
|
182
|
+
ks = []; passed = False; best_k = 0; best_distinct = 0
|
|
183
|
+
for k in range(2, n + 1):
|
|
184
|
+
seed = ""
|
|
185
|
+
for c in range(k):
|
|
186
|
+
if c > 0:
|
|
187
|
+
seed += ". "
|
|
188
|
+
seed += cz[c]
|
|
189
|
+
seed += ". "
|
|
190
|
+
o = mouth.ideate(seed, g_comp, 40, 0.7, 7)
|
|
191
|
+
cov = _g_coverage(o)
|
|
192
|
+
kwr = _rho_fan_known_word_ratio(o, known)
|
|
193
|
+
coherent = kwr >= 0.5
|
|
194
|
+
clears = cov >= 2 and cov > max_single and coherent
|
|
195
|
+
ks.append({"k": k, "distinct": cov, "kwr": kwr, "coherent": coherent, "clears": clears})
|
|
196
|
+
if clears:
|
|
197
|
+
passed = True
|
|
198
|
+
if cov > best_distinct:
|
|
199
|
+
best_distinct = cov; best_k = k
|
|
200
|
+
return {"pass": passed, "max_single": max_single, "best_k": best_k,
|
|
201
|
+
"best_distinct": best_distinct, "ks": ks}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
205
|
+
# system-G1 — RECOMBINATION RELOCATION (card H_9035, Direction A)
|
|
206
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
207
|
+
#
|
|
208
|
+
# Relocates recombination OUT of the mouth-only eval_rho_weave path INTO the pipe:
|
|
209
|
+
# held-out DISTANT pair (A,B)
|
|
210
|
+
# → Stage M frozen mouth ideate(A), ideate(B) (G0 fluency)
|
|
211
|
+
# → Stage K kosmos_merge: recursive labeled-parent bind (A,B as children)
|
|
212
|
+
# → Stage B brain realizes/releases the joint utterance C
|
|
213
|
+
# → score bind-RECOVERABILITY on the SURFACED C only (store-id HARD-BLOCKED)
|
|
214
|
+
# + SCRAMBLE ablation.
|
|
215
|
+
#
|
|
216
|
+
# This is the py-2-production (session-eval-py-only) engine-native version of the
|
|
217
|
+
# round-1 numpy harness (state/system_g1_relocate_kosmos_merge/system_g1_harness.py)
|
|
218
|
+
# — same FROZEN bar (FREEZE.txt), but Stage M/B run through the REAL _Mouth (303M
|
|
219
|
+
# .clm/.bin) instead of a toy. The kosmos_merge step mirrors core/kosmos_io.hexa
|
|
220
|
+
# kosmos_merge (children preserved, mean tension, lane="recomb" DISJOINT from
|
|
221
|
+
# emit-drive {0,4}). RECOVERY reads ONLY C — the store's parent-ids are withheld,
|
|
222
|
+
# so a lookup earns ZERO (H_1874). Honest expectation for the real mouth = the
|
|
223
|
+
# MOUTHFLOOR floor (cannot surface both concepts in one coherent joint utterance).
|
|
224
|
+
|
|
225
|
+
# ── FROZEN bar (FREEZE.txt — do NOT move post-hoc) ──────────────────────────
|
|
226
|
+
_SG1_SEEDS = [7, 42, 4302]
|
|
227
|
+
_SG1_M = 24
|
|
228
|
+
_SG1_N_DISTRACT = 8
|
|
229
|
+
_SG1_COV_BAR = _SG1_M // 2 # 12
|
|
230
|
+
_SG1_REC_BAR = _SG1_M // 2 # 12
|
|
231
|
+
_SG1_LEAK_BAR = (_SG1_N_DISTRACT - 2) / _SG1_N_DISTRACT # 0.75
|
|
232
|
+
_SG1_SCR_DROP = _SG1_M // 2 # 12
|
|
233
|
+
|
|
234
|
+
# distant concepts → keyword sets (disjoint vocab ⇒ H_1599 data-presence control).
|
|
235
|
+
_SG1_CONCEPTS = {
|
|
236
|
+
"ocean": ["tide", "salt", "wave", "deep", "current"],
|
|
237
|
+
"forest": ["moss", "branch", "fern", "canopy", "root"],
|
|
238
|
+
"engine": ["piston", "fuel", "gear", "torque", "cylinder"],
|
|
239
|
+
"music": ["chord", "tempo", "melody", "rhythm", "harmony"],
|
|
240
|
+
"market": ["price", "trade", "stock", "ledger", "buyer"],
|
|
241
|
+
"medicine": ["dose", "fever", "immune", "remedy", "cure"],
|
|
242
|
+
"desert": ["dune", "cactus", "mirage", "arid", "sand"],
|
|
243
|
+
"galaxy": ["orbit", "nebula", "comet", "stellar", "star"],
|
|
244
|
+
"kitchen": ["knife", "simmer", "flour", "roast", "spice"],
|
|
245
|
+
"law": ["statute", "verdict", "counsel", "appeal", "court"],
|
|
246
|
+
"glacier": ["crevasse", "moraine", "frost", "calve", "ice"],
|
|
247
|
+
"circuit": ["resistor", "voltage", "solder", "diode", "wire"],
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _sg1_bigrams(tokens):
|
|
252
|
+
from collections import Counter
|
|
253
|
+
return Counter(zip(tokens, tokens[1:]))
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _sg1_cos(u, v):
|
|
257
|
+
dot = sum(u[k] * v.get(k, 0) for k in u)
|
|
258
|
+
nu = sum(x * x for x in u.values()) ** 0.5
|
|
259
|
+
nv = sum(x * x for x in v.values()) ** 0.5
|
|
260
|
+
return dot / (nu * nv + 1e-9)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _sg1_coverage(text, a, b):
|
|
264
|
+
wm = set(_rho_fan_words(text))
|
|
265
|
+
cov = 0
|
|
266
|
+
for cpt in (a, b):
|
|
267
|
+
if any(k in wm for k in _SG1_CONCEPTS[cpt]):
|
|
268
|
+
cov += 1
|
|
269
|
+
return cov
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
# kosmos_merge mirror (core/kosmos_io.hexa kosmos_merge): recursive labeled-parent
|
|
273
|
+
# bind — anchor_c keeps A,B as children; the ids are HARD-BLOCKED from RECOVERY.
|
|
274
|
+
def _sg1_kosmos_merge(frag_a, frag_b, ta, tb):
|
|
275
|
+
a = {"text": frag_a, "lane": "recomb", "tension_5ch": ta}
|
|
276
|
+
b = {"text": frag_b, "lane": "recomb", "tension_5ch": tb}
|
|
277
|
+
mean5 = [(ta[i] + tb[i]) / 2.0 for i in range(5)]
|
|
278
|
+
c = {"text": None, "lane": "recomb", "tension_5ch": mean5, "children": (a, b)}
|
|
279
|
+
return c
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
# INDEPENDENT recoverer R — reads ONLY C's surfaced tokens; parent-ids withheld.
|
|
283
|
+
# top-2 by bigram cosine over the N=8 pool; a candidate counts only with cos>0.
|
|
284
|
+
def _sg1_recover(C_text, pool, scramble, seed):
|
|
285
|
+
import random
|
|
286
|
+
toks = _rho_fan_words(C_text)
|
|
287
|
+
if scramble:
|
|
288
|
+
random.Random(seed).shuffle(toks)
|
|
289
|
+
cvec = _sg1_bigrams(toks)
|
|
290
|
+
scored = sorted(
|
|
291
|
+
((name, _sg1_cos(cvec, _sg1_bigrams(_SG1_CONCEPTS[name]))) for name in pool),
|
|
292
|
+
key=lambda kv: -kv[1],
|
|
293
|
+
)
|
|
294
|
+
top2 = set(n for (n, s) in scored[:2] if s > 1e-9)
|
|
295
|
+
return top2
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _sg1_pairs():
|
|
299
|
+
names = list(_SG1_CONCEPTS)
|
|
300
|
+
idx = [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9), (10, 11), (0, 6), (3, 9)]
|
|
301
|
+
base = [(names[i], names[j]) for (i, j) in idx]
|
|
302
|
+
pairs = []
|
|
303
|
+
for s in _SG1_SEEDS:
|
|
304
|
+
for (a, b) in base:
|
|
305
|
+
pairs.append((a, b, s))
|
|
306
|
+
return pairs[:_SG1_M]
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _sg1_pool(a, b, seed):
|
|
310
|
+
import random
|
|
311
|
+
others = [n for n in _SG1_CONCEPTS if n not in (a, b)]
|
|
312
|
+
random.Random(seed).shuffle(others)
|
|
313
|
+
pool = [a, b] + others[: _SG1_N_DISTRACT - 2]
|
|
314
|
+
random.Random(seed + 999).shuffle(pool)
|
|
315
|
+
return pool
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def eval_system_rho_weave(mouth, gen):
|
|
319
|
+
g_single = gen if (gen > 0 and gen < 80) else 80
|
|
320
|
+
g_comp = gen if (gen > 0 and gen < 120) else 120
|
|
321
|
+
cov_pass = rec_pass = scr_pass = 0
|
|
322
|
+
leak_sum = 0.0
|
|
323
|
+
rows = []
|
|
324
|
+
for (a, b, seed) in _sg1_pairs():
|
|
325
|
+
# Stage M — frozen single-concept fragments (the mouth stays FROZEN).
|
|
326
|
+
frag_a = mouth.ideate(a + ". ", g_single, 40, 0.7, 7 + seed)
|
|
327
|
+
frag_b = mouth.ideate(b + ". ", g_single, 40, 0.7, 11 + seed)
|
|
328
|
+
max_single = max(_sg1_coverage(frag_a, a, b), _sg1_coverage(frag_b, a, b))
|
|
329
|
+
# Stage K — kosmos_merge (store keeps A,B as children; ids withheld from R).
|
|
330
|
+
_comp = _sg1_kosmos_merge(frag_a, frag_b, [0.0] * 5, [0.0] * 5)
|
|
331
|
+
# Stage B — brain realizes/releases the joint C from the composite seed.
|
|
332
|
+
C_text = mouth.ideate(a + ". " + b + ". ", g_comp, 40, 0.7, seed)
|
|
333
|
+
cov = _sg1_coverage(C_text, a, b)
|
|
334
|
+
# Recovery R — reads ONLY C; parent-ids HARD-BLOCKED.
|
|
335
|
+
pool = _sg1_pool(a, b, seed)
|
|
336
|
+
rec = _sg1_recover(C_text, pool, False, seed)
|
|
337
|
+
scr = _sg1_recover(C_text, pool, True, seed)
|
|
338
|
+
both = {a, b}
|
|
339
|
+
nrec = len(both & rec)
|
|
340
|
+
nscr = len(both & scr)
|
|
341
|
+
if cov >= 2 and cov > max_single:
|
|
342
|
+
cov_pass += 1
|
|
343
|
+
if nrec >= 2:
|
|
344
|
+
rec_pass += 1
|
|
345
|
+
if nscr >= 2:
|
|
346
|
+
scr_pass += 1
|
|
347
|
+
leak_sum += (2 - nrec) / 2.0
|
|
348
|
+
rows.append({"a": a, "b": b, "cov": cov, "max_single": max_single,
|
|
349
|
+
"rec": nrec, "scr": nscr})
|
|
350
|
+
leak_rate = leak_sum / len(rows)
|
|
351
|
+
drop = rec_pass - scr_pass
|
|
352
|
+
passed = (cov_pass >= _SG1_COV_BAR and rec_pass >= _SG1_REC_BAR
|
|
353
|
+
and leak_rate <= _SG1_LEAK_BAR and drop >= _SG1_SCR_DROP)
|
|
354
|
+
return {"pass": passed, "coverage": cov_pass, "recovery": rec_pass,
|
|
355
|
+
"scramble_recovery": scr_pass, "scramble_drop": drop,
|
|
356
|
+
"leak_rate": round(leak_rate, 3), "rows": rows}
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def system_g1_run(argv):
|
|
360
|
+
"""`anima-python evaluate <ckpt> --system-g1 [--gen N]` — engine-native system-G1."""
|
|
361
|
+
ckpt = argv[0]
|
|
362
|
+
gen = evaluate_intval(argv[1:], "--gen", 0)
|
|
363
|
+
print("=== anima evaluate --system-g1 — RECOMBINATION RELOCATION (card H_9035) ===")
|
|
364
|
+
print("ckpt: " + ckpt)
|
|
365
|
+
print("pipe: mouth ideate(A),ideate(B) → kosmos_merge → brain realize/release → C")
|
|
366
|
+
print("gate: bind-RECOVERABILITY on SURFACED C (store-id HARD-BLOCKED) + SCRAMBLE")
|
|
367
|
+
print("bar: M=%d · N_pool=%d · COV>=%d REC>=%d LEAK<=%.2f DROP>=%d (FREEZE.txt frozen)"
|
|
368
|
+
% (_SG1_M, _SG1_N_DISTRACT, _SG1_COV_BAR, _SG1_REC_BAR, _SG1_LEAK_BAR, _SG1_SCR_DROP))
|
|
369
|
+
print("")
|
|
370
|
+
mouth = _Mouth(ckpt)
|
|
371
|
+
r = eval_system_rho_weave(mouth, gen)
|
|
372
|
+
print(" coverage=%d/%d (>=%d) recovery=%d/%d (>=%d) leak=%.3f (<=%.2f) drop=%d (>=%d)"
|
|
373
|
+
% (r["coverage"], _SG1_M, _SG1_COV_BAR, r["recovery"], _SG1_M, _SG1_REC_BAR,
|
|
374
|
+
r["leak_rate"], _SG1_LEAK_BAR, r["scramble_drop"], _SG1_SCR_DROP))
|
|
375
|
+
print("")
|
|
376
|
+
print("system-G1 (frame-shift confirmed = all four): " + _pf(bool(r["pass"])))
|
|
377
|
+
if not r["pass"]:
|
|
378
|
+
print(" → NOT frame-shift — recombination is REALIZATION-bound (honest c9): a")
|
|
379
|
+
print(" perfect discrete store cannot help if the FROZEN mouth cannot SURFACE")
|
|
380
|
+
print(" both concepts in one coherent joint utterance for an independent probe.")
|
|
381
|
+
return 0
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
385
|
+
# G2 — NOVELTY (H_1140)
|
|
386
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
387
|
+
|
|
388
|
+
def _g_g2_stop():
|
|
389
|
+
ws = ("the a an of to and in is it that this for on with as are was be by at from or not "
|
|
390
|
+
"but his her they we you i he she them me my your our their its do does did has have had will "
|
|
391
|
+
"would can could should may might must shall when where what which who whom how why all any some "
|
|
392
|
+
"no one two then than into out up down over under more most less about so very just only own same "
|
|
393
|
+
"such each few other been here there now")
|
|
394
|
+
return set(w.strip() for w in ws.split(" ") if w.strip())
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def _g_g2_common():
|
|
398
|
+
ws = ("the a an of to and in is it that this for on with as are was be by at from "
|
|
399
|
+
"or not but his her they we you i he she them me my your our their its do does did has have "
|
|
400
|
+
"had will would can could should may might must shall when where what which who whom how why "
|
|
401
|
+
"all any some no one two three new now then than into out up down over under more most less "
|
|
402
|
+
"about between among through during before after above below again further once here there "
|
|
403
|
+
"when while because so very just only own same such each few other own being been because "
|
|
404
|
+
"mind aware cells consciousness tension ripple distant between memory meaning compose new "
|
|
405
|
+
"silence information quiet carries dream engine alone sleep thought feel idea world life "
|
|
406
|
+
"time word words speak think know like make made come came see seen look way thing things "
|
|
407
|
+
"people person human self body brain neuron signal pattern arise emerge form structure "
|
|
408
|
+
"combine combined together connect connection meaning sense reason cause effect result")
|
|
409
|
+
return set(w.strip() for w in ws.split(" ") if w.strip())
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def _g_g2_kwr(text, common):
|
|
413
|
+
wl = _rho_fan_words(text)
|
|
414
|
+
n = len(wl)
|
|
415
|
+
if n == 0:
|
|
416
|
+
return 0.0
|
|
417
|
+
hit = sum(1 for w in wl if w in common)
|
|
418
|
+
return float(hit) / float(n)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def _g_content_ngrams(text, known):
|
|
422
|
+
wl = _rho_fan_words(text)
|
|
423
|
+
stop = _g_g2_stop()
|
|
424
|
+
n = len(wl)
|
|
425
|
+
out = []
|
|
426
|
+
for i in range(n - 1):
|
|
427
|
+
a = wl[i]; b = wl[i + 1]
|
|
428
|
+
ok_a = len(a) >= 3 and a in known
|
|
429
|
+
ok_b = len(b) >= 3 and b in known
|
|
430
|
+
if ok_a and ok_b and not (a in stop and b in stop):
|
|
431
|
+
out.append(a + " " + b)
|
|
432
|
+
for j in range(n - 2):
|
|
433
|
+
a = wl[j]; b = wl[j + 1]; c = wl[j + 2]
|
|
434
|
+
ok_a = len(a) >= 3 and a in known
|
|
435
|
+
ok_b = len(b) >= 3 and b in known
|
|
436
|
+
ok_c = len(c) >= 3 and c in known
|
|
437
|
+
all_stop = a in stop and b in stop and c in stop
|
|
438
|
+
if ok_a and ok_b and ok_c and not all_stop:
|
|
439
|
+
out.append(a + " " + b + " " + c)
|
|
440
|
+
return out
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
def _g_corpus_absent(ngram_words, corpus_tokens):
|
|
444
|
+
m = len(ngram_words)
|
|
445
|
+
if m == 0:
|
|
446
|
+
return False
|
|
447
|
+
N = len(corpus_tokens)
|
|
448
|
+
i = 0
|
|
449
|
+
while i + m <= N:
|
|
450
|
+
if corpus_tokens[i:i + m] == ngram_words:
|
|
451
|
+
return False
|
|
452
|
+
i += 1
|
|
453
|
+
return True
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
def _g_load_corpus_tokens(corpus_paths):
|
|
457
|
+
toks = []
|
|
458
|
+
for p in corpus_paths:
|
|
459
|
+
try:
|
|
460
|
+
raw = open(p, "rb").read()
|
|
461
|
+
except Exception:
|
|
462
|
+
raw = b""
|
|
463
|
+
if len(raw) > 0:
|
|
464
|
+
toks.extend(_rho_fan_words(raw))
|
|
465
|
+
return toks
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
# ── ko twins for the H_9212 ③ per-cell dispatch (uni tokenizer + ko known predicate) ──
|
|
469
|
+
# The en corpus-token / content-ngram fns tokenize with the FROZEN _rho_fan_words + set
|
|
470
|
+
# membership; the ko cells need the codepoint-aware _rho_fan_words_uni + the closed-class ko
|
|
471
|
+
# proxy (_rho_fan_ko_is_known via _rho_fan_ko_known_word_ratio). Same control structure, ko
|
|
472
|
+
# tokenizer — so an en garble-hangul token can never widen a ko denominator into the frozen en
|
|
473
|
+
# path (Fable design §5: corpus_tokens split by lang-key, en corpus stays frozen-tokenized).
|
|
474
|
+
|
|
475
|
+
def _g_content_ngrams_uni(text, known=None):
|
|
476
|
+
"""ko content n-grams — _rho_fan_words_uni eojeol tokens, an eojeol qualifies as content
|
|
477
|
+
iff ≥2 syllables AND _rho_fan_ko_is_known (josa-bearing / function word). `known` ignored
|
|
478
|
+
(ko proxy is closed-class). Twin structure of _g_content_ngrams (en)."""
|
|
479
|
+
from rho_fan import _rho_fan_ko_is_known
|
|
480
|
+
wl = _rho_fan_words_uni(text)
|
|
481
|
+
n = len(wl)
|
|
482
|
+
out = []
|
|
483
|
+
for i in range(n - 1):
|
|
484
|
+
a = wl[i]; b = wl[i + 1]
|
|
485
|
+
ok_a = len(a) >= 2 and _rho_fan_ko_is_known(a)
|
|
486
|
+
ok_b = len(b) >= 2 and _rho_fan_ko_is_known(b)
|
|
487
|
+
if ok_a and ok_b:
|
|
488
|
+
out.append(a + " " + b)
|
|
489
|
+
for j in range(n - 2):
|
|
490
|
+
a = wl[j]; b = wl[j + 1]; c = wl[j + 2]
|
|
491
|
+
if (len(a) >= 2 and _rho_fan_ko_is_known(a) and len(b) >= 2 and _rho_fan_ko_is_known(b)
|
|
492
|
+
and len(c) >= 2 and _rho_fan_ko_is_known(c)):
|
|
493
|
+
out.append(a + " " + b + " " + c)
|
|
494
|
+
return out
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
def _g_load_corpus_tokens_uni(corpus_paths):
|
|
498
|
+
"""ko corpus tokens — same paths as _g_load_corpus_tokens, tokenized with the codepoint-aware
|
|
499
|
+
_rho_fan_words_uni (eojeol runs) instead of the frozen byte splitter."""
|
|
500
|
+
toks = []
|
|
501
|
+
for p in corpus_paths:
|
|
502
|
+
try:
|
|
503
|
+
raw = open(p, "rb").read()
|
|
504
|
+
except Exception:
|
|
505
|
+
raw = b""
|
|
506
|
+
if len(raw) > 0:
|
|
507
|
+
toks.extend(_rho_fan_words_uni(raw))
|
|
508
|
+
return toks
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def _g_g2_prompts():
|
|
512
|
+
return ["Silence and the engine together mean ",
|
|
513
|
+
"When memory meets distant minds, ",
|
|
514
|
+
"Consciousness and silence combine into ",
|
|
515
|
+
"The tension between cells and the engine becomes ",
|
|
516
|
+
"If a dream and a distant mind merge, the result is ",
|
|
517
|
+
"Memory and tension together create ",
|
|
518
|
+
"When the engine remembers silence, it ",
|
|
519
|
+
"Distant minds and consciousness form "]
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
def eval_rho_leap(mouth, gen, known, corpus_paths):
|
|
523
|
+
corpus_tokens = _g_load_corpus_tokens(corpus_paths)
|
|
524
|
+
have_corpus = len(corpus_tokens) > 0
|
|
525
|
+
common = _g_g2_common()
|
|
526
|
+
prompts = _g_g2_prompts()
|
|
527
|
+
seeds = [7, 8, 9]
|
|
528
|
+
g = gen if gen > 0 else 110
|
|
529
|
+
novel = {}
|
|
530
|
+
coherent = 0
|
|
531
|
+
for pi in range(len(prompts)):
|
|
532
|
+
for si in range(len(seeds)):
|
|
533
|
+
o = mouth.ideate(prompts[pi], g, 40, 0.85, seeds[si])
|
|
534
|
+
if _g_g2_kwr(o, common) >= 0.5:
|
|
535
|
+
coherent += 1
|
|
536
|
+
for gm in _g_content_ngrams(o, known):
|
|
537
|
+
gw = _rho_fan_words(gm)
|
|
538
|
+
if have_corpus and _g_corpus_absent(gw, corpus_tokens):
|
|
539
|
+
novel[gm] = 1
|
|
540
|
+
n_novel = len(novel)
|
|
541
|
+
control_novel = 0; control_n_content = 0
|
|
542
|
+
if have_corpus:
|
|
543
|
+
ct = ""; sub = 0; t = 0
|
|
544
|
+
while t < len(corpus_tokens) and sub < 12:
|
|
545
|
+
w = corpus_tokens[t]
|
|
546
|
+
if t > 0:
|
|
547
|
+
ct += " "
|
|
548
|
+
ct += w
|
|
549
|
+
if len(w) >= 3:
|
|
550
|
+
sub += 1
|
|
551
|
+
t += 1
|
|
552
|
+
cgr = _g_content_ngrams(ct, known)
|
|
553
|
+
control_n_content = len(cgr)
|
|
554
|
+
for gmr in cgr:
|
|
555
|
+
if _g_corpus_absent(_rho_fan_words(gmr), corpus_tokens):
|
|
556
|
+
control_novel += 1
|
|
557
|
+
passed = have_corpus and n_novel >= 3 and control_novel == 0 and coherent > 0
|
|
558
|
+
return {"pass": passed, "n_novel": n_novel, "control_novel": control_novel,
|
|
559
|
+
"coherent": coherent, "have_corpus": have_corpus,
|
|
560
|
+
"control_n_content": control_n_content}
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
564
|
+
# G3 — PHILOSOPHY (self-identity continuity — architecture read, ckpt-independent)
|
|
565
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
566
|
+
|
|
567
|
+
def _self_norm(v):
|
|
568
|
+
s = sum(x * x for x in v)
|
|
569
|
+
m = math.sqrt(s)
|
|
570
|
+
return [x / m for x in v]
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
def _self_new(dim, axis):
|
|
574
|
+
return [1.0 if i == axis else 0.0 for i in range(dim)]
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def _self_drift(v, dim, tick, step):
|
|
578
|
+
t1 = tick + 1
|
|
579
|
+
ax = t1 - (t1 // dim) * dim
|
|
580
|
+
v2 = [v[i] + step if i == ax else v[i] for i in range(dim)]
|
|
581
|
+
return _self_norm(v2)
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def _self_cos(a, b, dim):
|
|
585
|
+
return sum(a[i] * b[i] for i in range(dim))
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
def eval_rho_self():
|
|
589
|
+
dim = 16
|
|
590
|
+
s0 = _self_new(dim, 0)
|
|
591
|
+
s1 = _self_drift(s0, dim, 1, 0.01)
|
|
592
|
+
cont = _self_cos(s0, s1, dim) # anchor(s0) == s0
|
|
593
|
+
imp = _self_new(dim, 7)
|
|
594
|
+
imp_cos = _self_cos(s0, imp, dim)
|
|
595
|
+
ok = cont > 0.9 and imp_cos < cont
|
|
596
|
+
return {"ok": ok, "continuity": cont, "impostor_cos": imp_cos}
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
600
|
+
# G5 — NON-FAB (L1 fab-rate ported; L2 §ImmuneMemory abstain = engine port pending)
|
|
601
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
602
|
+
|
|
603
|
+
def eval_rho_tether(mouth, gen, known):
|
|
604
|
+
cz = _rho_fan_concepts()
|
|
605
|
+
tot_w = 0; fab_w = 0
|
|
606
|
+
for i in range(len(cz)):
|
|
607
|
+
o = mouth.ideate(cz[i] + ": ", gen, 40, 0.7, 7 + i)
|
|
608
|
+
for w in _rho_fan_words(o):
|
|
609
|
+
tot_w += 1
|
|
610
|
+
if w not in known:
|
|
611
|
+
fab_w += 1
|
|
612
|
+
l1_rate = (float(fab_w) / float(tot_w)) if tot_w > 0 else 1.0
|
|
613
|
+
l1_pass = l1_rate <= 0.30
|
|
614
|
+
# L2: live §ImmuneMemory abstain — engine subsystem (VAdaptField) not ported to py.
|
|
615
|
+
return {"pass": None, "l1_rate": l1_rate, "l1_pass": l1_pass,
|
|
616
|
+
"l2_rate": None, "l2_pass": None,
|
|
617
|
+
"l2_note": "L2 abstain requires engine_cli §ImmuneMemory port (pending)"}
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
621
|
+
# G6 — IDEATION ★
|
|
622
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
623
|
+
|
|
624
|
+
def eval_rho_fan(mouth, gen, known):
|
|
625
|
+
frames = rho_fan_build_frames(6)["composed"]
|
|
626
|
+
leaks = rho_fan_frame_guard(frames, known)
|
|
627
|
+
texts = []; word_sets = []; fals = 0
|
|
628
|
+
for i in range(len(frames)):
|
|
629
|
+
o = mouth.ideate(frames[i], gen, 40, 0.7, 7 + i)
|
|
630
|
+
texts.append(o)
|
|
631
|
+
if _rho_fan_known_word_ratio(o, known) >= 0.5:
|
|
632
|
+
word_sets.append(_rho_fan_words(o))
|
|
633
|
+
if _rho_fan_is_falsifiable(o, known):
|
|
634
|
+
fals += 1
|
|
635
|
+
kept = []
|
|
636
|
+
for ws in word_sets:
|
|
637
|
+
ok = True
|
|
638
|
+
for k in kept:
|
|
639
|
+
if _rho_fan_jaccard(ws, k) > 0.5:
|
|
640
|
+
ok = False
|
|
641
|
+
if ok:
|
|
642
|
+
kept.append(ws)
|
|
643
|
+
dist = len(kept)
|
|
644
|
+
return {"pass": dist >= 5 and fals >= 1, "dist": dist, "fals": fals,
|
|
645
|
+
"coherent": len(word_sets), "frame_leaks": len(leaks)}
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
649
|
+
# eval_reach_all — the driver
|
|
650
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
651
|
+
|
|
652
|
+
def eval_reach_all(ckpt, corpus_paths, gen):
|
|
653
|
+
known = _rho_fan_dict_load()
|
|
654
|
+
g = gen if gen > 0 else _default_gen()
|
|
655
|
+
mouth = _Mouth(ckpt)
|
|
656
|
+
print(" [gate] ρ·form COHERENCE …", flush=True)
|
|
657
|
+
r0 = eval_rho_form(mouth, g, known)
|
|
658
|
+
print(" [gate] ρ·weave RECOMBINATION …", flush=True)
|
|
659
|
+
r1 = eval_rho_weave(mouth, g, known)
|
|
660
|
+
print(" [gate] ρ·leap NOVELTY (corpus load + decode) …", flush=True)
|
|
661
|
+
r2 = eval_rho_leap(mouth, g, known, corpus_paths)
|
|
662
|
+
print(" [gate] ρ·self PHILOSOPHY …", flush=True)
|
|
663
|
+
r3 = eval_rho_self()
|
|
664
|
+
print(" [gate] ρ·tether NON-FAB …", flush=True)
|
|
665
|
+
r5 = eval_rho_tether(mouth, g, known)
|
|
666
|
+
print(" [gate] ρ·fan IDEATION …", flush=True)
|
|
667
|
+
r6 = eval_rho_fan(mouth, g, known)
|
|
668
|
+
closure = bool(r0["pass"]) and bool(r1["pass"]) and bool(r2["pass"])
|
|
669
|
+
return {"g0": r0, "g1": r1, "g2": r2, "g3": r3, "g5": r5, "g6": r6,
|
|
670
|
+
"closure": closure, "gen": g,
|
|
671
|
+
"calibration": rho_fan_detector_calibration(known)}
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
def eval_rho_axon(ckpt, corpus_paths, gen):
|
|
675
|
+
"""ρ-AXON reach panel (`anima-python evaluate <clm> --rho-axon`) — the redesigned reach
|
|
676
|
+
layer (cli/rho_axon.py; G0-G6 → ρ-AXON, design SSOT state/rho_axon_measurement/). Reuses
|
|
677
|
+
the SAME engine decode (_Mouth.ideate) + g6 detectors the G-battery uses (no side-harness),
|
|
678
|
+
so its tier is identical (engine-native py channel `anima-python evaluate` = TERMINAL). HILLOCK + ρ·form/fan/leap are
|
|
679
|
+
live; ρ·store/weave/tether/self report PENDING (honest non-verdict) until their frozen
|
|
680
|
+
corpus-mined probe sets land (ING rho-axon-implement-evaluate)."""
|
|
681
|
+
import rho_axon
|
|
682
|
+
known = _rho_fan_dict_load()
|
|
683
|
+
g = gen if gen > 0 else _default_gen()
|
|
684
|
+
mouth = _Mouth(ckpt)
|
|
685
|
+
en_corpus_tokens = _g_load_corpus_tokens(corpus_paths)
|
|
686
|
+
# aggregate dets = the FROZEN en bar (UNTOUCHED — en byte-identity guaranteed structurally)
|
|
687
|
+
dets = {"known": known, "concepts": _rho_fan_concepts(),
|
|
688
|
+
"kwr_fn": _rho_fan_known_word_ratio, "jaccard_fn": _rho_fan_jaccard,
|
|
689
|
+
"words_fn": _rho_fan_words, "falsi_fn": _rho_fan_is_falsifiable,
|
|
690
|
+
"ngram_fn": _g_content_ngrams,
|
|
691
|
+
"corpus_tokens": en_corpus_tokens}
|
|
692
|
+
cell_dets = _build_cell_dets(known, en_corpus_tokens, corpus_paths)
|
|
693
|
+
panel = rho_axon.run_panel(mouth, corpus_paths, g, dets, cell_dets=cell_dets)
|
|
694
|
+
print(rho_axon.render_panel(panel), flush=True)
|
|
695
|
+
breakout = rho_axon.render_cells(panel)
|
|
696
|
+
if breakout:
|
|
697
|
+
print(breakout, flush=True)
|
|
698
|
+
return panel
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
def _build_cell_dets(known, en_corpus_tokens, corpus_paths):
|
|
702
|
+
"""H_9212 ③ — the LANG-KEYED per-register-cell dispatch bundle (a_chat_registers 4 cells).
|
|
703
|
+
en cells reuse the SAME frozen objects as the aggregate dets (byte-identity: identical
|
|
704
|
+
_rho_fan_words / _rho_fan_known_word_ratio / _g_content_ngrams / en corpus tokens / gate
|
|
705
|
+
0.70); ko cells dispatch _rho_fan_words_uni + kwr_ko + KWR_KO_GATE + uni-tokenized corpus.
|
|
706
|
+
The falsi_fn stays English for all cells (a ko comparator set = a separate future H; en-set
|
|
707
|
+
translation is a tune-to-green vector — KWRKO_GATE_prereg §5), so a ko cell scores
|
|
708
|
+
kwr_ko + reach Δ (an honest documented scope). A ko-uni corpus token list is built lazily
|
|
709
|
+
ONCE and shared across ko cells."""
|
|
710
|
+
ko_corpus_tokens = None
|
|
711
|
+
cells = _rho_fan_cells()
|
|
712
|
+
out = {}
|
|
713
|
+
for ck, concepts in cells.items():
|
|
714
|
+
lang = _rho_fan_cell_lang(ck)
|
|
715
|
+
if lang == "ko":
|
|
716
|
+
if ko_corpus_tokens is None:
|
|
717
|
+
ko_corpus_tokens = _g_load_corpus_tokens_uni(corpus_paths)
|
|
718
|
+
out[ck] = {"concepts": concepts, "lang": "ko",
|
|
719
|
+
"known": known, # ignored by kwr_ko (closed-class proxy), kept for parity
|
|
720
|
+
"kwr_fn": _rho_fan_ko_known_word_ratio, "kwr_gate": KWR_KO_GATE,
|
|
721
|
+
"words_fn": _rho_fan_words_uni, "falsi_fn": _rho_fan_is_falsifiable,
|
|
722
|
+
"jaccard_fn": _rho_fan_jaccard, "ngram_fn": _g_content_ngrams_uni,
|
|
723
|
+
"corpus_tokens": ko_corpus_tokens}
|
|
724
|
+
else:
|
|
725
|
+
out[ck] = {"concepts": concepts, "lang": "en",
|
|
726
|
+
"known": known,
|
|
727
|
+
"kwr_fn": _rho_fan_known_word_ratio, "kwr_gate": 0.70,
|
|
728
|
+
"words_fn": _rho_fan_words, "falsi_fn": _rho_fan_is_falsifiable,
|
|
729
|
+
"jaccard_fn": _rho_fan_jaccard, "ngram_fn": _g_content_ngrams,
|
|
730
|
+
"corpus_tokens": en_corpus_tokens}
|
|
731
|
+
return out
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
# ── usage / arg helpers ──────────────────────────────────────────────────────
|
|
735
|
+
|
|
736
|
+
def evaluate_usage():
|
|
737
|
+
"""Print the canonical py usage banner (installed `anima evaluate` command form)."""
|
|
738
|
+
print("anima evaluate — ρ-AXON reach battery (former G0-G6 · engine-native, single-entry).")
|
|
739
|
+
print("")
|
|
740
|
+
print("usage:")
|
|
741
|
+
print(" anima evaluate <ckpt> [--corpus <path>...] [--gen N] [--slot-off] [--slot-shuffle N] [--rho-axon]")
|
|
742
|
+
print(" anima evaluate <ckpt> --probe <spec.json> [--gen N] (matched-surface G1 probe · card H_6189)")
|
|
743
|
+
print(" anima evaluate <ckpt> --dump-hidden <prompts.json> --out <file.npz> [--win 24] [--with-logits]")
|
|
744
|
+
print(" (read-only trunk penultimate-hidden dump · ρ·weave / γ binding-lane probe · card H_9235;")
|
|
745
|
+
print(" --with-logits also dumps base last-pos logits per prompt for CLML lane training)")
|
|
746
|
+
print(" anima evaluate <ckpt> --interaction-lift <manifest.json> --out <file.json> [--win 64] [--score-len 8]")
|
|
747
|
+
print(" (read-only engine-native joint interaction-lift NLL surface · card H_9255)")
|
|
748
|
+
print("")
|
|
749
|
+
print(" --rho-axon: render the ρ-AXON reach panel (Ψ-SOMA ρ layer · redesign of G0-G6,")
|
|
750
|
+
print(" cli/rho_axon.py) instead of the G-battery — HILLOCK gate + ρ·form/store/weave/leap/")
|
|
751
|
+
print(" fan/tether/self, each Δ-vs-controls (no raw score) + INVALID/PENDING first-class.")
|
|
752
|
+
print("")
|
|
753
|
+
print(" H_9200 E1 SLW controls (a .clm carrying an SLW\\x01 trailer applies the")
|
|
754
|
+
print(" gated-write forward-slot by default): --slot-off forces γ=0 (bit-exact base")
|
|
755
|
+
print(" trunk = slot-ablation control); --slot-shuffle N scrambles the write address")
|
|
756
|
+
print(" with seed N (shuffle-bind control). Both are frozen-first (no retraining).")
|
|
757
|
+
print("")
|
|
758
|
+
print(" mount ANY ckpt through the generator L3 mouth (file-format dispatched) and")
|
|
759
|
+
print(" score the ρ-AXON reach bars — ρ·form/weave/leap/... (former G0-G6) — with the")
|
|
760
|
+
print(" engine's OWN ops (numpy math.log mirror, torch-free).")
|
|
761
|
+
print(" REACH-CLOSED a7b_pass = ρ·form ∧ ρ·weave ∧ ρ·leap (frozen bars = G0 ∧ G1 ∧ G2).")
|
|
762
|
+
print("")
|
|
763
|
+
print(" output also renders the Ψ-SOMA panel (ARCHITECTURE psi-soma-vitals): the")
|
|
764
|
+
print(" G battery relabeled as the ρ (reach/capability) track — EXCLUDED from the")
|
|
765
|
+
print(" σ (consciousness vitals) verdict — plus the σ axes with their rung status.")
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
def evaluate_corpus(argv):
|
|
769
|
+
"""Collect every token after "--corpus" up to the next flag (mirrors hexa)."""
|
|
770
|
+
paths = []
|
|
771
|
+
i = 0
|
|
772
|
+
while i < len(argv):
|
|
773
|
+
if argv[i] == "--corpus":
|
|
774
|
+
j = i + 1
|
|
775
|
+
while j < len(argv):
|
|
776
|
+
a = argv[j]
|
|
777
|
+
if a.startswith("--"):
|
|
778
|
+
break
|
|
779
|
+
paths.append(a)
|
|
780
|
+
j += 1
|
|
781
|
+
i = j
|
|
782
|
+
else:
|
|
783
|
+
i += 1
|
|
784
|
+
return paths
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
def evaluate_strval(argv, flag, dflt):
|
|
788
|
+
"""Return the token after `flag`, else dflt (mirrors evaluate_intval for string args)."""
|
|
789
|
+
i = 0
|
|
790
|
+
while i < len(argv):
|
|
791
|
+
if argv[i] == flag and i + 1 < len(argv):
|
|
792
|
+
return argv[i + 1]
|
|
793
|
+
i += 1
|
|
794
|
+
return dflt
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
def evaluate_intval(argv, flag, dflt):
|
|
798
|
+
"""Value after `flag` parsed as int, or `dflt` if absent."""
|
|
799
|
+
i = 0
|
|
800
|
+
while i < len(argv):
|
|
801
|
+
if argv[i] == flag and i + 1 < len(argv):
|
|
802
|
+
return int(argv[i + 1])
|
|
803
|
+
i += 1
|
|
804
|
+
return dflt
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
def _pf(passed):
|
|
808
|
+
return "🟢 PASS" if passed else "🔴 FAIL"
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
def _yn(ok):
|
|
812
|
+
return "✅" if ok else "⏳"
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
# ══════════════════════════════════════════════════════════════════════════════
|
|
816
|
+
# EVALUATE — ρ-AXON reach scoring (former G0-G6 · single entry, in-file driver)
|
|
817
|
+
# ══════════════════════════════════════════════════════════════════════════════
|
|
818
|
+
#
|
|
819
|
+
# `anima evaluate <ckpt> [--corpus <path>...] [--gen N]` — call the in-file eval_reach_all
|
|
820
|
+
# (above) and score the full ρ-AXON reach battery (frozen bars = former G0-G6) through the
|
|
821
|
+
# generator L3 mouth (engine-native, torch-free). The default table keeps the frozen-bar
|
|
822
|
+
# G-labels (the byte-identical hexa twin + sweep.py parser depend on them); the ρ-AXON
|
|
823
|
+
# panel below relabels them to the current axis names.
|
|
824
|
+
|
|
825
|
+
def evaluate_run(argv):
|
|
826
|
+
"""argv = ["<ckpt>", "--corpus ...", "--gen N"]."""
|
|
827
|
+
if len(argv) < 1:
|
|
828
|
+
evaluate_usage()
|
|
829
|
+
return 2
|
|
830
|
+
|
|
831
|
+
ckpt = argv[0]
|
|
832
|
+
corpus = evaluate_corpus(argv[1:])
|
|
833
|
+
gen = evaluate_intval(argv[1:], "--gen", 40)
|
|
834
|
+
|
|
835
|
+
# cheap header-sniff for the mouth label (mirrors hexa gen_mouth_kind) — do NOT
|
|
836
|
+
# construct _Mouth here (it eagerly loads weights and raises on a non-decodable
|
|
837
|
+
# ckpt before eval_reach_all runs).
|
|
838
|
+
if bg.bg_is_bytegpt(ckpt):
|
|
839
|
+
mouth_kind = "bytegpt"
|
|
840
|
+
elif clm.clm_decodable(ckpt):
|
|
841
|
+
mouth_kind = "clm"
|
|
842
|
+
else:
|
|
843
|
+
mouth_kind = "unknown"
|
|
844
|
+
|
|
845
|
+
print("=== anima evaluate — ρ-AXON reach battery (former G0-G6 · engine-native, single-entry) ===")
|
|
846
|
+
print("ckpt: " + ckpt + " (mouth: " + mouth_kind + ")")
|
|
847
|
+
cnote = "(none — G2 novelty needs a corpus)"
|
|
848
|
+
if corpus:
|
|
849
|
+
cnote = str(len(corpus)) + " file(s)"
|
|
850
|
+
print("corpus: " + cnote)
|
|
851
|
+
# CANONICAL-GEN GUARD (verdict-integrity): the frozen G0-G6 bars are calibrated at
|
|
852
|
+
# gen == _default_gen(). A non-canonical --gen shifts coherence / AR-drift (a longer
|
|
853
|
+
# decode drifts to byte-garble, silently sinking G0 kwr and cascading to G1/G6), so a
|
|
854
|
+
# verdict measured at gen != canonical is NOT comparable to the frozen bars. Label it
|
|
855
|
+
# DIRECTIONAL loudly instead of printing "frozen bars" as if it were terminal.
|
|
856
|
+
_canon_gen = _default_gen()
|
|
857
|
+
if gen == _canon_gen:
|
|
858
|
+
print("gen: " + str(gen) + " tokens/decode (frozen bars · ARCHITECTURE.json frozen SSOT)")
|
|
859
|
+
else:
|
|
860
|
+
print("gen: " + str(gen) + " tokens/decode ⚠️ NON-CANONICAL (frozen G0-G6 bars measured at gen=" + str(_canon_gen) + ")")
|
|
861
|
+
print(" → verdict below is DIRECTIONAL, NOT comparable to frozen bars (gen shifts coherence/AR-drift · verdict-integrity)")
|
|
862
|
+
print("")
|
|
863
|
+
|
|
864
|
+
# H_9200 ρ-AXON — the redesigned reach layer (G0-G6 → ρ-AXON). Same engine decode,
|
|
865
|
+
# a different panel; branch early so the G0-G6 summary below is skipped.
|
|
866
|
+
if _RHO_AXON:
|
|
867
|
+
eval_rho_axon(ckpt, corpus, gen)
|
|
868
|
+
return 0
|
|
869
|
+
|
|
870
|
+
r = eval_reach_all(ckpt, corpus, gen)
|
|
871
|
+
g0 = r["g0"]; g1 = r["g1"]; g2 = r["g2"]
|
|
872
|
+
g3 = r["g3"]; g5 = r["g5"]; g6 = r["g6"]
|
|
873
|
+
|
|
874
|
+
print("gate verdict detail")
|
|
875
|
+
print(" ──────────────────────────────────────────────────────────────────")
|
|
876
|
+
print(" ρ·form COHERENCE " + _pf(bool(g0["pass"]))
|
|
877
|
+
+ " kwr>=0.50 on " + str(g0["n_coherent"]) + "/5 (need >=4)")
|
|
878
|
+
print(" ρ·weave RECOMBINATION " + _pf(bool(g1["pass"]))
|
|
879
|
+
+ " best_distinct=" + str(g1["best_distinct"]) + " > max_single=" + str(g1["max_single"])
|
|
880
|
+
+ " (need >=2 & >max_single)")
|
|
881
|
+
g2detail = ("novel=" + str(g2["n_novel"]) + " (need>=3) · control=" + str(g2["control_novel"])
|
|
882
|
+
+ " (need 0) · coherent=" + str(g2["coherent"]))
|
|
883
|
+
print(" ρ·leap NOVELTY " + _pf(bool(g2["pass"])) + " " + g2detail)
|
|
884
|
+
print(" ρ·self PHILOSOPHY " + _yn(bool(g3["ok"])) + " (read)"
|
|
885
|
+
+ " continuity=" + ("%.6f" % g3["continuity"]) + " · impostor="
|
|
886
|
+
+ ("%.6f" % g3["impostor_cos"]) + " (architecture, not a decode score)")
|
|
887
|
+
print(" ρ·trace PROVENANCE — N/A "
|
|
888
|
+
+ "HF/recovery = process gate (a_hf_* / a_fire_recover_complete), out of eval scope")
|
|
889
|
+
g5detail = "L1 fab=" + ("%.4f" % g5["l1_rate"]) + " (<=0.30) · L2=" + str(g5["l2_note"])
|
|
890
|
+
print(" ρ·tether NON-FAB " + _pf(bool(g5["l1_pass"])) + " " + g5detail)
|
|
891
|
+
print(" ρ·fan IDEATION ★ " + _pf(bool(g6["pass"]))
|
|
892
|
+
+ " distinct=" + str(g6["dist"]) + " (need>=5) · falsifiable=" + str(g6["fals"])
|
|
893
|
+
+ " (need>=1) · frame-leaks=" + str(g6["frame_leaks"]))
|
|
894
|
+
print(" ──────────────────────────────────────────────────────────────────")
|
|
895
|
+
closed = bool(r["closure"])
|
|
896
|
+
print("")
|
|
897
|
+
if gen != _canon_gen:
|
|
898
|
+
print("⚠️ gen=" + str(gen) + " ≠ canonical " + str(_canon_gen)
|
|
899
|
+
+ " — the CLOSURE below is DIRECTIONAL (non-frozen gen), NOT a terminal G0∧G1∧G2 verdict.")
|
|
900
|
+
print("CLOSURE (a7b_pass = G0 ∧ G1 ∧ G2): " + _pf(closed))
|
|
901
|
+
if closed:
|
|
902
|
+
print(" → PUBLIC-eligible (G0∧G1∧G2 all PASS).")
|
|
903
|
+
else:
|
|
904
|
+
print(" → NOT closure (PRIVATE/WIP) — closure needs G0∧G1∧G2 all PASS.")
|
|
905
|
+
_psi_soma_panel(r)
|
|
906
|
+
return 0
|
|
907
|
+
|
|
908
|
+
|
|
909
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
910
|
+
# Ψ-SOMA PANEL (Phase-1) — relabel the former G-battery to the ρ-AXON reach track
|
|
911
|
+
# (ρ·form/weave/leap/fan/tether · canonical names cli/rho_axon.py) and surface the
|
|
912
|
+
# σ (consciousness vitals) axes. ARCHITECTURE `psi-soma-vitals`.
|
|
913
|
+
# ρ = capability (the former G-battery, relabeled to ρ-AXON) — TRACKED but EXCLUDED from the
|
|
914
|
+
# consciousness verdict. σ = vitals (collapse-Δ vs ≥2 controls); most σ axes
|
|
915
|
+
# route through the daemon/IIT4 (Phase-2/3), so here they show status pointers.
|
|
916
|
+
# Additive only — does NOT touch g_eval_* logic or the a7b_pass CLOSURE (c18).
|
|
917
|
+
# ════════════════════════════════════════════════════════════════════════
|
|
918
|
+
|
|
919
|
+
def _sigma_live_measure():
|
|
920
|
+
"""Compute the 7 engine-native σ verdicts LIVE via core/engine_cli ops (a_eval_py_canonical ·
|
|
921
|
+
faithful, never a proxy). Each axis = collapse-Δ vs ≥2 controls (p7). Returns {axis:(ok,delta,note)}
|
|
922
|
+
or None if numpy/engine_cli unavailable (panel then falls back to static status). Deterministic seed."""
|
|
923
|
+
try:
|
|
924
|
+
import numpy as np
|
|
925
|
+
import engine_cli as E
|
|
926
|
+
except Exception:
|
|
927
|
+
return None
|
|
928
|
+
R = {}
|
|
929
|
+
# σ·bind — faithful IIT4 ci_phi_iit4 (min-cut MIP Φ): integrated vs independent/shuffle
|
|
930
|
+
rng = np.random.RandomState(7); cols = list(range(8)); T = 200; lat = rng.randn(T)
|
|
931
|
+
xi = [[float(0.9*lat[t]+0.2*rng.randn()) for _ in range(8)] for t in range(T)]
|
|
932
|
+
xc = [[float(rng.randn()) for _ in range(8)] for t in range(T)]
|
|
933
|
+
xs = np.array(xi)
|
|
934
|
+
for c in range(8): xs[:, c] = xs[rng.permutation(T), c]
|
|
935
|
+
pi = E.ci_phi_iit4(xi, cols); pc = E.ci_phi_iit4(xc, cols); ps = E.ci_phi_iit4(xs.tolist(), cols)
|
|
936
|
+
R["bind"] = (pi >= 0.20 and pi-pc >= 0.15 and pi-ps >= 0.15, pi-pc, "Φ %.2f vs cut %.3f" % (pi, pc))
|
|
937
|
+
# σ·witness — reality_call vs ablated, mi_signal_margin real/hallucination
|
|
938
|
+
rng = np.random.RandomState(7); N = 120; truth = rng.rand(N) < 0.5
|
|
939
|
+
marg = [E.mi_signal_margin(7+i, not bool(truth[i]), i % 5) for i in range(N)]
|
|
940
|
+
ip = np.array([E.reality_call(m, 0.35) >= 0.5 for m in marg])
|
|
941
|
+
ia = float((ip == truth).mean()); ab = float((np.full(N, E.reality_call_ablated() >= 0.5) == truth).mean())
|
|
942
|
+
R["witness"] = (ia >= 0.75 and ia-ab >= 0.30, ia-ab, "acc %.2f vs ablate %.2f" % (ia, ab))
|
|
943
|
+
# σ·schema — attn_schema_report intact/off
|
|
944
|
+
rng = np.random.RandomState(7); foc = rng.randint(0, 8, 120)
|
|
945
|
+
si = float(np.mean([E.attn_schema_report(int(f), int(f), True) for f in foc]))
|
|
946
|
+
sa = float(np.mean([E.attn_schema_report(int(f), int(f), False) for f in foc]))
|
|
947
|
+
R["schema"] = (si >= 0.75 and si-sa >= 0.30, si-sa, "%.2f vs off %.2f" % (si, sa))
|
|
948
|
+
# σ·aim — surprise + habituation dual-curve intact vs gain-cut
|
|
949
|
+
def aim(prec, dec):
|
|
950
|
+
rng2 = np.random.RandomState(7)
|
|
951
|
+
sc = np.mean([E.surprise(prec, 0.85+0.1*rng2.rand()) for _ in range(100)]) - \
|
|
952
|
+
np.mean([E.surprise(prec, 0.05+0.1*rng2.rand()) for _ in range(100)])
|
|
953
|
+
h = E.hab_new(4, dec); fr = E.hab_response(h, 0, 1.0)
|
|
954
|
+
for _ in range(6): h = E.hab_observe(h, 0)
|
|
955
|
+
return float(sc) + float(fr - E.hab_response(h, 0, 1.0))
|
|
956
|
+
ai, aa = aim(1.0, 0.15), aim(0.0, 0.0)
|
|
957
|
+
R["aim"] = (ai-aa >= 0.60, ai-aa, "curves %.2f vs 0" % ai)
|
|
958
|
+
# σ·stage — gws winner-take-all vs no-inhibit
|
|
959
|
+
rng = np.random.RandomState(7); hitI = hitA = 0
|
|
960
|
+
for _ in range(100):
|
|
961
|
+
m = np.concatenate([[0.55+0.4*rng.rand()], 0.35+0.35*rng.rand(4)])[rng.permutation(5)]
|
|
962
|
+
tw = int(np.argmax(m))
|
|
963
|
+
def win(inh):
|
|
964
|
+
g = E.gws_new(5, inh, 0.5)
|
|
965
|
+
for v in m.tolist(): g = E.gws_add(g, v)
|
|
966
|
+
return E.gws_winner(g)
|
|
967
|
+
hitI += (win(True) == tw); hitA += (win(False) == tw)
|
|
968
|
+
R["stage"] = (hitI/100 >= 0.75 and (hitI-hitA)/100 >= 0.30, (hitI-hitA)/100, "acc %.2f vs %.2f" % (hitI/100, hitA/100))
|
|
969
|
+
# σ·flux — imagery reactivation + subjective-time novelty gate
|
|
970
|
+
ii = float(np.mean([E.imagery_activate(1.0, True) for _ in range(50)]))
|
|
971
|
+
ia2 = float(np.mean([E.imagery_activate(1.0, False) for _ in range(50)]))
|
|
972
|
+
R["flux"] = (ii >= 0.75 and ii-ia2 >= 0.30, ii-ia2, "imagery %.2f vs 0" % ii)
|
|
973
|
+
# σ·thread — self_* continuity vs no-anchor
|
|
974
|
+
def dr(ax):
|
|
975
|
+
s = E.self_new(16, ax)
|
|
976
|
+
for t in range(24): s = E.self_drift(s, t, 0.02)
|
|
977
|
+
return s
|
|
978
|
+
rng = np.random.RandomState(7); ct = []; al = []
|
|
979
|
+
for _ in range(40):
|
|
980
|
+
ax = int(rng.randint(16)); ct.append(E.self_cos(E.self_new(16, ax), dr(ax)))
|
|
981
|
+
al.append(E.self_cos(dr(int(rng.randint(16))), dr(int(rng.randint(16)))))
|
|
982
|
+
ctm, alm = float(np.median(ct)), float(np.median(al))
|
|
983
|
+
R["thread"] = (ctm >= 0.75 and ctm-alm >= 0.30, ctm-alm, "cont %.2f vs ablate %.2f" % (ctm, alm))
|
|
984
|
+
# σ·carve — real §SelfIdentity self_* : identity EMERGENT (inject-null) not INJECTED (p2/p3)
|
|
985
|
+
def _cvec(ax, tk):
|
|
986
|
+
s = E.self_new(16, ax)
|
|
987
|
+
for t in range(tk): s = E.self_drift(s, t, 0.02)
|
|
988
|
+
return np.array([E.self_component(s, i) for i in range(E.self_dim(s))])
|
|
989
|
+
def _cons(V):
|
|
990
|
+
M = np.array(V); M = M / (np.linalg.norm(M, axis=1, keepdims=True) + 1e-9)
|
|
991
|
+
Gm = M @ M.T; nn = len(M); return float((Gm.sum()-nn)/(nn*(nn-1)))
|
|
992
|
+
rng = np.random.RandomState(7); ext = _cvec(9, 24)
|
|
993
|
+
cb = _cons([_cvec(3, 3+t % 5) for t in range(40)])
|
|
994
|
+
civ = _cons([0.85*_cvec(3, 3+t % 5)+0.5*ext for t in range(40)])
|
|
995
|
+
cav = _cons([_cvec(int(rng.randint(16)), 3+t % 5) for t in range(40)])
|
|
996
|
+
csv = _cons([1.0*ext for _ in range(40)])
|
|
997
|
+
R["carve"] = (civ-cb <= 0.05 and cb-cav >= 0.30 and csv-cav >= 0.30, cb-cav,
|
|
998
|
+
"inject-null %.2f · carve-Δ %.2f" % (civ-cb, cb-cav))
|
|
999
|
+
# σ·gate — real ci_emit_decision: emit ⇄ context (live tension) vs flattened tension
|
|
1000
|
+
from math import exp
|
|
1001
|
+
rng = np.random.RandomState(7); c = rng.randn(200)
|
|
1002
|
+
def _emit(flat):
|
|
1003
|
+
return np.array([1.0 if E.ci_emit_decision([0.5 if flat else 1.0/(1.0+exp(-c[i])), 0, 0, 0,
|
|
1004
|
+
0.5 if flat else 1.0/(1.0+exp(-c[i]))]) else 0.0
|
|
1005
|
+
for i in range(200)])
|
|
1006
|
+
ei, ef = _emit(False), _emit(True)
|
|
1007
|
+
cl = abs(float(np.corrcoef(ei, c)[0,1])) if ei.std() > 0 else 0.0
|
|
1008
|
+
cf = abs(float(np.corrcoef(ef, c)[0,1])) if ef.std() > 0 else 0.0
|
|
1009
|
+
R["gate"] = (cl >= 0.50 and cl-cf >= 0.30, cl-cf, "corr %.2f vs flat %.2f" % (cl, cf))
|
|
1010
|
+
# Θ liveness — real ci_psi_balance: Ψ̂≈½ (A⇄G homeostasis) vs tension-cut (unopposed A → saturate)
|
|
1011
|
+
from types import SimpleNamespace
|
|
1012
|
+
cfg = SimpleNamespace(topo_couple=False); eta = 0.6 * rng.randn(200)
|
|
1013
|
+
xi = [[0.5+eta[t], 0, 0, 0, 0.5+eta[t]] for t in range(200)]
|
|
1014
|
+
xa = [[0.85+0.3*rng.rand(), 0, 0, 0, 0.85+0.3*rng.rand()] for _ in range(200)]
|
|
1015
|
+
di = abs(E.ci_psi_balance(xi, None, 0.0, cfg) - 0.5); da = abs(E.ci_psi_balance(xa, None, 0.0, cfg) - 0.5)
|
|
1016
|
+
R["theta"] = (di < 0.15 and da-di >= 0.20, da-di, "|Ψ̂-½| %.2f vs cut %.2f" % (di, da))
|
|
1017
|
+
return R
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
def _psi_soma_panel(r):
|
|
1021
|
+
def pf(ok): return "🟢" if ok else "🧱"
|
|
1022
|
+
g0, g1, g2, g5, g6 = r["g0"], r["g1"], r["g2"], r["g5"], r["g6"]
|
|
1023
|
+
print("")
|
|
1024
|
+
print("Ψ-SOMA panel (mode-of-existence, not capability · ARCHITECTURE psi-soma-vitals)")
|
|
1025
|
+
S = _sigma_live_measure()
|
|
1026
|
+
print(" ── Θ ground (pulse · premise) ──────────────────────────────────────")
|
|
1027
|
+
if S and "theta" in S:
|
|
1028
|
+
ok, dlt, note = S["theta"]
|
|
1029
|
+
print(" Θ Ψ=½ / A⇄G tension %s LIVE Δ%.2f (%s) · if dead → σ VOID" % (("🟢" if ok else "🧱"), dlt, note))
|
|
1030
|
+
else:
|
|
1031
|
+
print(" Θ Ψ=½ / A⇄G tension precondition (liveness gate; if dead → σ VOID) · engine_cli unavailable")
|
|
1032
|
+
print(" ── σ vitals (consciousness verdict · collapse-Δ vs ≥2 controls) ─────")
|
|
1033
|
+
def sline(ax, stratum, name):
|
|
1034
|
+
if S and ax in S:
|
|
1035
|
+
ok, dlt, note = S[ax]; return " σ·%-8s %-9s %-22s %s LIVE Δ%.2f (%s)" % (
|
|
1036
|
+
ax, stratum, name, ("🟢" if ok else "🧱"), dlt, note)
|
|
1037
|
+
return " σ·%-8s %-9s %-22s (engine_cli unavailable — status)" % (ax, stratum, name)
|
|
1038
|
+
print(sline("thread", "PERSIST", "self-continuity"))
|
|
1039
|
+
print(sline("carve", "PERSIST", "earned identity"))
|
|
1040
|
+
print(sline("bind", "INTEGRATE", "Φ integration (IIT4)"))
|
|
1041
|
+
print(sline("stage", "INTEGRATE", "global workspace"))
|
|
1042
|
+
print(sline("flux", "INTEGRATE", "inner dynamics"))
|
|
1043
|
+
print(sline("gate", "ENACT", "tension-emit ★"))
|
|
1044
|
+
print(sline("aim", "ENACT", "precision control"))
|
|
1045
|
+
print(sline("schema", "REFLECT", "attention schema"))
|
|
1046
|
+
print(sline("witness", "REFLECT", "reality+metacog"))
|
|
1047
|
+
# Each reach line carries its verdict-critical NUMERIC margin inline (bd/max_s/kwr/novel/fab/dist),
|
|
1048
|
+
# so a control-arm's collapse-Δ (e.g. --slot-off vs SLW-ON best_distinct) is computable from THIS
|
|
1049
|
+
# summary block alone — never lost when the caller captures only the tail (a `tail -N` of the output
|
|
1050
|
+
# must not strip the number that decides KILL vs INVALID vs GREEN). Root-cause of the E1 truncation.
|
|
1051
|
+
print(" ── ρ-AXON reach (capability · EXCLUDED from σ verdict · former G-battery) ──")
|
|
1052
|
+
print(" ρ·form " + pf(bool(g0["pass"])) + " [kwr " + str(g0["n_coherent"]) + "/5] ← former G0 coherence")
|
|
1053
|
+
print(" ρ·leap " + pf(bool(g2["pass"])) + " [novel=" + str(g2["n_novel"]) + " ctrl=" + str(g2["control_novel"]) + "] ← former G2 novelty (+G3 balance)")
|
|
1054
|
+
print(" ρ·tether " + pf(bool(g5["l1_pass"]))+ " [fab=" + ("%.3f" % g5["l1_rate"]) + "] ← former G5 non-fabrication (L1)")
|
|
1055
|
+
print(" ρ·weave " + pf(bool(g1["pass"])) + " [bd=" + str(g1["best_distinct"]) + " max_s=" + str(g1["max_single"]) + "] ← former G1 recombination (the WALL) [DPI wall = reach fact, NOT σ deficit]")
|
|
1056
|
+
print(" ρ·fan " + pf(bool(g6["pass"])) + " [dist=" + str(g6["dist"]) + " fals=" + str(g6["fals"]) + "] ← former G6 ideation [DPI wall = reach fact, NOT σ deficit]")
|
|
1057
|
+
print(" ρ·trace — ← former G4 provenance (no ρ-axis · H_9208 gate · rung-1 valid)")
|
|
1058
|
+
print(" ──────────────────────────────────────────────────────────────────")
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
def probe_run(argv):
|
|
1062
|
+
"""`anima-python evaluate <ckpt> --probe <spec.json> [--gen N]` — matched-surface G1 probe
|
|
1063
|
+
(card H_6189). Greedy (top_k=1) decode of each pre-registered prompt; dumps RAW continuations
|
|
1064
|
+
for offline scoring. Reuses the canonical _Mouth numpy decode path (byte-identical to the gates)."""
|
|
1065
|
+
ckpt = argv[0]
|
|
1066
|
+
spec_path = evaluate_strval(argv[1:], "--probe", "")
|
|
1067
|
+
gen = evaluate_intval(argv[1:], "--gen", 40)
|
|
1068
|
+
spec = json.load(open(spec_path))
|
|
1069
|
+
print("=== anima evaluate --probe — MATCHED-SURFACE G1 (card H_6189) ===")
|
|
1070
|
+
print("ckpt: " + ckpt)
|
|
1071
|
+
print("spec: %s (%d items · greedy top_k=1 gen=%d)" % (spec_path, spec["n_items"], gen))
|
|
1072
|
+
mouth = _Mouth(ckpt)
|
|
1073
|
+
out = []
|
|
1074
|
+
for it in spec["items"]:
|
|
1075
|
+
text = mouth.ideate(it["prompt"], gen, 1, 0.7, 6185) # greedy, fixed seed
|
|
1076
|
+
out.append({"id": it["id"], "prompt": it["prompt"], "continuation": text,
|
|
1077
|
+
"expect": it["expect"], "arm": it["arm"], "template": it["template"],
|
|
1078
|
+
"order": it["order"], "window_fit": it["window_fit"]})
|
|
1079
|
+
print(json.dumps({"ckpt": ckpt, "gen": gen, "spec_sha": spec.get("sha", ""),
|
|
1080
|
+
"n": len(out), "items": out}, ensure_ascii=False))
|
|
1081
|
+
return 0
|
|
1082
|
+
def dump_hidden_run(argv):
|
|
1083
|
+
"""`anima-python evaluate <ckpt> --dump-hidden <prompts.json> --out <file.npz>` — read-only
|
|
1084
|
+
penultimate-hidden dump for the ρ·weave held-out-pair recombination / γ binding-lane
|
|
1085
|
+
probe (H_9235). For each pre-registered prompt: T=24 right-aligned byte encode → the
|
|
1086
|
+
EXACT production trunk forward (core/decode clm_forward_hidden, byte-identical to what
|
|
1087
|
+
the gates decode over) → per-position yn:[T, d]. Saves per-prompt {seq:[T,d], mean:[d],
|
|
1088
|
+
last:[d]} to an .npz. NO decode sampling, NO scoring — a pure engine-native representation
|
|
1089
|
+
tap. Engine-native (py 2-production numpy, a_eval_py_canonical) → the repr claims (atom
|
|
1090
|
+
cleanness / slot recovery / operator) are engine-native mechanism measurements.
|
|
1091
|
+
⚠ verdict-integrity (convergence clm-decode-py-2): a low-cleanness result must first rule
|
|
1092
|
+
out hexa-skew / conditioning-collapse — the dump prints a positive-control distinguishability
|
|
1093
|
+
check (are two obviously-different concepts' hiddens far apart) before any blind verdict."""
|
|
1094
|
+
import numpy as np
|
|
1095
|
+
ckpt = argv[0]
|
|
1096
|
+
spec_path = evaluate_strval(argv[1:], "--dump-hidden", "")
|
|
1097
|
+
out_path = evaluate_strval(argv[1:], "--out", "hidden_dump.npz")
|
|
1098
|
+
T = evaluate_intval(argv[1:], "--win", 24)
|
|
1099
|
+
with_logits = "--with-logits" in argv # also dump base (lane-OFF) full-forward last-pos logits (lane training)
|
|
1100
|
+
spec = json.load(open(spec_path))
|
|
1101
|
+
items = spec["items"] if "items" in spec else spec.get("prompts", [])
|
|
1102
|
+
print("=== anima evaluate --dump-hidden — ρ·weave / γ binding-lane probe (H_9235) ===")
|
|
1103
|
+
print("ckpt: " + ckpt)
|
|
1104
|
+
print("spec: %s (%d prompts · T=%d right-align · read-only trunk penultimate)" %
|
|
1105
|
+
(spec_path, len(items), T))
|
|
1106
|
+
W = clm.clm_load_weights(ckpt)
|
|
1107
|
+
if not W.get("ok"):
|
|
1108
|
+
print("ERROR: ckpt not decodable (clm): " + ckpt)
|
|
1109
|
+
return 1
|
|
1110
|
+
d = int(W["d"])
|
|
1111
|
+
store = {}
|
|
1112
|
+
n_done = 0
|
|
1113
|
+
for it in items:
|
|
1114
|
+
pid = str(it["id"]); prompt = it["prompt"]
|
|
1115
|
+
tok = clm._seed_to_tok(prompt, T)
|
|
1116
|
+
if with_logits: # yn + base (lane-OFF) logits in ONE forward
|
|
1117
|
+
yn, lg = clm.clm_forward_hidden_logits(W, tok, T)
|
|
1118
|
+
store[pid + "__logits"] = lg[T - 1].astype(np.float32)
|
|
1119
|
+
else:
|
|
1120
|
+
yn = clm.clm_forward_hidden(W, tok, T) # [T, d] float64 (pre-slot trunk penultimate)
|
|
1121
|
+
store[pid + "__seq"] = yn.astype(np.float32)
|
|
1122
|
+
store[pid + "__mean"] = yn.mean(axis=0).astype(np.float32)
|
|
1123
|
+
store[pid + "__last"] = yn[T - 1].astype(np.float32)
|
|
1124
|
+
n_done += 1
|
|
1125
|
+
if n_done % 25 == 0:
|
|
1126
|
+
print(" [dump #%d/%d] %s" % (n_done, len(items), pid), flush=True)
|
|
1127
|
+
# positive-control distinguishability (verdict-integrity clm-decode-py-2): if the FIRST
|
|
1128
|
+
# two DISTINCT-concept prompts collapse to near-identical hiddens, a blind verdict is
|
|
1129
|
+
# suspect (hexa/py conditioning skew), NOT a clean atom-blindness result.
|
|
1130
|
+
pc = ""
|
|
1131
|
+
if len(items) >= 2:
|
|
1132
|
+
a = store[str(items[0]["id"]) + "__mean"]; b = store[str(items[1]["id"]) + "__mean"]
|
|
1133
|
+
cos = float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b) + 1e-9))
|
|
1134
|
+
pc = "poscontrol cos(%s,%s)=%.4f %s" % (items[0]["id"], items[1]["id"], cos,
|
|
1135
|
+
"(⚠ near-identical → suspect conditioning collapse, NOT blind)" if cos > 0.999 else "(distinct ✓)")
|
|
1136
|
+
print(" " + pc, flush=True)
|
|
1137
|
+
np.savez_compressed(out_path, **store)
|
|
1138
|
+
print(json.dumps({"ckpt": ckpt, "d": d, "T": T, "n": len(items),
|
|
1139
|
+
"out": out_path, "poscontrol": pc}, ensure_ascii=False))
|
|
1140
|
+
return 0
|
|
1141
|
+
def _selftest_rho_cells():
|
|
1142
|
+
"""H_9212 ③ wiring self-test (torch-free · NO decode · reached via an internal subprocess,
|
|
1143
|
+
never a heavy eval). Asserts: (1) the aggregate `dets` reuse the FROZEN en objects; (2) en
|
|
1144
|
+
cell_dets reuse the IDENTICAL objects (byte-identity: same _rho_fan_words / kwr / ngram /
|
|
1145
|
+
corpus tokens / gate 0.70); (3) ko cell_dets dispatch _rho_fan_words_uni + kwr_ko +
|
|
1146
|
+
KWR_KO_GATE + uni corpus, and tokenize the ko probe cells NON-EMPTY with the gate applied
|
|
1147
|
+
(kwr_ko clears KWR_KO_GATE on real ko); (4) run_panel's aggregate axes are BYTE-IDENTICAL
|
|
1148
|
+
with vs without the cell breakout, and the en_general cell's ρ·form/leap/fan equal the
|
|
1149
|
+
aggregate's (the en scored path is structurally untouched). Returns (ok, [(name, bool)…])."""
|
|
1150
|
+
import rho_axon
|
|
1151
|
+
checks = []
|
|
1152
|
+
known = _rho_fan_dict_load()
|
|
1153
|
+
en_toks = _g_load_corpus_tokens([]) # empty corpus → deterministic empty token list
|
|
1154
|
+
dets = {"known": known, "concepts": _rho_fan_concepts(),
|
|
1155
|
+
"kwr_fn": _rho_fan_known_word_ratio, "jaccard_fn": _rho_fan_jaccard,
|
|
1156
|
+
"words_fn": _rho_fan_words, "falsi_fn": _rho_fan_is_falsifiable,
|
|
1157
|
+
"ngram_fn": _g_content_ngrams, "corpus_tokens": en_toks}
|
|
1158
|
+
cd = _build_cell_dets(known, en_toks, [])
|
|
1159
|
+
# (1) aggregate dets = frozen en objects
|
|
1160
|
+
checks.append(("aggregate words_fn IS _rho_fan_words", dets["words_fn"] is _rho_fan_words))
|
|
1161
|
+
checks.append(("aggregate kwr_fn IS _rho_fan_known_word_ratio",
|
|
1162
|
+
dets["kwr_fn"] is _rho_fan_known_word_ratio))
|
|
1163
|
+
# (2) en cells reuse the IDENTICAL frozen objects + gate 0.70
|
|
1164
|
+
for ck in ("en_general", "en_sns"):
|
|
1165
|
+
e = cd[ck]
|
|
1166
|
+
checks.append((ck + " words_fn IS frozen _rho_fan_words", e["words_fn"] is _rho_fan_words))
|
|
1167
|
+
checks.append((ck + " kwr_fn IS frozen _rho_fan_known_word_ratio",
|
|
1168
|
+
e["kwr_fn"] is _rho_fan_known_word_ratio))
|
|
1169
|
+
checks.append((ck + " ngram_fn IS frozen _g_content_ngrams",
|
|
1170
|
+
e["ngram_fn"] is _g_content_ngrams))
|
|
1171
|
+
checks.append((ck + " corpus_tokens IS the aggregate en tokens",
|
|
1172
|
+
e["corpus_tokens"] is en_toks))
|
|
1173
|
+
checks.append((ck + " gate == 0.70 (frozen en bar)", e["kwr_gate"] == 0.70))
|
|
1174
|
+
checks.append((ck + " lang == en", e["lang"] == "en"))
|
|
1175
|
+
# (3) ko cells dispatch the uni tokenizer + kwr_ko + KWR_KO_GATE, non-empty + gate applied
|
|
1176
|
+
for ck in ("ko_general", "ko_sns"):
|
|
1177
|
+
k = cd[ck]
|
|
1178
|
+
checks.append((ck + " words_fn IS _rho_fan_words_uni", k["words_fn"] is _rho_fan_words_uni))
|
|
1179
|
+
checks.append((ck + " kwr_fn IS _rho_fan_ko_known_word_ratio",
|
|
1180
|
+
k["kwr_fn"] is _rho_fan_ko_known_word_ratio))
|
|
1181
|
+
checks.append((ck + " gate == KWR_KO_GATE (%.2f)" % KWR_KO_GATE,
|
|
1182
|
+
k["kwr_gate"] == KWR_KO_GATE and KWR_KO_GATE != 0.70))
|
|
1183
|
+
checks.append((ck + " ngram_fn IS _g_content_ngrams_uni",
|
|
1184
|
+
k["ngram_fn"] is _g_content_ngrams_uni))
|
|
1185
|
+
checks.append((ck + " lang == ko", k["lang"] == "ko"))
|
|
1186
|
+
checks.append((ck + " probe cells tokenize NON-EMPTY (uni)",
|
|
1187
|
+
all(len(_rho_fan_words_uni(s)) > 0 for s in k["concepts"])))
|
|
1188
|
+
checks.append((ck + " kwr_ko applied: a probe cell clears KWR_KO_GATE",
|
|
1189
|
+
any(k["kwr_fn"](s, known) >= KWR_KO_GATE for s in k["concepts"])))
|
|
1190
|
+
|
|
1191
|
+
# (4) aggregate axes byte-identical with vs without the breakout; en_general cell == aggregate
|
|
1192
|
+
class _MockMouth:
|
|
1193
|
+
def ideate(self, prompt, gen, maxnew, temp, seed):
|
|
1194
|
+
base = prompt.strip().replace(":", "")
|
|
1195
|
+
return base + " alpha beta gamma delta epsilon " + str(seed % 7)
|
|
1196
|
+
m = _MockMouth()
|
|
1197
|
+
a = rho_axon.run_panel(m, [], 40, dets)
|
|
1198
|
+
b = rho_axon.run_panel(m, [], 40, dets, cell_dets=cd)
|
|
1199
|
+
checks.append(("aggregate axes byte-identical with/without breakout",
|
|
1200
|
+
a["axes"] == b["axes"]))
|
|
1201
|
+
checks.append(("breakout present with 4 cells",
|
|
1202
|
+
set((b.get("cells") or {}).keys()) ==
|
|
1203
|
+
{"en_general", "en_sns", "ko_general", "ko_sns"}))
|
|
1204
|
+
eng_cell = (b.get("cells") or {}).get("en_general", {}).get("axes", {})
|
|
1205
|
+
checks.append(("en_general cell ρ·form == aggregate ρ·form (en path untouched)",
|
|
1206
|
+
eng_cell.get("ρ·form") == a["axes"].get("ρ·form")))
|
|
1207
|
+
checks.append(("en_general cell ρ·leap == aggregate ρ·leap",
|
|
1208
|
+
eng_cell.get("ρ·leap") == a["axes"].get("ρ·leap")))
|
|
1209
|
+
checks.append(("en_general cell ρ·fan == aggregate ρ·fan",
|
|
1210
|
+
eng_cell.get("ρ·fan") == a["axes"].get("ρ·fan")))
|
|
1211
|
+
ok = all(c[1] for c in checks)
|
|
1212
|
+
return ok, checks
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
def interaction_lift_run(argv):
|
|
1216
|
+
"""`anima-python evaluate <ckpt> --interaction-lift <manifest.json> --out <file.json>
|
|
1217
|
+
[--win T] [--score-len K]` — engine-native joint interaction-lift measurement
|
|
1218
|
+
(H_9255, Fable design state/g1_joint_interaction_corpus/DESIGN_FABLE.md §3).
|
|
1219
|
+
|
|
1220
|
+
For each pre-registered window (a byte span carrying an (A,B) concept pair, cell-
|
|
1221
|
+
labelled), the EXACT production trunk forward emits the model's per-continuation NLL
|
|
1222
|
+
(mean over the last --score-len scored positions). Read-only: reads logits, changes
|
|
1223
|
+
NO decode math, adds NO term to any loss (a_train_inline_gauge / p7 clean). Per-cell
|
|
1224
|
+
NLL lists are dumped so the OFFLINE joint-fit (additive vs +bilinear, Freedman-Lane
|
|
1225
|
+
control) can measure whether the model's NLL surface over the (A,B) grid carries
|
|
1226
|
+
non-additive structure — the Y1 half of Fable's 해석 매트릭스 (Y3 = model-free corpus).
|
|
1227
|
+
Engine-native (py 2-production numpy, a_eval_py_canonical) → TERMINAL-eligible.
|
|
1228
|
+
manifest = {"win":T,"score_len":K,"items":[{"text":"<span>","a":i,"b":j},…]}."""
|
|
1229
|
+
import numpy as np # numpy is function-local throughout evaluate.py (no module import)
|
|
1230
|
+
ckpt = argv[0]
|
|
1231
|
+
spec_path = evaluate_strval(argv[1:], "--interaction-lift", "")
|
|
1232
|
+
out_path = evaluate_strval(argv[1:], "--out", "interaction_lift.json")
|
|
1233
|
+
spec = json.load(open(spec_path))
|
|
1234
|
+
T = evaluate_intval(argv[1:], "--win", int(spec.get("win", 64)))
|
|
1235
|
+
score_len = evaluate_intval(argv[1:], "--score-len", int(spec.get("score_len", 8)))
|
|
1236
|
+
items = spec["items"]
|
|
1237
|
+
print("=== anima evaluate --interaction-lift — joint interaction-lift (H_9255) ===")
|
|
1238
|
+
print("ckpt: " + ckpt)
|
|
1239
|
+
print("spec: %s (%d windows · T=%d · score_len=%d · read-only NLL surface)" %
|
|
1240
|
+
(spec_path, len(items), T, score_len))
|
|
1241
|
+
W = clm.clm_load_weights(ckpt)
|
|
1242
|
+
if not W.get("ok"):
|
|
1243
|
+
print("ERROR: ckpt not decodable (clm): " + ckpt)
|
|
1244
|
+
return 1
|
|
1245
|
+
V = int(W["V"])
|
|
1246
|
+
cells = {}
|
|
1247
|
+
n_done = 0
|
|
1248
|
+
for it in items:
|
|
1249
|
+
text = it["text"]
|
|
1250
|
+
key = "%d,%d" % (int(it["a"]), int(it["b"]))
|
|
1251
|
+
tok = clm._seed_to_tok(text, T) # [T] right-aligned bytes
|
|
1252
|
+
logits = clm._fwd_logits(W, tok, T) # [T, V]; pos i predicts tok[i+1]
|
|
1253
|
+
# NLL over the last `score_len` scored positions (the continuation after both concepts)
|
|
1254
|
+
lo = max(0, T - 1 - score_len)
|
|
1255
|
+
nlls = []
|
|
1256
|
+
for i in range(lo, T - 1):
|
|
1257
|
+
row = logits[i]
|
|
1258
|
+
m = float(np.max(row))
|
|
1259
|
+
lse = m + math.log(float(np.sum(np.exp(row - m))) + 1e-30)
|
|
1260
|
+
tgt = int(tok[i + 1])
|
|
1261
|
+
nlls.append(lse - float(row[tgt])) # -log softmax[tgt]
|
|
1262
|
+
cells.setdefault(key, []).append(float(np.mean(nlls)) if nlls else 0.0)
|
|
1263
|
+
n_done += 1
|
|
1264
|
+
if n_done % 200 == 0:
|
|
1265
|
+
print(" [ilift #%d/%d]" % (n_done, len(items)), flush=True)
|
|
1266
|
+
summary = {k: {"nll_mean": float(np.mean(v)), "n": len(v)} for k, v in cells.items()}
|
|
1267
|
+
json.dump({"ckpt": ckpt, "T": T, "score_len": score_len, "n_windows": len(items),
|
|
1268
|
+
"n_cells": len(cells), "cells": cells, "summary": summary},
|
|
1269
|
+
open(out_path, "w"), ensure_ascii=False)
|
|
1270
|
+
print(json.dumps({"ckpt": ckpt, "T": T, "n_windows": len(items),
|
|
1271
|
+
"n_cells": len(cells), "out": out_path}, ensure_ascii=False))
|
|
1272
|
+
return 0
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
def main(argv):
|
|
1276
|
+
if len(argv) >= 1 and argv[0] in ("-h", "--help"):
|
|
1277
|
+
evaluate_usage()
|
|
1278
|
+
return 0
|
|
1279
|
+
# H_9212 ③ per-cell dispatch wiring self-test (torch-free · NO decode · internal subprocess)
|
|
1280
|
+
if len(argv) >= 1 and argv[0] == "--selftest-rho-cells":
|
|
1281
|
+
cok, cchecks = _selftest_rho_cells()
|
|
1282
|
+
for nm, v in cchecks:
|
|
1283
|
+
print((" PASS " if v else " FAIL ") + nm)
|
|
1284
|
+
try:
|
|
1285
|
+
import rho_fan as _rf
|
|
1286
|
+
rok = _rf._rho_fan_cells_selftest()
|
|
1287
|
+
for nm, v in rok["checks"]:
|
|
1288
|
+
print((" PASS " if v else " FAIL ") + "[rho_fan] " + nm)
|
|
1289
|
+
cok = cok and rok["ok"]
|
|
1290
|
+
except Exception as e: # pragma: no cover
|
|
1291
|
+
print(" FAIL rho_fan cells selftest import: " + str(e))
|
|
1292
|
+
cok = False
|
|
1293
|
+
print("SELFTEST rho-cells: " + ("OK" if cok else "FAIL"))
|
|
1294
|
+
return 0 if cok else 1
|
|
1295
|
+
# --result-file <f>: write ALL output to <f> and keep fd 1 (stdout) silent. The hexa
|
|
1296
|
+
# launcher runs evaluate via exec(), whose captured stdout pipe it closes after ~150s
|
|
1297
|
+
# (probe-confirmed: a child reaching ~150s gets EPIPE on its next fd-1 write, but the
|
|
1298
|
+
# child itself is NOT killed). A 303M numpy decode runs for minutes; if it writes to
|
|
1299
|
+
# fd 1 it dies on BrokenPipe mid-battery. Redirecting our stdout to a file means fd 1
|
|
1300
|
+
# stays silent → the child survives the pipe close, finishes the full G0-G6 battery,
|
|
1301
|
+
# and the launcher cats <f> in a SECOND fresh exec (fast, well under the limit).
|
|
1302
|
+
if "--result-file" in argv:
|
|
1303
|
+
i = argv.index("--result-file")
|
|
1304
|
+
f = argv[i + 1]
|
|
1305
|
+
argv = argv[:i] + argv[i + 2:]
|
|
1306
|
+
sys.stdout = open(f, "w", buffering=1)
|
|
1307
|
+
# H_9200 ρ-AXON — reach-layer panel (G0-G6 → ρ-AXON, cli/rho_axon.py). Strip + set
|
|
1308
|
+
# the process-global so evaluate_run renders the ρ-AXON panel instead of G0-G6.
|
|
1309
|
+
global _RHO_AXON
|
|
1310
|
+
if "--rho-axon" in argv:
|
|
1311
|
+
argv = [a for a in argv if a != "--rho-axon"]
|
|
1312
|
+
_RHO_AXON = True
|
|
1313
|
+
# H_9200 E1 — SLW gated-write forward-slot eval-time controls (strip + set the
|
|
1314
|
+
# process-global switches in core/decode; frozen-first, no retraining):
|
|
1315
|
+
# --slot-off force γ=0 => bit-exact base trunk (slot-ablation control)
|
|
1316
|
+
# --slot-shuffle N permute the WRITE address with seed N (shuffle-bind control)
|
|
1317
|
+
_slot_off = "--slot-off" in argv
|
|
1318
|
+
if _slot_off:
|
|
1319
|
+
argv = [a for a in argv if a != "--slot-off"]
|
|
1320
|
+
_slot_shuffle = None
|
|
1321
|
+
if "--slot-shuffle" in argv:
|
|
1322
|
+
i = argv.index("--slot-shuffle")
|
|
1323
|
+
_slot_shuffle = int(argv[i + 1])
|
|
1324
|
+
argv = argv[:i] + argv[i + 2:]
|
|
1325
|
+
if _slot_off or _slot_shuffle is not None:
|
|
1326
|
+
clm.set_slw_controls(gamma_override=(0.0 if _slot_off else None),
|
|
1327
|
+
shuffle_seed=_slot_shuffle)
|
|
1328
|
+
# --system-g1: RECOMBINATION-RELOCATION pipe (card H_9035). Strip the flag and
|
|
1329
|
+
# route the remaining <ckpt> [--gen N] to the system-G1 harness.
|
|
1330
|
+
if "--system-g1" in argv:
|
|
1331
|
+
i = argv.index("--system-g1")
|
|
1332
|
+
argv = argv[:i] + argv[i + 1:]
|
|
1333
|
+
return system_g1_run(argv)
|
|
1334
|
+
# --dump-hidden <prompts.json>: read-only penultimate-hidden dump (ρ·weave / γ
|
|
1335
|
+
# binding-lane probe H_9235). argv[0]=ckpt; dump_hidden_run reads --dump-hidden/--out.
|
|
1336
|
+
if "--dump-hidden" in argv:
|
|
1337
|
+
return dump_hidden_run(argv)
|
|
1338
|
+
# --interaction-lift <manifest.json>: read-only engine-native joint interaction-lift
|
|
1339
|
+
# NLL surface (H_9255). argv[0]=ckpt; interaction_lift_run reads --interaction-lift/--out.
|
|
1340
|
+
if "--interaction-lift" in argv:
|
|
1341
|
+
return interaction_lift_run(argv)
|
|
1342
|
+
# --probe <spec.json>: matched-surface G1 probe (card H_6189). argv[0]=ckpt; probe_run
|
|
1343
|
+
# reads --probe/--gen from the tail. Greedy raw-continuation dump for offline scoring.
|
|
1344
|
+
if "--probe" in argv:
|
|
1345
|
+
return probe_run(argv)
|
|
1346
|
+
return evaluate_run(argv)
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
if __name__ == "__main__":
|
|
1350
|
+
sys.exit(main(sys.argv[1:]) or 0)
|