@statewalker/indexer-mem 0.1.2 → 0.1.3
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 +42 -22
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -1,37 +1,57 @@
|
|
|
1
1
|
# @statewalker/indexer-mem
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## What it is
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
An in-memory vector sub-index, `MemVectorIndex`, and `memVectorProvider`, the `VectorProvider` that creates it. Search is a brute-force cosine scan over all stored embeddings. The index can save itself as one Apache Arrow IPC stream.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Why it exists
|
|
8
|
+
|
|
9
|
+
The in-memory indexers (`@statewalker/indexer-mem-flexsearch`, `@statewalker/indexer-mem-minisearch`) differ only in their full-text engine. Both use this package for the vector side, so the vector code and its file format exist once.
|
|
10
|
+
|
|
11
|
+
## How to use
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
pnpm add @statewalker/indexer-mem
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
One entry point, `@statewalker/indexer-mem`: `MemVectorIndex`, `memVectorProvider`. Runs anywhere (browser, Node, workers).
|
|
18
|
+
|
|
19
|
+
Most applications use `createFlexSearchIndexer` or `createMiniSearchIndexer`, which already include `memVectorProvider`. Use this package directly when you build your own indexer from providers.
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
Combine with a full-text provider in a custom indexer:
|
|
8
24
|
|
|
9
25
|
```ts
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
const indexer =
|
|
15
|
-
|
|
16
|
-
name: "docs",
|
|
17
|
-
fulltext: { language: "en" },
|
|
18
|
-
vector: { dimensionality: 384, model: "all-MiniLM-L6-v2" },
|
|
26
|
+
import { createPersistenceBackedIndexer } from "@statewalker/indexer-core";
|
|
27
|
+
import { memVectorProvider } from "@statewalker/indexer-mem";
|
|
28
|
+
import { flexSearchFullTextProvider } from "@statewalker/indexer-mem-flexsearch";
|
|
29
|
+
|
|
30
|
+
const indexer = createPersistenceBackedIndexer({
|
|
31
|
+
providers: [flexSearchFullTextProvider, memVectorProvider],
|
|
19
32
|
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Use a `MemVectorIndex` on its own:
|
|
20
36
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
]);
|
|
37
|
+
```ts
|
|
38
|
+
import { MemVectorIndex } from "@statewalker/indexer-mem";
|
|
24
39
|
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
const vectors = new MemVectorIndex({ dimensionality: 3, model: "test" });
|
|
41
|
+
await vectors.addDocument([{ path: "/a", blockId: "1", embedding: new Float32Array([1, 0, 0]) }]);
|
|
42
|
+
for await (const hit of vectors.search({ embeddings: [new Float32Array([1, 0, 0])], topK: 5 })) {
|
|
43
|
+
console.log(hit.path, hit.blockId, hit.score); // cosine similarity
|
|
27
44
|
}
|
|
28
45
|
```
|
|
29
46
|
|
|
30
|
-
##
|
|
47
|
+
## Internals
|
|
31
48
|
|
|
32
|
-
-
|
|
49
|
+
- **Brute force, on purpose.** Every search computes cosine similarity against every stored vector. There is no ANN index, so cost grows linearly with the number of blocks. For large collections use `@statewalker/indexer-duckdb` or `@statewalker/indexer-pglite` (HNSW).
|
|
50
|
+
- **Persistence.** `serialise()` yields one entry named `arrow`: an Arrow IPC stream with columns `path`, `blockId`, `embedding` (`FixedSizeList<Float32>[dimensionality]`) and `metadata` (JSON text). The bytes are cached until the next change, so repeated `flush()` calls without writes do not re-encode. `loadFrom` ignores entries with other names.
|
|
51
|
+
- **Several query embeddings**: each block keeps its best similarity across them.
|
|
52
|
+
- **Dimensionality is checked** on `addDocument` and `search`: `Expected dimensionality 384, got 768`.
|
|
53
|
+
- Dependencies: `@uwdata/flechette` (Arrow encoding without the full Apache Arrow library), `@statewalker/indexer-api`, `@statewalker/indexer-vector`, `@statewalker/indexer-core`.
|
|
33
54
|
|
|
34
|
-
##
|
|
55
|
+
## License
|
|
35
56
|
|
|
36
|
-
|
|
37
|
-
- `@statewalker/indexer-mem-flexsearch` / `@statewalker/indexer-mem-minisearch` — end-user factories combining `MemVectorIndex` with a full-text backend
|
|
57
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statewalker/indexer-mem",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
|
-
"description": "In-memory
|
|
7
|
-
"
|
|
6
|
+
"description": "In-memory vector sub-index (MemVectorIndex, brute-force cosine, Arrow persistence) and its VectorProvider.",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/statewalker/statewalker-search/issues"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/statewalker/statewalker-search/tree/main/packages/indexer-mem#readme",
|
|
8
11
|
"author": {
|
|
9
12
|
"name": "Mikhail Kotelnikov",
|
|
10
13
|
"email": "mikhail.kotelnikov@gmail.com"
|
|
@@ -12,7 +15,8 @@
|
|
|
12
15
|
"license": "MIT",
|
|
13
16
|
"repository": {
|
|
14
17
|
"type": "git",
|
|
15
|
-
"url": "git+
|
|
18
|
+
"url": "git+https://github.com/statewalker/statewalker-search.git",
|
|
19
|
+
"directory": "packages/indexer-mem"
|
|
16
20
|
},
|
|
17
21
|
"exports": {
|
|
18
22
|
".": {
|
|
@@ -28,9 +32,9 @@
|
|
|
28
32
|
],
|
|
29
33
|
"dependencies": {
|
|
30
34
|
"@uwdata/flechette": "^2.5.0",
|
|
31
|
-
"@statewalker/indexer-api": "^0.1.
|
|
32
|
-
"@statewalker/indexer-
|
|
33
|
-
"@statewalker/indexer-
|
|
35
|
+
"@statewalker/indexer-api": "^0.1.2",
|
|
36
|
+
"@statewalker/indexer-core": "^0.1.2",
|
|
37
|
+
"@statewalker/indexer-vector": "^0.1.2"
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
36
40
|
"rimraf": "^6.1.3",
|