@hviana/sema 0.4.0 → 0.4.2

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.
Files changed (154) hide show
  1. package/CONTRIBUTING.md +92 -10
  2. package/LICENSE.md +2 -2
  3. package/package.json +1 -1
  4. package/src/ingest-cache.ts +4 -0
  5. package/src/meter.ts +5 -0
  6. package/src/mind/attention.ts +18 -1
  7. package/src/mind/bridge.ts +292 -54
  8. package/src/mind/junction.ts +21 -7
  9. package/src/mind/match.ts +92 -1
  10. package/src/mind/mechanisms/cast.ts +12 -0
  11. package/src/mind/mechanisms/confluence.ts +30 -1
  12. package/src/mind/mechanisms/cover.ts +36 -4
  13. package/src/mind/mechanisms/recall.ts +21 -44
  14. package/src/mind/mind.ts +39 -2
  15. package/src/mind/pipeline-mechanism.ts +86 -4
  16. package/src/mind/pipeline.ts +1 -1
  17. package/src/mind/reasoning.ts +15 -8
  18. package/src/mind/recognition.ts +40 -0
  19. package/src/mind/resonance.ts +0 -0
  20. package/src/mind/traverse.ts +17 -15
  21. package/src/mind/types.ts +10 -0
  22. package/test/49-natural-units-synonym-bridge.test.mjs +56 -15
  23. package/dist/example/demo.d.ts +0 -1
  24. package/dist/example/demo.js +0 -39
  25. package/dist/example/train_base.d.ts +0 -87
  26. package/dist/example/train_base.js +0 -2252
  27. package/dist/src/alphabet.d.ts +0 -7
  28. package/dist/src/alphabet.js +0 -33
  29. package/dist/src/alu/src/alu.d.ts +0 -185
  30. package/dist/src/alu/src/alu.js +0 -440
  31. package/dist/src/alu/src/expr.d.ts +0 -61
  32. package/dist/src/alu/src/expr.js +0 -318
  33. package/dist/src/alu/src/index.d.ts +0 -11
  34. package/dist/src/alu/src/index.js +0 -19
  35. package/dist/src/alu/src/kernel-arith.d.ts +0 -16
  36. package/dist/src/alu/src/kernel-arith.js +0 -264
  37. package/dist/src/alu/src/kernel-bits.d.ts +0 -19
  38. package/dist/src/alu/src/kernel-bits.js +0 -152
  39. package/dist/src/alu/src/kernel-logic.d.ts +0 -4
  40. package/dist/src/alu/src/kernel-logic.js +0 -60
  41. package/dist/src/alu/src/kernel-nd.d.ts +0 -3
  42. package/dist/src/alu/src/kernel-nd.js +0 -208
  43. package/dist/src/alu/src/kernel-numeric.d.ts +0 -54
  44. package/dist/src/alu/src/kernel-numeric.js +0 -366
  45. package/dist/src/alu/src/operation.d.ts +0 -168
  46. package/dist/src/alu/src/operation.js +0 -189
  47. package/dist/src/alu/src/parser.d.ts +0 -221
  48. package/dist/src/alu/src/parser.js +0 -577
  49. package/dist/src/alu/src/resonance.d.ts +0 -55
  50. package/dist/src/alu/src/resonance.js +0 -126
  51. package/dist/src/alu/src/text.d.ts +0 -31
  52. package/dist/src/alu/src/text.js +0 -73
  53. package/dist/src/alu/src/value.d.ts +0 -109
  54. package/dist/src/alu/src/value.js +0 -300
  55. package/dist/src/alu/test/alu.test.d.ts +0 -1
  56. package/dist/src/alu/test/alu.test.js +0 -764
  57. package/dist/src/bytes.d.ts +0 -14
  58. package/dist/src/bytes.js +0 -59
  59. package/dist/src/canon.d.ts +0 -26
  60. package/dist/src/canon.js +0 -57
  61. package/dist/src/config.d.ts +0 -111
  62. package/dist/src/config.js +0 -91
  63. package/dist/src/derive/src/deduction.d.ts +0 -136
  64. package/dist/src/derive/src/deduction.js +0 -159
  65. package/dist/src/derive/src/index.d.ts +0 -8
  66. package/dist/src/derive/src/index.js +0 -11
  67. package/dist/src/derive/src/priority-queue.d.ts +0 -20
  68. package/dist/src/derive/src/priority-queue.js +0 -73
  69. package/dist/src/derive/src/rewrite.d.ts +0 -56
  70. package/dist/src/derive/src/rewrite.js +0 -100
  71. package/dist/src/derive/src/trie.d.ts +0 -90
  72. package/dist/src/derive/src/trie.js +0 -217
  73. package/dist/src/derive/test/derive.test.d.ts +0 -1
  74. package/dist/src/derive/test/derive.test.js +0 -122
  75. package/dist/src/extension.d.ts +0 -37
  76. package/dist/src/extension.js +0 -7
  77. package/dist/src/geometry.d.ts +0 -175
  78. package/dist/src/geometry.js +0 -823
  79. package/dist/src/index.d.ts +0 -17
  80. package/dist/src/index.js +0 -19
  81. package/dist/src/ingest-cache.d.ts +0 -41
  82. package/dist/src/ingest-cache.js +0 -161
  83. package/dist/src/meter.d.ts +0 -171
  84. package/dist/src/meter.js +0 -269
  85. package/dist/src/mind/articulation.d.ts +0 -6
  86. package/dist/src/mind/articulation.js +0 -99
  87. package/dist/src/mind/attention.d.ts +0 -414
  88. package/dist/src/mind/attention.js +0 -2065
  89. package/dist/src/mind/bridge.d.ts +0 -39
  90. package/dist/src/mind/bridge.js +0 -738
  91. package/dist/src/mind/canonical.d.ts +0 -34
  92. package/dist/src/mind/canonical.js +0 -93
  93. package/dist/src/mind/graph-search.d.ts +0 -294
  94. package/dist/src/mind/graph-search.js +0 -996
  95. package/dist/src/mind/index.d.ts +0 -9
  96. package/dist/src/mind/index.js +0 -5
  97. package/dist/src/mind/junction.d.ts +0 -134
  98. package/dist/src/mind/junction.js +0 -331
  99. package/dist/src/mind/learning.d.ts +0 -75
  100. package/dist/src/mind/learning.js +0 -270
  101. package/dist/src/mind/match.d.ts +0 -166
  102. package/dist/src/mind/match.js +0 -565
  103. package/dist/src/mind/mechanisms/alu.d.ts +0 -4
  104. package/dist/src/mind/mechanisms/alu.js +0 -36
  105. package/dist/src/mind/mechanisms/cast.d.ts +0 -89
  106. package/dist/src/mind/mechanisms/cast.js +0 -773
  107. package/dist/src/mind/mechanisms/confluence.d.ts +0 -24
  108. package/dist/src/mind/mechanisms/confluence.js +0 -225
  109. package/dist/src/mind/mechanisms/cover.d.ts +0 -6
  110. package/dist/src/mind/mechanisms/cover.js +0 -203
  111. package/dist/src/mind/mechanisms/extraction.d.ts +0 -33
  112. package/dist/src/mind/mechanisms/extraction.js +0 -300
  113. package/dist/src/mind/mechanisms/recall.d.ts +0 -16
  114. package/dist/src/mind/mechanisms/recall.js +0 -388
  115. package/dist/src/mind/mind.d.ts +0 -330
  116. package/dist/src/mind/mind.js +0 -594
  117. package/dist/src/mind/pipeline-mechanism.d.ts +0 -172
  118. package/dist/src/mind/pipeline-mechanism.js +0 -382
  119. package/dist/src/mind/pipeline.d.ts +0 -49
  120. package/dist/src/mind/pipeline.js +0 -275
  121. package/dist/src/mind/primitives.d.ts +0 -66
  122. package/dist/src/mind/primitives.js +0 -306
  123. package/dist/src/mind/rationale.d.ts +0 -139
  124. package/dist/src/mind/rationale.js +0 -163
  125. package/dist/src/mind/reasoning.d.ts +0 -40
  126. package/dist/src/mind/reasoning.js +0 -272
  127. package/dist/src/mind/recognition.d.ts +0 -20
  128. package/dist/src/mind/recognition.js +0 -463
  129. package/dist/src/mind/resonance.d.ts +0 -23
  130. package/dist/src/mind/resonance.js +0 -0
  131. package/dist/src/mind/trace.d.ts +0 -15
  132. package/dist/src/mind/trace.js +0 -73
  133. package/dist/src/mind/traverse.d.ts +0 -124
  134. package/dist/src/mind/traverse.js +0 -649
  135. package/dist/src/mind/types.d.ts +0 -323
  136. package/dist/src/mind/types.js +0 -130
  137. package/dist/src/rabitq-ivf/src/database.d.ts +0 -113
  138. package/dist/src/rabitq-ivf/src/database.js +0 -201
  139. package/dist/src/rabitq-ivf/src/index.d.ts +0 -7
  140. package/dist/src/rabitq-ivf/src/index.js +0 -4
  141. package/dist/src/rabitq-ivf/src/ivf.d.ts +0 -200
  142. package/dist/src/rabitq-ivf/src/ivf.js +0 -1165
  143. package/dist/src/rabitq-ivf/src/prng.d.ts +0 -19
  144. package/dist/src/rabitq-ivf/src/prng.js +0 -36
  145. package/dist/src/rabitq-ivf/src/rabitq.d.ts +0 -95
  146. package/dist/src/rabitq-ivf/src/rabitq.js +0 -283
  147. package/dist/src/sema.d.ts +0 -31
  148. package/dist/src/sema.js +0 -63
  149. package/dist/src/store-sqlite.d.ts +0 -184
  150. package/dist/src/store-sqlite.js +0 -942
  151. package/dist/src/store.d.ts +0 -678
  152. package/dist/src/store.js +0 -1703
  153. package/dist/src/vec.d.ts +0 -31
  154. package/dist/src/vec.js +0 -109
@@ -10,9 +10,9 @@ import { cosine, Vec } from "../vec.js";
10
10
  import type { AncestorReach, MindContext, SaturationStop } from "./types.js";
11
11
  import { gistOf, read } from "./primitives.js";
12
12
 
13
- // ── Per-response structural memo ────────────────────────────────────────
13
+ // ── Session structural memo ─────────────────────────────────────────────
14
14
  //
15
- // Within one respond() the store is read-only, so structural reads are pure
15
+ // Between ingests the store is read-only, so structural reads are pure
16
16
  // functions of the node id. edgeAncestors climbs different start nodes that
17
17
  // share ancestry (regions sharing a chunk, canonicalChunkId's prefix probes)
18
18
  // — the reachMemo already caches whole-climb results, but a node visited as an
@@ -42,21 +42,17 @@ const structCaches = new WeakMap<object, StructCache>();
42
42
  // every mechanism that prices commonality" — was reached only by confluence.
43
43
  // The climb is by far the biggest consumer.
44
44
  //
45
- // Keyed off `ctx.climbMemo`'s OBJECT IDENTITY, exactly like the struct cache
46
- // above, which buys the right lifetime for free: a plain respond() has a
47
- // fresh climbMemo, so the memo is response-scoped; a conversation turn has
48
- // the conversation's persistent one, so it is conversation-scoped. That
49
- // matters — the stable-prefix fold makes each turn's subtree independent of
50
- // what follows, so 59–70% of a later turn's climb regions are byte-identical
51
- // repeats of an earlier turn's (measured on a 4-turn session), and every one
52
- // of them used to re-climb from cold.
45
+ // Keyed by the Mind's structural lifecycle identity: ordinary and
46
+ // conversational asks share it, and every ingest invalidates it. A real
47
+ // battery repeatedly reaches the same corpus scaffolding even when its
48
+ // surface questions differ.
53
49
  //
54
50
  // Budgeted, not unbounded (AGENTS §2.12): past the cap the whole map is
55
51
  // dropped and re-derived, costing a cold climb and never a wrong answer.
56
52
  const REACH_MEMO_MAX = 100_000;
57
53
  const reachCaches = new WeakMap<object, Map<number, AncestorReach>>();
58
54
 
59
- /** The reach memo this response should use — see the note above.
55
+ /** The reach memo this ask should use — see the note above.
60
56
  *
61
57
  * A TRACED response always gets a fresh, empty one. `AncestorReach`'s
62
58
  * `visited`/`maxDepth`/`saturation` fields are populated only when a trace
@@ -70,18 +66,18 @@ export function sharedReachMemo(
70
66
  ctx: MindContext,
71
67
  ): Map<number, AncestorReach> {
72
68
  if (ctx.trace !== null || ctx.climbMemo === null) return new Map();
73
- let m = reachCaches.get(ctx.climbMemo);
74
- if (m === undefined) reachCaches.set(ctx.climbMemo, m = new Map());
69
+ let m = reachCaches.get(ctx._structMemoKey);
70
+ if (m === undefined) reachCaches.set(ctx._structMemoKey, m = new Map());
75
71
  else if (m.size >= REACH_MEMO_MAX) m.clear();
76
72
  return m;
77
73
  }
78
74
 
79
75
  function getStructCache(ctx: MindContext): StructCache | null {
80
76
  if (ctx.climbMemo === null) return null;
81
- let c = structCaches.get(ctx.climbMemo);
77
+ let c = structCaches.get(ctx._structMemoKey);
82
78
  if (c === undefined) {
83
79
  structCaches.set(
84
- ctx.climbMemo,
80
+ ctx._structMemoKey,
85
81
  c = {
86
82
  hasNext: new Map(),
87
83
  prevCount: new Map(),
@@ -92,6 +88,12 @@ function getStructCache(ctx: MindContext): StructCache | null {
92
88
  return c;
93
89
  }
94
90
 
91
+ /** Invalidate every session-lifetime structural read after a write. */
92
+ export function invalidateStructuralCaches(ctx: MindContext): void {
93
+ reachCaches.delete(ctx._structMemoKey);
94
+ structCaches.delete(ctx._structMemoKey);
95
+ }
96
+
95
97
  /** Cached {@link Store.hasNext} — pure during one respond(). */
96
98
  function cachedHasNext(
97
99
  ctx: MindContext,
package/src/mind/types.ts CHANGED
@@ -279,6 +279,9 @@ export interface MindContext extends GraphSearchHost {
279
279
  * Null outside respond(); during respondTurn() the conversation's
280
280
  * persistent map is swapped in. */
281
281
  climbMemo: Map<string, Map<string, AttentionRead>> | null;
282
+ /** Stable identity for session-lifetime, write-invalidated structural
283
+ * caches. Query-level climb results remain on climbMemo. */
284
+ _structMemoKey: object;
282
285
  /** Memo of {@link recognise} — content-keyed (latin1) so recognised
283
286
  * forms carry forward across conversation turns. Bypassed while a
284
287
  * trace is attached. Null outside respond(). */
@@ -295,6 +298,13 @@ export interface MindContext extends GraphSearchHost {
295
298
  * O(suffix) instead of O(context). Mind-lifetime (WeakMap keys are
296
299
  * the Sema objects the pyramid keeps alive). */
297
300
  _resolvedSubtrees: WeakMap<Sema, { id: number; len: number }> | null;
301
+ /** Completed assistant-turn byte spans in the current cumulative query.
302
+ * Empty for ordinary respond(); response-scoped structural context for
303
+ * mechanisms that must not re-derive already-produced replies. */
304
+ answeredSpans: ReadonlyArray<readonly [number, number]>;
305
+ /** Start offset of the user turn currently being answered. Zero for an
306
+ * ordinary respond() and for the first turn of a conversation. */
307
+ currentTurnStart: number;
298
308
  _edgeGuide: Vec | null;
299
309
  _edgeChoice: Map<number, number>;
300
310
  _prevSeen: Set<number> | null;
@@ -14,20 +14,25 @@
14
14
  // entry point to it — the halo system is real and works, it is simply
15
15
  // never asked about a node that was never minted.
16
16
  //
17
- // Fix (units.ts): a derived, corpus-statistics-only notion of a "natural
18
- // unit" a run of adjacent chunks whose pairing recurs at least as often
19
- // as either chunk alone (the same principle behind BPE/content-defined
20
- // chunking, computed from this store's own reuse/containment counts, no
21
- // injected modality-specific segmenter). Interned at deposit time,
22
- // pairwise halo-poured as each other's company; read at query time via the
23
- // same derived merge (existingUnits) plus a halo-corroborated substitution
24
- // fallback in recognise().
17
+ // Fix: compose the distributional meaning of an arbitrary byte span from
18
+ // existing canonical-window containment and episode halos. No lexical unit
19
+ // index is introduced: each stored W-window ascends to the learned episodes
20
+ // containing it, their company halos are VSA-bundled, and the bridge admits
21
+ // the substitution only above the existing significanceBar plus its exact
22
+ // alignment/corroboration gates.
25
23
 
26
24
  import { test } from "node:test";
27
25
  import assert from "node:assert/strict";
28
- import { Mind } from "../dist/src/index.js";
26
+ import {
27
+ conceptThreshold,
28
+ cosine,
29
+ Mind,
30
+ significanceBar,
31
+ } from "../dist/src/index.js";
29
32
  import { SQliteStore } from "../dist/src/store-sqlite.js";
30
- import { resolve } from "../dist/src/mind/primitives.js";
33
+ import { substitutionBridge } from "../dist/src/mind/bridge.js";
34
+ import { spanSynonymStrength } from "../dist/src/mind/match.js";
35
+ import { perceive, resolve } from "../dist/src/mind/primitives.js";
31
36
 
32
37
  const enc = (s) => new TextEncoder().encode(s);
33
38
  const dec = (b) => new TextDecoder().decode(b).replace(/\0+$/, "");
@@ -55,18 +60,17 @@ const TRAIN = [
55
60
  ["What is the biggest island on Earth?", "The biggest island is Greenland."],
56
61
  ];
57
62
 
58
- test("baseline: 'biggest'/'largest' never resolve as independent nodes without natural units", async () => {
63
+ test("bare synonym words remain unaddressable without a lexical unit index", async () => {
59
64
  const m = new Mind({ seed: 7, store: new SQliteStore({ path: ":memory:" }) });
60
65
  await m.ingest(TRAIN);
61
- // This assertion documents the ROOT CAUSE (still true even after the
62
- // fix units.ts does not change what resolve() itself returns for a
63
- // bare word; it changes what recognise() can bridge to via halos).
66
+ // The capability composes meaning at read time; it deliberately does not
67
+ // mint or index modality-specific word nodes.
64
68
  assert.equal(resolve(m, enc("biggest")), null);
65
69
  assert.equal(resolve(m, enc("largest")), null);
66
70
  await m.store.close();
67
71
  });
68
72
 
69
- test("irrefutable failure: a trained fact is unreachable through an untrained near-synonym", async () => {
73
+ test("a trained fact is reachable through an untrained near-synonym", async () => {
70
74
  const m = new Mind({ seed: 7, store: new SQliteStore({ path: ":memory:" }) });
71
75
  await m.ingest(TRAIN);
72
76
 
@@ -173,3 +177,40 @@ test(
173
177
  );
174
178
  },
175
179
  );
180
+
181
+ test("VSA company grounds a differently-spelled synonym without a lexical unit index", async () => {
182
+ const m = new Mind({ seed: 7, store: new SQliteStore({ path: ":memory:" }) });
183
+ await m.ingest([
184
+ ["A physician treats illness.", "A healer treats illness."],
185
+ ["A doctor treats illness.", "A healer treats illness."],
186
+ ["The physician named Alice works today.", "Alice is on duty."],
187
+ ["Which physician is on duty?", "Alice is on duty."],
188
+ ]);
189
+
190
+ const doctor = enc(" doctor");
191
+ const physician = enc(" physician");
192
+ const geometric = cosine(
193
+ perceive(m, doctor).v,
194
+ perceive(m, physician).v,
195
+ );
196
+ const distributional = spanSynonymStrength(m, doctor, physician);
197
+ assert.ok(
198
+ geometric < conceptThreshold(m.store.D),
199
+ "the fixture must not pass through lexical/geometric similarity",
200
+ );
201
+ assert.ok(
202
+ distributional >= significanceBar(m.store.D),
203
+ "shared episode company must provide significant VSA synonym evidence",
204
+ );
205
+
206
+ const trained = resolve(m, enc("Which physician is on duty?"));
207
+ assert.notEqual(trained, null);
208
+ const hit = await substitutionBridge(
209
+ m,
210
+ enc("Which doctor is on duty?"),
211
+ async () => [trained],
212
+ );
213
+ assert.equal(hit?.id, trained);
214
+ assert.ok(hit?.subs.length > 0);
215
+ await m.store.close();
216
+ });
@@ -1 +0,0 @@
1
- export {};
@@ -1,39 +0,0 @@
1
- // demo.ts — one short session that drives the WHOLE pipeline from one memory.
2
- //
3
- // We give Sema a handful of plain notes, then ask things that no single note
4
- // answers. The headline query is the third one: from three worked examples Sema
5
- // learns the shape of "X was painted by Y", lifts the painter out of a sentence
6
- // it has NEVER seen, and then — in the same pass — reasons forward to a separate
7
- // fact about that painter. The reply contains no word from the question. That is
8
- // retrieval, generalization, and reasoning composing as a single act, with every
9
- // step traceable back to the notes behind it.
10
- import { Mind } from "../src/index.js";
11
- import { SQliteStore } from "../src/store-sqlite.js";
12
- async function main() {
13
- const mind = new Mind({ store: new SQliteStore({ path: ":memory:" }) });
14
- const ask = async (q) => (await mind.respondText(q)).trim();
15
- // ── Jot down what we know. Each line is just (context → what follows). ──
16
- await mind.ingest([
17
- // One relation, shown three times — a pattern taught purely by example:
18
- ["The Mona Lisa was painted by Leonardo da Vinci.", "Leonardo da Vinci"],
19
- ["The Starry Night was painted by Vincent van Gogh.", "Vincent van Gogh"],
20
- [
21
- "The Night Watch was painted by Rembrandt van Rijn.",
22
- "Rembrandt van Rijn",
23
- ],
24
- // One stray fact, keyed on a name none of the examples mention:
25
- ["Pablo Picasso", "Pablo Picasso co-founded the Cubist movement"],
26
- ]);
27
- // 1) GENERALIZE — apply the learned pattern to an unseen sentence and read out
28
- // the painter. "Pablo Picasso" was never given as an answer; Sema locates it
29
- // by analogy to the three examples.
30
- console.log(await ask("The Weeping Woman was painted by Pablo Picasso."));
31
- // → "Pablo Picasso co-founded the Cubist movement"
32
- // …and, having found the painter, it KEEPS GOING: the name bridges into the
33
- // one fact it holds about him. The answer appears in no word of the question.
34
- // 2) COMPUTE — exact arithmetic, grounded right where the notes go silent.
35
- console.log(await ask("a museum charges 12*4 for a family ticket"));
36
- // → "48"
37
- await mind.store.close();
38
- }
39
- main();
@@ -1,87 +0,0 @@
1
- export interface Episode {
2
- context: string;
3
- continuation: string;
4
- }
5
- export type TrainingItem = string | Episode;
6
- /** Dedup + trim a concept's items: drop empty/degenerate pairs and exact
7
- * repeats so a concept never deposits the same form twice. */
8
- export declare function refineItems(items: TrainingItem[]): TrainingItem[];
9
- /** One normalized SmolSent row. */
10
- export interface SmolSentRow {
11
- src: string;
12
- trg: string;
13
- sl: string;
14
- tl: string;
15
- }
16
- /** Normalize a raw datasets-server row into a SmolSentRow, or null when it lacks
17
- * both sides or a side is implausibly large (a dump, not a sentence). */
18
- export declare function toSmolSentRow(row: unknown): SmolSentRow | null;
19
- /** Translate ONE SmolSent pair into SEMA facts: the two sentences are one
20
- * meaning in two languages, so bind them BOTH ways. refineItems drops the
21
- * degenerate case where src === trg. */
22
- export declare function smolSentRowToItems(row: SmolSentRow): TrainingItem[];
23
- /** One normalized Aya row. */
24
- export interface AyaRow {
25
- inputs: string;
26
- targets: string;
27
- language: string;
28
- }
29
- /** Normalize a raw datasets-server row object into an AyaRow, or null when it
30
- * lacks a usable prompt/answer or a field is implausibly large (a dump, not a
31
- * cognitive example). Trims surrounding whitespace; keeps inner text verbatim
32
- * (human prose, possibly multi-paragraph). */
33
- export declare function toAyaRow(row: unknown): AyaRow | null;
34
- /** Translate ONE Aya row into SEMA training items. A row is a single human
35
- * (question → answer) exchange — exactly one FACT, the (inputs → targets) edge.
36
- * No standalone-answer experience and no one-exchange "cumulative" walk: a lone
37
- * Q→A is not multi-turn, and both would only replicate the same edge. */
38
- export declare function ayaRowToItems(row: AyaRow): TrainingItem[];
39
- /** A single oasst2 message node (the fields we use; the tree nests via replies). */
40
- interface OasstNode {
41
- role?: string;
42
- text?: string;
43
- rank?: number | null;
44
- deleted?: boolean;
45
- replies?: OasstNode[];
46
- }
47
- /** One conversational turn extracted from a tree. */
48
- export interface OasstTurn {
49
- role: string;
50
- text: string;
51
- }
52
- /** Collapse a conversation tree to ONE linear path: at each node, descend into
53
- * its best-ranked, non-deleted reply (rank 0 preferred; unranked sorts last).
54
- * Returns the ordered turns (already strictly alternating in this corpus). */
55
- export declare function bestOasstPath(root: OasstNode): OasstTurn[];
56
- /** Translate ONE multi-turn oasst2 conversation into SEMA training items.
57
- *
58
- * This is the ONE stage where cumulative continuous context is truly necessary:
59
- * the data is a real multi-turn dialogue, and what must be learned is how each
60
- * turn follows from the WHOLE conversation so far — not from the previous turn
61
- * alone. The conversation is emitted ONLY as the accumulated walk; standalone
62
- * turn experiences and local adjacent-pair facts are NOT emitted (they are
63
- * subsumed by it and would merely replicate the content).
64
- *
65
- * The walk is byte-for-byte the pattern proven in test/13-conversation.test.mjs
66
- * ("teachConversation"): each turn is the continuation of all prior turns joined
67
- * by "\n", with BARE turn text — NO "User:/Assistant:" labels. Roles already
68
- * alternate by position in an oasst2 best-path (the root is a prompter), so a
69
- * label adds nothing the position does not, while a clean continuation matches
70
- * the test's recall (predictNext queries bare prior turns) and lets a turn share
71
- * its gist with the same text elsewhere (e.g. an Aya question stored bare).
72
- *
73
- * Returns [] for a conversation below the multi-turn threshold, so callers can
74
- * simply skip empties. */
75
- export declare function oasstConversationToItems(turns: OasstTurn[]): TrainingItem[];
76
- /** One normalized General-Knowledge row. */
77
- export interface GenKnowRow {
78
- question: string;
79
- answer: string;
80
- }
81
- /** Normalize a raw datasets-server row into a GenKnowRow, or null when it lacks
82
- * a usable question/answer or a side is implausibly large (corruption). */
83
- export declare function toGenKnowRow(row: unknown): GenKnowRow | null;
84
- /** Translate ONE General-Knowledge row into SEMA items: exactly one
85
- * (question → answer) FACT. refineItems drops a degenerate question === answer. */
86
- export declare function genKnowRowToItems(row: GenKnowRow): TrainingItem[];
87
- export {};