@mrplex/embedder 0.1.0 → 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 +18 -13
- package/embedder.mjs +18 -13
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @mrplex/embedder
|
|
2
2
|
|
|
3
3
|
A ready-to-use local embedding provider for [mrplex](https://github.com/usergenic/mrplex)'s
|
|
4
|
-
`--
|
|
4
|
+
`--embedder` hook. It runs `bge-small-en-v1.5` (384-dim) on CPU via ONNX — no GPU, no
|
|
5
5
|
separate service. mrplex spawns it once and keeps it resident, so the model loads a single
|
|
6
6
|
time and each batch is one JSON line in / one JSON line out.
|
|
7
7
|
|
|
@@ -19,8 +19,9 @@ embeddings.
|
|
|
19
19
|
npm install -g @mrplex/embedder
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
The model (~130 MB) auto-downloads
|
|
23
|
-
`~/.cache/
|
|
22
|
+
The model (~130 MB) auto-downloads on first run and caches under
|
|
23
|
+
`~/.cache/mrplex/embedder` (or `$XDG_CACHE_HOME/mrplex/embedder`). Override with
|
|
24
|
+
`MRPLEX_EMBEDDER_CACHE` or `--cache-dir PATH`.
|
|
24
25
|
|
|
25
26
|
**From the mrplex monorepo** (development):
|
|
26
27
|
|
|
@@ -30,34 +31,34 @@ cd packages/embedder && npm install
|
|
|
30
31
|
|
|
31
32
|
## Use with mrplex
|
|
32
33
|
|
|
33
|
-
After a global install
|
|
34
|
+
After a global install:
|
|
34
35
|
|
|
35
36
|
```bash
|
|
36
37
|
# Serve with the hook — every write auto-embeds.
|
|
37
|
-
mrplex serve --unsafe --
|
|
38
|
+
mrplex serve --unsafe --embedder mrplex-embedder
|
|
38
39
|
|
|
39
40
|
# One-off backfill of an existing repo.
|
|
40
|
-
mrplex embed backfill -r notes --
|
|
41
|
+
mrplex embed backfill -r notes --embedder mrplex-embedder
|
|
41
42
|
|
|
42
|
-
# Or make it ambient
|
|
43
|
-
export
|
|
43
|
+
# Or make it ambient for every mrplex command:
|
|
44
|
+
export MRPLEX_EMBEDDER=mrplex-embedder
|
|
45
|
+
# mrplex config set-embedder mrplex-embedder # same thing, persisted
|
|
44
46
|
```
|
|
45
47
|
|
|
46
48
|
**Monorepo / local checkout** (no global install):
|
|
47
49
|
|
|
48
50
|
```bash
|
|
49
|
-
mrplex serve --unsafe
|
|
50
|
-
--embed-cmd "node packages/embedder/embedder.mjs --stdio"
|
|
51
|
+
mrplex serve --unsafe --embedder "node packages/embedder/embedder.mjs"
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
### Different models
|
|
54
55
|
|
|
55
56
|
```bash
|
|
56
57
|
# Stronger, slower (768-dim).
|
|
57
|
-
export
|
|
58
|
+
export MRPLEX_EMBEDDER="mrplex-embedder --model fast-bge-base-en-v1.5"
|
|
58
59
|
|
|
59
60
|
# Matryoshka truncation (re-embed after changing --dim).
|
|
60
|
-
export
|
|
61
|
+
export MRPLEX_EMBEDDER="mrplex-embedder --dim 256"
|
|
61
62
|
```
|
|
62
63
|
|
|
63
64
|
List supported model keys:
|
|
@@ -68,13 +69,17 @@ mrplex-embedder --list-models
|
|
|
68
69
|
|
|
69
70
|
## Flags
|
|
70
71
|
|
|
71
|
-
- `--stdio` — required transport (one JSON line per batch over stdin/stdout).
|
|
72
72
|
- `--model KEY` — any `fastembed` model key. Default `fast-bge-small-en-v1.5`.
|
|
73
73
|
Others include `fast-all-MiniLM-L6-v2`, `fast-bge-base-en-v1.5`,
|
|
74
74
|
`fast-multilingual-e5-large`. Run `--list-models` for the full set.
|
|
75
75
|
- `--dim N` — truncate + re-normalize each vector to `N` dims (for Matryoshka
|
|
76
76
|
models). The truncation is encoded into the reported model string
|
|
77
77
|
(`<key>@<N>`) so mrplex treats a dim change as a model change and re-embeds.
|
|
78
|
+
- `--cache-dir PATH` — where ONNX model archives are stored. Default
|
|
79
|
+
`$MRPLEX_EMBEDDER_CACHE`, else `$XDG_CACHE_HOME/mrplex/embedder` or
|
|
80
|
+
`~/.cache/mrplex/embedder`.
|
|
81
|
+
- `--stdio` — optional no-op; stdio is the default transport (one JSON line
|
|
82
|
+
per batch over stdin/stdout).
|
|
78
83
|
- `--list-models` — print supported `--model` keys and exit.
|
|
79
84
|
- `--help`, `--version` — usage and version.
|
|
80
85
|
|
package/embedder.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Local embedding provider for mrplex's `--
|
|
3
|
+
* Local embedding provider for mrplex's `--embedder` hook.
|
|
4
4
|
*
|
|
5
5
|
* Speaks the subprocess contract (design §5.3): one JSON line in on stdin
|
|
6
6
|
* `{ chunks: string[] }`, one JSON line out on stdout
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* ONCE and reuses it for every batch (src/embed/cmd-hook.ts), so the model
|
|
9
9
|
* loads a single time and stays resident — no per-call cold start.
|
|
10
10
|
*
|
|
11
|
-
* mrplex serve --unsafe --
|
|
12
|
-
* mrplex embed backfill -r notes --
|
|
11
|
+
* mrplex serve --unsafe --embedder mrplex-embedder
|
|
12
|
+
* mrplex embed backfill -r notes --embedder mrplex-embedder
|
|
13
13
|
*
|
|
14
14
|
* Model: bge-small-en-v1.5 (384-dim) by default — strong retrieval quality for
|
|
15
15
|
* its size, and small vectors keep mrplex's brute-force cosine scan fast. Runs
|
|
@@ -17,10 +17,18 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { readFileSync } from "node:fs";
|
|
20
|
+
import { homedir } from "node:os";
|
|
20
21
|
import { createInterface } from "node:readline";
|
|
21
22
|
import { dirname, join } from "node:path";
|
|
22
23
|
import { fileURLToPath } from "node:url";
|
|
23
24
|
|
|
25
|
+
/** Where fastembed stores downloaded ONNX model archives (not HuggingFace hub). */
|
|
26
|
+
function defaultCacheDir() {
|
|
27
|
+
if (process.env.MRPLEX_EMBEDDER_CACHE) return process.env.MRPLEX_EMBEDDER_CACHE;
|
|
28
|
+
const xdgCache = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
|
|
29
|
+
return join(xdgCache, "mrplex", "embedder");
|
|
30
|
+
}
|
|
31
|
+
|
|
24
32
|
const pkg = JSON.parse(
|
|
25
33
|
readFileSync(join(dirname(fileURLToPath(import.meta.url)), "package.json"), "utf8"),
|
|
26
34
|
);
|
|
@@ -35,15 +43,16 @@ const has = (name) => argv.includes(name);
|
|
|
35
43
|
|
|
36
44
|
function printHelp() {
|
|
37
45
|
console.error(`mrplex-embedder ${VERSION}
|
|
38
|
-
Local CPU embedding provider for mrplex's --
|
|
46
|
+
Local CPU embedding provider for mrplex's --embedder hook.
|
|
39
47
|
|
|
40
48
|
Usage:
|
|
41
|
-
mrplex-embedder
|
|
49
|
+
mrplex-embedder [--model KEY] [--dim N] [--cache-dir PATH]
|
|
42
50
|
|
|
43
51
|
Options:
|
|
44
|
-
--stdio
|
|
52
|
+
--stdio optional; stdio is the default (one JSON line per batch over stdin/stdout)
|
|
45
53
|
--model KEY fastembed model key (default: fast-bge-small-en-v1.5)
|
|
46
54
|
--dim N truncate + re-normalize to N dims (Matryoshka models only)
|
|
55
|
+
--cache-dir PATH model download cache (default: $MRPLEX_EMBEDDER_CACHE or ~/.cache/mrplex/embedder)
|
|
47
56
|
--list-models print supported --model keys and exit
|
|
48
57
|
--help, -h show this help
|
|
49
58
|
--version, -V print version
|
|
@@ -63,6 +72,7 @@ if (has("--version") || has("-V")) {
|
|
|
63
72
|
|
|
64
73
|
const modelKey = flag("--model", "fast-bge-small-en-v1.5");
|
|
65
74
|
const truncateDim = argv.includes("--dim") ? Number.parseInt(flag("--dim", ""), 10) : null;
|
|
75
|
+
const cacheDir = argv.includes("--cache-dir") ? flag("--cache-dir", "") : defaultCacheDir();
|
|
66
76
|
|
|
67
77
|
if (truncateDim !== null && (!Number.isInteger(truncateDim) || truncateDim <= 0)) {
|
|
68
78
|
console.error(`embedder: --dim must be a positive integer (got ${flag("--dim", "")})`);
|
|
@@ -89,11 +99,6 @@ if (has("--list-models")) {
|
|
|
89
99
|
process.exit(0);
|
|
90
100
|
}
|
|
91
101
|
|
|
92
|
-
if (!has("--stdio")) {
|
|
93
|
-
printHelp();
|
|
94
|
-
process.exit(2);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
102
|
// fastembed keys its models by an enum whose values are the string keys above.
|
|
98
103
|
const model = Object.values(EmbeddingModel).find((v) => v === modelKey);
|
|
99
104
|
if (!model) {
|
|
@@ -104,7 +109,7 @@ if (!model) {
|
|
|
104
109
|
}
|
|
105
110
|
|
|
106
111
|
// maxLength covers the chunker's 2000-char cap (~512 tokens); bge tops out at 512.
|
|
107
|
-
const embedder = await FlagEmbedding.init({ model, maxLength: 512 });
|
|
112
|
+
const embedder = await FlagEmbedding.init({ model, maxLength: 512, cacheDir });
|
|
108
113
|
|
|
109
114
|
/** Truncate a unit vector to `n` dims and re-normalize (Matryoshka). */
|
|
110
115
|
function truncate(vec, n) {
|
|
@@ -186,5 +191,5 @@ rl.on("line", (line) => {
|
|
|
186
191
|
});
|
|
187
192
|
|
|
188
193
|
console.error(
|
|
189
|
-
`embedder stdio model=${modelKey}${truncateDim !== null ? ` dim=${truncateDim}` : ""}`,
|
|
194
|
+
`embedder stdio model=${modelKey}${truncateDim !== null ? ` dim=${truncateDim}` : ""} cache=${cacheDir}`,
|
|
190
195
|
);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrplex/embedder",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Local CPU embedding provider for mrplex's --
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Local CPU embedding provider for mrplex's --embedder hook (bge-small-en-v1.5 via fastembed). Isolated from mrplex core so fastembed/tar stay out of the core dependency graph.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Brendan Baldwin <brendan@usergenic.com>",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"README.md"
|
|
34
34
|
],
|
|
35
35
|
"scripts": {
|
|
36
|
-
"
|
|
36
|
+
"pretest": "node -e \"try{require.resolve('fastembed')}catch{console.error('pretest: run npm install first');process.exit(1)}\"",
|
|
37
|
+
"start": "node embedder.mjs",
|
|
37
38
|
"test": "node --test test/*.test.mjs"
|
|
38
39
|
},
|
|
39
40
|
"engines": {
|