@delali/narsil 0.1.5 → 0.1.7
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 +130 -2
- package/dist/adapters/filesystem.d.ts +1 -1
- package/dist/adapters/filesystem.mjs +1 -1
- package/dist/adapters/indexeddb.d.ts +1 -1
- package/dist/adapters/indexeddb.mjs +1 -1
- package/dist/adapters/memory.d.ts +1 -1
- package/dist/{adapters-XODT2F3h.d.ts → adapters-BbRkoiu9.d.ts} +7 -1
- package/dist/{chunk-WYC635GI.mjs → chunk-I24SGLFS.mjs} +5 -6
- package/dist/{chunk-TFWBALU4.mjs → chunk-KHL4RPC3.mjs} +1957 -1053
- package/dist/{chunk-7GKPWGCN.mjs → chunk-R2C2EQGO.mjs} +12 -2
- package/dist/{chunk-GVN2W4VA.mjs → chunk-VVORJOXR.mjs} +273 -84
- package/dist/direct-executor-LBJLGMJ2.mjs +4 -0
- package/dist/embeddings/openai.d.ts +13 -0
- package/dist/embeddings/openai.mjs +248 -0
- package/dist/index.browser.mjs +7887 -5557
- package/dist/index.d.ts +83 -49
- package/dist/index.mjs +1886 -702
- package/dist/invalidation/broadcast-channel.d.ts +1 -1
- package/dist/invalidation/filesystem.d.ts +1 -1
- package/dist/invalidation/noop.d.ts +1 -1
- package/dist/languages/english.mjs +1 -1
- package/dist/vector/hnsw-build-worker.d.ts +9 -2
- package/dist/vector/hnsw-build-worker.mjs +54 -10
- package/dist/workers/entry.mjs +1 -1
- package/package.json +10 -3
- package/dist/direct-executor-6TSG7GWH.mjs +0 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
export { english } from '../chunk-
|
|
1
|
+
export { english } from '../chunk-I24SGLFS.mjs';
|
|
@@ -6,7 +6,7 @@ interface HNSWConfig {
|
|
|
6
6
|
metric?: VectorMetric;
|
|
7
7
|
}
|
|
8
8
|
interface SerializedHNSWGraph {
|
|
9
|
-
entryPoint: string;
|
|
9
|
+
entryPoint: string | null;
|
|
10
10
|
maxLayer: number;
|
|
11
11
|
m: number;
|
|
12
12
|
efConstruction: number;
|
|
@@ -23,6 +23,13 @@ interface HNSWBuildRequest {
|
|
|
23
23
|
dimension: number;
|
|
24
24
|
config: HNSWConfig;
|
|
25
25
|
}
|
|
26
|
+
interface HNSWBuildRequestBinary {
|
|
27
|
+
type: 'build-binary';
|
|
28
|
+
docIds: string[];
|
|
29
|
+
vectorData: Float32Array;
|
|
30
|
+
dimension: number;
|
|
31
|
+
config: HNSWConfig;
|
|
32
|
+
}
|
|
26
33
|
interface HNSWBuildResponse {
|
|
27
34
|
type: 'success';
|
|
28
35
|
graph: SerializedHNSWGraph;
|
|
@@ -34,4 +41,4 @@ interface HNSWBuildError {
|
|
|
34
41
|
type HNSWWorkerMessage = HNSWBuildResponse | HNSWBuildError;
|
|
35
42
|
declare function handleBuildRequest(request: HNSWBuildRequest): SerializedHNSWGraph;
|
|
36
43
|
|
|
37
|
-
export { type HNSWBuildError, type HNSWBuildRequest, type HNSWBuildResponse, type HNSWWorkerMessage, handleBuildRequest };
|
|
44
|
+
export { type HNSWBuildError, type HNSWBuildRequest, type HNSWBuildRequestBinary, type HNSWBuildResponse, type HNSWWorkerMessage, handleBuildRequest };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHNSWIndex } from '../chunk-
|
|
1
|
+
import { createVectorStore, createHNSWIndex } from '../chunk-VVORJOXR.mjs';
|
|
2
2
|
|
|
3
3
|
// src/vector/hnsw-build-worker.ts
|
|
4
4
|
var MAX_WORKER_DIMENSION = 8192;
|
|
@@ -23,15 +23,63 @@ function validateBuildRequest(request) {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
function clampHNSWConfig(config) {
|
|
27
|
+
return {
|
|
28
|
+
...config,
|
|
29
|
+
m: config.m != null ? Math.max(2, Math.min(64, config.m)) : void 0,
|
|
30
|
+
efConstruction: config.efConstruction != null ? Math.max(10, Math.min(1e3, config.efConstruction)) : void 0
|
|
31
|
+
};
|
|
32
|
+
}
|
|
26
33
|
function handleBuildRequest(request) {
|
|
27
34
|
validateBuildRequest(request);
|
|
28
|
-
const
|
|
35
|
+
const safeConfig = clampHNSWConfig(request.config);
|
|
36
|
+
const store = createVectorStore();
|
|
37
|
+
for (const entry of request.vectors) {
|
|
38
|
+
store.insert(entry.docId, new Float32Array(entry.values));
|
|
39
|
+
}
|
|
40
|
+
const hnsw = createHNSWIndex(request.dimension, store, safeConfig);
|
|
29
41
|
for (const entry of request.vectors) {
|
|
30
|
-
|
|
31
|
-
hnsw.insert(entry.docId, vec);
|
|
42
|
+
hnsw.insertNode(entry.docId);
|
|
32
43
|
}
|
|
33
44
|
return hnsw.serialize();
|
|
34
45
|
}
|
|
46
|
+
function handleBuildRequestBinary(request) {
|
|
47
|
+
const { docIds, vectorData, dimension, config } = request;
|
|
48
|
+
if (!Number.isInteger(dimension) || dimension <= 0 || dimension > MAX_WORKER_DIMENSION) {
|
|
49
|
+
throw new Error(`Invalid dimension: ${dimension} (must be 1..${MAX_WORKER_DIMENSION})`);
|
|
50
|
+
}
|
|
51
|
+
if (docIds.length > MAX_WORKER_VECTORS) {
|
|
52
|
+
throw new Error(`Too many vectors: ${docIds.length} (max ${MAX_WORKER_VECTORS})`);
|
|
53
|
+
}
|
|
54
|
+
const expectedLength = docIds.length * dimension;
|
|
55
|
+
if (vectorData.length !== expectedLength) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`vectorData length ${vectorData.length} does not match ${docIds.length} * ${dimension} = ${expectedLength}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
const safeConfig = clampHNSWConfig(config);
|
|
61
|
+
const store = createVectorStore();
|
|
62
|
+
for (let i = 0; i < docIds.length; i++) {
|
|
63
|
+
const offset = i * dimension;
|
|
64
|
+
const vec = vectorData.subarray(offset, offset + dimension);
|
|
65
|
+
store.insert(docIds[i], new Float32Array(vec));
|
|
66
|
+
}
|
|
67
|
+
const hnsw = createHNSWIndex(dimension, store, safeConfig);
|
|
68
|
+
for (const docId of docIds) {
|
|
69
|
+
hnsw.insertNode(docId);
|
|
70
|
+
}
|
|
71
|
+
return hnsw.serialize();
|
|
72
|
+
}
|
|
73
|
+
function handleAnyRequest(raw) {
|
|
74
|
+
const request = raw;
|
|
75
|
+
if (request.type === "build") {
|
|
76
|
+
return handleBuildRequest(raw);
|
|
77
|
+
}
|
|
78
|
+
if (request.type === "build-binary") {
|
|
79
|
+
return handleBuildRequestBinary(raw);
|
|
80
|
+
}
|
|
81
|
+
throw new Error(`Unknown request type: ${request.type}`);
|
|
82
|
+
}
|
|
35
83
|
function setupWorker() {
|
|
36
84
|
setupAsync().catch((err) => {
|
|
37
85
|
console.error("HNSW build worker setup failed:", err);
|
|
@@ -48,10 +96,8 @@ async function setupAsync() {
|
|
|
48
96
|
if (parentPort) {
|
|
49
97
|
const port = parentPort;
|
|
50
98
|
port.on("message", (raw) => {
|
|
51
|
-
const request = raw;
|
|
52
|
-
if (request.type !== "build") return;
|
|
53
99
|
try {
|
|
54
|
-
const graph =
|
|
100
|
+
const graph = handleAnyRequest(raw);
|
|
55
101
|
port.postMessage({ type: "success", graph });
|
|
56
102
|
} catch (err) {
|
|
57
103
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -64,10 +110,8 @@ async function setupAsync() {
|
|
|
64
110
|
if (globalSelf && typeof globalSelf.postMessage === "function") {
|
|
65
111
|
const webSelf = globalSelf;
|
|
66
112
|
webSelf.onmessage = (event) => {
|
|
67
|
-
const request = event.data;
|
|
68
|
-
if (request.type !== "build") return;
|
|
69
113
|
try {
|
|
70
|
-
const graph =
|
|
114
|
+
const graph = handleAnyRequest(event.data);
|
|
71
115
|
webSelf.postMessage({ type: "success", graph });
|
|
72
116
|
} catch (err) {
|
|
73
117
|
const message = err instanceof Error ? err.message : String(err);
|
package/dist/workers/entry.mjs
CHANGED
|
@@ -15,7 +15,7 @@ async function setup() {
|
|
|
15
15
|
} catch {
|
|
16
16
|
parentPort = null;
|
|
17
17
|
}
|
|
18
|
-
const { createDirectExecutor } = await import('../direct-executor-
|
|
18
|
+
const { createDirectExecutor } = await import('../direct-executor-LBJLGMJ2.mjs');
|
|
19
19
|
const executor = createDirectExecutor();
|
|
20
20
|
function buildErrorResponse(requestId, code, message) {
|
|
21
21
|
return { type: "error", requestId, code, message };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@delali/narsil",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A distributed full-text search engine with cross-language portable binary format.",
|
|
6
6
|
"author": "Delali (https://sondelali.com)",
|
|
@@ -74,6 +74,10 @@
|
|
|
74
74
|
"import": "./dist/vector/hnsw-build-worker.mjs",
|
|
75
75
|
"types": "./dist/vector/hnsw-build-worker.d.ts"
|
|
76
76
|
},
|
|
77
|
+
"./embeddings/openai": {
|
|
78
|
+
"import": "./dist/embeddings/openai.mjs",
|
|
79
|
+
"types": "./dist/embeddings/openai.d.ts"
|
|
80
|
+
},
|
|
77
81
|
"./languages/*": {
|
|
78
82
|
"import": "./dist/languages/*.mjs",
|
|
79
83
|
"types": "./dist/languages/*.d.ts"
|
|
@@ -93,13 +97,16 @@
|
|
|
93
97
|
"tsup": "8.5.1",
|
|
94
98
|
"typescript": "5.9.3",
|
|
95
99
|
"vitest": "4.0.18",
|
|
96
|
-
"wabt": "1.0.39"
|
|
100
|
+
"wabt": "1.0.39",
|
|
101
|
+
"@delali/narsil-embeddings-transformers": "0.1.6"
|
|
97
102
|
},
|
|
98
103
|
"scripts": {
|
|
99
104
|
"build": "tsup",
|
|
100
|
-
"test": "vitest run",
|
|
105
|
+
"test": "vitest run --exclude='**/vector/recall.test.ts'",
|
|
101
106
|
"test:watch": "vitest",
|
|
102
107
|
"test:coverage": "vitest run --coverage",
|
|
108
|
+
"test:recall": "vitest run src/__tests__/vector/recall.test.ts",
|
|
109
|
+
"test:embeddings": "NARSIL_TEST_EMBEDDINGS=1 vitest run embedding-e2e",
|
|
103
110
|
"bench": "vitest bench",
|
|
104
111
|
"lint": "biome check src/",
|
|
105
112
|
"typecheck": "tsc --noEmit"
|