@adhd/sox-embedding-provider 0.1.0
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/README.md +20 -0
- package/dist/cache.d.ts +70 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +217 -0
- package/dist/cache.js.map +1 -0
- package/dist/embedWorker.d.ts +77 -0
- package/dist/embedWorker.d.ts.map +1 -0
- package/dist/embedWorker.js +326 -0
- package/dist/embedWorker.js.map +1 -0
- package/dist/fastembed.d.ts +62 -0
- package/dist/fastembed.d.ts.map +1 -0
- package/dist/fastembed.js +259 -0
- package/dist/fastembed.js.map +1 -0
- package/dist/fastembedProcessHost.d.ts +60 -0
- package/dist/fastembedProcessHost.d.ts.map +1 -0
- package/dist/fastembedProcessHost.js +166 -0
- package/dist/fastembedProcessHost.js.map +1 -0
- package/dist/index.d.ts +145 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +138 -0
- package/dist/index.js.map +1 -0
- package/dist/package.json +52 -0
- package/dist/remote.d.ts +23 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +91 -0
- package/dist/remote.js.map +1 -0
- package/dist/sharedFastembedProcess.d.ts +56 -0
- package/dist/sharedFastembedProcess.d.ts.map +1 -0
- package/dist/sharedFastembedProcess.js +180 -0
- package/dist/sharedFastembedProcess.js.map +1 -0
- package/dist/sharedOnnxWorker.d.ts +135 -0
- package/dist/sharedOnnxWorker.d.ts.map +1 -0
- package/dist/sharedOnnxWorker.js +255 -0
- package/dist/sharedOnnxWorker.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastembed.js","sourceRoot":"","sources":["../src/fastembed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,yBAAyB,EAAqC,MAAM,6BAA6B,CAAC;AAgB3G,MAAM,aAAa,GAAyC;IAC1D,mBAAmB,EAAE;QACnB,OAAO,EAAE,mBAAmB;QAC5B,QAAQ,EAAE,wBAAwB;QAClC,GAAG,EAAE,GAAG;QACR,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,qEAAqE;KACnF;IACD,kBAAkB,EAAE;QAClB,OAAO,EAAE,kBAAkB;QAC3B,QAAQ,EAAE,uBAAuB;QACjC,GAAG,EAAE,GAAG;QACR,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,kEAAkE;KAChF;IACD,uBAAuB,EAAE;QACvB,OAAO,EAAE,uBAAuB;QAChC,QAAQ,EAAE,4BAA4B;QACtC,GAAG,EAAE,IAAI;QACT,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,gEAAgE;KAC9E;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,QAAQ;QACjB,QAAQ,EAAE,aAAa;QACvB,GAAG,EAAE,IAAI;QACT,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,qEAAqE;KACnF;IACD,iBAAiB,EAAE;QACjB,OAAO,EAAE,iBAAiB;QAC1B,QAAQ,EAAE,2BAA2B;QACrC,GAAG,EAAE,IAAI;QACT,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,iEAAiE;KAC/E;CACF,CAAC;AAEF,0DAA0D;AAC1D,MAAM,UAAU,GAA2B,MAAM,CAAC,WAAW,CAC3D,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAChE,CAAC;AAEF,gEAAgE;AAChE,MAAM,gBAAgB,GAA2B,MAAM,CAAC,WAAW,CACjE,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CACtE,CAAC;AAEF,MAAM,aAAa,GAAG,kBAAkB,CAAC;AACzC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B;;;;;;;;;GASG;AACH,MAAM,OAAO,iBAAiB;IACnB,QAAQ,CAA4B;IACrC,KAAK,CAAS;IACd,QAAQ,CAAS;IACzB,kEAAkE;IAClE,mEAAmE;IACnE,0EAA0E;IAC1E,+BAA+B;IACvB,MAAM,GAAiC,yBAAyB,EAAE,CAAC;IACnE,KAAK,GAAG,KAAK,CAAC;IACd,YAAY,GAAyB,IAAI,CAAC;IAC1C,QAAQ,GAAG,CAAC,CAAC;IACb,YAAY,GAAG,GAAG,CAAC;IACnB,UAAU,GAAkB,IAAI,CAAC;IAEzC,YAAY,KAAa,EAAE,UAAkB,EAAE,QAAgB;QAC7D,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC;QAC3B,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,YAAY,GAAG,GAAG,EAAE,SAAS,IAAI,GAAG,CAAC;QAC1C,IAAI,CAAC,QAAQ,GAAG;YACd,OAAO,EAAE,KAAK;YACd,UAAU;YACV,SAAS,EAAE,IAAI,CAAC,YAAY;YAC5B,QAAQ,EAAE,KAAK;YACf,eAAe,EAAE,KAAK;YACtB,WAAW,EAAE,cAAc,KAAK,EAAE;SACnC,CAAC;IACJ,CAAC;IAED,MAAM;QACJ,IAAI,KAAK,GAA6B,eAAe,CAAC;QACtD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,KAAK,GAAG,OAAO,CAAC;QAClB,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtB,KAAK,GAAG,MAAM,CAAC;QACjB,CAAC;aAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC7B,KAAK,GAAG,SAAS,CAAC;QACpB,CAAC;QACD,OAAO;YACL,UAAU,EAAE,aAAa,IAAI,CAAC,KAAK,EAAE;YACrC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;YACjD,KAAK;YACL,UAAU,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU;YACrD,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,KAAiB;QAC/C,wEAAwE;QACxE,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YAClD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YACvD,MAAM,UAAU,GAAmB,EAAE,CAAC;YACtC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YACzB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACrF,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;YAC3D,CAAC;YACD,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACnC,CAAC;QAED,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,CAAC,UAAU,CACf,KAAe,EACf,IAA+C;QAE/C,KAAK,IAAI,EAAE,IAAI,CAAC;QAChB,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAEzB,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,kBAAkB,CAAC;QACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;YAC5C,mDAAmD;YACnD,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;YACpF,IAAI,aAAa,EAAE,CAAC;gBAClB,2DAA2D;gBAC3D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,MAAM,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAC/C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;oBAC7B,MAAM,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAe;QAC1B,8DAA8D;QAC9D,mEAAmE;QACnE,mDAAmD;QACnD,KAAK,KAAK,CAAC;IACb,CAAC;IAED;;;OAGG;IACK,cAAc,CAAC,IAAY;QACjC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACK,SAAS,CAAC,IAAY,EAAE,SAAiB;QAC/C,MAAM,QAAQ,GAAG,SAAS,GAAG,CAAC,CAAC;QAC/B,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAE3C,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,OAAO,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YAC3B,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAClD,sDAAsD;YACtD,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtB,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC7C,IAAI,SAAS,GAAG,KAAK;oBAAE,GAAG,GAAG,SAAS,CAAC;YACzC,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;YACpC,KAAK,GAAG,GAAG,CAAC;QACd,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACK,QAAQ,CAAC,OAAuB;QACtC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC,CAAC,CAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;QACrC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,CAAC,CAAC,CAAE,IAAI,GAAG,CAAC,CAAC,CAAE,CAAC;YACxB,CAAC;QACH,CAAC;QACD,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;QACD,8BAA8B;QAC9B,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,IAAI,IAAI,MAAM,CAAC,CAAC,CAAE,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QAClC,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC;QAChC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACK,WAAW;QACjB,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACvC,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CACnC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,EAC5D,eAAe,EAAE,CAClB,CAAC;YACF,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;gBAChB,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC;YAC1B,CAAC;YACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1D,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC;YAC9B,oEAAoE;YACpE,8CAA8C;YAC9C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,KAAe;QACrC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAqB,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;QACzF,OAAO,GAAG,CAAC,UAAU,CAAC;IACxB,CAAC;IAEO,mBAAmB,CAAC,GAAa;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACrB,IAAI,IAAI,GAAG,CAAC,CAAC,CAAE,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC;QAC5B,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC;QAC1B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Child-PROCESS host for fastembed (onnxruntime-node@1.21.0) ONNX inference —
|
|
3
|
+
* BL-238/BL-171.
|
|
4
|
+
*
|
|
5
|
+
* ── Why a PROCESS, not a worker thread ──────────────────────────────────────
|
|
6
|
+
*
|
|
7
|
+
* `embedWorker.ts` (a `worker_threads.Worker`) hosts the cross-encoder rerank
|
|
8
|
+
* and NLI verify workloads, both driven by `@huggingface/transformers`'
|
|
9
|
+
* onnxruntime-node@1.24.3. Two independent, empirically-proven native hazards
|
|
10
|
+
* rule out ALSO hosting fastembed's onnxruntime-node@1.21.0 in that same
|
|
11
|
+
* worker (or any second worker thread):
|
|
12
|
+
*
|
|
13
|
+
* 1. **Cross-isolate hazard (whole-process fatal).** 2+ *separate*
|
|
14
|
+
* `worker_threads.Worker` instances, each holding an active
|
|
15
|
+
* onnxruntime-node `InferenceSession` and running inference
|
|
16
|
+
* concurrently, fatally crash the ENTIRE process with:
|
|
17
|
+
* `FATAL ERROR: HandleScope::HandleScope Entering the V8 API without
|
|
18
|
+
* proper locking in place` (inside `InferenceSessionWrap::Run`).
|
|
19
|
+
* Reproduced even with TWO workers on the exact SAME onnxruntime-node
|
|
20
|
+
* version (fastembed's 1.21.0, twice) — not an ABI/version-mismatch bug,
|
|
21
|
+
* a real thread-safety limitation of the addon whenever 2+ instances are
|
|
22
|
+
* concurrently active in one process. (See `sharedOnnxWorker.ts`.)
|
|
23
|
+
*
|
|
24
|
+
* 2. **Same-thread native timing hazard (std::bad_alloc), proven even with
|
|
25
|
+
* strict JS-level serialization.** Loading fastembed's
|
|
26
|
+
* onnxruntime-node@1.21.0 in the SAME worker thread immediately after
|
|
27
|
+
* `@huggingface/transformers`' onnxruntime-node@1.24.3 finishes loading
|
|
28
|
+
* — even when every JS `await` is fully resolved and the two `init`
|
|
29
|
+
* calls are proven (via instrumented tracing) to run strictly one after
|
|
30
|
+
* the other with zero JS-level overlap — still deterministically threw
|
|
31
|
+
* `std::bad_alloc` on the second (fastembed) init. This means the two
|
|
32
|
+
* onnxruntime-node major versions leave lingering native state (e.g.
|
|
33
|
+
* background thread-pool teardown) that is not synchronized by the JS
|
|
34
|
+
* Promise resolving, so no amount of JS-side queuing/mutexing can make
|
|
35
|
+
* sharing one thread safe — the hazard is at the native addon level,
|
|
36
|
+
* below what JS scheduling can observe or serialize.
|
|
37
|
+
*
|
|
38
|
+
* Because (2) cannot be fixed by better JS scheduling, fastembed is hosted in
|
|
39
|
+
* its OWN **child process** (`node:child_process.fork()`), never a
|
|
40
|
+
* `worker_threads.Worker` and never sharing a thread or address space with
|
|
41
|
+
* `embedWorker.ts`. Separate OS processes cannot share native TLS/global
|
|
42
|
+
* allocator state or V8 isolates by construction — both hazard classes above
|
|
43
|
+
* are structurally impossible across a process boundary, not merely
|
|
44
|
+
* statistically less likely. This mirrors the exact isolation
|
|
45
|
+
* `tools/e2e/child-embed.mjs` already validated as a test-harness-side
|
|
46
|
+
* mitigation; this file makes it the real, package-level fix instead of a
|
|
47
|
+
* test-only workaround (BL-238's option (c)).
|
|
48
|
+
*
|
|
49
|
+
* ── Protocol (IPC via `process.send`/`process.on('message')`) ──────────────
|
|
50
|
+
* request: { id, type: 'init', model: string, cacheDir: string }
|
|
51
|
+
* request: { id, type: 'embed', text: string }
|
|
52
|
+
* request: { id, type: 'embedBatch', texts: string[] }
|
|
53
|
+
* response: { id, initOk: true, dim }
|
|
54
|
+
* response: { id, embedding: number[] }
|
|
55
|
+
* response: { id, embeddings: number[][] }
|
|
56
|
+
* response: { id, error: string }
|
|
57
|
+
* internal: { __shutdown: true }
|
|
58
|
+
*/
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=fastembedProcessHost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastembedProcessHost.d.ts","sourceRoot":"","sources":["../src/fastembedProcessHost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Child-PROCESS host for fastembed (onnxruntime-node@1.21.0) ONNX inference —
|
|
3
|
+
* BL-238/BL-171.
|
|
4
|
+
*
|
|
5
|
+
* ── Why a PROCESS, not a worker thread ──────────────────────────────────────
|
|
6
|
+
*
|
|
7
|
+
* `embedWorker.ts` (a `worker_threads.Worker`) hosts the cross-encoder rerank
|
|
8
|
+
* and NLI verify workloads, both driven by `@huggingface/transformers`'
|
|
9
|
+
* onnxruntime-node@1.24.3. Two independent, empirically-proven native hazards
|
|
10
|
+
* rule out ALSO hosting fastembed's onnxruntime-node@1.21.0 in that same
|
|
11
|
+
* worker (or any second worker thread):
|
|
12
|
+
*
|
|
13
|
+
* 1. **Cross-isolate hazard (whole-process fatal).** 2+ *separate*
|
|
14
|
+
* `worker_threads.Worker` instances, each holding an active
|
|
15
|
+
* onnxruntime-node `InferenceSession` and running inference
|
|
16
|
+
* concurrently, fatally crash the ENTIRE process with:
|
|
17
|
+
* `FATAL ERROR: HandleScope::HandleScope Entering the V8 API without
|
|
18
|
+
* proper locking in place` (inside `InferenceSessionWrap::Run`).
|
|
19
|
+
* Reproduced even with TWO workers on the exact SAME onnxruntime-node
|
|
20
|
+
* version (fastembed's 1.21.0, twice) — not an ABI/version-mismatch bug,
|
|
21
|
+
* a real thread-safety limitation of the addon whenever 2+ instances are
|
|
22
|
+
* concurrently active in one process. (See `sharedOnnxWorker.ts`.)
|
|
23
|
+
*
|
|
24
|
+
* 2. **Same-thread native timing hazard (std::bad_alloc), proven even with
|
|
25
|
+
* strict JS-level serialization.** Loading fastembed's
|
|
26
|
+
* onnxruntime-node@1.21.0 in the SAME worker thread immediately after
|
|
27
|
+
* `@huggingface/transformers`' onnxruntime-node@1.24.3 finishes loading
|
|
28
|
+
* — even when every JS `await` is fully resolved and the two `init`
|
|
29
|
+
* calls are proven (via instrumented tracing) to run strictly one after
|
|
30
|
+
* the other with zero JS-level overlap — still deterministically threw
|
|
31
|
+
* `std::bad_alloc` on the second (fastembed) init. This means the two
|
|
32
|
+
* onnxruntime-node major versions leave lingering native state (e.g.
|
|
33
|
+
* background thread-pool teardown) that is not synchronized by the JS
|
|
34
|
+
* Promise resolving, so no amount of JS-side queuing/mutexing can make
|
|
35
|
+
* sharing one thread safe — the hazard is at the native addon level,
|
|
36
|
+
* below what JS scheduling can observe or serialize.
|
|
37
|
+
*
|
|
38
|
+
* Because (2) cannot be fixed by better JS scheduling, fastembed is hosted in
|
|
39
|
+
* its OWN **child process** (`node:child_process.fork()`), never a
|
|
40
|
+
* `worker_threads.Worker` and never sharing a thread or address space with
|
|
41
|
+
* `embedWorker.ts`. Separate OS processes cannot share native TLS/global
|
|
42
|
+
* allocator state or V8 isolates by construction — both hazard classes above
|
|
43
|
+
* are structurally impossible across a process boundary, not merely
|
|
44
|
+
* statistically less likely. This mirrors the exact isolation
|
|
45
|
+
* `tools/e2e/child-embed.mjs` already validated as a test-harness-side
|
|
46
|
+
* mitigation; this file makes it the real, package-level fix instead of a
|
|
47
|
+
* test-only workaround (BL-238's option (c)).
|
|
48
|
+
*
|
|
49
|
+
* ── Protocol (IPC via `process.send`/`process.on('message')`) ──────────────
|
|
50
|
+
* request: { id, type: 'init', model: string, cacheDir: string }
|
|
51
|
+
* request: { id, type: 'embed', text: string }
|
|
52
|
+
* request: { id, type: 'embedBatch', texts: string[] }
|
|
53
|
+
* response: { id, initOk: true, dim }
|
|
54
|
+
* response: { id, embedding: number[] }
|
|
55
|
+
* response: { id, embeddings: number[][] }
|
|
56
|
+
* response: { id, error: string }
|
|
57
|
+
* internal: { __shutdown: true }
|
|
58
|
+
*/
|
|
59
|
+
import * as fs from 'node:fs';
|
|
60
|
+
// ── Model management ──────────────────────────────────────────────────────────
|
|
61
|
+
const MODEL_MAP = {
|
|
62
|
+
'bge-small-en-v1.5': 'fast-bge-small-en-v1.5',
|
|
63
|
+
'bge-base-en-v1.5': 'fast-bge-base-en-v1.5',
|
|
64
|
+
'multilingual-e5-large': 'fast-multilingual-e5-large',
|
|
65
|
+
'bge-m3': 'BAAI/bge-m3',
|
|
66
|
+
'codexembed-400m': 'CodeXEmbed-400M',
|
|
67
|
+
};
|
|
68
|
+
let _embedder = null;
|
|
69
|
+
let _currentModel = '';
|
|
70
|
+
let _currentCacheDir = '';
|
|
71
|
+
async function loadModel(model, cacheDir) {
|
|
72
|
+
if (_embedder && _currentModel === model && _currentCacheDir === cacheDir) {
|
|
73
|
+
const models = _embedder.listSupportedModels();
|
|
74
|
+
const info = models.find((m) => m.model === model);
|
|
75
|
+
return { dim: info?.dim ?? 0 };
|
|
76
|
+
}
|
|
77
|
+
const { FlagEmbedding, EmbeddingModel: EM } = await import('fastembed');
|
|
78
|
+
const fastModel = MODEL_MAP[model] ?? model;
|
|
79
|
+
const modelKeys = Object.keys(EM);
|
|
80
|
+
const foundKey = modelKeys.find((k) => EM[k] === fastModel);
|
|
81
|
+
const modelEnum = foundKey ? EM[foundKey] : fastModel;
|
|
82
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
83
|
+
_embedder = (await FlagEmbedding.init({
|
|
84
|
+
model: modelEnum,
|
|
85
|
+
cacheDir,
|
|
86
|
+
showDownloadProgress: false,
|
|
87
|
+
}));
|
|
88
|
+
_currentModel = model;
|
|
89
|
+
_currentCacheDir = cacheDir;
|
|
90
|
+
const models = _embedder.listSupportedModels();
|
|
91
|
+
const info = models.find((m) => m.model === model);
|
|
92
|
+
return { dim: info?.dim ?? 0 };
|
|
93
|
+
}
|
|
94
|
+
async function collectEmbeddings(embedder, texts) {
|
|
95
|
+
const results = [];
|
|
96
|
+
for await (const batch of embedder.embed(texts, 256)) {
|
|
97
|
+
for (const vec of batch) {
|
|
98
|
+
results.push(vec);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return results;
|
|
102
|
+
}
|
|
103
|
+
// ── Serialized request queue ────────────────────────────────────────────────
|
|
104
|
+
//
|
|
105
|
+
// Defense in depth: also serialize requests within this process (init vs.
|
|
106
|
+
// embed/embedBatch racing against each other has no known hazard today since
|
|
107
|
+
// only ONE onnxruntime-node version ever loads in this process, but there is
|
|
108
|
+
// no benefit to concurrent native calls here either — correctness first).
|
|
109
|
+
let _queue = Promise.resolve();
|
|
110
|
+
function enqueue(task) {
|
|
111
|
+
_queue = _queue.then(task, task);
|
|
112
|
+
}
|
|
113
|
+
function send(msg) {
|
|
114
|
+
process.send?.(msg);
|
|
115
|
+
}
|
|
116
|
+
async function handleRequest(msg) {
|
|
117
|
+
if (msg.type === 'init') {
|
|
118
|
+
try {
|
|
119
|
+
const { dim } = await loadModel(msg.model, msg.cacheDir);
|
|
120
|
+
send({ id: msg.id, initOk: true, dim });
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
send({ id: msg.id, error: String(e instanceof Error ? e.message : e) });
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (msg.type === 'embed') {
|
|
128
|
+
if (!_embedder) {
|
|
129
|
+
send({ id: msg.id, error: 'Model not initialized' });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const vec = await _embedder.queryEmbed(msg.text);
|
|
134
|
+
send({ id: msg.id, embedding: Array.from(vec) });
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
send({ id: msg.id, error: String(e instanceof Error ? e.message : e) });
|
|
138
|
+
}
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (msg.type === 'embedBatch') {
|
|
142
|
+
if (!_embedder) {
|
|
143
|
+
send({ id: msg.id, error: 'Model not initialized' });
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
const embeddings = await collectEmbeddings(_embedder, msg.texts);
|
|
148
|
+
send({ id: msg.id, embeddings });
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
send({ id: msg.id, error: String(e instanceof Error ? e.message : e) });
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
process.on('message', (msg) => {
|
|
157
|
+
if ('__shutdown' in msg) {
|
|
158
|
+
process.exit(0);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
enqueue(() => handleRequest(msg));
|
|
162
|
+
});
|
|
163
|
+
// Let the parent decide the process lifecycle (it never calls `.ref()`/relies
|
|
164
|
+
// on this process staying alive beyond its own `disconnect`/`kill`); nothing
|
|
165
|
+
// else to keep this process alive once IPC is torn down.
|
|
166
|
+
//# sourceMappingURL=fastembedProcessHost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastembedProcessHost.js","sourceRoot":"","sources":["../src/fastembedProcessHost.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
export type EmbedRole = 'document' | 'query';
|
|
2
|
+
export interface EmbeddingProviderMetadata {
|
|
3
|
+
modelId: string;
|
|
4
|
+
dimensions: number;
|
|
5
|
+
maxTokens: number;
|
|
6
|
+
isRemote: boolean;
|
|
7
|
+
isDeterministic: boolean;
|
|
8
|
+
providerUri?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface EmbeddingHealth {
|
|
11
|
+
configured: string;
|
|
12
|
+
active: string | null;
|
|
13
|
+
state: 'uninitialized' | 'warming' | 'real' | 'error';
|
|
14
|
+
dimensions: number | null;
|
|
15
|
+
last_error: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface EmbeddingProvider {
|
|
18
|
+
readonly metadata: EmbeddingProviderMetadata;
|
|
19
|
+
embedSingle(text: string, role?: EmbedRole): Promise<Float32Array>;
|
|
20
|
+
embedBatch(texts: string[], opts?: {
|
|
21
|
+
role?: EmbedRole;
|
|
22
|
+
batchSize?: number;
|
|
23
|
+
}): AsyncIterable<Float32Array>;
|
|
24
|
+
warmUp(texts: string[]): Promise<void>;
|
|
25
|
+
/** Return the current embedding health per CONTRACTS §E. */
|
|
26
|
+
health(): EmbeddingHealth;
|
|
27
|
+
}
|
|
28
|
+
export interface EmbeddingProviderConfig {
|
|
29
|
+
type: string;
|
|
30
|
+
model: string;
|
|
31
|
+
options?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
export declare class TransientEmbeddingError extends Error {
|
|
34
|
+
readonly retryAfterMs: number | undefined;
|
|
35
|
+
constructor(message: string, retryAfterMs?: number);
|
|
36
|
+
}
|
|
37
|
+
export declare class PermanentEmbeddingError extends Error {
|
|
38
|
+
constructor(message: string);
|
|
39
|
+
}
|
|
40
|
+
export declare class ResolutionError extends Error {
|
|
41
|
+
constructor(message: string);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Static registration for a fastembed ONNX model.
|
|
45
|
+
* Each model has a known HF repo, dimension, context window, and description.
|
|
46
|
+
*/
|
|
47
|
+
export interface FastEmbedModelConfig {
|
|
48
|
+
modelId: string;
|
|
49
|
+
hfRepoId: string;
|
|
50
|
+
dim: number;
|
|
51
|
+
maxTokens: number;
|
|
52
|
+
description: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Worker thread pool configuration for fastembed ONNX inference.
|
|
56
|
+
*
|
|
57
|
+
* SOX-DOC-004: not currently consumed by `createEmbeddingProvider()` /
|
|
58
|
+
* `createFastembedProvider()` — no code constructs or reads a
|
|
59
|
+
* `FastEmbedPoolConfig` today. Kept as a forward-declared shape for a future
|
|
60
|
+
* multi-worker pool; do not assume it has any runtime effect yet.
|
|
61
|
+
*/
|
|
62
|
+
export interface FastEmbedPoolConfig {
|
|
63
|
+
/** Maximum number of ONNX inference workers. Default: os.cpus().length / 2, minimum 1. */
|
|
64
|
+
maxWorkers?: number;
|
|
65
|
+
/** Models to preload at pool init. Lazy-load on first use if omitted. */
|
|
66
|
+
preloadModels?: string[];
|
|
67
|
+
/** Per-model batch size hint. Overrides the default 256 (`DEFAULT_BATCH_SIZE` in fastembed.ts). */
|
|
68
|
+
batchSizes?: Record<string, number>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Policy for migrating vectors from one embedding model to another.
|
|
72
|
+
*/
|
|
73
|
+
export interface ReembedPolicy {
|
|
74
|
+
sourceModel: string;
|
|
75
|
+
targetModel: string;
|
|
76
|
+
batchSize: number;
|
|
77
|
+
dryRun: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Local model cache: download, verify SHA-256, and manage model binaries.
|
|
81
|
+
* Binaries are stored at <dataRoot>/models/<modelId>/<version>/ with a sidecar .sha256 file.
|
|
82
|
+
*
|
|
83
|
+
* @deprecated SOX-BUG-002: dead API. `createEmbeddingProvider()` /
|
|
84
|
+
* `FastembedProvider` never accept or use a `ModelCache` — fastembed resolves
|
|
85
|
+
* a plain `cacheDir` STRING and `FlagEmbedding.init({ model, cacheDir })`
|
|
86
|
+
* downloads and caches the model for itself. That string is resolved as
|
|
87
|
+
* `config.options.cacheDir` → `SOX_EMBED_CACHE_DIR` → `$XDG_CACHE_HOME/sox/models`
|
|
88
|
+
* → `~/.cache/sox/models`. This interface (and `FileSystemModelCache` below)
|
|
89
|
+
* is kept only for external consumers who may already depend on it; do not
|
|
90
|
+
* wire it into the factory expecting it to have any effect.
|
|
91
|
+
*/
|
|
92
|
+
export interface ModelCache {
|
|
93
|
+
/** Download and verify model binary. Returns once the model is ready. Throws ResolutionError on SHA-256 mismatch. */
|
|
94
|
+
ensure(modelId: string): Promise<void>;
|
|
95
|
+
/** Check whether the model binary is already in local cache. */
|
|
96
|
+
cached(modelId: string): boolean;
|
|
97
|
+
/** Remove a single model from cache. Does not affect other models. */
|
|
98
|
+
clear(modelId: string): Promise<void>;
|
|
99
|
+
/** Streaming download with progress. Yields byte-level progress updates. */
|
|
100
|
+
ensureStream(modelId: string): AsyncIterable<{
|
|
101
|
+
bytesDownloaded: number;
|
|
102
|
+
totalBytes: number;
|
|
103
|
+
}>;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* @deprecated SOX-BUG-002: dead API, not used by `createEmbeddingProvider` or
|
|
107
|
+
* `FastembedProvider`. Fastembed manages its own model cache internally via
|
|
108
|
+
* the `cacheDir` string (see `ModelCache` JSDoc above for the resolution
|
|
109
|
+
* order). Kept only for external consumers; do not wire it into the factory.
|
|
110
|
+
*/
|
|
111
|
+
export { FileSystemModelCache } from './cache.js';
|
|
112
|
+
/**
|
|
113
|
+
* BL-238/BL-171 fix: the single shared ONNX worker singleton for rerank +
|
|
114
|
+
* verify. `@adhd/sox-hybrid-search`'s cross-encoder and
|
|
115
|
+
* `@adhd/sox-claim-verification`'s NLI verifier MUST route ONNX inference
|
|
116
|
+
* through this one process-wide `worker_threads.Worker` instead of
|
|
117
|
+
* constructing their own — see `sharedOnnxWorker.ts` for the full
|
|
118
|
+
* root-cause writeup and rationale.
|
|
119
|
+
*/
|
|
120
|
+
export { getSharedOnnxWorker, SharedOnnxWorkerClient } from './sharedOnnxWorker.js';
|
|
121
|
+
/**
|
|
122
|
+
* BL-238/BL-171 fix: the single shared fastembed CHILD PROCESS singleton.
|
|
123
|
+
* This package's own `FastembedProvider` routes ONNX inference through this
|
|
124
|
+
* one process-wide child process instead of constructing its own
|
|
125
|
+
* `worker_threads.Worker` or process — fastembed's onnxruntime-node@1.21.0
|
|
126
|
+
* cannot safely share a thread with `getSharedOnnxWorker()`'s
|
|
127
|
+
* onnxruntime-node@1.24.3, even sequentially — see
|
|
128
|
+
* `sharedFastembedProcess.ts` / `fastembedProcessHost.ts` for the full
|
|
129
|
+
* root-cause writeup and rationale.
|
|
130
|
+
*/
|
|
131
|
+
export { getSharedFastembedProcess, SharedFastembedProcessClient, } from './sharedFastembedProcess.js';
|
|
132
|
+
export declare function createEmbeddingProvider(config: EmbeddingProviderConfig): Promise<EmbeddingProvider>;
|
|
133
|
+
/**
|
|
134
|
+
* Single source of truth for the fastembed warmup/init timeout budget.
|
|
135
|
+
*
|
|
136
|
+
* Shared by TWO call sites that were previously two disagreeing copies
|
|
137
|
+
* (SOX-BUG-001): the outer `createFastembedProvider()` factory wrapper
|
|
138
|
+
* (below) that bounds the initial `embedSingle('warmup')` call, AND the
|
|
139
|
+
* inner `FastembedProvider`'s worker-init `readyPromise` timeout
|
|
140
|
+
* (fastembed.ts) that bounds the actual ONNX model load inside the worker
|
|
141
|
+
* thread. Both now read this one function/env var so a cold ONNX model
|
|
142
|
+
* download is bounded consistently end-to-end.
|
|
143
|
+
*/
|
|
144
|
+
export declare function warmupTimeoutMs(): number;
|
|
145
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAE7C,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACtD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,CAAC;IAC7C,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACnE,UAAU,CACR,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,aAAa,CAAC,YAAY,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,4DAA4D;IAC5D,MAAM,IAAI,eAAe,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAID,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;gBAC9B,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;CAKnD;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAID;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,0FAA0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,UAAU;IACzB,qHAAqH;IACrH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,gEAAgE;IAChE,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,sEAAsE;IACtE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,4EAA4E;IAC5E,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/F;AAID;;;;;GAKG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;;;GAOG;AACH,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEpF;;;;;;;;;GASG;AACH,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,6BAA6B,CAAC;AAIrC,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,iBAAiB,CAAC,CAe5B;AA2DD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAGxC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// @adhd/sox-embedding-provider — pluggable text→vector embedding
|
|
2
|
+
// Authoritative interface spec: docs/plan/memory-refactor/COMPILED_INTERFACES.md
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
// ── Error taxonomy — three tiers, no silent degradation ──────────────────────
|
|
6
|
+
export class TransientEmbeddingError extends Error {
|
|
7
|
+
retryAfterMs;
|
|
8
|
+
constructor(message, retryAfterMs) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'TransientEmbeddingError';
|
|
11
|
+
this.retryAfterMs = retryAfterMs;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class PermanentEmbeddingError extends Error {
|
|
15
|
+
constructor(message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = 'PermanentEmbeddingError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class ResolutionError extends Error {
|
|
21
|
+
constructor(message) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = 'ResolutionError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// ── Re-exports ────────────────────────────────────────────────────────────────
|
|
27
|
+
/**
|
|
28
|
+
* @deprecated SOX-BUG-002: dead API, not used by `createEmbeddingProvider` or
|
|
29
|
+
* `FastembedProvider`. Fastembed manages its own model cache internally via
|
|
30
|
+
* the `cacheDir` string (see `ModelCache` JSDoc above for the resolution
|
|
31
|
+
* order). Kept only for external consumers; do not wire it into the factory.
|
|
32
|
+
*/
|
|
33
|
+
export { FileSystemModelCache } from './cache.js';
|
|
34
|
+
/**
|
|
35
|
+
* BL-238/BL-171 fix: the single shared ONNX worker singleton for rerank +
|
|
36
|
+
* verify. `@adhd/sox-hybrid-search`'s cross-encoder and
|
|
37
|
+
* `@adhd/sox-claim-verification`'s NLI verifier MUST route ONNX inference
|
|
38
|
+
* through this one process-wide `worker_threads.Worker` instead of
|
|
39
|
+
* constructing their own — see `sharedOnnxWorker.ts` for the full
|
|
40
|
+
* root-cause writeup and rationale.
|
|
41
|
+
*/
|
|
42
|
+
export { getSharedOnnxWorker, SharedOnnxWorkerClient } from './sharedOnnxWorker.js';
|
|
43
|
+
/**
|
|
44
|
+
* BL-238/BL-171 fix: the single shared fastembed CHILD PROCESS singleton.
|
|
45
|
+
* This package's own `FastembedProvider` routes ONNX inference through this
|
|
46
|
+
* one process-wide child process instead of constructing its own
|
|
47
|
+
* `worker_threads.Worker` or process — fastembed's onnxruntime-node@1.21.0
|
|
48
|
+
* cannot safely share a thread with `getSharedOnnxWorker()`'s
|
|
49
|
+
* onnxruntime-node@1.24.3, even sequentially — see
|
|
50
|
+
* `sharedFastembedProcess.ts` / `fastembedProcessHost.ts` for the full
|
|
51
|
+
* root-cause writeup and rationale.
|
|
52
|
+
*/
|
|
53
|
+
export { getSharedFastembedProcess, SharedFastembedProcessClient, } from './sharedFastembedProcess.js';
|
|
54
|
+
// ── Factory ───────────────────────────────────────────────────────────────────
|
|
55
|
+
export async function createEmbeddingProvider(config) {
|
|
56
|
+
if (!config.type || typeof config.type !== 'string') {
|
|
57
|
+
throw new ResolutionError(`Invalid provider type: ${String(config.type)}`);
|
|
58
|
+
}
|
|
59
|
+
switch (config.type) {
|
|
60
|
+
case 'fastembed':
|
|
61
|
+
return createFastembedProvider(config);
|
|
62
|
+
case 'remote':
|
|
63
|
+
return createRemoteProvider(config);
|
|
64
|
+
default:
|
|
65
|
+
throw new ResolutionError(`Unknown embedding provider type: "${config.type}" (expected 'fastembed' or 'remote')`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// ── Provider factories ────────────────────────────────────────────────────────
|
|
69
|
+
async function createFastembedProvider(config) {
|
|
70
|
+
const { FastembedProvider, MODEL_CONFIGS, DEFAULT_MODEL } = await import('./fastembed.js');
|
|
71
|
+
const modelId = config.model || DEFAULT_MODEL;
|
|
72
|
+
const cfg = MODEL_CONFIGS[modelId];
|
|
73
|
+
if (!cfg) {
|
|
74
|
+
throw new ResolutionError(`Unknown fastembed model: "${modelId}". Supported: ${Object.keys(MODEL_CONFIGS).join(', ')}`);
|
|
75
|
+
}
|
|
76
|
+
const cacheDir = config.options?.['cacheDir'] ??
|
|
77
|
+
process.env['SOX_EMBED_CACHE_DIR'] ??
|
|
78
|
+
joinDefaultCacheDir();
|
|
79
|
+
try {
|
|
80
|
+
const provider = new FastembedProvider(modelId, cfg.dim, cacheDir);
|
|
81
|
+
await withTimeout(provider.embedSingle('warmup'), warmupTimeoutMs(), 'fastembed warmup');
|
|
82
|
+
return provider;
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
if (err instanceof ResolutionError)
|
|
86
|
+
throw err;
|
|
87
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
88
|
+
throw new ResolutionError(`Fastembed provider "${modelId}" failed to initialise: ${message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async function createRemoteProvider(config) {
|
|
92
|
+
const { RemoteProvider } = await import('./remote.js');
|
|
93
|
+
const modelId = config.model || 'remote-768';
|
|
94
|
+
const dimensions = config.options?.['dimensions'] ?? 768;
|
|
95
|
+
const endpoint = config.options?.['endpoint'] ?? '';
|
|
96
|
+
const apiKey = config.options?.['apiKey'];
|
|
97
|
+
if (!endpoint) {
|
|
98
|
+
throw new ResolutionError('Remote provider requires an endpoint URL in config.options.endpoint');
|
|
99
|
+
}
|
|
100
|
+
return new RemoteProvider(modelId, dimensions, endpoint, apiKey);
|
|
101
|
+
}
|
|
102
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
103
|
+
/**
|
|
104
|
+
* Single source of truth for the fastembed warmup/init timeout budget.
|
|
105
|
+
*
|
|
106
|
+
* Shared by TWO call sites that were previously two disagreeing copies
|
|
107
|
+
* (SOX-BUG-001): the outer `createFastembedProvider()` factory wrapper
|
|
108
|
+
* (below) that bounds the initial `embedSingle('warmup')` call, AND the
|
|
109
|
+
* inner `FastembedProvider`'s worker-init `readyPromise` timeout
|
|
110
|
+
* (fastembed.ts) that bounds the actual ONNX model load inside the worker
|
|
111
|
+
* thread. Both now read this one function/env var so a cold ONNX model
|
|
112
|
+
* download is bounded consistently end-to-end.
|
|
113
|
+
*/
|
|
114
|
+
export function warmupTimeoutMs() {
|
|
115
|
+
const raw = Number(process.env['SOX_EMBED_WARMUP_TIMEOUT_MS']);
|
|
116
|
+
return Number.isFinite(raw) && raw > 0 ? raw : 180_000;
|
|
117
|
+
}
|
|
118
|
+
function withTimeout(p, ms, label) {
|
|
119
|
+
return new Promise((resolve, reject) => {
|
|
120
|
+
const to = setTimeout(() => {
|
|
121
|
+
reject(new Error(`${label} timed out after ${ms}ms`));
|
|
122
|
+
}, ms);
|
|
123
|
+
if (typeof to.unref === 'function')
|
|
124
|
+
to.unref();
|
|
125
|
+
p.then((v) => {
|
|
126
|
+
clearTimeout(to);
|
|
127
|
+
resolve(v);
|
|
128
|
+
}, (e) => {
|
|
129
|
+
clearTimeout(to);
|
|
130
|
+
reject(e instanceof Error ? e : new Error(String(e)));
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function joinDefaultCacheDir() {
|
|
135
|
+
const xdg = process.env['XDG_CACHE_HOME'];
|
|
136
|
+
return join(xdg ?? join(homedir(), '.cache'), 'sox', 'models');
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@adhd/sox-embedding-provider",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Pluggable text→vector embedding provider — generic EmbeddingProvider interface, config-driven model resolution, async batch-first API (AsyncIterable). Default: fastembed (local ONNX, >=3 model dims proven). Loud-fail: createEmbeddingProvider() throws ResolutionError if config is invalid or model cannot load — no silent downgrade.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"private": false,
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=22"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@huggingface/transformers": "^4.2.0",
|
|
27
|
+
"fastembed": "^2.1.0"
|
|
28
|
+
},
|
|
29
|
+
"sox": {
|
|
30
|
+
"area": "data",
|
|
31
|
+
"group": "embed",
|
|
32
|
+
"concerns": [
|
|
33
|
+
"text→vector (EmbeddingProvider interface)",
|
|
34
|
+
"config-driven model resolution (createEmbeddingProvider factory)",
|
|
35
|
+
"async batch embed (AsyncIterable<Float32Array>)",
|
|
36
|
+
"EmbedRole param (document | query) accepted on embedSingle/embedBatch for interface compatibility — currently ignored (not yet applied) by the fastembed provider",
|
|
37
|
+
"loud-fail ResolutionError at factory time (never mid-call)",
|
|
38
|
+
"three-tier error taxonomy (Transient / Permanent / Resolution)"
|
|
39
|
+
],
|
|
40
|
+
"invariants": [
|
|
41
|
+
"createEmbeddingProvider() THROWS ResolutionError synchronously or as a rejection if the config is invalid or the model/runtime cannot load — never silently downgrades",
|
|
42
|
+
"every provider advertises { modelId, dimensions, isRemote, isDeterministic, providerUri? } via metadata — callers never hardcode dims",
|
|
43
|
+
"embedBatch() returns AsyncIterable<Float32Array> — callers receive first result before last batch finishes (critical for sequential local inference)",
|
|
44
|
+
"warmUp() is a no-op when isDeterministic === false — currently ALWAYS true, since every shipped provider (fastembed, remote) hard-codes isDeterministic: false, so warmUp() is a no-op on every path today",
|
|
45
|
+
"TransientEmbeddingError → caller may retry; PermanentEmbeddingError → caller must not retry; ResolutionError → factory-time only, never thrown mid-call"
|
|
46
|
+
],
|
|
47
|
+
"entrypoints": [
|
|
48
|
+
"dist/index.js"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"module": "./index.js"
|
|
52
|
+
}
|
package/dist/remote.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { EmbeddingHealth, EmbeddingProvider, EmbeddingProviderMetadata, EmbedRole } from './index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Remote provider adapter — typed reference implementation.
|
|
4
|
+
*
|
|
5
|
+
* Implements EmbeddingProvider against the same async+batch-first contract.
|
|
6
|
+
* NOT wired to a live/paid endpoint — proves context-agnosticism without spend.
|
|
7
|
+
*/
|
|
8
|
+
export declare class RemoteProvider implements EmbeddingProvider {
|
|
9
|
+
readonly metadata: EmbeddingProviderMetadata;
|
|
10
|
+
private endpoint;
|
|
11
|
+
private apiKey;
|
|
12
|
+
constructor(modelId: string, dimensions: number, endpoint: string, apiKey?: string);
|
|
13
|
+
embedSingle(text: string, role?: EmbedRole): Promise<Float32Array>;
|
|
14
|
+
embedBatch(texts: string[], opts?: {
|
|
15
|
+
role?: EmbedRole;
|
|
16
|
+
batchSize?: number;
|
|
17
|
+
}): AsyncIterable<Float32Array>;
|
|
18
|
+
health(): EmbeddingHealth;
|
|
19
|
+
warmUp(_texts: string[]): Promise<void>;
|
|
20
|
+
private validateEndpoint;
|
|
21
|
+
private simulatedRemoteEmbed;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=remote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG3G;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,iBAAiB;IACtD,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,CAAC;IAC7C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAqB;gBAEvB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAa5E,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC;IAgBjE,UAAU,CACf,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,aAAa,CAAC,YAAY,CAAC;IAqB9B,MAAM,IAAI,eAAe;IAUnB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,OAAO,CAAC,gBAAgB;YAaV,oBAAoB;CAgBnC"}
|