@hviana/sema 0.1.5 → 0.1.7
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.
- package/AGENTS.md +6 -5
- package/CITATION.cff +49 -0
- package/HOW_IT_WORKS.md +11 -12
- package/README.md +7 -5
- package/dist/example/demo.js +25 -25
- package/dist/example/train_base.d.ts +19 -21
- package/dist/example/train_base.js +1700 -1952
- package/dist/src/alphabet.d.ts +3 -3
- package/dist/src/alphabet.js +24 -27
- package/dist/src/alu/src/alu.d.ts +169 -194
- package/dist/src/alu/src/alu.js +374 -414
- package/dist/src/alu/src/expr.d.ts +36 -43
- package/dist/src/alu/src/expr.js +252 -278
- package/dist/src/alu/src/index.d.ts +9 -98
- package/dist/src/alu/src/index.js +10 -64
- package/dist/src/alu/src/kernel-arith.d.ts +1 -5
- package/dist/src/alu/src/kernel-arith.js +195 -285
- package/dist/src/alu/src/kernel-bits.d.ts +1 -5
- package/dist/src/alu/src/kernel-bits.js +81 -115
- package/dist/src/alu/src/kernel-logic.js +33 -63
- package/dist/src/alu/src/kernel-nd.js +155 -195
- package/dist/src/alu/src/kernel-numeric.d.ts +16 -80
- package/dist/src/alu/src/kernel-numeric.js +259 -331
- package/dist/src/alu/src/operation.d.ts +112 -132
- package/dist/src/alu/src/operation.js +149 -163
- package/dist/src/alu/src/parser.d.ts +168 -175
- package/dist/src/alu/src/parser.js +382 -421
- package/dist/src/alu/src/resonance.d.ts +16 -25
- package/dist/src/alu/src/resonance.js +49 -56
- package/dist/src/alu/src/text.d.ts +3 -7
- package/dist/src/alu/src/text.js +31 -37
- package/dist/src/alu/src/value.d.ts +14 -14
- package/dist/src/alu/src/value.js +150 -160
- package/dist/src/alu/test/alu.test.js +543 -656
- package/dist/src/bytes.d.ts +1 -5
- package/dist/src/bytes.js +33 -40
- package/dist/src/config.d.ts +99 -102
- package/dist/src/config.js +78 -83
- package/dist/src/derive/src/deduction.d.ts +60 -62
- package/dist/src/derive/src/deduction.js +103 -109
- package/dist/src/derive/src/index.d.ts +1 -7
- package/dist/src/derive/src/priority-queue.d.ts +8 -8
- package/dist/src/derive/src/priority-queue.js +57 -61
- package/dist/src/derive/src/rewrite.d.ts +15 -18
- package/dist/src/derive/src/rewrite.js +59 -67
- package/dist/src/derive/src/trie.d.ts +56 -56
- package/dist/src/derive/src/trie.js +175 -179
- package/dist/src/derive/test/derive.test.js +96 -100
- package/dist/src/extension.d.ts +13 -16
- package/dist/src/geometry.d.ts +29 -43
- package/dist/src/geometry.js +324 -268
- package/dist/src/index.d.ts +2 -17
- package/dist/src/index.js +2 -12
- package/dist/src/ingest-cache.d.ts +25 -30
- package/dist/src/ingest-cache.js +108 -127
- package/dist/src/mind/articulation.d.ts +1 -5
- package/dist/src/mind/articulation.js +77 -112
- package/dist/src/mind/attention.d.ts +40 -108
- package/dist/src/mind/attention.js +754 -872
- package/dist/src/mind/canonical.d.ts +4 -19
- package/dist/src/mind/canonical.js +27 -31
- package/dist/src/mind/graph-search.d.ts +201 -225
- package/dist/src/mind/graph-search.js +742 -821
- package/dist/src/mind/index.d.ts +2 -10
- package/dist/src/mind/junction.d.ts +31 -58
- package/dist/src/mind/junction.js +172 -237
- package/dist/src/mind/learning.d.ts +16 -52
- package/dist/src/mind/learning.js +143 -165
- package/dist/src/mind/match.d.ts +20 -69
- package/dist/src/mind/match.js +259 -318
- package/dist/src/mind/mechanisms/alu.js +16 -16
- package/dist/src/mind/mechanisms/cast.d.ts +9 -13
- package/dist/src/mind/mechanisms/cast.js +363 -456
- package/dist/src/mind/mechanisms/confluence.d.ts +8 -12
- package/dist/src/mind/mechanisms/confluence.js +152 -183
- package/dist/src/mind/mechanisms/cover.d.ts +2 -8
- package/dist/src/mind/mechanisms/cover.js +148 -210
- package/dist/src/mind/mechanisms/extraction.d.ts +8 -34
- package/dist/src/mind/mechanisms/extraction.js +234 -288
- package/dist/src/mind/mechanisms/recall.d.ts +6 -10
- package/dist/src/mind/mechanisms/recall.js +141 -185
- package/dist/src/mind/mind.d.ts +194 -155
- package/dist/src/mind/mind.js +392 -289
- package/dist/src/mind/pipeline-mechanism.d.ts +112 -124
- package/dist/src/mind/pipeline-mechanism.js +161 -172
- package/dist/src/mind/pipeline.d.ts +4 -14
- package/dist/src/mind/pipeline.js +125 -189
- package/dist/src/mind/primitives.d.ts +20 -33
- package/dist/src/mind/primitives.js +124 -120
- package/dist/src/mind/rationale.d.ts +86 -98
- package/dist/src/mind/rationale.js +113 -121
- package/dist/src/mind/reasoning.d.ts +2 -13
- package/dist/src/mind/reasoning.js +129 -166
- package/dist/src/mind/recognition.d.ts +1 -4
- package/dist/src/mind/recognition.js +198 -210
- package/dist/src/mind/resonance.d.ts +5 -22
- package/dist/src/mind/resonance.js +0 -0
- package/dist/src/mind/trace.d.ts +6 -25
- package/dist/src/mind/trace.js +50 -58
- package/dist/src/mind/traverse.d.ts +29 -58
- package/dist/src/mind/traverse.js +344 -356
- package/dist/src/mind/types.d.ts +122 -127
- package/dist/src/mind/types.js +60 -69
- package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
- package/dist/src/rabitq-ivf/src/database.js +201 -0
- package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
- package/dist/src/{rabitq-hnsw → rabitq-ivf}/src/index.js +1 -3
- package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
- package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
- package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
- package/dist/src/rabitq-ivf/src/prng.js +36 -0
- package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
- package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
- package/dist/src/sema.d.ts +9 -13
- package/dist/src/sema.js +26 -40
- package/dist/src/store-sqlite.d.ts +171 -166
- package/dist/src/store-sqlite.js +768 -662
- package/dist/src/store.d.ts +597 -630
- package/dist/src/store.js +1434 -1581
- package/dist/src/vec.d.ts +5 -9
- package/dist/src/vec.js +61 -73
- package/example/train_base.ts +33 -15
- package/index.html +65 -0
- package/package.json +1 -1
- package/src/alu/README.md +1 -1
- package/src/alu/src/index.ts +1 -1
- package/src/config.ts +19 -27
- package/src/geometry.ts +93 -1
- package/src/index.ts +6 -11
- package/src/mind/attention.ts +11 -6
- package/src/mind/mechanisms/recall.ts +29 -13
- package/src/mind/mind.ts +250 -19
- package/src/mind/primitives.ts +43 -6
- package/src/mind/recognition.ts +26 -8
- package/src/mind/traverse.ts +47 -0
- package/src/mind/types.ts +20 -21
- package/src/rabitq-ivf/README.md +56 -0
- package/src/rabitq-ivf/src/database.ts +276 -0
- package/src/{rabitq-hnsw → rabitq-ivf}/src/index.ts +2 -5
- package/src/rabitq-ivf/src/ivf.ts +1330 -0
- package/src/{rabitq-hnsw → rabitq-ivf}/src/prng.ts +1 -1
- package/src/store-sqlite.ts +204 -9
- package/src/store.ts +27 -34
- package/test/08-storage.test.mjs +3 -3
- package/test/13-conversation.test.mjs +190 -20
- package/test/14-scaling.test.mjs +2 -2
- package/test/35-ivf.test.mjs +263 -0
- package/test/36-bloom.test.mjs +123 -0
- package/dist/src/rabitq-hnsw/src/database.d.ts +0 -202
- package/dist/src/rabitq-hnsw/src/database.js +0 -405
- package/dist/src/rabitq-hnsw/src/heap.d.ts +0 -22
- package/dist/src/rabitq-hnsw/src/heap.js +0 -94
- package/dist/src/rabitq-hnsw/src/hnsw.d.ts +0 -125
- package/dist/src/rabitq-hnsw/src/hnsw.js +0 -500
- package/dist/src/rabitq-hnsw/src/index.d.ts +0 -15
- package/dist/src/rabitq-hnsw/src/prng.d.ts +0 -19
- package/dist/src/rabitq-hnsw/src/prng.js +0 -38
- package/dist/src/rabitq-hnsw/src/rabitq.d.ts +0 -95
- package/dist/src/rabitq-hnsw/src/rabitq.js +0 -299
- package/dist/src/rabitq-hnsw/src/store.d.ts +0 -162
- package/dist/src/rabitq-hnsw/src/store.js +0 -916
- package/dist/src/rabitq-hnsw/test/hnsw.test.d.ts +0 -1
- package/dist/src/rabitq-hnsw/test/hnsw.test.js +0 -1197
- package/src/rabitq-hnsw/README.md +0 -303
- package/src/rabitq-hnsw/src/database.ts +0 -492
- package/src/rabitq-hnsw/src/heap.ts +0 -90
- package/src/rabitq-hnsw/src/hnsw.ts +0 -514
- package/src/rabitq-hnsw/src/store.ts +0 -994
- package/src/rabitq-hnsw/test/hnsw.test.ts +0 -1213
- /package/src/{rabitq-hnsw → rabitq-ivf}/src/rabitq.ts +0 -0
package/dist/src/vec.d.ts
CHANGED
|
@@ -14,21 +14,17 @@ export declare function normalize(v: Vec): Vec;
|
|
|
14
14
|
export declare function cosine(a: Vec, b: Vec): number;
|
|
15
15
|
/** Set vector epsilon thresholds. Called once by Mind at construction. */
|
|
16
16
|
export declare function setVecConfig(cfg: {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
normalizeEpsilon?: number;
|
|
18
|
+
cosineEpsilon?: number;
|
|
19
19
|
}): void;
|
|
20
20
|
export interface Permutation {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
fwd: Uint32Array;
|
|
22
|
+
inv: Uint32Array;
|
|
23
23
|
}
|
|
24
24
|
/** The keyring: one independent permutation per seat.
|
|
25
25
|
* Independent keys do not commute, so an address in a tree is the
|
|
26
26
|
* path itself — "seat 2 inside seat 1" ≠ "seat 1 inside seat 2". */
|
|
27
|
-
export declare function makeKeyring(
|
|
28
|
-
D: number,
|
|
29
|
-
seats: number,
|
|
30
|
-
rand: () => number,
|
|
31
|
-
): Permutation[];
|
|
27
|
+
export declare function makeKeyring(D: number, seats: number, rand: () => number): Permutation[];
|
|
32
28
|
/** Apply permutation: out[i] = v[table[i]]. */
|
|
33
29
|
export declare function permute(v: Vec, table: Uint32Array): Vec;
|
|
34
30
|
/** Permute into existing buffer — zero allocation. */
|
package/dist/src/vec.js
CHANGED
|
@@ -4,49 +4,44 @@
|
|
|
4
4
|
// No weights. No gradients.
|
|
5
5
|
/** Deterministic PRNG (32-bit mixer). */
|
|
6
6
|
export function rng(seed) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
let s = seed >>> 0;
|
|
8
|
+
return () => {
|
|
9
|
+
s = (s + 0x6d2b79f5) >>> 0;
|
|
10
|
+
let t = s;
|
|
11
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
12
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
13
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
14
|
+
};
|
|
15
15
|
}
|
|
16
16
|
/** Standard normal sample (Box–Muller). */
|
|
17
17
|
function gaussian(rand) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
|
|
18
|
+
let u = 0, v = 0;
|
|
19
|
+
while (u === 0)
|
|
20
|
+
u = rand();
|
|
21
|
+
while (v === 0)
|
|
22
|
+
v = rand();
|
|
23
|
+
return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
|
|
26
24
|
}
|
|
27
25
|
export const zeros = (D) => new Float32Array(D);
|
|
28
26
|
export const copy = (v) => new Float32Array(v);
|
|
29
27
|
/** Random point on the unit sphere. */
|
|
30
28
|
export function randomUnit(D, rand) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return normalize(v);
|
|
29
|
+
const v = zeros(D);
|
|
30
|
+
for (let i = 0; i < D; i++)
|
|
31
|
+
v[i] = gaussian(rand);
|
|
32
|
+
return normalize(v);
|
|
36
33
|
}
|
|
37
34
|
/** target += src * scale (in place). */
|
|
38
35
|
export function addInto(target, src, scale = 1) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return target;
|
|
36
|
+
for (let i = 0; i < target.length; i++)
|
|
37
|
+
target[i] += src[i] * scale;
|
|
38
|
+
return target;
|
|
43
39
|
}
|
|
44
40
|
export function dot(a, b) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return s;
|
|
41
|
+
let s = 0;
|
|
42
|
+
for (let i = 0; i < a.length; i++)
|
|
43
|
+
s += a[i] * b[i];
|
|
44
|
+
return s;
|
|
50
45
|
}
|
|
51
46
|
const norm = (v) => Math.sqrt(dot(v, v));
|
|
52
47
|
// Epsilon thresholds (settable once via setVecConfig).
|
|
@@ -54,68 +49,61 @@ let _normalizeEpsilon = 1e-12;
|
|
|
54
49
|
let _cosineEpsilon = 1e-12;
|
|
55
50
|
/** In-place normalization. */
|
|
56
51
|
export function normalize(v) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
const n = norm(v);
|
|
53
|
+
if (n > _normalizeEpsilon) {
|
|
54
|
+
for (let i = 0; i < v.length; i++)
|
|
55
|
+
v[i] /= n;
|
|
61
56
|
}
|
|
62
|
-
|
|
63
|
-
return v;
|
|
57
|
+
return v;
|
|
64
58
|
}
|
|
65
59
|
/** Resonance: 1 = same, 0 = unrelated. */
|
|
66
60
|
export function cosine(a, b) {
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
const na = norm(a), nb = norm(b);
|
|
62
|
+
return na > _cosineEpsilon && nb > _cosineEpsilon ? dot(a, b) / (na * nb) : 0;
|
|
69
63
|
}
|
|
70
64
|
/** Set vector epsilon thresholds. Called once by Mind at construction. */
|
|
71
65
|
export function setVecConfig(cfg) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
66
|
+
if (cfg.normalizeEpsilon !== undefined) {
|
|
67
|
+
_normalizeEpsilon = cfg.normalizeEpsilon;
|
|
68
|
+
}
|
|
69
|
+
if (cfg.cosineEpsilon !== undefined)
|
|
70
|
+
_cosineEpsilon = cfg.cosineEpsilon;
|
|
78
71
|
}
|
|
79
72
|
/** One fixed random permutation (Fisher–Yates). */
|
|
80
73
|
function makePermutation(D, rand) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
return { fwd, inv };
|
|
74
|
+
const fwd = new Uint32Array(D);
|
|
75
|
+
for (let i = 0; i < D; i++)
|
|
76
|
+
fwd[i] = i;
|
|
77
|
+
for (let i = D - 1; i > 0; i--) {
|
|
78
|
+
const j = Math.floor(rand() * (i + 1));
|
|
79
|
+
const t = fwd[i];
|
|
80
|
+
fwd[i] = fwd[j];
|
|
81
|
+
fwd[j] = t;
|
|
82
|
+
}
|
|
83
|
+
const inv = new Uint32Array(D);
|
|
84
|
+
for (let i = 0; i < D; i++)
|
|
85
|
+
inv[fwd[i]] = i;
|
|
86
|
+
return { fwd, inv };
|
|
96
87
|
}
|
|
97
88
|
/** The keyring: one independent permutation per seat.
|
|
98
89
|
* Independent keys do not commute, so an address in a tree is the
|
|
99
90
|
* path itself — "seat 2 inside seat 1" ≠ "seat 1 inside seat 2". */
|
|
100
91
|
export function makeKeyring(D, seats, rand) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return ring;
|
|
92
|
+
const ring = [];
|
|
93
|
+
for (let s = 0; s < seats; s++)
|
|
94
|
+
ring.push(makePermutation(D, rand));
|
|
95
|
+
return ring;
|
|
106
96
|
}
|
|
107
97
|
/** Apply permutation: out[i] = v[table[i]]. */
|
|
108
98
|
export function permute(v, table) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return out;
|
|
99
|
+
const out = new Float32Array(v.length);
|
|
100
|
+
for (let i = 0; i < v.length; i++)
|
|
101
|
+
out[i] = v[table[i]];
|
|
102
|
+
return out;
|
|
114
103
|
}
|
|
115
104
|
/** Permute into existing buffer — zero allocation. */
|
|
116
105
|
export function permuteInto(out, v, table) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return out;
|
|
106
|
+
for (let i = 0; i < v.length; i++)
|
|
107
|
+
out[i] = v[table[i]];
|
|
108
|
+
return out;
|
|
121
109
|
}
|
package/example/train_base.ts
CHANGED
|
@@ -1610,20 +1610,23 @@ async function saveProgress(store: Store, p: SavedProgress): Promise<void> {
|
|
|
1610
1610
|
// ═══════════════════════════════════════════════════════════════════════
|
|
1611
1611
|
|
|
1612
1612
|
async function main(): Promise<void> {
|
|
1613
|
-
// The vector indices'
|
|
1614
|
-
//
|
|
1615
|
-
//
|
|
1616
|
-
//
|
|
1617
|
-
//
|
|
1618
|
-
|
|
1619
|
-
//
|
|
1620
|
-
//
|
|
1621
|
-
//
|
|
1622
|
-
|
|
1613
|
+
// The vector indices' memory knob (MiB) — each index's SQLite page cache.
|
|
1614
|
+
// The IVF index routes inserts through a RAM-resident pivot table and
|
|
1615
|
+
// appends to chunk blobs, so this cache mostly serves query-time cluster
|
|
1616
|
+
// scans; 256 MiB comfortably covers the probed working set of a trained
|
|
1617
|
+
// store. Override with VECTOR_CACHE_MB (64 is the library default).
|
|
1618
|
+
const VECTOR_CACHE_MB = Math.max(0, Number(env("VECTOR_CACHE_MB", "256")));
|
|
1619
|
+
// Page cache for the MAIN DAG database (node/kid/edge/contain tables).
|
|
1620
|
+
// Training issues millions of content-addressed point probes per session
|
|
1621
|
+
// against a GB-scale file; the library default (64 MiB) is sized for a
|
|
1622
|
+
// small machine — a training box affords more. Override with
|
|
1623
|
+
// SQLITE_CACHE_MB.
|
|
1624
|
+
const SQLITE_CACHE_MB = Math.max(0, Number(env("SQLITE_CACHE_MB", "256")));
|
|
1623
1625
|
const store = new SQliteStore({
|
|
1624
1626
|
path: DB_PATH,
|
|
1625
1627
|
D,
|
|
1626
1628
|
vectorCacheMb: VECTOR_CACHE_MB,
|
|
1629
|
+
sqliteCacheMb: SQLITE_CACHE_MB,
|
|
1627
1630
|
});
|
|
1628
1631
|
|
|
1629
1632
|
// The store IS the model: memories, progress, and metadata all persist in
|
|
@@ -1822,9 +1825,22 @@ async function main(): Promise<void> {
|
|
|
1822
1825
|
|
|
1823
1826
|
/** Run index maintenance: compact (remove garbage) then repair (fill gaps).
|
|
1824
1827
|
* Both are idempotent — running twice produces the same result as once.
|
|
1825
|
-
* Compaction frees index space first; repair then adds back
|
|
1826
|
-
* whose
|
|
1827
|
-
*
|
|
1828
|
+
* Compaction frees index space first; repair then adds back every
|
|
1829
|
+
* edge/halo-bearing node whose gist was evicted from the pending cache
|
|
1830
|
+
* before it reached the content index, completing the coverage that
|
|
1831
|
+
* incremental promotion alone cannot guarantee.
|
|
1832
|
+
*
|
|
1833
|
+
* repair runs with minParents = 0, NOT the library default of 2. The
|
|
1834
|
+
* default repairs only structural BRIDGES (≥2 parents), but this
|
|
1835
|
+
* trainer's fact deposits also leave answer-side DEPOSIT ROOTS with 0
|
|
1836
|
+
* structural parents ("The capital of France is Paris." as the dst of a
|
|
1837
|
+
* Q→A edge is a root of its own tree, contained in nothing). Those are
|
|
1838
|
+
* resonance targets recall depends on — a trained store shipped without
|
|
1839
|
+
* them cannot ground statement-shaped queries against its own answers
|
|
1840
|
+
* (observed: 33 such roots missing after a full curriculum, including
|
|
1841
|
+
* high-traffic conversation replies). minParents = 0 admits every
|
|
1842
|
+
* edge/halo bearer; the candidate set is still corpus-of-experiences-
|
|
1843
|
+
* sized, so the pass stays cheap.
|
|
1828
1844
|
*
|
|
1829
1845
|
* Logs the number of entries removed/added so a run that silently degrades
|
|
1830
1846
|
* (growing compaction count, or repair never recovering anything) is
|
|
@@ -1846,10 +1862,12 @@ async function main(): Promise<void> {
|
|
|
1846
1862
|
);
|
|
1847
1863
|
}
|
|
1848
1864
|
try {
|
|
1849
|
-
const added = await mind.repairContentIndex();
|
|
1865
|
+
const added = await mind.repairContentIndex(0);
|
|
1850
1866
|
if (added > 0) {
|
|
1851
1867
|
progress.log(
|
|
1852
|
-
` ${GRN}index repair: added ${
|
|
1868
|
+
` ${GRN}index repair: added ${
|
|
1869
|
+
int(added)
|
|
1870
|
+
} missing resonance targets${R}`,
|
|
1853
1871
|
);
|
|
1854
1872
|
}
|
|
1855
1873
|
} catch (err) {
|
package/index.html
CHANGED
|
@@ -52,6 +52,10 @@
|
|
|
52
52
|
z-index: 0;
|
|
53
53
|
overflow: hidden;
|
|
54
54
|
background: var(--bg);
|
|
55
|
+
/* own stacking context + GPU layer: keeps the blend-mode orbs from
|
|
56
|
+
forcing full-page re-rasterization every frame on mobile */
|
|
57
|
+
isolation: isolate;
|
|
58
|
+
transform: translateZ(0);
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
/* — colour weather: two huge drifting orbs + aurora sweep — */
|
|
@@ -60,6 +64,7 @@
|
|
|
60
64
|
border-radius: 50%;
|
|
61
65
|
filter: blur(70px);
|
|
62
66
|
mix-blend-mode: screen;
|
|
67
|
+
will-change: transform;
|
|
63
68
|
}
|
|
64
69
|
.orb.a {
|
|
65
70
|
width: 75vmax;
|
|
@@ -130,6 +135,7 @@
|
|
|
130
135
|
transparent 360deg
|
|
131
136
|
);
|
|
132
137
|
animation: spin 70s linear infinite;
|
|
138
|
+
will-change: transform;
|
|
133
139
|
}
|
|
134
140
|
@keyframes spin {
|
|
135
141
|
to {
|
|
@@ -158,6 +164,7 @@
|
|
|
158
164
|
);
|
|
159
165
|
animation: drift 50s linear infinite alternate;
|
|
160
166
|
opacity: 0.8;
|
|
167
|
+
will-change: transform;
|
|
161
168
|
}
|
|
162
169
|
@keyframes drift {
|
|
163
170
|
to {
|
|
@@ -180,10 +187,12 @@
|
|
|
180
187
|
.layerA {
|
|
181
188
|
animation: sway 30s ease-in-out infinite alternate;
|
|
182
189
|
transform-origin: 50% 50%;
|
|
190
|
+
will-change: transform;
|
|
183
191
|
}
|
|
184
192
|
.layerB {
|
|
185
193
|
animation: sway 44s ease-in-out infinite alternate-reverse;
|
|
186
194
|
transform-origin: 50% 50%;
|
|
195
|
+
will-change: transform;
|
|
187
196
|
}
|
|
188
197
|
@keyframes sway {
|
|
189
198
|
from {
|
|
@@ -341,6 +350,7 @@
|
|
|
341
350
|
opacity: 0.5;
|
|
342
351
|
animation: spin 40s linear infinite;
|
|
343
352
|
filter: drop-shadow(0 0 30px rgba(57, 230, 255, 0.3));
|
|
353
|
+
will-change: transform;
|
|
344
354
|
}
|
|
345
355
|
.hexring::before {
|
|
346
356
|
content: "";
|
|
@@ -373,6 +383,7 @@
|
|
|
373
383
|
transparent 70%
|
|
374
384
|
);
|
|
375
385
|
animation: breath 7s ease-in-out infinite;
|
|
386
|
+
will-change: transform, opacity;
|
|
376
387
|
}
|
|
377
388
|
@keyframes breath {
|
|
378
389
|
0%, 100% {
|
|
@@ -423,6 +434,11 @@
|
|
|
423
434
|
filter: drop-shadow(0 0 22px rgba(57, 230, 255, 0.35)) drop-shadow(
|
|
424
435
|
0 8px 60px rgba(168, 120, 255, 0.25)
|
|
425
436
|
);
|
|
437
|
+
/* gradient-clipped text flickers on iOS while its background animates
|
|
438
|
+
unless the element sits on its own composited layer */
|
|
439
|
+
-webkit-backface-visibility: hidden;
|
|
440
|
+
backface-visibility: hidden;
|
|
441
|
+
transform: translateZ(0);
|
|
426
442
|
}
|
|
427
443
|
@keyframes sheen {
|
|
428
444
|
0%, 100% {
|
|
@@ -450,6 +466,7 @@
|
|
|
450
466
|
color: transparent;
|
|
451
467
|
-webkit-text-stroke: 1px rgba(57, 230, 255, 0.22);
|
|
452
468
|
animation: echo 8s ease-in-out infinite;
|
|
469
|
+
will-change: transform, opacity;
|
|
453
470
|
}
|
|
454
471
|
@keyframes echo {
|
|
455
472
|
0%, 100% {
|
|
@@ -594,6 +611,7 @@
|
|
|
594
611
|
white-space: nowrap;
|
|
595
612
|
width: max-content;
|
|
596
613
|
animation: scroll 34s linear infinite;
|
|
614
|
+
will-change: transform;
|
|
597
615
|
}
|
|
598
616
|
.ticker span {
|
|
599
617
|
padding: 0.72em 0;
|
|
@@ -652,6 +670,53 @@
|
|
|
652
670
|
}
|
|
653
671
|
}
|
|
654
672
|
|
|
673
|
+
/* ——————————————————— mobile / touch performance ——————————————————
|
|
674
|
+
Phones can't sustain the per-frame repaint work: SVG dash/scale
|
|
675
|
+
animations and background-position sheens repaint every frame, and
|
|
676
|
+
each pass runs through blur/drop-shadow filters. Strip the filters
|
|
677
|
+
and the repaint-driven animations; keep every compositor-friendly
|
|
678
|
+
transform/opacity animation so the page stays alive. */
|
|
679
|
+
@media (max-width: 820px), (pointer: coarse) {
|
|
680
|
+
.orb {
|
|
681
|
+
filter: blur(40px);
|
|
682
|
+
}
|
|
683
|
+
.aurora {
|
|
684
|
+
animation: none;
|
|
685
|
+
}
|
|
686
|
+
.grain {
|
|
687
|
+
display: none;
|
|
688
|
+
}
|
|
689
|
+
.wire,
|
|
690
|
+
.wire.v,
|
|
691
|
+
.wire.m,
|
|
692
|
+
.wire.g {
|
|
693
|
+
filter: none;
|
|
694
|
+
animation: none;
|
|
695
|
+
stroke-dasharray: none;
|
|
696
|
+
stroke-width: 1.2;
|
|
697
|
+
opacity: 0.75;
|
|
698
|
+
}
|
|
699
|
+
.layerA,
|
|
700
|
+
.layerB {
|
|
701
|
+
animation: none;
|
|
702
|
+
}
|
|
703
|
+
.ring {
|
|
704
|
+
animation-duration: 7s;
|
|
705
|
+
}
|
|
706
|
+
.hexring {
|
|
707
|
+
filter: none;
|
|
708
|
+
}
|
|
709
|
+
h1 {
|
|
710
|
+
animation: up 1s 0.2s cubic-bezier(0.2, 0.7, 0.2, 1) both;
|
|
711
|
+
background-position: 35% 50%;
|
|
712
|
+
filter: drop-shadow(0 0 22px rgba(57, 230, 255, 0.35));
|
|
713
|
+
}
|
|
714
|
+
.btn.primary {
|
|
715
|
+
animation: none;
|
|
716
|
+
background-position: 50% 50%;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
655
720
|
/* ————————————————————————— reduced motion ———————————————————————— */
|
|
656
721
|
@media (prefers-reduced-motion: reduce) {
|
|
657
722
|
*, *::before, *::after {
|
package/package.json
CHANGED
package/src/alu/README.md
CHANGED
|
@@ -15,7 +15,7 @@ search as authoritative axioms (at `STEP` cost, like a learned edge).
|
|
|
15
15
|
|
|
16
16
|
It has no dependency on the rest of the codebase except the pure byte helpers in
|
|
17
17
|
`../bytes.ts`, and is intended to be reused as a self-contained sublibrary in
|
|
18
|
-
the spirit of `derive/` and `rabitq-
|
|
18
|
+
the spirit of `derive/` and `rabitq-ivf/`.
|
|
19
19
|
|
|
20
20
|
## The thesis: one tiny kernel, everything else is a rewrite
|
|
21
21
|
|
package/src/alu/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// alu — the ALU sub-library: a tiny irreducible kernel from which arithmetic,
|
|
2
2
|
// logic, and numerical computation are all DERIVED.
|
|
3
3
|
//
|
|
4
|
-
// Self-contained in the spirit of derive/ and rabitq-
|
|
4
|
+
// Self-contained in the spirit of derive/ and rabitq-ivf/: it imports only the
|
|
5
5
|
// pure byte helpers (../../bytes.js) and nothing else from SEMA. The host
|
|
6
6
|
// reaches meaning (operator synonymy, the symbolic inverse) through the injected
|
|
7
7
|
// AluResonance, pre-resolved into a synchronous snapshot before the search runs.
|
package/src/config.ts
CHANGED
|
@@ -39,18 +39,9 @@ export interface AlphabetConfig {
|
|
|
39
39
|
|
|
40
40
|
export interface StoreConfig {
|
|
41
41
|
minHaloMass: number;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
* index inserts that exist so a partial query can resonate a sub-region
|
|
46
|
-
* and climb, never as dedup targets. Deposit roots and halo-bearing
|
|
47
|
-
* targets always build with the full `efConstruction`. A smaller budget
|
|
48
|
-
* here is the one deliberate speed-for-quality trade in ingestion (an
|
|
49
|
-
* interior's layer-0 wiring is built from a narrower candidate beam);
|
|
50
|
-
* the recall suite (partial recall, multi-topic attention, counterfactual
|
|
51
|
-
* anchoring) is the gate for its value. Set equal to `efConstruction`
|
|
52
|
-
* to disable the trade. */
|
|
53
|
-
efConstructionInterior: number;
|
|
42
|
+
/** Query breadth of the IVF vector indices: clusters probed per query =
|
|
43
|
+
* ceil(efSearch / 4). Inserts have no quality knob — the partitioned
|
|
44
|
+
* index routes and appends, so ingestion cost is flat by construction. */
|
|
54
45
|
efSearch: number;
|
|
55
46
|
/** Compact the in-memory vector indices after this many vectors are written.
|
|
56
47
|
* Compaction rebuilds an index from its live codes to reclaim the slots left
|
|
@@ -58,7 +49,7 @@ export interface StoreConfig {
|
|
|
58
49
|
* (not on a flush count that goes quiet during repeat-heavy training) keeps
|
|
59
50
|
* the index dense and query cost bounded. */
|
|
60
51
|
compactEveryNWrites: number;
|
|
61
|
-
/** Over-fetch factor for
|
|
52
|
+
/** Over-fetch factor for vector-index queries (ANN recall cushion). */
|
|
62
53
|
overfetch: number;
|
|
63
54
|
/** Combined buffered-write ceiling before a flush of both vector indices
|
|
64
55
|
* (content + halo). Higher ⇒ fewer, larger flushes into the in-memory
|
|
@@ -91,14 +82,20 @@ export interface StoreConfig {
|
|
|
91
82
|
* round-trips through the quantizer. An eviction or a reopen reads the
|
|
92
83
|
* 2-bit row — the fidelity every cross-session consumer already gets. */
|
|
93
84
|
haloCacheBytes: number;
|
|
94
|
-
/** Size, in MiB, of each `rabitq-
|
|
95
|
-
* (forwarded as its `cacheSizeMb`
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* with the budget at 0. Exposed so a scaling test can set it to 0 and measure
|
|
85
|
+
/** Size, in MiB, of each `rabitq-ivf` `VectorDatabase`'s memory budget
|
|
86
|
+
* (forwarded as its `cacheSizeMb` — its SQLite page cache). A PURE latency
|
|
87
|
+
* optimisation — the index reads chunk blobs from SQLite on demand, so its
|
|
88
|
+
* correctness and its per-operation storage-read count are identical with
|
|
89
|
+
* the budget at 0. Exposed so a scaling test can set it to 0 and measure
|
|
100
90
|
* the honest, cache-independent cost. */
|
|
101
91
|
vectorCacheMb: number;
|
|
92
|
+
/** Size, in MiB, of the MAIN DAG database's SQLite page cache. The node /
|
|
93
|
+
* kid / edge / contain tables serve millions of point probes per training
|
|
94
|
+
* session (content-addressed findLeaf/findBranch, parent probes, contain
|
|
95
|
+
* appends); SQLite's default cache (~2 MiB) thrashes once the DB outgrows
|
|
96
|
+
* it, so every probe pays a file read. A PURE latency knob — correctness
|
|
97
|
+
* and result identical at any value. */
|
|
98
|
+
sqliteCacheMb: number;
|
|
102
99
|
/** Max entries in the skipped-interior LRU set. Interiors that
|
|
103
100
|
* {@link Store.indexSubtree} has already visited (indexed or skipped) are
|
|
104
101
|
* remembered here so subsequent calls prune their subtrees. Session-local
|
|
@@ -151,9 +148,6 @@ export const DEFAULT_CONFIG: MindConfig = {
|
|
|
151
148
|
},
|
|
152
149
|
store: {
|
|
153
150
|
minHaloMass: 1,
|
|
154
|
-
m: 8,
|
|
155
|
-
efConstruction: 64,
|
|
156
|
-
efConstructionInterior: 16,
|
|
157
151
|
efSearch: 64,
|
|
158
152
|
compactEveryNWrites: 50_000,
|
|
159
153
|
overfetch: 4,
|
|
@@ -165,6 +159,7 @@ export const DEFAULT_CONFIG: MindConfig = {
|
|
|
165
159
|
pendingGistBytes: 16_000_000,
|
|
166
160
|
haloCacheBytes: 16_000_000,
|
|
167
161
|
vectorCacheMb: 64,
|
|
162
|
+
sqliteCacheMb: 64,
|
|
168
163
|
coveredIdsMax: 100_000,
|
|
169
164
|
chainCacheBytes: 16_000_000,
|
|
170
165
|
},
|
|
@@ -194,11 +189,6 @@ export function resolveConfig(opts: Partial<MindConfig> = {}): MindConfig {
|
|
|
194
189
|
},
|
|
195
190
|
store: {
|
|
196
191
|
minHaloMass: opts.store?.minHaloMass ?? DEFAULT_CONFIG.store.minHaloMass,
|
|
197
|
-
m: opts.store?.m ?? DEFAULT_CONFIG.store.m,
|
|
198
|
-
efConstruction: opts.store?.efConstruction ??
|
|
199
|
-
DEFAULT_CONFIG.store.efConstruction,
|
|
200
|
-
efConstructionInterior: opts.store?.efConstructionInterior ??
|
|
201
|
-
DEFAULT_CONFIG.store.efConstructionInterior,
|
|
202
192
|
efSearch: opts.store?.efSearch ?? DEFAULT_CONFIG.store.efSearch,
|
|
203
193
|
compactEveryNWrites: opts.store?.compactEveryNWrites ??
|
|
204
194
|
DEFAULT_CONFIG.store.compactEveryNWrites,
|
|
@@ -218,6 +208,8 @@ export function resolveConfig(opts: Partial<MindConfig> = {}): MindConfig {
|
|
|
218
208
|
DEFAULT_CONFIG.store.haloCacheBytes,
|
|
219
209
|
vectorCacheMb: opts.store?.vectorCacheMb ??
|
|
220
210
|
DEFAULT_CONFIG.store.vectorCacheMb,
|
|
211
|
+
sqliteCacheMb: opts.store?.sqliteCacheMb ??
|
|
212
|
+
DEFAULT_CONFIG.store.sqliteCacheMb,
|
|
221
213
|
coveredIdsMax: opts.store?.coveredIdsMax ??
|
|
222
214
|
DEFAULT_CONFIG.store.coveredIdsMax,
|
|
223
215
|
chainCacheBytes: opts.store?.chainCacheBytes ??
|
package/src/geometry.ts
CHANGED
|
@@ -314,17 +314,32 @@ export function knownPrefixLength(
|
|
|
314
314
|
/** Bytes → Sema tree. `leafAt` and `lookup` are store capabilities for
|
|
315
315
|
* detecting previously-stored prefixes so the river can split at the
|
|
316
316
|
* correct boundary. Pass them through from `perceive`; the geometry
|
|
317
|
-
* computes the stable prefix internally.
|
|
317
|
+
* computes the stable prefix internally.
|
|
318
|
+
*
|
|
319
|
+
* `boundaries` is the CALLER-computed stable-prefix boundary set (§10.3):
|
|
320
|
+
* strictly-increasing proper byte offsets, each the length of a prefix that
|
|
321
|
+
* is already a stored whole-stream form. When given, the fold splits into
|
|
322
|
+
* the segments between consecutive boundaries — each folded independently,
|
|
323
|
+
* exactly as it folded when it was learned — and the segment roots join
|
|
324
|
+
* LEFT-NESTED (((s₀·s₁)·s₂)…), so every learnt cumulative-context root
|
|
325
|
+
* reappears as an identical subtree (and, by hash-consing, the very same
|
|
326
|
+
* node) inside the grown stream. This is what lets a conversation's next
|
|
327
|
+
* turn extend perception instead of refolding it: identical prefixes
|
|
328
|
+
* produce identical subtrees regardless of what follows them. */
|
|
318
329
|
export function bytesToTree(
|
|
319
330
|
space: Space,
|
|
320
331
|
alphabet: Alphabet,
|
|
321
332
|
bytes: Uint8Array,
|
|
322
333
|
leafAt?: (i: number) => number | null,
|
|
323
334
|
lookup?: (leafIds: number[]) => number | null,
|
|
335
|
+
boundaries?: readonly number[],
|
|
324
336
|
): Sema {
|
|
325
337
|
if (bytes.length === 0) {
|
|
326
338
|
return sema(alphabet.vecs[0], new Uint8Array(0), null);
|
|
327
339
|
}
|
|
340
|
+
if (boundaries !== undefined && boundaries.length > 0) {
|
|
341
|
+
return stablePrefixFold(space, alphabet, bytes, boundaries);
|
|
342
|
+
}
|
|
328
343
|
const sb = (leafAt && lookup) ? knownPrefixLength(bytes, leafAt, lookup) : 0;
|
|
329
344
|
return riverFold(
|
|
330
345
|
space,
|
|
@@ -333,6 +348,83 @@ export function bytesToTree(
|
|
|
333
348
|
).tree;
|
|
334
349
|
}
|
|
335
350
|
|
|
351
|
+
/** The stable-prefix segmented fold (§10.3). Each segment between
|
|
352
|
+
* consecutive boundaries folds PLAINLY and independently; segment roots
|
|
353
|
+
* join left-nested, and only the final root is normalized (the linear-fold
|
|
354
|
+
* contract: one normalize per perception). A segment's own inner splits
|
|
355
|
+
* need no recursion here: a nested learnt prefix is itself an earlier
|
|
356
|
+
* boundary, so the left-nested join reproduces every intermediate learnt
|
|
357
|
+
* root ((s₀·s₁) IS the root the store learnt for the first two segments'
|
|
358
|
+
* bytes, and so on). */
|
|
359
|
+
function stablePrefixFold(
|
|
360
|
+
space: Space,
|
|
361
|
+
alphabet: Alphabet,
|
|
362
|
+
bytes: Uint8Array,
|
|
363
|
+
boundaries: readonly number[],
|
|
364
|
+
): Sema {
|
|
365
|
+
const cuts: number[] = [];
|
|
366
|
+
let prev = 0;
|
|
367
|
+
for (const b of boundaries) {
|
|
368
|
+
if (b > prev && b < bytes.length) {
|
|
369
|
+
cuts.push(b);
|
|
370
|
+
prev = b;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (cuts.length === 0) {
|
|
374
|
+
return riverFold(space, bytesToLeaves(alphabet, bytes), bytes.length).tree;
|
|
375
|
+
}
|
|
376
|
+
const edges = [0, ...cuts, bytes.length];
|
|
377
|
+
const segs: Folded[] = [];
|
|
378
|
+
for (let i = 0; i + 1 < edges.length; i++) {
|
|
379
|
+
const seg = bytes.subarray(edges[i], edges[i + 1]);
|
|
380
|
+
segs.push(riverFoldRaw(space, bytesToLeaves(alphabet, seg)));
|
|
381
|
+
}
|
|
382
|
+
let cur = segs[0];
|
|
383
|
+
for (let i = 1; i < segs.length; i++) cur = fold2(space, cur, segs[i]);
|
|
384
|
+
normalize(cur.tree.v);
|
|
385
|
+
return cur.tree;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/** Join two folded items as one 2-kid branch — the top-level join of the
|
|
389
|
+
* stable-prefix fold, identical FP ops to foldSlice's seat-bound
|
|
390
|
+
* accumulation over a group of two. Unnormalized (interior). */
|
|
391
|
+
function fold2(space: Space, a: Folded, b: Folded): Folded {
|
|
392
|
+
const D = space.D;
|
|
393
|
+
const gist = new Float32Array(D);
|
|
394
|
+
const kids = [a.tree, b.tree];
|
|
395
|
+
for (let k = 0; k < 2; k++) {
|
|
396
|
+
const seat = space.seats[k].fwd;
|
|
397
|
+
const v = kids[k].v;
|
|
398
|
+
for (let d = 0; d < D; d++) gist[d] += v[seat[d]];
|
|
399
|
+
}
|
|
400
|
+
return { tree: sema(gist, null, kids), len: a.len + b.len };
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/** Plain river fold WITHOUT the final root normalize — the segment-level
|
|
404
|
+
* building block of {@link stablePrefixFold} (interiors must keep their
|
|
405
|
+
* byte-proportional magnitude; only the whole perception's root is ever
|
|
406
|
+
* normalized). */
|
|
407
|
+
function riverFoldRaw(space: Space, row: Folded[]): Folded {
|
|
408
|
+
if (row.length === 0) {
|
|
409
|
+
const z = new Float32Array(space.D);
|
|
410
|
+
return { tree: sema(z, new Uint8Array(0), null), len: 0 };
|
|
411
|
+
}
|
|
412
|
+
if (row.length === 1) return row[0];
|
|
413
|
+
let level = row;
|
|
414
|
+
while (level.length > 1) {
|
|
415
|
+
const next: Folded[] = [];
|
|
416
|
+
foldSlice(space, level, 0, level.length, next, false);
|
|
417
|
+
if (next.length === level.length) {
|
|
418
|
+
const forced: Folded[] = [];
|
|
419
|
+
foldSlice(space, next, 0, next.length, forced, true);
|
|
420
|
+
level = forced;
|
|
421
|
+
} else {
|
|
422
|
+
level = next;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return level[0];
|
|
426
|
+
}
|
|
427
|
+
|
|
336
428
|
// ---- pyramid fold (incremental plain perception) ----
|
|
337
429
|
|
|
338
430
|
/** The PLAIN fold's full level pyramid — every level's item list, bottom
|