@velvetmonkey/flywheel-memory 2.5.10 → 2.5.12
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/embedding-worker.js +76 -0
- package/dist/index.js +806 -781
- package/package.json +4 -4
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// src/core/read/embedding-worker.ts
|
|
2
|
+
import { parentPort } from "node:worker_threads";
|
|
3
|
+
if (!parentPort) {
|
|
4
|
+
throw new Error("embedding-worker.ts must be run as a worker thread");
|
|
5
|
+
}
|
|
6
|
+
var port = parentPort;
|
|
7
|
+
var pipeline = null;
|
|
8
|
+
var modelDims = 0;
|
|
9
|
+
async function loadModel(modelId) {
|
|
10
|
+
const MAX_RETRIES = 3;
|
|
11
|
+
const RETRY_DELAYS = [2e3, 5e3, 1e4];
|
|
12
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
13
|
+
try {
|
|
14
|
+
const transformers = await Function("specifier", "return import(specifier)")("@huggingface/transformers");
|
|
15
|
+
pipeline = await transformers.pipeline("feature-extraction", modelId, {
|
|
16
|
+
dtype: "fp32"
|
|
17
|
+
});
|
|
18
|
+
const probe = await pipeline("test", { pooling: "mean", normalize: true });
|
|
19
|
+
modelDims = probe.data.length;
|
|
20
|
+
port.postMessage({ type: "ready", dims: modelDims });
|
|
21
|
+
return;
|
|
22
|
+
} catch (err) {
|
|
23
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
24
|
+
if (err instanceof Error && (errMsg.includes("Cannot find package") || errMsg.includes("MODULE_NOT_FOUND") || errMsg.includes("Cannot find module") || errMsg.includes("ERR_MODULE_NOT_FOUND"))) {
|
|
25
|
+
port.postMessage({
|
|
26
|
+
type: "error",
|
|
27
|
+
message: "Semantic search requires @huggingface/transformers. Install it with: npm install @huggingface/transformers",
|
|
28
|
+
fatal: true
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (attempt < MAX_RETRIES) {
|
|
33
|
+
const delay = RETRY_DELAYS[attempt - 1];
|
|
34
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
35
|
+
} else {
|
|
36
|
+
port.postMessage({
|
|
37
|
+
type: "error",
|
|
38
|
+
message: `Model load failed after ${MAX_RETRIES} attempts: ${errMsg}`,
|
|
39
|
+
fatal: true
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function embed(id, text) {
|
|
46
|
+
if (!pipeline) {
|
|
47
|
+
port.postMessage({ type: "error", id, message: "Model not loaded", fatal: false });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const truncated = text.slice(0, 2e3);
|
|
52
|
+
const result = await pipeline(truncated, { pooling: "mean", normalize: true });
|
|
53
|
+
const embedding = new Float32Array(result.data);
|
|
54
|
+
port.postMessage({ type: "result", id, embedding }, [embedding.buffer]);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
port.postMessage({
|
|
57
|
+
type: "error",
|
|
58
|
+
id,
|
|
59
|
+
message: err instanceof Error ? err.message : String(err),
|
|
60
|
+
fatal: false
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
port.on("message", (msg) => {
|
|
65
|
+
switch (msg.type) {
|
|
66
|
+
case "init":
|
|
67
|
+
loadModel(msg.modelId);
|
|
68
|
+
break;
|
|
69
|
+
case "embed":
|
|
70
|
+
embed(msg.id, msg.text);
|
|
71
|
+
break;
|
|
72
|
+
case "shutdown":
|
|
73
|
+
process.exit(0);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
});
|