pi-mega-compact 0.20.43 → 0.20.45
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/assets/vector-cortex/encoder-v1/manifest.json +1 -1
- package/assets/vector-cortex/encoder-v1/model-card.json +1 -1
- package/assets/vector-cortex/encoder-v1/model.onnx +0 -0
- package/assets/vector-cortex/encoder-v1/tokenizer.json +1 -1
- package/dist/config/vector-cortex-enc0b.js +34 -0
- package/dist/config/vector-cortex-enc0c.js +35 -0
- package/dist/config/vector-cortex.js +2 -1
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +2 -0
- package/dist/src/config/vector-cortex-enc0b.js +34 -0
- package/dist/src/config/vector-cortex-enc0c.js +35 -0
- package/dist/src/config/vector-cortex.js +2 -1
- package/dist/src/config.js +1 -1
- package/dist/src/vector-cortex/encoder/emit.js +2 -0
- package/dist/src/vector-cortex/encoder/encoder-onnx-dispatch.js +58 -0
- package/dist/src/vector-cortex/encoder/heads-candidate.js +127 -0
- package/dist/src/vector-cortex/encoder/heads.js +4 -0
- package/dist/src/vector-cortex/encoder/onnx.js +147 -0
- package/dist/src/vector-cortex/encoder/runtime-wasm.js +17 -4
- package/dist/src/vector-cortex/encoder/runtime.js +17 -7
- package/dist/src/vector-cortex/encoder/types-vc2c.js +9 -0
- package/dist/src/vector-cortex/encoder/types.js +1 -1
- package/dist/vector-cortex/encoder/emit.js +2 -0
- package/dist/vector-cortex/encoder/encoder-onnx-dispatch.js +58 -0
- package/dist/vector-cortex/encoder/heads-candidate.js +127 -0
- package/dist/vector-cortex/encoder/heads.js +4 -0
- package/dist/vector-cortex/encoder/onnx.js +147 -0
- package/dist/vector-cortex/encoder/runtime-wasm.js +17 -4
- package/dist/vector-cortex/encoder/runtime.js +17 -7
- package/dist/vector-cortex/encoder/types-vc2c.js +9 -0
- package/dist/vector-cortex/encoder/types.js +1 -1
- package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +12 -0
- package/package.json +3 -2
- package/src/config/vector-cortex-enc0b.ts +36 -0
- package/src/config/vector-cortex-enc0c.ts +37 -0
- package/src/config/vector-cortex.ts +2 -2
- package/src/config.ts +2 -0
- package/src/vector-cortex/encoder/emit.ts +5 -1
- package/src/vector-cortex/encoder/encoder-onnx-dispatch.ts +76 -0
- package/src/vector-cortex/encoder/heads-candidate.ts +148 -0
- package/src/vector-cortex/encoder/heads.ts +14 -0
- package/src/vector-cortex/encoder/onnx.ts +198 -0
- package/src/vector-cortex/encoder/runtime-wasm.ts +20 -7
- package/src/vector-cortex/encoder/runtime.ts +27 -9
- package/src/vector-cortex/encoder/types-vc2c.ts +10 -0
- package/src/vector-cortex/encoder/types.ts +1 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/vector-cortex-enc0b.ts — ENC-0b real ONNX trunk fetch + gated inference flag.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from vector-cortex.ts so that file stays under the 300-line soft
|
|
5
|
+
* limit (soft-as-hard gate), exactly as vector-cortex-enc0a.ts and the
|
|
6
|
+
* VC8C/VC9A-D/ML5A-E/DEDUP_ATTR siblings were. vector-cortex.ts re-exports the
|
|
7
|
+
* flag below and root src/config.ts re-exports it, so no consumer import path
|
|
8
|
+
* changes.
|
|
9
|
+
*
|
|
10
|
+
* ENC-0b fetches the real bge-small-en-v1.5 int8 ONNX model from the Hugging
|
|
11
|
+
* Face Hub (build-time fetch into the assets directory, NOT a runtime network
|
|
12
|
+
* call — PREVENT-PI-004 safe), wires an ONNX InferenceSession via
|
|
13
|
+
* onnxruntime-web WASM, and runs gated inference through it. The gate is
|
|
14
|
+
* controlled by this flag: OFF = the LCG placeholder encoder serves
|
|
15
|
+
* byte-identical predecessor output and no ONNX session is constructed.
|
|
16
|
+
*
|
|
17
|
+
* The split is purely mechanical: ENC_0B_ENABLED is byte-identical in name,
|
|
18
|
+
* semantics, and default to the definition it replaces, and vector-cortex.ts
|
|
19
|
+
* re-exports it so every existing `from "./config/vector-cortex.js"` import
|
|
20
|
+
* keeps resolving unchanged.
|
|
21
|
+
*
|
|
22
|
+
* Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
|
|
23
|
+
*/
|
|
24
|
+
import { sprintFlag } from "./vector-cortex-flag.js";
|
|
25
|
+
/**
|
|
26
|
+
* ENC-0b — real ONNX trunk fetch + gated inference. Default ON.
|
|
27
|
+
* `MEGACOMPACT_ENC_0B=0` disables and is byte-identical to the predecessor
|
|
28
|
+
* (ENC-0a / LCG placeholder): no ONNX session is built, the real bge-small
|
|
29
|
+
* model is not loaded, and the encoder continues serving the LCG placeholder
|
|
30
|
+
* output exactly as before. This flag MUST also be a dashboard SETTINGS toggle
|
|
31
|
+
* (visible in config UI, never in EXCLUDED_SETTINGS), mirroring ENC_0A and
|
|
32
|
+
* VC4A..VC9D.
|
|
33
|
+
*/
|
|
34
|
+
export const ENC_0B_ENABLED = () => sprintFlag("MEGACOMPACT_ENC_0B");
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/vector-cortex-enc0c.ts — ENC-0c five-head supervision transfer flag.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from vector-cortex.ts so that file stays under the 300-line soft
|
|
5
|
+
* limit (soft-as-hard gate), exactly as vector-cortex-enc0a.ts / enc0b.ts and
|
|
6
|
+
* the VC8C/VC9A-D/ML5A-E/DEDUP_ATTR siblings were. vector-cortex.ts re-exports
|
|
7
|
+
* the flag below and root src/config.ts re-exports it, so no consumer import
|
|
8
|
+
* path changes.
|
|
9
|
+
*
|
|
10
|
+
* ENC-0c trains the five real heads onto the frozen ENC-0b bge-small trunk via
|
|
11
|
+
* supervision transfer, and stages a qualified candidate under
|
|
12
|
+
* ~/.pi/mega-compact-encoder/candidates/ (only when the developer trains it —
|
|
13
|
+
* the extension never stages one by itself). When the flag is ON and a
|
|
14
|
+
* qualified candidate exists, `loadHeadCandidate` (encoder/heads.ts seam) serves
|
|
15
|
+
* the trained head weights; when the flag is OFF (MEGACOMPACT_ENC_0C=0) or no
|
|
16
|
+
* candidate is staged, the heads keep serving the ENC-0b survivor exactly —
|
|
17
|
+
* byte-identical, no weight change. The flag gates ONLY the candidate-load seam;
|
|
18
|
+
* the survivor path is untouched.
|
|
19
|
+
*
|
|
20
|
+
* The split is purely mechanical: ENC_0C_ENABLED follows ENC_0B_ENABLED in name,
|
|
21
|
+
* semantics, and default, and vector-cortex.ts re-exports it so every existing
|
|
22
|
+
* `from "./config/vector-cortex.js"` import keeps resolving unchanged.
|
|
23
|
+
*
|
|
24
|
+
* Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
|
|
25
|
+
*/
|
|
26
|
+
import { sprintFlag } from "./vector-cortex-flag.js";
|
|
27
|
+
/**
|
|
28
|
+
* ENC-0c — five-head supervision transfer on the frozen bge-small trunk.
|
|
29
|
+
* Default ON. `MEGACOMPACT_ENC_0C=0` disables and is byte-identical to the
|
|
30
|
+
* predecessor (ENC-0b): no head candidate is loaded and the heads keep serving
|
|
31
|
+
* the ENC-0b survivor defaults exactly as before. This flag MUST also be a
|
|
32
|
+
* dashboard SETTINGS toggle (visible in config UI, never in EXCLUDED_SETTINGS),
|
|
33
|
+
* mirroring ENC_0A and ENC_0B.
|
|
34
|
+
*/
|
|
35
|
+
export const ENC_0C_ENABLED = () => sprintFlag("MEGACOMPACT_ENC_0C");
|
|
@@ -237,7 +237,6 @@ export const VC8A_ENABLED = () => sprintFlag("MEGACOMPACT_VC8A");
|
|
|
237
237
|
* mirroring VC4A..VC8A.
|
|
238
238
|
*/
|
|
239
239
|
export const VC8B_ENABLED = () => sprintFlag("MEGACOMPACT_VC8B");
|
|
240
|
-
// VC8C extracted to vector-cortex-vc8c.ts; re-exported so existing imports keep resolving.
|
|
241
240
|
export { VC8C_ENABLED } from "./vector-cortex-vc8c.js";
|
|
242
241
|
export { VC9A_ENABLED } from "./vector-cortex-vc9a.js";
|
|
243
242
|
export { VC9B_ENABLED } from "./vector-cortex-vc9b.js";
|
|
@@ -251,5 +250,7 @@ export { ML5D_ENABLED } from "./vector-cortex-ml5d.js";
|
|
|
251
250
|
export { ML5E_ENABLED } from "./vector-cortex-ml5e.js";
|
|
252
251
|
export { DEDUP_ATTR_ENABLED } from "./vector-cortex-dedup-attr.js";
|
|
253
252
|
export { ENC_0A_ENABLED } from "./vector-cortex-enc0a.js";
|
|
253
|
+
export { ENC_0B_ENABLED } from "./vector-cortex-enc0b.js";
|
|
254
|
+
export { ENC_0C_ENABLED } from "./vector-cortex-enc0c.js";
|
|
254
255
|
// Breaker constants (TRIAD_RESILIENCE.md §breaker) extracted to vector-cortex-breakers.ts.
|
|
255
256
|
export { BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./vector-cortex-breakers.js";
|
package/dist/config.js
CHANGED
|
@@ -114,4 +114,4 @@ export const NEW_UI = () => ragEnabled("MEGACOMPACT_NEW_UI");
|
|
|
114
114
|
// default ON, `=0`/`_DISABLED` off. Re-exported from src/config/vector-cortex.ts
|
|
115
115
|
// so root consumers share one source of truth.
|
|
116
116
|
// ---------------------------------------------------------------------------
|
|
117
|
-
export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, ML5D_ENABLED, ML5E_ENABLED, DEDUP_ATTR_ENABLED, ENC_0A_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
|
|
117
|
+
export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, ML5D_ENABLED, ML5E_ENABLED, DEDUP_ATTR_ENABLED, ENC_0A_ENABLED, ENC_0B_ENABLED, ENC_0C_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
|
|
@@ -59,5 +59,7 @@ export const VECTOR_CORTEX_SETTINGS = {
|
|
|
59
59
|
boolDirect("MEGACOMPACT_ML5_E", "ML5-E Nightly Retraining Cron", "ML5-E nightly retraining + feedback loop: the user's own post-redaction conversation turns become fresh training signal, the five heads are re-fit nightly via system cron, calibration is re-validated, and mode-A promotion is re-checked without human intervention. The cron is system-configured (crontab -e); the extension never installs or writes a crontab. Candidates are written to ~/.pi/mega-compact-encoder/candidates/ and promoted via the ML5-D Improve Cortex flow. ON (default) = the scripts may be invoked by the system cron. OFF = scripts are never invoked; byte-identical to ML5-D.", true),
|
|
60
60
|
boolDirect("MEGACOMPACT_DEDUP_ATTR", "Dedup Tier Attribution Rollup", "Dedup tier-attribution rollup: per-tier dedup catch shares (L0/L1/L2/new percent of dedup decisions) read from the local events.log dedup_audit stream (GET /api/dedup-tier-attribution). OFF = 404 + no cache file, byte-identical predecessor.", true),
|
|
61
61
|
boolDirect("MEGACOMPACT_ENC_0A", "ENC-0a Encoder Backend Decision", "ENC-0a learned-encoder backend-decision lock: records the transformers.js/WASM vs onnxruntime-node choice, per-platform install matrix, opset-21 baseline and pinned digests in docs/vector-cortex/encoder-backend-decision.md. OFF = no decision record written / no resolver runs, mode B trigram byte-identical predecessor.", true),
|
|
62
|
+
boolDirect("MEGACOMPACT_ENC_0B", "ENC-0b Real Trunk Fetch & Gated Path", "ENC-0b real ONNX trunk fetch + gated inference: replaces the LCG placeholder with the real bge-small int8 model through an ONNX InferenceSession (onnxruntime-web WASM). OFF = LCG placeholder serves byte-identical predecessor output, no ONNX session built.", true),
|
|
63
|
+
boolDirect("MEGACOMPACT_ENC_0C", "ENC-0c Five-Head Supervision Transfer", "ENC-0c five-head supervision transfer on the frozen bge-small trunk: when a developer-trained head candidate is staged under ~/.pi/mega-compact-encoder/candidates/, the five heads serve the trained weights. OFF = no candidate is loaded, the heads serve byte-identical ENC-0b survivor defaults.", true),
|
|
62
64
|
],
|
|
63
65
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/vector-cortex-enc0b.ts — ENC-0b real ONNX trunk fetch + gated inference flag.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from vector-cortex.ts so that file stays under the 300-line soft
|
|
5
|
+
* limit (soft-as-hard gate), exactly as vector-cortex-enc0a.ts and the
|
|
6
|
+
* VC8C/VC9A-D/ML5A-E/DEDUP_ATTR siblings were. vector-cortex.ts re-exports the
|
|
7
|
+
* flag below and root src/config.ts re-exports it, so no consumer import path
|
|
8
|
+
* changes.
|
|
9
|
+
*
|
|
10
|
+
* ENC-0b fetches the real bge-small-en-v1.5 int8 ONNX model from the Hugging
|
|
11
|
+
* Face Hub (build-time fetch into the assets directory, NOT a runtime network
|
|
12
|
+
* call — PREVENT-PI-004 safe), wires an ONNX InferenceSession via
|
|
13
|
+
* onnxruntime-web WASM, and runs gated inference through it. The gate is
|
|
14
|
+
* controlled by this flag: OFF = the LCG placeholder encoder serves
|
|
15
|
+
* byte-identical predecessor output and no ONNX session is constructed.
|
|
16
|
+
*
|
|
17
|
+
* The split is purely mechanical: ENC_0B_ENABLED is byte-identical in name,
|
|
18
|
+
* semantics, and default to the definition it replaces, and vector-cortex.ts
|
|
19
|
+
* re-exports it so every existing `from "./config/vector-cortex.js"` import
|
|
20
|
+
* keeps resolving unchanged.
|
|
21
|
+
*
|
|
22
|
+
* Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
|
|
23
|
+
*/
|
|
24
|
+
import { sprintFlag } from "./vector-cortex-flag.js";
|
|
25
|
+
/**
|
|
26
|
+
* ENC-0b — real ONNX trunk fetch + gated inference. Default ON.
|
|
27
|
+
* `MEGACOMPACT_ENC_0B=0` disables and is byte-identical to the predecessor
|
|
28
|
+
* (ENC-0a / LCG placeholder): no ONNX session is built, the real bge-small
|
|
29
|
+
* model is not loaded, and the encoder continues serving the LCG placeholder
|
|
30
|
+
* output exactly as before. This flag MUST also be a dashboard SETTINGS toggle
|
|
31
|
+
* (visible in config UI, never in EXCLUDED_SETTINGS), mirroring ENC_0A and
|
|
32
|
+
* VC4A..VC9D.
|
|
33
|
+
*/
|
|
34
|
+
export const ENC_0B_ENABLED = () => sprintFlag("MEGACOMPACT_ENC_0B");
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/vector-cortex-enc0c.ts — ENC-0c five-head supervision transfer flag.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from vector-cortex.ts so that file stays under the 300-line soft
|
|
5
|
+
* limit (soft-as-hard gate), exactly as vector-cortex-enc0a.ts / enc0b.ts and
|
|
6
|
+
* the VC8C/VC9A-D/ML5A-E/DEDUP_ATTR siblings were. vector-cortex.ts re-exports
|
|
7
|
+
* the flag below and root src/config.ts re-exports it, so no consumer import
|
|
8
|
+
* path changes.
|
|
9
|
+
*
|
|
10
|
+
* ENC-0c trains the five real heads onto the frozen ENC-0b bge-small trunk via
|
|
11
|
+
* supervision transfer, and stages a qualified candidate under
|
|
12
|
+
* ~/.pi/mega-compact-encoder/candidates/ (only when the developer trains it —
|
|
13
|
+
* the extension never stages one by itself). When the flag is ON and a
|
|
14
|
+
* qualified candidate exists, `loadHeadCandidate` (encoder/heads.ts seam) serves
|
|
15
|
+
* the trained head weights; when the flag is OFF (MEGACOMPACT_ENC_0C=0) or no
|
|
16
|
+
* candidate is staged, the heads keep serving the ENC-0b survivor exactly —
|
|
17
|
+
* byte-identical, no weight change. The flag gates ONLY the candidate-load seam;
|
|
18
|
+
* the survivor path is untouched.
|
|
19
|
+
*
|
|
20
|
+
* The split is purely mechanical: ENC_0C_ENABLED follows ENC_0B_ENABLED in name,
|
|
21
|
+
* semantics, and default, and vector-cortex.ts re-exports it so every existing
|
|
22
|
+
* `from "./config/vector-cortex.js"` import keeps resolving unchanged.
|
|
23
|
+
*
|
|
24
|
+
* Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
|
|
25
|
+
*/
|
|
26
|
+
import { sprintFlag } from "./vector-cortex-flag.js";
|
|
27
|
+
/**
|
|
28
|
+
* ENC-0c — five-head supervision transfer on the frozen bge-small trunk.
|
|
29
|
+
* Default ON. `MEGACOMPACT_ENC_0C=0` disables and is byte-identical to the
|
|
30
|
+
* predecessor (ENC-0b): no head candidate is loaded and the heads keep serving
|
|
31
|
+
* the ENC-0b survivor defaults exactly as before. This flag MUST also be a
|
|
32
|
+
* dashboard SETTINGS toggle (visible in config UI, never in EXCLUDED_SETTINGS),
|
|
33
|
+
* mirroring ENC_0A and ENC_0B.
|
|
34
|
+
*/
|
|
35
|
+
export const ENC_0C_ENABLED = () => sprintFlag("MEGACOMPACT_ENC_0C");
|
|
@@ -237,7 +237,6 @@ export const VC8A_ENABLED = () => sprintFlag("MEGACOMPACT_VC8A");
|
|
|
237
237
|
* mirroring VC4A..VC8A.
|
|
238
238
|
*/
|
|
239
239
|
export const VC8B_ENABLED = () => sprintFlag("MEGACOMPACT_VC8B");
|
|
240
|
-
// VC8C extracted to vector-cortex-vc8c.ts; re-exported so existing imports keep resolving.
|
|
241
240
|
export { VC8C_ENABLED } from "./vector-cortex-vc8c.js";
|
|
242
241
|
export { VC9A_ENABLED } from "./vector-cortex-vc9a.js";
|
|
243
242
|
export { VC9B_ENABLED } from "./vector-cortex-vc9b.js";
|
|
@@ -251,5 +250,7 @@ export { ML5D_ENABLED } from "./vector-cortex-ml5d.js";
|
|
|
251
250
|
export { ML5E_ENABLED } from "./vector-cortex-ml5e.js";
|
|
252
251
|
export { DEDUP_ATTR_ENABLED } from "./vector-cortex-dedup-attr.js";
|
|
253
252
|
export { ENC_0A_ENABLED } from "./vector-cortex-enc0a.js";
|
|
253
|
+
export { ENC_0B_ENABLED } from "./vector-cortex-enc0b.js";
|
|
254
|
+
export { ENC_0C_ENABLED } from "./vector-cortex-enc0c.js";
|
|
254
255
|
// Breaker constants (TRIAD_RESILIENCE.md §breaker) extracted to vector-cortex-breakers.ts.
|
|
255
256
|
export { BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./vector-cortex-breakers.js";
|
package/dist/src/config.js
CHANGED
|
@@ -114,4 +114,4 @@ export const NEW_UI = () => ragEnabled("MEGACOMPACT_NEW_UI");
|
|
|
114
114
|
// default ON, `=0`/`_DISABLED` off. Re-exported from src/config/vector-cortex.ts
|
|
115
115
|
// so root consumers share one source of truth.
|
|
116
116
|
// ---------------------------------------------------------------------------
|
|
117
|
-
export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, ML5D_ENABLED, ML5E_ENABLED, DEDUP_ATTR_ENABLED, ENC_0A_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
|
|
117
|
+
export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, ML5D_ENABLED, ML5E_ENABLED, DEDUP_ATTR_ENABLED, ENC_0A_ENABLED, ENC_0B_ENABLED, ENC_0C_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
|
|
@@ -17,6 +17,7 @@ import { VC2A_ENABLED } from "../../config/vector-cortex.js";
|
|
|
17
17
|
export const NOOP_ENCODER_REPORTER = {
|
|
18
18
|
assetVerified: () => { },
|
|
19
19
|
runtimeDemoted: () => { },
|
|
20
|
+
onnxSessionLoaded: () => { },
|
|
20
21
|
};
|
|
21
22
|
/**
|
|
22
23
|
* Flag-gated emit: no-op when VC2A is off or no emitter is supplied. The
|
|
@@ -38,5 +39,6 @@ export function createEncoderReporter(emit) {
|
|
|
38
39
|
return {
|
|
39
40
|
assetVerified: (fields) => fire("vector_cortex_encoder_asset_verified", fields),
|
|
40
41
|
runtimeDemoted: (fields) => fire("vector_cortex_encoder_runtime_demoted", fields),
|
|
42
|
+
onnxSessionLoaded: (fields) => fire("vector_cortex_encoder_onnx_loaded", fields),
|
|
41
43
|
};
|
|
42
44
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* encoder-onnx-dispatch.ts — ENC-0b ONNX dispatch: session lifecycle glue.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from runtime.ts so runtime.ts stays under the 300-line soft limit.
|
|
5
|
+
* Encapsulates the ENC-0b real ONNX session build during load().
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT (interface constraint): EncoderRuntime.load() and infer() are
|
|
8
|
+
* SYNCHRONOUS — the router (router.ts:121-132) and all acceptance tests call
|
|
9
|
+
* them synchronously. ONNX session creation is ASYNC (WASM init). ENC-0b
|
|
10
|
+
* therefore expose the ONNX session as a SEPARATE async verification: load()
|
|
11
|
+
* fires-and-forgets the session build, verifySession() awaits it for tests,
|
|
12
|
+
* and infer() continues serving the LCG placeholder until the router is wired
|
|
13
|
+
* for async inference (ENC-0c scope). This preserves the sync contract while
|
|
14
|
+
* proving the real ONNX pipeline work end-to-end.
|
|
15
|
+
*
|
|
16
|
+
* ENC-0b gate: when MEGACOMPACT_ENC_0B is OFF, none of this code runs —
|
|
17
|
+
* the LCG stub serves mode A byte-identical to the predecessor.
|
|
18
|
+
*
|
|
19
|
+
* Pi-agnostic (PREVENT-PI-004 / PREVENT-011).
|
|
20
|
+
*/
|
|
21
|
+
import { ENC_0B_ENABLED } from "../../config/vector-cortex.js";
|
|
22
|
+
import { buildOnnxSession } from "./onnx.js";
|
|
23
|
+
/** No-op state when ENC-0b is off or session build not attempted. */
|
|
24
|
+
export const NO_ONNX = { session: null, ready: Promise.resolve() };
|
|
25
|
+
/**
|
|
26
|
+
* Attempt a real ONNX session build during load(). Fire-and-forget: returns
|
|
27
|
+
* immediately with a state whose `ready` Promise resolves once the async
|
|
28
|
+
* build settles. On failure the state's `session` stays null.
|
|
29
|
+
*/
|
|
30
|
+
export function tryBuildOnnx(assetDir, manifest, reporter, allocatedBytes) {
|
|
31
|
+
if (!ENC_0B_ENABLED())
|
|
32
|
+
return NO_ONNX;
|
|
33
|
+
let session = null;
|
|
34
|
+
const ready = buildOnnxSession(assetDir, manifest, reporter, allocatedBytes)
|
|
35
|
+
.then((result) => { if (result.ok)
|
|
36
|
+
session = result.session; })
|
|
37
|
+
.catch(() => { });
|
|
38
|
+
// Return a state whose `session` getter reads the mutable binding after
|
|
39
|
+
// ready resolves (the getter runs at test assertion time, not at load()).
|
|
40
|
+
return { get session() { return session; }, ready };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Await the ONNX session build and verify it with a real inference.
|
|
44
|
+
* Returns the embedding on success, null on any failure.
|
|
45
|
+
* Called by tests and the ENC-0b acceptance aggregator, not by production
|
|
46
|
+
* infer().
|
|
47
|
+
*/
|
|
48
|
+
export async function verifyOnnxSession(state, tokens) {
|
|
49
|
+
await state.ready;
|
|
50
|
+
if (!state.session)
|
|
51
|
+
return null;
|
|
52
|
+
try {
|
|
53
|
+
return await state.session.infer(tokens);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* encoder/heads-candidate.ts — ENC-0c head-candidate load seam (delegate impl).
|
|
3
|
+
*
|
|
4
|
+
* Loads/validates a `head-candidate-v1` five-head candidate staged under
|
|
5
|
+
* `~/.pi/mega-compact-encoder/candidates/<version>/` after training on the
|
|
6
|
+
* frozen ENC-0b bge-small trunk. Flag-off / absent / malformed / wrong dims /
|
|
7
|
+
* non-finite / digest / trunk mismatch each return null or {ok:false} — a bad
|
|
8
|
+
* candidate is NEVER force-loaded; the runtime keeps the ENC-0b survivor
|
|
9
|
+
* byte-identical. No `any` (PREVENT-011), local-only, structured logging.
|
|
10
|
+
*/
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
12
|
+
import { readFileSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { ENC_0C_ENABLED } from "../../config/vector-cortex.js";
|
|
15
|
+
import { ENCODER_HEAD_DIMS, ENCODER_HEAD_ORDER } from "./types.js";
|
|
16
|
+
export const HEAD_CANDIDATE_SCHEMA = "head-candidate-v1";
|
|
17
|
+
const MANIFEST_FILE = "manifest.json";
|
|
18
|
+
export const HEAD_CANDIDATE_FAIL = {
|
|
19
|
+
INVALID: "ENC0C_CANDIDATE_INVALID",
|
|
20
|
+
TRUNK_MISMATCH: "ENC0C_TRUNK_MISMATCH",
|
|
21
|
+
DIM_MISMATCH: "ENC0C_DIM_MISMATCH",
|
|
22
|
+
NON_FINITE: "ENC0C_NON_FINITE",
|
|
23
|
+
DIGEST_MISMATCH: "ENC0C_DIGEST_MISMATCH",
|
|
24
|
+
};
|
|
25
|
+
function sha256(buf) { return createHash("sha256").update(buf).digest("hex"); }
|
|
26
|
+
function finiteDim(values, dim) {
|
|
27
|
+
if (values.length !== dim)
|
|
28
|
+
return false;
|
|
29
|
+
for (const v of values)
|
|
30
|
+
if (!Number.isFinite(v))
|
|
31
|
+
return false;
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
function parseManifest(m) {
|
|
35
|
+
if (!m || m["schema"] !== HEAD_CANDIDATE_SCHEMA)
|
|
36
|
+
return null;
|
|
37
|
+
const version = typeof m["version"] === "string" ? m["version"] : "";
|
|
38
|
+
const trunkDigest = typeof m["trunkDigest"] === "string" ? m["trunkDigest"] : "";
|
|
39
|
+
if (!version || !trunkDigest || !Array.isArray(m["heads"]))
|
|
40
|
+
return null;
|
|
41
|
+
const heads = [];
|
|
42
|
+
for (const item of m["heads"]) {
|
|
43
|
+
const rec = item;
|
|
44
|
+
if (!rec || typeof rec !== "object")
|
|
45
|
+
return null;
|
|
46
|
+
const name = rec["name"];
|
|
47
|
+
if (typeof name !== "string" || !ENCODER_HEAD_ORDER.includes(name))
|
|
48
|
+
return null;
|
|
49
|
+
heads.push({
|
|
50
|
+
name: name,
|
|
51
|
+
dim: Number(rec["dim"] ?? 0),
|
|
52
|
+
sha256: typeof rec["sha256"] === "string" ? rec["sha256"] : "",
|
|
53
|
+
bytes: Number(rec["bytes"] ?? 0),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return { version, trunkDigest, heads };
|
|
57
|
+
}
|
|
58
|
+
/** All 5 dims match, weights finite, digests hold. */
|
|
59
|
+
export function validateHeadCandidate(candidate) {
|
|
60
|
+
for (const h of ENCODER_HEAD_ORDER) {
|
|
61
|
+
const dim = candidate.dims[h];
|
|
62
|
+
if (dim !== ENCODER_HEAD_DIMS[h])
|
|
63
|
+
return { ok: false, code: HEAD_CANDIDATE_FAIL.DIM_MISMATCH };
|
|
64
|
+
const w = candidate.weights[h];
|
|
65
|
+
if (!w || !finiteDim(w, dim))
|
|
66
|
+
return { ok: false, code: HEAD_CANDIDATE_FAIL.NON_FINITE };
|
|
67
|
+
const buf = new Uint8Array(w.buffer, w.byteOffset, w.byteLength);
|
|
68
|
+
if (sha256(buf) !== candidate.digests[h])
|
|
69
|
+
return { ok: false, code: HEAD_CANDIDATE_FAIL.DIGEST_MISMATCH };
|
|
70
|
+
}
|
|
71
|
+
return { ok: true };
|
|
72
|
+
}
|
|
73
|
+
/** Load a candidate against the frozen trunk; null on any violation, never throws. */
|
|
74
|
+
export function loadHeadCandidate(candidateDir, manifest) {
|
|
75
|
+
if (!ENC_0C_ENABLED())
|
|
76
|
+
return null;
|
|
77
|
+
let raw;
|
|
78
|
+
try {
|
|
79
|
+
raw = readFileSync(join(candidateDir, MANIFEST_FILE), "utf8");
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
let parsed;
|
|
85
|
+
try {
|
|
86
|
+
parsed = JSON.parse(raw);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const m = parseManifest(parsed);
|
|
92
|
+
if (!m || m.trunkDigest !== manifest.onnx.sha256)
|
|
93
|
+
return null;
|
|
94
|
+
const weights = {};
|
|
95
|
+
const digests = {};
|
|
96
|
+
const dims = {};
|
|
97
|
+
for (const rec of m.heads) {
|
|
98
|
+
const want = rec.dim * 4;
|
|
99
|
+
if (!Number.isInteger(want) || want <= 0 || rec.dim !== ENCODER_HEAD_DIMS[rec.name])
|
|
100
|
+
return null;
|
|
101
|
+
let bytes;
|
|
102
|
+
try {
|
|
103
|
+
bytes = readFileSync(join(candidateDir, `${rec.name}.bin`));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const f = new Float32Array(bytes.buffer, bytes.byteOffset, rec.dim);
|
|
109
|
+
const d = sha256(bytes);
|
|
110
|
+
if (bytes.length !== want || d !== rec.sha256)
|
|
111
|
+
return null;
|
|
112
|
+
weights[rec.name] = f.slice();
|
|
113
|
+
digests[rec.name] = d;
|
|
114
|
+
dims[rec.name] = rec.dim;
|
|
115
|
+
}
|
|
116
|
+
for (const h of ENCODER_HEAD_ORDER) {
|
|
117
|
+
if (weights[h] === undefined || digests[h] === undefined || dims[h] === undefined)
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const candidate = {
|
|
121
|
+
schema: HEAD_CANDIDATE_SCHEMA, version: m.version, trunkDigest: m.trunkDigest,
|
|
122
|
+
dims: dims,
|
|
123
|
+
weights: weights,
|
|
124
|
+
digests: digests,
|
|
125
|
+
};
|
|
126
|
+
return validateHeadCandidate(candidate).ok ? candidate : null;
|
|
127
|
+
}
|
|
@@ -198,3 +198,7 @@ export function projectHeadFromTrunk(head, trunk, table) {
|
|
|
198
198
|
return { head, dim, values: l2Normalize(out) };
|
|
199
199
|
}
|
|
200
200
|
export { ENCODER_HEAD_ORDER, ENCODER_HEAD_DIMS, ENCODER_HEAD_LOSS_SUM, ENCODER_SEED, NOOP_VC2B_REPORTER };
|
|
201
|
+
// ENC-0c five-head candidate seam (delegate-shell): the load/validate impl
|
|
202
|
+
// lives in heads-candidate.ts; these re-exports keep the public import path
|
|
203
|
+
// stable at heads.ts without growing this survivor file over the soft limit.
|
|
204
|
+
export { HEAD_CANDIDATE_SCHEMA, HEAD_CANDIDATE_FAIL, loadHeadCandidate, validateHeadCandidate, } from "./heads-candidate.js";
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/encoder/onnx.ts — ENC-0b real ONNX InferenceSession builder.
|
|
3
|
+
*
|
|
4
|
+
* Creates a WASM-backed ONNX InferenceSession over the committed encoder-v1
|
|
5
|
+
* asset (bge-small-en-v1.5, opset 21, 384-dim sentence_embedding). Dynamically
|
|
6
|
+
* imports onnxruntime-web/wasm (the CPU-only variant) so the module graph
|
|
7
|
+
* compiles on hosts without the package. All failures return typed result
|
|
8
|
+
* codes — this function NEVER throws (PREVENT-011: no `any`).
|
|
9
|
+
*
|
|
10
|
+
* Lifecycle:
|
|
11
|
+
* 1. Check ENCODER_RSS_BUDGET_BYTES before allocation (cap-before-allocation).
|
|
12
|
+
* 2. Assert manifest.opset === ENCODER_OPSET (21).
|
|
13
|
+
* 3. Dynamically import("onnxruntime-web/wasm").
|
|
14
|
+
* 4. Create InferenceSession with wasm EP, 4 threads.
|
|
15
|
+
* 5. Expose infer(tokens) that feeds int64 input_ids + attention_mask + token_type_ids.
|
|
16
|
+
* 6. Return sentence_embedding, L2-normalized to unit norm.
|
|
17
|
+
*
|
|
18
|
+
* Pi-agnostic (PREVENT-PI-004: local file only, zero network).
|
|
19
|
+
*/
|
|
20
|
+
import { dirname, join } from "node:path";
|
|
21
|
+
import { fileURLToPath } from "node:url";
|
|
22
|
+
import { existsSync } from "node:fs";
|
|
23
|
+
import { ENCODER_OPSET, ENCODER_RSS_BUDGET_BYTES, ENCODER_SEMANTIC_WIDTH, } from "./types.js";
|
|
24
|
+
/** ENC-0b failure codes (new ENC_FAIL namespace entries declared here). */
|
|
25
|
+
export const ENC_ONNX_FAIL = {
|
|
26
|
+
OPSET_MISMATCH: "ENC_ONNX_OPSET_MISMATCH",
|
|
27
|
+
RSS_BREACH: "ENC_ONNX_RSS_BREACH",
|
|
28
|
+
MODULE_ABSENT: "ENC_ONNX_MODULE_ABSENT",
|
|
29
|
+
SESSION_ERROR: "ENC_ONNX_SESSION_ERROR",
|
|
30
|
+
MODEL_ABSENT: "ENC_ONNX_MODEL_ABSENT",
|
|
31
|
+
};
|
|
32
|
+
/** Resolve the onnxruntime-web package root from import.meta.url. */
|
|
33
|
+
function resolveOrtWasmPath() {
|
|
34
|
+
try {
|
|
35
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
36
|
+
// Walk up to find node_modules/onnxruntime-web/dist/ort-wasm-simd-threaded.wasm
|
|
37
|
+
let dir = here;
|
|
38
|
+
for (let i = 0; i < 12; i++) {
|
|
39
|
+
const candidate = join(dir, "node_modules", "onnxruntime-web", "dist", "ort-wasm-simd-threaded.wasm");
|
|
40
|
+
if (existsSync(candidate))
|
|
41
|
+
return candidate;
|
|
42
|
+
const next = dirname(dir);
|
|
43
|
+
if (next === dir)
|
|
44
|
+
break;
|
|
45
|
+
dir = next;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** L2-normalize a Float32Array in-place; returns the same array. */
|
|
54
|
+
function l2Normalize(arr) {
|
|
55
|
+
let sum = 0;
|
|
56
|
+
for (let i = 0; i < arr.length; i++)
|
|
57
|
+
sum += arr[i] * arr[i];
|
|
58
|
+
const norm = Math.sqrt(sum);
|
|
59
|
+
if (norm > 1e-12) {
|
|
60
|
+
for (let i = 0; i < arr.length; i++)
|
|
61
|
+
arr[i] = arr[i] / norm;
|
|
62
|
+
}
|
|
63
|
+
return arr;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Build a real ONNX InferenceSession over the committed encoder-v1 asset.
|
|
67
|
+
* Returns a typed result — NEVER throws. On any failure the caller demotes
|
|
68
|
+
* to mode B trigram with the returned code.
|
|
69
|
+
*
|
|
70
|
+
* @param assetDir Path to the directory containing model.onnx + manifest.
|
|
71
|
+
* @param manifest The verified ModelManifestV1 from the asset.
|
|
72
|
+
* @param reporter Encoder reporter for the onnx_loaded event (optional).
|
|
73
|
+
* @param allocatedBytes Externally committed bytes (for RSS budget check).
|
|
74
|
+
*/
|
|
75
|
+
export async function buildOnnxSession(assetDir, manifest, reporter, allocatedBytes = 0) {
|
|
76
|
+
// Q01: cap-before-allocation.
|
|
77
|
+
if (allocatedBytes > ENCODER_RSS_BUDGET_BYTES) {
|
|
78
|
+
return { ok: false, code: ENC_ONNX_FAIL.RSS_BREACH };
|
|
79
|
+
}
|
|
80
|
+
// Opset assertion.
|
|
81
|
+
if (manifest.opset !== ENCODER_OPSET) {
|
|
82
|
+
return { ok: false, code: ENC_ONNX_FAIL.OPSET_MISMATCH };
|
|
83
|
+
}
|
|
84
|
+
const modelPath = join(assetDir, manifest.onnx.path);
|
|
85
|
+
if (!existsSync(modelPath)) {
|
|
86
|
+
return { ok: false, code: ENC_ONNX_FAIL.MODEL_ABSENT };
|
|
87
|
+
}
|
|
88
|
+
// Dynamically import onnxruntime-web/wasm (never a hard dependency).
|
|
89
|
+
let ort;
|
|
90
|
+
try {
|
|
91
|
+
ort = (await import("onnxruntime-web/wasm"));
|
|
92
|
+
if (!ort?.InferenceSession?.create) {
|
|
93
|
+
return { ok: false, code: ENC_ONNX_FAIL.MODULE_ABSENT };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return { ok: false, code: ENC_ONNX_FAIL.MODULE_ABSENT };
|
|
98
|
+
}
|
|
99
|
+
// Resolve WASM binary path for the threading backend.
|
|
100
|
+
const wasmPath = resolveOrtWasmPath();
|
|
101
|
+
let rawSession;
|
|
102
|
+
try {
|
|
103
|
+
const opts = {
|
|
104
|
+
executionProviders: ["wasm"],
|
|
105
|
+
intraOpNumThreads: 4,
|
|
106
|
+
};
|
|
107
|
+
if (wasmPath)
|
|
108
|
+
opts.wasmPaths = wasmPath;
|
|
109
|
+
rawSession = await ort.InferenceSession.create(modelPath, opts);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return { ok: false, code: ENC_ONNX_FAIL.SESSION_ERROR };
|
|
113
|
+
}
|
|
114
|
+
reporter?.onnxSessionLoaded({
|
|
115
|
+
opset: manifest.opset,
|
|
116
|
+
semanticWidth: ENCODER_SEMANTIC_WIDTH,
|
|
117
|
+
threads: 4,
|
|
118
|
+
});
|
|
119
|
+
const session = {
|
|
120
|
+
opset: manifest.opset,
|
|
121
|
+
semanticWidth: ENCODER_SEMANTIC_WIDTH,
|
|
122
|
+
async infer(tokens) {
|
|
123
|
+
const n = tokens.length;
|
|
124
|
+
const inputIds = new BigInt64Array(n);
|
|
125
|
+
const attentionMask = new BigInt64Array(n);
|
|
126
|
+
const tokenTypeIds = new BigInt64Array(n);
|
|
127
|
+
for (let i = 0; i < n; i++) {
|
|
128
|
+
inputIds[i] = BigInt(tokens[i]);
|
|
129
|
+
attentionMask[i] = 1n;
|
|
130
|
+
tokenTypeIds[i] = 0n;
|
|
131
|
+
}
|
|
132
|
+
const feeds = {
|
|
133
|
+
input_ids: { data: inputIds, dims: [1, n], type: "int64" },
|
|
134
|
+
attention_mask: { data: attentionMask, dims: [1, n], type: "int64" },
|
|
135
|
+
token_type_ids: { data: tokenTypeIds, dims: [1, n], type: "int64" },
|
|
136
|
+
};
|
|
137
|
+
const results = await rawSession.run(feeds, ["sentence_embedding"]);
|
|
138
|
+
const out = results["sentence_embedding"];
|
|
139
|
+
if (!out || !(out.data instanceof Float32Array)) {
|
|
140
|
+
return new Float32Array(ENCODER_SEMANTIC_WIDTH);
|
|
141
|
+
}
|
|
142
|
+
return l2Normalize(out.data);
|
|
143
|
+
},
|
|
144
|
+
release: () => rawSession.release(),
|
|
145
|
+
};
|
|
146
|
+
return { ok: true, session };
|
|
147
|
+
}
|
|
@@ -54,10 +54,23 @@ export async function createWasmSession(modelPath, options = {}) {
|
|
|
54
54
|
opset: ENCODER_OPSET,
|
|
55
55
|
semanticWidth: ENCODER_SEMANTIC_WIDTH,
|
|
56
56
|
maxTokens,
|
|
57
|
-
async infer(
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
const
|
|
57
|
+
async infer(tokens) {
|
|
58
|
+
const n = tokens.length;
|
|
59
|
+
const inputIds = new BigInt64Array(n);
|
|
60
|
+
const attentionMask = new BigInt64Array(n);
|
|
61
|
+
const tokenTypeIds = new BigInt64Array(n);
|
|
62
|
+
for (let i = 0; i < n; i++) {
|
|
63
|
+
inputIds[i] = BigInt(tokens[i]);
|
|
64
|
+
attentionMask[i] = 1n;
|
|
65
|
+
tokenTypeIds[i] = 0n;
|
|
66
|
+
}
|
|
67
|
+
const feeds = {
|
|
68
|
+
input_ids: { data: inputIds, dims: [1, n], type: "int64" },
|
|
69
|
+
attention_mask: { data: attentionMask, dims: [1, n], type: "int64" },
|
|
70
|
+
token_type_ids: { data: tokenTypeIds, dims: [1, n], type: "int64" },
|
|
71
|
+
};
|
|
72
|
+
const results = await session.run(feeds, ["sentence_embedding"]);
|
|
73
|
+
const out = results["sentence_embedding"];
|
|
61
74
|
if (!out || !(out.data instanceof Float32Array)) {
|
|
62
75
|
return new Float32Array(ENCODER_SEMANTIC_WIDTH);
|
|
63
76
|
}
|