@seanhogg/builderforce-memory-engine 2026.10.1 → 2026.10.3

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 (149) hide show
  1. package/dist/evermind/adapt.d.ts +7 -0
  2. package/dist/evermind/adapt.d.ts.map +1 -1
  3. package/dist/evermind/adapt.js +1 -1
  4. package/dist/evermind/adapt.js.map +1 -1
  5. package/dist/evermind/delta_wire.d.ts +16 -1
  6. package/dist/evermind/delta_wire.d.ts.map +1 -1
  7. package/dist/evermind/delta_wire.js +22 -2
  8. package/dist/evermind/delta_wire.js.map +1 -1
  9. package/dist/evermind/index.d.ts +2 -2
  10. package/dist/evermind/index.d.ts.map +1 -1
  11. package/dist/evermind/index.js +1 -1
  12. package/dist/evermind/index.js.map +1 -1
  13. package/dist/evermind/merge.d.ts +5 -2
  14. package/dist/evermind/merge.d.ts.map +1 -1
  15. package/dist/evermind/merge.js +5 -2
  16. package/dist/evermind/merge.js.map +1 -1
  17. package/dist/evermind/ml_head.d.ts +28 -0
  18. package/dist/evermind/ml_head.d.ts.map +1 -0
  19. package/dist/evermind/ml_head.js +47 -0
  20. package/dist/evermind/ml_head.js.map +1 -0
  21. package/dist/evermind/package.d.ts +2 -2
  22. package/dist/evermind/package.d.ts.map +1 -1
  23. package/dist/evermind/package.js +1 -1
  24. package/dist/evermind/package.js.map +1 -1
  25. package/dist/experience/index.d.ts +2 -2
  26. package/dist/experience/index.d.ts.map +1 -1
  27. package/dist/experience/index.js.map +1 -1
  28. package/dist/experience/store.d.ts +19 -1
  29. package/dist/experience/store.d.ts.map +1 -1
  30. package/dist/experience/store.js +14 -2
  31. package/dist/experience/store.js.map +1 -1
  32. package/dist/experience/types.d.ts +18 -0
  33. package/dist/experience/types.d.ts.map +1 -1
  34. package/dist/experience/types.js.map +1 -1
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/kernels/weight_update.d.ts.map +1 -1
  40. package/dist/kernels/weight_update.js +12 -0
  41. package/dist/kernels/weight_update.js.map +1 -1
  42. package/dist/limbic/limbic_model.d.ts.map +1 -1
  43. package/dist/limbic/limbic_model.js +1 -3
  44. package/dist/limbic/limbic_model.js.map +1 -1
  45. package/dist/ml/classical/anomaly_composite.d.ts +32 -0
  46. package/dist/ml/classical/anomaly_composite.d.ts.map +1 -0
  47. package/dist/ml/classical/anomaly_composite.js +29 -0
  48. package/dist/ml/classical/anomaly_composite.js.map +1 -0
  49. package/dist/ml/classical/ewma.d.ts +7 -1
  50. package/dist/ml/classical/ewma.d.ts.map +1 -1
  51. package/dist/ml/classical/ewma.js +6 -4
  52. package/dist/ml/classical/ewma.js.map +1 -1
  53. package/dist/ml/classical/gbm.d.ts.map +1 -1
  54. package/dist/ml/classical/gbm.js +2 -1
  55. package/dist/ml/classical/gbm.js.map +1 -1
  56. package/dist/ml/classical/index.d.ts +6 -2
  57. package/dist/ml/classical/index.d.ts.map +1 -1
  58. package/dist/ml/classical/index.js +5 -1
  59. package/dist/ml/classical/index.js.map +1 -1
  60. package/dist/ml/classical/kmeans.d.ts.map +1 -1
  61. package/dist/ml/classical/kmeans.js +23 -4
  62. package/dist/ml/classical/kmeans.js.map +1 -1
  63. package/dist/ml/classical/knn.d.ts +15 -5
  64. package/dist/ml/classical/knn.d.ts.map +1 -1
  65. package/dist/ml/classical/knn.js +28 -7
  66. package/dist/ml/classical/knn.js.map +1 -1
  67. package/dist/ml/classical/logistic.d.ts +1 -9
  68. package/dist/ml/classical/logistic.d.ts.map +1 -1
  69. package/dist/ml/classical/logistic.js +17 -9
  70. package/dist/ml/classical/logistic.js.map +1 -1
  71. package/dist/ml/classical/naive_bayes.d.ts +5 -1
  72. package/dist/ml/classical/naive_bayes.d.ts.map +1 -1
  73. package/dist/ml/classical/naive_bayes.js +8 -3
  74. package/dist/ml/classical/naive_bayes.js.map +1 -1
  75. package/dist/ml/classical/robust_z.d.ts +15 -1
  76. package/dist/ml/classical/robust_z.d.ts.map +1 -1
  77. package/dist/ml/classical/robust_z.js +6 -1
  78. package/dist/ml/classical/robust_z.js.map +1 -1
  79. package/dist/ml/eval_loss.d.ts +15 -0
  80. package/dist/ml/eval_loss.d.ts.map +1 -0
  81. package/dist/ml/eval_loss.js +20 -0
  82. package/dist/ml/eval_loss.js.map +1 -0
  83. package/dist/ml/federate.d.ts +11 -25
  84. package/dist/ml/federate.d.ts.map +1 -1
  85. package/dist/ml/federate.js +15 -38
  86. package/dist/ml/federate.js.map +1 -1
  87. package/dist/ml/head_trainer.d.ts +16 -2
  88. package/dist/ml/head_trainer.d.ts.map +1 -1
  89. package/dist/ml/head_trainer.js +64 -27
  90. package/dist/ml/head_trainer.js.map +1 -1
  91. package/dist/ml/run.d.ts +11 -2
  92. package/dist/ml/run.d.ts.map +1 -1
  93. package/dist/ml/run.js +56 -17
  94. package/dist/ml/run.js.map +1 -1
  95. package/dist/ml/tasks/experience.d.ts +95 -13
  96. package/dist/ml/tasks/experience.d.ts.map +1 -1
  97. package/dist/ml/tasks/experience.js +172 -20
  98. package/dist/ml/tasks/experience.js.map +1 -1
  99. package/dist/ml/tasks/run_anomaly.d.ts +37 -19
  100. package/dist/ml/tasks/run_anomaly.d.ts.map +1 -1
  101. package/dist/ml/tasks/run_anomaly.js +50 -31
  102. package/dist/ml/tasks/run_anomaly.js.map +1 -1
  103. package/dist/ml/train.d.ts +8 -7
  104. package/dist/ml/train.d.ts.map +1 -1
  105. package/dist/ml/train.js +21 -30
  106. package/dist/ml/train.js.map +1 -1
  107. package/dist/ml/types.d.ts +6 -3
  108. package/dist/ml/types.d.ts.map +1 -1
  109. package/dist/ml/types.js +3 -2
  110. package/dist/ml/types.js.map +1 -1
  111. package/dist/optim/adamw.d.ts +11 -5
  112. package/dist/optim/adamw.d.ts.map +1 -1
  113. package/dist/optim/adamw.js +19 -4
  114. package/dist/optim/adamw.js.map +1 -1
  115. package/package.json +1 -1
  116. package/src/evermind/adapt.ts +8 -2
  117. package/src/evermind/delta_wire.ts +173 -148
  118. package/src/evermind/index.ts +36 -35
  119. package/src/evermind/merge.ts +10 -4
  120. package/src/evermind/ml_head.ts +63 -0
  121. package/src/evermind/package.ts +488 -488
  122. package/src/experience/index.ts +2 -1
  123. package/src/experience/store.ts +35 -3
  124. package/src/experience/types.ts +19 -0
  125. package/src/index.ts +2 -0
  126. package/src/kernels/weight_update.ts +12 -0
  127. package/src/limbic/limbic_model.ts +1 -4
  128. package/src/limbic/limbic_trainer.ts +91 -91
  129. package/src/ml/classical/anomaly_composite.ts +46 -0
  130. package/src/ml/classical/ewma.ts +8 -2
  131. package/src/ml/classical/gbm.ts +144 -143
  132. package/src/ml/classical/index.ts +8 -2
  133. package/src/ml/classical/kmeans.ts +22 -4
  134. package/src/ml/classical/knn.ts +31 -8
  135. package/src/ml/classical/logistic.ts +9 -9
  136. package/src/ml/classical/math.ts +93 -93
  137. package/src/ml/classical/naive_bayes.ts +10 -3
  138. package/src/ml/classical/robust_z.ts +21 -2
  139. package/src/ml/eval_loss.ts +27 -0
  140. package/src/ml/federate.ts +22 -52
  141. package/src/ml/head_trainer.ts +66 -48
  142. package/src/ml/registry.ts +44 -44
  143. package/src/ml/run.ts +57 -13
  144. package/src/ml/tasks/experience.ts +222 -23
  145. package/src/ml/tasks/run_anomaly.ts +62 -37
  146. package/src/ml/train.ts +34 -31
  147. package/src/ml/types.ts +135 -132
  148. package/src/optim/adamw.ts +21 -5
  149. package/src/training/cpu_ops.ts +141 -141
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Mean loss of `predictor` on `samples` for a task of `kind` — classify: weighted
3
+ * cross-entropy of the true class; regress: weighted ½·squared error. Null for
4
+ * kinds without a supervised loss, or an empty (or zero-weight) set.
5
+ */
6
+ export function mlEvalLoss(kind, predictor, samples) {
7
+ if (samples.length === 0 || (kind !== "classify" && kind !== "regress"))
8
+ return null;
9
+ let sum = 0;
10
+ let wSum = 0;
11
+ for (const s of samples) {
12
+ const w = s.weight ?? 1;
13
+ const p = predictor.predict(s.x);
14
+ const loss = kind === "classify" ? -Math.log(Math.max(p.scores[s.y] ?? 0, 1e-12)) : 0.5 * (p.scores[0] - s.y) ** 2;
15
+ sum += w * loss;
16
+ wSum += w;
17
+ }
18
+ return wSum > 0 ? sum / wSum : null;
19
+ }
20
+ //# sourceMappingURL=eval_loss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval_loss.js","sourceRoot":"","sources":["../../src/ml/eval_loss.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAgB,EAAE,SAAsB,EAAE,OAA4B;IAC/F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACrF,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpH,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAChB,IAAI,IAAI,CAAC,CAAC;IACZ,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC"}
@@ -8,35 +8,16 @@
8
8
  * `target: "ml:<task>"`, and the writer folds N of them with the existing FedAvg
9
9
  * (`mergeCheckpointDiffsGated` → `mergeCheckpointDiffs`), refusing a merge whose
10
10
  * held-out loss regresses. No second wire, no second merge.
11
+ *
12
+ * The head's manifest entry and checkpoint format live with the artifact
13
+ * (`evermind/ml_head.ts`); this module only imports evermind/, never the reverse.
11
14
  */
12
15
  import { type DeltaLearnPayload } from "../evermind/delta_wire.js";
13
16
  import { type GatedMergeResult, type MergeGateOptions } from "../evermind/merge.js";
17
+ import { type EvermindMlHead } from "../evermind/ml_head.js";
14
18
  import type { EvermindModelPackage } from "../evermind/package.js";
15
- /**
16
- * One trained ML-catalog head carried in a model's manifest (`mlHeads`): small, so
17
- * it rides in the manifest, and versioned, so it federates — a delta against it is
18
- * `target: "ml:<task>"`, `baseVersion: version` on the delta wire.
19
- */
20
- export interface EvermindMlHead {
21
- /** Catalog task id, e.g. `run.local-success`. */
22
- task: string;
23
- /** Engine key, e.g. `local:classical:logistic`. */
24
- engine: string;
25
- /** Integer head version — what a federated delta for it is diffed against. */
26
- version: number;
27
- /** What a loader needs to rebuild the predictor (e.g. `{ dim, classes }`). */
28
- shape: Record<string, number>;
29
- /** base64 of the CRC-trailed f32 checkpoint of the head's flat parameters. */
30
- params: string;
31
- /** Held-out loss of this version, when measured. */
32
- evalLoss?: number;
33
- }
34
- /** A head's flat parameters as a CRC-trailed f32 checkpoint. */
35
- export declare function headCheckpoint(params: ArrayLike<number>): ArrayBuffer;
36
- /** The flat parameters of a head checkpoint. Throws on a failed CRC. */
37
- export declare function headParams(checkpoint: ArrayBuffer): Float32Array;
38
- /** Why a manifest head entry is unusable, or null (the package's validate() calls this). */
39
- export declare function mlHeadUnusableReason(h: EvermindMlHead): string | null;
19
+ export { headCheckpoint, headParams, mlHeadUnusableReason } from "../evermind/ml_head.js";
20
+ export type { EvermindMlHead } from "../evermind/ml_head.js";
40
21
  /** A manifest entry for a head's current parameters. */
41
22
  export declare function mlHeadEntry(task: string, engine: string, version: number, params: ArrayLike<number>, shape?: Record<string, number>, evalLoss?: number): EvermindMlHead;
42
23
  /** The entry's flat parameters. */
@@ -65,6 +46,11 @@ export interface MlHeadMergeOutcome {
65
46
  * target, stale base or a malformed diff costs only itself), FedAvg the rest, and
66
47
  * keep the result only if `score` (held-out loss of a parameter vector, lower is
67
48
  * better) does not regress.
49
+ *
50
+ * Fails CLOSED: `requireEval` defaults to true here, so a round `score` cannot judge
51
+ * (null — e.g. `mlEvalLoss` for an anomaly/cluster head or an empty holdout — or a
52
+ * non-finite loss) is refused. A caller that federates an unscorable head on purpose
53
+ * passes `{ requireEval: false }` explicitly.
68
54
  */
69
55
  export declare function mergeMlHeadDeltas(base: EvermindMlHead, payloads: readonly DeltaLearnPayload[], score: (params: Float32Array) => number | null, opts?: MergeGateOptions): MlHeadMergeOutcome;
70
56
  //# sourceMappingURL=federate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"federate.d.ts","sourceRoot":"","sources":["../../src/ml/federate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAiF,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAClJ,OAAO,EAA6B,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC/G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAKnE;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,gEAAgE;AAChE,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,WAAW,CAIrE;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,UAAU,EAAE,WAAW,GAAG,YAAY,CAKhE;AAED,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAWrE;AAED,wDAAwD;AACxD,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,EACzB,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAClC,QAAQ,CAAC,EAAE,MAAM,GAChB,cAAc,CAShB;AAED,mCAAmC;AACnC,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,CAEhE;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEjG;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,oBAAoB,EAAE,KAAK,EAAE,cAAc,GAAG,oBAAoB,CAExG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAGrI;AAED,MAAM,WAAW,kBAAkB;IACjC,4FAA4F;IAC5F,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,gBAAgB,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,SAAS,iBAAiB,EAAE,EACtC,KAAK,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,MAAM,GAAG,IAAI,EAC9C,IAAI,GAAE,gBAAqB,GAC1B,kBAAkB,CA8BpB"}
1
+ {"version":3,"file":"federate.d.ts","sourceRoot":"","sources":["../../src/ml/federate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAML,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAA6B,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC/G,OAAO,EAA8B,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAInE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,wDAAwD;AACxD,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,EACzB,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAClC,QAAQ,CAAC,EAAE,MAAM,GAChB,cAAc,CAShB;AAED,mCAAmC;AACnC,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,CAEhE;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEjG;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,oBAAoB,EAAE,KAAK,EAAE,cAAc,GAAG,oBAAoB,CAExG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAGrI;AAED,MAAM,WAAW,kBAAkB;IACjC,4FAA4F;IAC5F,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,gBAAgB,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,SAAS,iBAAiB,EAAE,EACtC,KAAK,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,MAAM,GAAG,IAAI,EAC9C,IAAI,GAAE,gBAAqB,GAC1B,kBAAkB,CA+BpB"}
@@ -8,45 +8,16 @@
8
8
  * `target: "ml:<task>"`, and the writer folds N of them with the existing FedAvg
9
9
  * (`mergeCheckpointDiffsGated` → `mergeCheckpointDiffs`), refusing a merge whose
10
10
  * held-out loss regresses. No second wire, no second merge.
11
+ *
12
+ * The head's manifest entry and checkpoint format live with the artifact
13
+ * (`evermind/ml_head.ts`); this module only imports evermind/, never the reverse.
11
14
  */
12
- import { buildDeltaLearnPayload, decodeDeltaPayload, deltaUnusableReason, mlHeadTarget } from "../evermind/delta_wire.js";
15
+ import { buildDeltaLearnPayload, decodeDeltaPayload, deltaTargetMismatch, deltaUnusableReason, mlHeadTarget, } from "../evermind/delta_wire.js";
13
16
  import { mergeCheckpointDiffsGated } from "../evermind/merge.js";
17
+ import { headCheckpoint, headParams } from "../evermind/ml_head.js";
14
18
  import { base64ToBytes, bytesToBase64 } from "../utils/base64.js";
15
- import { appendCrcTrailer, verifyCrcTrailer } from "../utils/crc32.js";
16
19
  import { diffCheckpoints } from "../utils/delta.js";
17
- /** A head's flat parameters as a CRC-trailed f32 checkpoint. */
18
- export function headCheckpoint(params) {
19
- const body = new ArrayBuffer(params.length * 4);
20
- new Float32Array(body).set(Array.from(params));
21
- return appendCrcTrailer(body);
22
- }
23
- /** The flat parameters of a head checkpoint. Throws on a failed CRC. */
24
- export function headParams(checkpoint) {
25
- const crc = verifyCrcTrailer(checkpoint);
26
- if (!crc.ok)
27
- throw new Error("headParams: checkpoint failed its CRC check");
28
- if (crc.body.byteLength % 4 !== 0)
29
- throw new Error("headParams: checkpoint is not f32");
30
- return new Float32Array(crc.body);
31
- }
32
- /** Why a manifest head entry is unusable, or null (the package's validate() calls this). */
33
- export function mlHeadUnusableReason(h) {
34
- if (!h || typeof h.task !== "string" || typeof h.engine !== "string")
35
- return "task and engine are required";
36
- if (!Number.isInteger(h.version) || h.version < 0)
37
- return "version must be a non-negative integer";
38
- try {
39
- const crc = verifyCrcTrailer(base64ToBytes(h.params));
40
- if (!crc.hasTrailer || !crc.ok)
41
- return "params checkpoint failed its CRC check";
42
- if (crc.body.byteLength % 4 !== 0)
43
- return "params checkpoint is not f32";
44
- }
45
- catch {
46
- return "params is not base64";
47
- }
48
- return null;
49
- }
20
+ export { headCheckpoint, headParams, mlHeadUnusableReason } from "../evermind/ml_head.js";
50
21
  /** A manifest entry for a head's current parameters. */
51
22
  export function mlHeadEntry(task, engine, version, params, shape = {}, evalLoss) {
52
23
  return {
@@ -83,6 +54,11 @@ export function buildMlHeadDelta(base, trained, weight, label) {
83
54
  * target, stale base or a malformed diff costs only itself), FedAvg the rest, and
84
55
  * keep the result only if `score` (held-out loss of a parameter vector, lower is
85
56
  * better) does not regress.
57
+ *
58
+ * Fails CLOSED: `requireEval` defaults to true here, so a round `score` cannot judge
59
+ * (null — e.g. `mlEvalLoss` for an anomaly/cluster head or an empty holdout — or a
60
+ * non-finite loss) is refused. A caller that federates an unscorable head on purpose
61
+ * passes `{ requireEval: false }` explicitly.
86
62
  */
87
63
  export function mergeMlHeadDeltas(base, payloads, score, opts = {}) {
88
64
  const baseCp = base64ToBytes(base.params);
@@ -91,8 +67,9 @@ export function mergeMlHeadDeltas(base, payloads, score, opts = {}) {
91
67
  const weights = [];
92
68
  const rejected = [];
93
69
  payloads.forEach((p, index) => {
94
- if (p.target !== target)
95
- return void rejected.push({ index, reason: `target ${p.target ?? "(model)"} is not ${target}` });
70
+ const wrongTarget = deltaTargetMismatch(p.target, target);
71
+ if (wrongTarget)
72
+ return void rejected.push({ index, reason: wrongTarget });
96
73
  if (p.baseVersion !== base.version)
97
74
  return void rejected.push({ index, reason: `stale base version ${p.baseVersion} (head is ${base.version})` });
98
75
  let diff;
@@ -108,7 +85,7 @@ export function mergeMlHeadDeltas(base, payloads, score, opts = {}) {
108
85
  diffs.push(diff);
109
86
  weights.push(p.weight ?? 1);
110
87
  });
111
- const merge = mergeCheckpointDiffsGated(baseCp, diffs, weights, (cp) => score(headParams(cp)), opts);
88
+ const merge = mergeCheckpointDiffsGated(baseCp, diffs, weights, (cp) => score(headParams(cp)), { ...opts, requireEval: opts.requireEval ?? true });
112
89
  if (!merge.accepted)
113
90
  return { head: base, merge, rejected };
114
91
  const head = {
@@ -1 +1 @@
1
- {"version":3,"file":"federate.js","sourceRoot":"","sources":["../../src/ml/federate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"federate.js","sourceRoot":"","sources":["../../src/ml/federate.ts"],"names":[],"mappings":"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"}
@@ -5,8 +5,13 @@
5
5
  *
6
6
  * Full-batch gradient descent with AdamW. When a GPUDevice is supplied the
7
7
  * optimiser step runs on the GPU via the shared WEIGHT_UPDATE_WGSL kernel; with
8
- * no device it uses a numerically-equivalent CPU AdamW, so training works
9
- * everywhere (CI, Node without @webgpu/node, a laptop with no GPU).
8
+ * no device it runs the kernel's CPU mirror, `adamwUpdateInPlace` (`optim/adamw.ts`,
9
+ * NaN/Inf guard included), so training works everywhere (CI, Node without
10
+ * @webgpu/node, a laptop with no GPU). Neither path bounds the step (maxDelta 0).
11
+ *
12
+ * A non-finite gradient element is skipped by both paths — its moments and weight
13
+ * are left as they were, so the next finite step trains it again — and counted in
14
+ * {@link HeadTrainer.skippedNonFinite}, so a caller can see a run that diverged.
10
15
  *
11
16
  * The head owns its forward/backward and its loss (MSE for regression, BCE /
12
17
  * softmax cross-entropy for classification); this file owns only the loop:
@@ -50,10 +55,18 @@ export declare class HeadTrainer<S> {
50
55
  readonly device: GPUDevice | null;
51
56
  private _moments;
52
57
  private _step;
58
+ private _skippedNonFinite;
53
59
  private readonly _adamwPipeline;
54
60
  constructor(head: TrainableHead<S>, device?: GPUDevice | null,
55
61
  /** Name used in error messages (the registration that owns this trainer). */
56
62
  label?: string);
63
+ /**
64
+ * Parameter elements whose gradient was non-finite (NaN/±Inf) and whose update was
65
+ * therefore skipped, summed over every step this trainer has taken. 0 on a healthy run.
66
+ */
67
+ get skippedNonFinite(): number;
68
+ /** Whether any step had to skip a non-finite gradient element. */
69
+ get diverged(): boolean;
57
70
  /** Whether the optimiser step runs on the GPU. */
58
71
  get gpuTraining(): boolean;
59
72
  private _initMoments;
@@ -65,6 +78,7 @@ export declare class HeadTrainer<S> {
65
78
  train(samples: S[], opts?: HeadTrainOptions): Promise<number[]>;
66
79
  /** Mean loss over samples (no weight update). 0 for an empty set. */
67
80
  evaluate(samples: S[]): number;
81
+ /** AdamW on the CPU via the kernel's shared mirror (`adamwUpdateInPlace`), which counts its skips. */
68
82
  private _adamwStepCpu;
69
83
  /** AdamW on the GPU via the shared WEIGHT_UPDATE_WGSL kernel. Awaited per step. */
70
84
  private _adamwStepGpu;
@@ -1 +1 @@
1
- {"version":3,"file":"head_trainer.d.ts","sourceRoot":"","sources":["../../src/ml/head_trainer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAaH,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,oEAAoE;AACpE,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,+CAA+C;IAC/C,UAAU,IAAI,SAAS,EAAE,CAAC;IAC1B,+DAA+D;IAC/D,SAAS,IAAI,SAAS,EAAE,CAAC;IACzB,QAAQ,IAAI,IAAI,CAAC;IACjB,oFAAoF;IACpF,UAAU,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC;IAC9B,uCAAuC;IACvC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;mFAC+E;IAC/E,UAAU,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;CAChF;AAiCD,qBAAa,WAAW,CAAC,CAAC;IAUtB,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,KAAK;IAVxB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IAClC,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA4B;gBAGzD,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,EACtB,MAAM,GAAE,SAAS,GAAG,IAAW;IAC/B,6EAA6E;IAC5D,KAAK,GAAE,MAAsB;IAShD,kDAAkD;IAClD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,OAAO,CAAC,YAAY;IAQpB;;;;OAIG;IACG,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA8CzE,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,MAAM;IAO9B,OAAO,CAAC,aAAa;IAkBrB,mFAAmF;YACrE,aAAa;CA+B5B;AAcD,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,YAAY,CAQxE;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAQxF"}
1
+ {"version":3,"file":"head_trainer.d.ts","sourceRoot":"","sources":["../../src/ml/head_trainer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAcH,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,oEAAoE;AACpE,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,+CAA+C;IAC/C,UAAU,IAAI,SAAS,EAAE,CAAC;IAC1B,+DAA+D;IAC/D,SAAS,IAAI,SAAS,EAAE,CAAC;IACzB,QAAQ,IAAI,IAAI,CAAC;IACjB,oFAAoF;IACpF,UAAU,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC;IAC9B,uCAAuC;IACvC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;mFAC+E;IAC/E,UAAU,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;CAChF;AAuBD,qBAAa,WAAW,CAAC,CAAC;IAWtB,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,KAAK;IAXxB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IAClC,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA4B;gBAGzD,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,EACtB,MAAM,GAAE,SAAS,GAAG,IAAW;IAC/B,6EAA6E;IAC5D,KAAK,GAAE,MAAsB;IAShD;;;OAGG;IACH,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,kEAAkE;IAClE,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,kDAAkD;IAClD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,OAAO,CAAC,YAAY;IAQpB;;;;OAIG;IACG,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA8CzE,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,MAAM;IAO9B,sGAAsG;IACtG,OAAO,CAAC,aAAa;IAQrB,mFAAmF;YACrE,aAAa;CA6B5B;AAiCD,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,YAAY,CAQxE;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAQxF"}
@@ -5,8 +5,13 @@
5
5
  *
6
6
  * Full-batch gradient descent with AdamW. When a GPUDevice is supplied the
7
7
  * optimiser step runs on the GPU via the shared WEIGHT_UPDATE_WGSL kernel; with
8
- * no device it uses a numerically-equivalent CPU AdamW, so training works
9
- * everywhere (CI, Node without @webgpu/node, a laptop with no GPU).
8
+ * no device it runs the kernel's CPU mirror, `adamwUpdateInPlace` (`optim/adamw.ts`,
9
+ * NaN/Inf guard included), so training works everywhere (CI, Node without
10
+ * @webgpu/node, a laptop with no GPU). Neither path bounds the step (maxDelta 0).
11
+ *
12
+ * A non-finite gradient element is skipped by both paths — its moments and weight
13
+ * are left as they were, so the next finite step trains it again — and counted in
14
+ * {@link HeadTrainer.skippedNonFinite}, so a caller can see a run that diverged.
10
15
  *
11
16
  * The head owns its forward/backward and its loss (MSE for regression, BCE /
12
17
  * softmax cross-entropy for classification); this file owns only the loop:
@@ -14,10 +19,19 @@
14
19
  */
15
20
  import { createUniformBuffer, createStorageBuffer, createComputePipeline, createBindGroup, dispatchKernel, readBuffer, cdiv, } from "../utils/gpu_utils.js";
16
21
  import { WEIGHT_UPDATE_WGSL } from "../kernels/weight_update.js";
17
- function packAdamParams(numElements, lr, beta1, beta2, eps, weightDecay, beta1_t, beta2_t) {
18
- const buf = new ArrayBuffer(32);
22
+ import { adamwUpdateInPlace } from "../optim/adamw.js";
23
+ /** Byte size of WEIGHT_UPDATE_WGSL's `AdamParams` uniform: 1 u32 + 8 f32 + 3 f32 pad = 48. */
24
+ const ADAM_PARAMS_BYTES = 48;
25
+ /**
26
+ * Pack `AdamParams` exactly as WEIGHT_UPDATE_WGSL declares it:
27
+ * `num_elements: u32, lr, beta1, beta2, eps, weight_decay, beta1_t, beta2_t,
28
+ * max_delta, _pad0, _pad1, _pad2` (all f32 after the first) — 48 bytes.
29
+ */
30
+ function packAdamParams(numElements, hp) {
31
+ const buf = new ArrayBuffer(ADAM_PARAMS_BYTES);
19
32
  new Uint32Array(buf, 0, 1).set([numElements]);
20
- new Float32Array(buf, 4, 7).set([lr, beta1, beta2, eps, weightDecay, beta1_t, beta2_t]);
33
+ // Pads stay 0 (fresh ArrayBuffer).
34
+ new Float32Array(buf, 4, 8).set([hp.lr, hp.beta1, hp.beta2, hp.eps, hp.weightDecay, hp.beta1_t, hp.beta2_t, hp.maxDelta]);
21
35
  return buf;
22
36
  }
23
37
  export class HeadTrainer {
@@ -26,6 +40,7 @@ export class HeadTrainer {
26
40
  device;
27
41
  _moments = null;
28
42
  _step = 0;
43
+ _skippedNonFinite = 0;
29
44
  _adamwPipeline;
30
45
  constructor(head, device = null,
31
46
  /** Name used in error messages (the registration that owns this trainer). */
@@ -37,6 +52,17 @@ export class HeadTrainer {
37
52
  ? createComputePipeline(device, WEIGHT_UPDATE_WGSL, "adamw_update")
38
53
  : null;
39
54
  }
55
+ /**
56
+ * Parameter elements whose gradient was non-finite (NaN/±Inf) and whose update was
57
+ * therefore skipped, summed over every step this trainer has taken. 0 on a healthy run.
58
+ */
59
+ get skippedNonFinite() {
60
+ return this._skippedNonFinite;
61
+ }
62
+ /** Whether any step had to skip a non-finite gradient element. */
63
+ get diverged() {
64
+ return this._skippedNonFinite > 0;
65
+ }
40
66
  /** Whether the optimiser step runs on the GPU. */
41
67
  get gpuTraining() {
42
68
  return this.device != null && this._adamwPipeline != null;
@@ -75,7 +101,7 @@ export class HeadTrainer {
75
101
  this._step++;
76
102
  const beta1_t = Math.pow(beta1, this._step);
77
103
  const beta2_t = Math.pow(beta2, this._step);
78
- const hp = { learningRate, weightDecay, beta1, beta2, eps, beta1_t, beta2_t };
104
+ const hp = { lr: learningRate, weightDecay, beta1, beta2, eps, beta1_t, beta2_t, maxDelta: 0 };
79
105
  if (this.gpuTraining) {
80
106
  await this._adamwStepGpu(grads, hp);
81
107
  }
@@ -98,21 +124,12 @@ export class HeadTrainer {
98
124
  total += this.head.loss(s);
99
125
  return total / samples.length;
100
126
  }
127
+ /** AdamW on the CPU via the kernel's shared mirror (`adamwUpdateInPlace`), which counts its skips. */
101
128
  _adamwStepCpu(grads, hp) {
102
129
  const params = this.head.parameters();
103
- const { learningRate: lr, weightDecay: wd, beta1, beta2, eps, beta1_t, beta2_t } = hp;
104
130
  for (let pi = 0; pi < params.length; pi++) {
105
- const p = params[pi].data;
106
- const g = grads[pi].data;
107
131
  const mom = this._moments[pi];
108
- for (let i = 0; i < p.length; i++) {
109
- const gi = g[i];
110
- mom.m[i] = beta1 * mom.m[i] + (1 - beta1) * gi;
111
- mom.v[i] = beta2 * mom.v[i] + (1 - beta2) * gi * gi;
112
- const mHat = mom.m[i] / (1 - beta1_t);
113
- const vHat = mom.v[i] / (1 - beta2_t);
114
- p[i] = p[i] * (1 - lr * wd) - (lr * mHat) / (Math.sqrt(vHat) + eps);
115
- }
132
+ this._skippedNonFinite += adamwUpdateInPlace(params[pi].data, grads[pi].data, mom.m, mom.v, hp);
116
133
  }
117
134
  }
118
135
  /** AdamW on the GPU via the shared WEIGHT_UPDATE_WGSL kernel. Awaited per step. */
@@ -120,15 +137,16 @@ export class HeadTrainer {
120
137
  const device = this.device;
121
138
  const pipeline = this._adamwPipeline;
122
139
  const params = this.head.parameters();
123
- const { learningRate: lr, weightDecay: wd, beta1, beta2, eps, beta1_t, beta2_t } = hp;
124
140
  for (let pi = 0; pi < params.length; pi++) {
125
141
  const p = params[pi];
126
142
  const mom = this._moments[pi];
143
+ // The kernel skips these elements too; it cannot count, so count them here.
144
+ this._skippedNonFinite += countNonFinite(grads[pi].data);
127
145
  const paramBuf = createStorageBuffer(device, p.data, true);
128
146
  const gradBuf = createStorageBuffer(device, grads[pi].data, false);
129
147
  const mBuf = createStorageBuffer(device, mom.m, true);
130
148
  const vBuf = createStorageBuffer(device, mom.v, true);
131
- const uni = createUniformBuffer(device, packAdamParams(p.numel, lr, beta1, beta2, eps, wd, beta1_t, beta2_t));
149
+ const uni = createUniformBuffer(device, packAdamParams(p.numel, hp));
132
150
  const bg = createBindGroup(device, pipeline, [uni, paramBuf, gradBuf, mBuf, vBuf]);
133
151
  dispatchKernel(device, pipeline, bg, [cdiv(p.numel, 256), 1, 1]);
134
152
  p.data.set((await readBuffer(device, paramBuf, p.numel * 4)).subarray(0, p.numel));
@@ -142,20 +160,39 @@ export class HeadTrainer {
142
160
  }
143
161
  }
144
162
  }
145
- /** Clip grads to `maxNorm` in place; returns the PRE-clip L2 norm (the signal). */
163
+ /** Elements of `a` that are NaN or ±Inf. */
164
+ function countNonFinite(a) {
165
+ let n = 0;
166
+ for (let i = 0; i < a.length; i++)
167
+ if (!Number.isFinite(a[i]))
168
+ n++;
169
+ return n;
170
+ }
171
+ /**
172
+ * Clip grads to `maxNorm` in place; returns the PRE-clip L2 norm (the signal — NaN
173
+ * or Inf when any element is). The clip itself uses the norm of the FINITE elements:
174
+ * those are skipped by the optimiser anyway, and one NaN must not exempt the rest
175
+ * from clipping.
176
+ */
146
177
  function clipGradients(grads, maxNorm) {
147
178
  let normSq = 0;
148
- for (const g of grads)
149
- for (let i = 0; i < g.data.length; i++)
150
- normSq += g.data[i] * g.data[i];
151
- const norm = Math.sqrt(normSq);
152
- if (norm > maxNorm && norm > 0) {
153
- const scale = maxNorm / norm;
179
+ let finiteSq = 0;
180
+ for (const g of grads) {
181
+ for (let i = 0; i < g.data.length; i++) {
182
+ const sq = g.data[i] * g.data[i];
183
+ normSq += sq;
184
+ if (Number.isFinite(sq))
185
+ finiteSq += sq;
186
+ }
187
+ }
188
+ const finiteNorm = Math.sqrt(finiteSq);
189
+ if (finiteNorm > maxNorm && finiteNorm > 0) {
190
+ const scale = maxNorm / finiteNorm;
154
191
  for (const g of grads)
155
192
  for (let i = 0; i < g.data.length; i++)
156
193
  g.data[i] *= scale;
157
194
  }
158
- return norm;
195
+ return Math.sqrt(normSq);
159
196
  }
160
197
  /** Concatenate a head's parameters into one flat vector (the federation unit). */
161
198
  export function flattenParams(params) {
@@ -1 +1 @@
1
- {"version":3,"file":"head_trainer.js","sourceRoot":"","sources":["../../src/ml/head_trainer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"head_trainer.js","sourceRoot":"","sources":["../../src/ml/head_trainer.ts"],"names":[],"mappings":"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"}
package/dist/ml/run.d.ts CHANGED
@@ -87,8 +87,17 @@ export declare class MlEngineUnavailableError extends Error {
87
87
  readonly decision: MlDecision;
88
88
  constructor(taskId: string, decision: MlDecision);
89
89
  }
90
- /** The task's engines the mode allows, in the order the runner tries them. */
90
+ /**
91
+ * The task's engines the mode allows, in the order the runner tries them. Exhaustive:
92
+ * a mode string outside {@link InferenceMode} (a host passing a stale or mistyped
93
+ * setting) throws instead of being read as `specific`.
94
+ */
91
95
  export declare function candidateEngines(task: MlTask<any, any>, mode: InferenceMode, specific?: MlEngineRef | string): MlEngineRef[];
92
- /** Answer task `id` for `input` with the first engine the mode allows that can. */
96
+ /**
97
+ * Answer task `id` for `input` with the first engine the mode allows that can. An
98
+ * engine that throws (feature extraction or its own predict) is recorded as an
99
+ * `error` skip and the next allowed engine is tried — in Hybrid, the cloud. Throws
100
+ * {@link MlEngineUnavailableError}, carrying every engine's reason, only when none answers.
101
+ */
93
102
  export declare function runMlTask<O = unknown, I = unknown>(id: string, input: I, ctx: MlRunContext): Promise<MlResult<O>>;
94
103
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/ml/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/ml/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAa,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAE/H,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IAC7D,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CACnE;AAED,kCAAkC;AAClC,qBAAa,gBAAiB,YAAW,YAAY;IACnD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAkC;IACrD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAG5D,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,IAAI;CAGlE;AAED,wFAAwF;AACxF,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9F;AAED,2CAA2C;AAC3C,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,gBAAgB,GAAG,OAAO,CAAC;AAEtE,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,aAAa,CAAC;IACpB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,uDAAuD;IACvD,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtE;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI,CAAC;CACpC;AAED,gEAAgE;AAChE,qBAAa,aAAc,YAAW,cAAc;IAEtC,QAAQ,CAAC,QAAQ;IAD7B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;gBAClB,QAAQ,SAAM;IAEnC,MAAM,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI;IAKlC,IAAI,IAAI,SAAS,UAAU,EAAE;IAI7B,0FAA0F;IAC1F,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CAkBjI;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,aAAa,CAAC;IACpB,sDAAsD;IACtD,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC9B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,gGAAgG;IAChG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,MAAM,EAAE,CAAC,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,kDAAkD;AAClD,qBAAa,wBAAyB,SAAQ,KAAK;IAE/C,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,QAAQ,EAAE,UAAU;gBADpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,UAAU;CAShC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,WAAW,EAAE,CAkB5H;AAID;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAiEvH"}
package/dist/ml/run.js CHANGED
@@ -59,32 +59,51 @@ export class MlEngineUnavailableError extends Error {
59
59
  taskId;
60
60
  decision;
61
61
  constructor(taskId, decision) {
62
- super(`runMlTask(${taskId}): no engine could answer in '${decision.mode}' mode (${decision.skipped.map((s) => `${s.engine}: ${s.reason}`).join(", ") || "none allowed"})`);
62
+ super(`runMlTask(${taskId}): no engine could answer in '${decision.mode}' mode (${decision.skipped.map((s) => `${s.engine}: ${s.reason}${s.detail ? ` (${s.detail})` : ""}`).join(", ") || "none allowed"})`);
63
63
  this.taskId = taskId;
64
64
  this.decision = decision;
65
65
  this.name = "MlEngineUnavailableError";
66
66
  }
67
67
  }
68
- /** The task's engines the mode allows, in the order the runner tries them. */
68
+ /**
69
+ * The task's engines the mode allows, in the order the runner tries them. Exhaustive:
70
+ * a mode string outside {@link InferenceMode} (a host passing a stale or mistyped
71
+ * setting) throws instead of being read as `specific`.
72
+ */
69
73
  export function candidateEngines(task, mode, specific) {
70
- if (mode === "local-only")
71
- return task.engines.filter((e) => e.tier === "local");
72
- if (mode === "hybrid")
73
- return [...task.engines.filter((e) => e.tier === "local"), ...task.engines.filter((e) => e.tier === "cloud")];
74
- if (specific == null)
75
- throw new Error(`runMlTask(${task.id}): 'specific' mode needs ctx.engine`);
76
- const key = typeof specific === "string" ? specific : engineKey(specific);
77
- const match = task.engines.filter((e) => engineKey(e) === key);
78
- if (match.length === 0)
79
- throw new Error(`runMlTask(${task.id}): engine '${key}' is not one of this task's engines`);
80
- return match;
74
+ switch (mode) {
75
+ case "local-only":
76
+ return task.engines.filter((e) => e.tier === "local");
77
+ case "hybrid":
78
+ return [...task.engines.filter((e) => e.tier === "local"), ...task.engines.filter((e) => e.tier === "cloud")];
79
+ case "specific": {
80
+ if (specific == null)
81
+ throw new Error(`runMlTask(${task.id}): 'specific' mode needs ctx.engine`);
82
+ const key = typeof specific === "string" ? specific : engineKey(specific);
83
+ const match = task.engines.filter((e) => engineKey(e) === key);
84
+ if (match.length === 0)
85
+ throw new Error(`runMlTask(${task.id}): engine '${key}' is not one of this task's engines`);
86
+ return match;
87
+ }
88
+ default: {
89
+ const unknown = mode;
90
+ throw new Error(`runMlTask(${task.id}): unknown inference mode '${String(unknown)}'`);
91
+ }
92
+ }
81
93
  }
82
- /** Answer task `id` for `input` with the first engine the mode allows that can. */
94
+ const errorDetail = (error) => (error instanceof Error ? error.message : String(error));
95
+ /**
96
+ * Answer task `id` for `input` with the first engine the mode allows that can. An
97
+ * engine that throws (feature extraction or its own predict) is recorded as an
98
+ * `error` skip and the next allowed engine is tried — in Hybrid, the cloud. Throws
99
+ * {@link MlEngineUnavailableError}, carrying every engine's reason, only when none answers.
100
+ */
83
101
  export async function runMlTask(id, input, ctx) {
84
102
  const task = ctx.registry.require(id);
85
103
  const engines = candidateEngines(task, ctx.mode, ctx.engine);
86
104
  const skipped = [];
87
105
  let features = null;
106
+ let featureError = null;
88
107
  let deferred = null;
89
108
  const finish = (ref, p) => {
90
109
  ctx.decisions?.record({ taskId: id, mode: ctx.mode, engine: engineKey(ref), tier: ref.tier, confidence: p.confidence, skipped });
@@ -99,8 +118,28 @@ export async function runMlTask(id, input, ctx) {
99
118
  skipped.push({ engine: key, reason: "unavailable" });
100
119
  continue;
101
120
  }
102
- features ??= await extractFeatures(task.features, input, ctx.embedder);
103
- const p = predictor.predict(features);
121
+ // Extract once; a failure (e.g. no embedder) fails every local engine alike, so
122
+ // it is remembered rather than retried per engine.
123
+ if (!features && featureError == null) {
124
+ try {
125
+ features = await extractFeatures(task.features, input, ctx.embedder);
126
+ }
127
+ catch (error) {
128
+ featureError = error;
129
+ }
130
+ }
131
+ if (!features) {
132
+ skipped.push({ engine: key, reason: "error", detail: `features: ${errorDetail(featureError)}` });
133
+ continue;
134
+ }
135
+ let p;
136
+ try {
137
+ p = predictor.predict(features);
138
+ }
139
+ catch (error) {
140
+ skipped.push({ engine: key, reason: "error", detail: errorDetail(error) });
141
+ continue;
142
+ }
104
143
  const cloudLater = ctx.mode === "hybrid" && !!ctx.cloud && engines.slice(i + 1).some((e) => e.tier === "cloud");
105
144
  if (ctx.minConfidence != null && p.confidence < ctx.minConfidence && cloudLater) {
106
145
  skipped.push({ engine: key, reason: "low-confidence", detail: p.confidence.toFixed(3) });
@@ -117,7 +156,7 @@ export async function runMlTask(id, input, ctx) {
117
156
  return finish(ref, await ctx.cloud.run({ taskId: id, engine: ref, input }));
118
157
  }
119
158
  catch (error) {
120
- skipped.push({ engine: key, reason: "error", detail: error instanceof Error ? error.message : String(error) });
159
+ skipped.push({ engine: key, reason: "error", detail: errorDetail(error) });
121
160
  }
122
161
  }
123
162
  // The cloud could not answer after a low-confidence local one: the local answer stands.