@kelceyp/caw-server 1.0.197 → 1.0.199
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 +37 -11
- package/dist/main.js +395 -385
- package/dist/pty-wrapper.mjs +375 -0
- package/dist/public_html/main.js +450 -449
- package/dist/public_html/styles.css +1 -1
- package/package.json +5 -3
package/dist/embedding-worker.js
CHANGED
|
@@ -21,6 +21,17 @@
|
|
|
21
21
|
|
|
22
22
|
import { createInterface } from 'readline';
|
|
23
23
|
|
|
24
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
25
|
+
const pad3 = (n) => String(n).padStart(3, '0');
|
|
26
|
+
const formatTimestamp = () => {
|
|
27
|
+
const now = new Date();
|
|
28
|
+
const h = now.getHours();
|
|
29
|
+
const ampm = h >= 12 ? 'pm' : 'am';
|
|
30
|
+
const h12 = h % 12 || 12;
|
|
31
|
+
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}` +
|
|
32
|
+
` ${pad(h12)}:${pad(now.getMinutes())}:${pad(now.getSeconds())}.${pad3(now.getMilliseconds())} ${ampm}`;
|
|
33
|
+
};
|
|
34
|
+
|
|
24
35
|
const MODEL_NAME = process.env.EMBEDDING_MODEL || 'nomic-ai/nomic-embed-text-v1.5';
|
|
25
36
|
const CACHE_DIR = process.env.EMBEDDING_CACHE_DIR || null;
|
|
26
37
|
|
|
@@ -50,17 +61,17 @@ const run = async () => {
|
|
|
50
61
|
},
|
|
51
62
|
progress_callback: (progress) => {
|
|
52
63
|
if (progress.status === 'download') {
|
|
53
|
-
process.stderr.write(
|
|
64
|
+
process.stderr.write(`${formatTimestamp()} [EmbeddingWorker] Downloading: ${progress.file} (${Math.round((progress.loaded / progress.total) * 100)}%)\n`);
|
|
54
65
|
} else if (progress.status === 'ready') {
|
|
55
66
|
const suffix = progress.file ? `: ${progress.file}` : '';
|
|
56
|
-
process.stderr.write(
|
|
67
|
+
process.stderr.write(`${formatTimestamp()} [EmbeddingWorker] Ready${suffix}\n`);
|
|
57
68
|
}
|
|
58
69
|
}
|
|
59
70
|
});
|
|
60
71
|
|
|
61
72
|
// Log loaded model details and baseline memory
|
|
62
73
|
const rss = Math.round(process.memoryUsage().rss / 1024 / 1024);
|
|
63
|
-
process.stderr.write(
|
|
74
|
+
process.stderr.write(`${formatTimestamp()} [EmbeddingWorker] Model loaded. RSS: ${rss}MB\n`);
|
|
64
75
|
|
|
65
76
|
sendLine({ ready: true });
|
|
66
77
|
} catch (err) {
|
|
@@ -81,26 +92,41 @@ const run = async () => {
|
|
|
81
92
|
return;
|
|
82
93
|
}
|
|
83
94
|
|
|
84
|
-
const { texts } = req;
|
|
95
|
+
const { texts, maxLength } = req;
|
|
85
96
|
if (!Array.isArray(texts)) {
|
|
86
97
|
sendLine({ error: 'Request must have a texts array' });
|
|
87
98
|
return;
|
|
88
99
|
}
|
|
89
100
|
|
|
90
|
-
|
|
91
|
-
const output = await pipe(texts, { pooling: 'mean', normalize: false });
|
|
92
|
-
// Serialise: output.data is a flat Float32Array [batch * dims]
|
|
101
|
+
const extractVectors = (output, count) => {
|
|
93
102
|
const dims = output.dims[output.dims.length - 1];
|
|
94
103
|
const vectors = [];
|
|
95
|
-
for (let i = 0; i <
|
|
104
|
+
for (let i = 0; i < count; i++) {
|
|
96
105
|
const start = i * dims;
|
|
97
|
-
|
|
98
|
-
vectors.push(Array.from(output.data.slice(start, end)));
|
|
106
|
+
vectors.push(Array.from(output.data.slice(start, start + dims)));
|
|
99
107
|
}
|
|
100
108
|
output.dispose();
|
|
109
|
+
return vectors;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
let output;
|
|
114
|
+
if (maxLength !== undefined) {
|
|
115
|
+
const paddingOptions = { pooling: 'mean', normalize: false, padding: 'max_length', max_length: maxLength };
|
|
116
|
+
try {
|
|
117
|
+
output = await pipe(texts, paddingOptions);
|
|
118
|
+
} catch (_paddingErr) {
|
|
119
|
+
process.stderr.write(`${formatTimestamp()} [EmbeddingWorker] padding options unsupported, retrying without padding\n`);
|
|
120
|
+
output = await pipe(texts, { pooling: 'mean', normalize: false });
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
output = await pipe(texts, { pooling: 'mean', normalize: false });
|
|
124
|
+
}
|
|
125
|
+
const vectors = extractVectors(output, texts.length);
|
|
101
126
|
embedCallCount++;
|
|
102
127
|
const embedRss = Math.round(process.memoryUsage().rss / 1024 / 1024);
|
|
103
|
-
|
|
128
|
+
const shapeStr = maxLength !== undefined ? `[${texts.length}×${maxLength}]` : `[${texts.length}×var]`;
|
|
129
|
+
process.stderr.write(`${formatTimestamp()} [EmbeddingWorker] Embed #${embedCallCount}: shape=${shapeStr}, RSS: ${embedRss}MB\n`);
|
|
104
130
|
sendLine({ vectors });
|
|
105
131
|
} catch (err) {
|
|
106
132
|
sendLine({ error: `Embedding failed: ${err.message}` });
|