@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.
- package/dist/evermind/adapt.d.ts +7 -0
- package/dist/evermind/adapt.d.ts.map +1 -1
- package/dist/evermind/adapt.js +1 -1
- package/dist/evermind/adapt.js.map +1 -1
- package/dist/evermind/delta_wire.d.ts +16 -1
- package/dist/evermind/delta_wire.d.ts.map +1 -1
- package/dist/evermind/delta_wire.js +22 -2
- package/dist/evermind/delta_wire.js.map +1 -1
- package/dist/evermind/index.d.ts +2 -2
- package/dist/evermind/index.d.ts.map +1 -1
- package/dist/evermind/index.js +1 -1
- package/dist/evermind/index.js.map +1 -1
- package/dist/evermind/merge.d.ts +5 -2
- package/dist/evermind/merge.d.ts.map +1 -1
- package/dist/evermind/merge.js +5 -2
- package/dist/evermind/merge.js.map +1 -1
- package/dist/evermind/ml_head.d.ts +28 -0
- package/dist/evermind/ml_head.d.ts.map +1 -0
- package/dist/evermind/ml_head.js +47 -0
- package/dist/evermind/ml_head.js.map +1 -0
- package/dist/evermind/package.d.ts +2 -2
- package/dist/evermind/package.d.ts.map +1 -1
- package/dist/evermind/package.js +1 -1
- package/dist/evermind/package.js.map +1 -1
- package/dist/experience/index.d.ts +2 -2
- package/dist/experience/index.d.ts.map +1 -1
- package/dist/experience/index.js.map +1 -1
- package/dist/experience/store.d.ts +19 -1
- package/dist/experience/store.d.ts.map +1 -1
- package/dist/experience/store.js +14 -2
- package/dist/experience/store.js.map +1 -1
- package/dist/experience/types.d.ts +18 -0
- package/dist/experience/types.d.ts.map +1 -1
- package/dist/experience/types.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kernels/weight_update.d.ts.map +1 -1
- package/dist/kernels/weight_update.js +12 -0
- package/dist/kernels/weight_update.js.map +1 -1
- package/dist/limbic/limbic_model.d.ts.map +1 -1
- package/dist/limbic/limbic_model.js +1 -3
- package/dist/limbic/limbic_model.js.map +1 -1
- package/dist/ml/classical/anomaly_composite.d.ts +32 -0
- package/dist/ml/classical/anomaly_composite.d.ts.map +1 -0
- package/dist/ml/classical/anomaly_composite.js +29 -0
- package/dist/ml/classical/anomaly_composite.js.map +1 -0
- package/dist/ml/classical/ewma.d.ts +7 -1
- package/dist/ml/classical/ewma.d.ts.map +1 -1
- package/dist/ml/classical/ewma.js +6 -4
- package/dist/ml/classical/ewma.js.map +1 -1
- package/dist/ml/classical/gbm.d.ts.map +1 -1
- package/dist/ml/classical/gbm.js +2 -1
- package/dist/ml/classical/gbm.js.map +1 -1
- package/dist/ml/classical/index.d.ts +6 -2
- package/dist/ml/classical/index.d.ts.map +1 -1
- package/dist/ml/classical/index.js +5 -1
- package/dist/ml/classical/index.js.map +1 -1
- package/dist/ml/classical/kmeans.d.ts.map +1 -1
- package/dist/ml/classical/kmeans.js +23 -4
- package/dist/ml/classical/kmeans.js.map +1 -1
- package/dist/ml/classical/knn.d.ts +15 -5
- package/dist/ml/classical/knn.d.ts.map +1 -1
- package/dist/ml/classical/knn.js +28 -7
- package/dist/ml/classical/knn.js.map +1 -1
- package/dist/ml/classical/logistic.d.ts +1 -9
- package/dist/ml/classical/logistic.d.ts.map +1 -1
- package/dist/ml/classical/logistic.js +17 -9
- package/dist/ml/classical/logistic.js.map +1 -1
- package/dist/ml/classical/naive_bayes.d.ts +5 -1
- package/dist/ml/classical/naive_bayes.d.ts.map +1 -1
- package/dist/ml/classical/naive_bayes.js +8 -3
- package/dist/ml/classical/naive_bayes.js.map +1 -1
- package/dist/ml/classical/robust_z.d.ts +15 -1
- package/dist/ml/classical/robust_z.d.ts.map +1 -1
- package/dist/ml/classical/robust_z.js +6 -1
- package/dist/ml/classical/robust_z.js.map +1 -1
- package/dist/ml/eval_loss.d.ts +15 -0
- package/dist/ml/eval_loss.d.ts.map +1 -0
- package/dist/ml/eval_loss.js +20 -0
- package/dist/ml/eval_loss.js.map +1 -0
- package/dist/ml/federate.d.ts +11 -25
- package/dist/ml/federate.d.ts.map +1 -1
- package/dist/ml/federate.js +15 -38
- package/dist/ml/federate.js.map +1 -1
- package/dist/ml/head_trainer.d.ts +16 -2
- package/dist/ml/head_trainer.d.ts.map +1 -1
- package/dist/ml/head_trainer.js +64 -27
- package/dist/ml/head_trainer.js.map +1 -1
- package/dist/ml/run.d.ts +11 -2
- package/dist/ml/run.d.ts.map +1 -1
- package/dist/ml/run.js +56 -17
- package/dist/ml/run.js.map +1 -1
- package/dist/ml/tasks/experience.d.ts +95 -13
- package/dist/ml/tasks/experience.d.ts.map +1 -1
- package/dist/ml/tasks/experience.js +172 -20
- package/dist/ml/tasks/experience.js.map +1 -1
- package/dist/ml/tasks/run_anomaly.d.ts +37 -19
- package/dist/ml/tasks/run_anomaly.d.ts.map +1 -1
- package/dist/ml/tasks/run_anomaly.js +50 -31
- package/dist/ml/tasks/run_anomaly.js.map +1 -1
- package/dist/ml/train.d.ts +8 -7
- package/dist/ml/train.d.ts.map +1 -1
- package/dist/ml/train.js +21 -30
- package/dist/ml/train.js.map +1 -1
- package/dist/ml/types.d.ts +6 -3
- package/dist/ml/types.d.ts.map +1 -1
- package/dist/ml/types.js +3 -2
- package/dist/ml/types.js.map +1 -1
- package/dist/optim/adamw.d.ts +11 -5
- package/dist/optim/adamw.d.ts.map +1 -1
- package/dist/optim/adamw.js +19 -4
- package/dist/optim/adamw.js.map +1 -1
- package/package.json +1 -1
- package/src/evermind/adapt.ts +8 -2
- package/src/evermind/delta_wire.ts +173 -148
- package/src/evermind/index.ts +36 -35
- package/src/evermind/merge.ts +10 -4
- package/src/evermind/ml_head.ts +63 -0
- package/src/evermind/package.ts +488 -488
- package/src/experience/index.ts +2 -1
- package/src/experience/store.ts +35 -3
- package/src/experience/types.ts +19 -0
- package/src/index.ts +2 -0
- package/src/kernels/weight_update.ts +12 -0
- package/src/limbic/limbic_model.ts +1 -4
- package/src/limbic/limbic_trainer.ts +91 -91
- package/src/ml/classical/anomaly_composite.ts +46 -0
- package/src/ml/classical/ewma.ts +8 -2
- package/src/ml/classical/gbm.ts +144 -143
- package/src/ml/classical/index.ts +8 -2
- package/src/ml/classical/kmeans.ts +22 -4
- package/src/ml/classical/knn.ts +31 -8
- package/src/ml/classical/logistic.ts +9 -9
- package/src/ml/classical/math.ts +93 -93
- package/src/ml/classical/naive_bayes.ts +10 -3
- package/src/ml/classical/robust_z.ts +21 -2
- package/src/ml/eval_loss.ts +27 -0
- package/src/ml/federate.ts +22 -52
- package/src/ml/head_trainer.ts +66 -48
- package/src/ml/registry.ts +44 -44
- package/src/ml/run.ts +57 -13
- package/src/ml/tasks/experience.ts +222 -23
- package/src/ml/tasks/run_anomaly.ts +62 -37
- package/src/ml/train.ts +34 -31
- package/src/ml/types.ts +135 -132
- package/src/optim/adamw.ts +21 -5
- 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"}
|
package/dist/ml/federate.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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"}
|
package/dist/ml/federate.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
95
|
-
|
|
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 = {
|
package/dist/ml/federate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"federate.js","sourceRoot":"","sources":["../../src/ml/federate.ts"],"names":[],"mappings":"AAAA
|
|
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
|
|
9
|
-
* everywhere (CI, Node without
|
|
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
|
|
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"}
|
package/dist/ml/head_trainer.js
CHANGED
|
@@ -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
|
|
9
|
-
* everywhere (CI, Node without
|
|
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
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
/**
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
|
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":"AAAA
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
package/dist/ml/run.d.ts.map
CHANGED
|
@@ -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":"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"}
|
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
|
-
/**
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
|
|
103
|
-
|
|
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:
|
|
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.
|