@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.
Files changed (3) hide show
  1. package/README.md +18 -13
  2. package/embedder.mjs +18 -13
  3. 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
- `--embed-cmd` hook. It runs `bge-small-en-v1.5` (384-dim) on CPU via ONNX — no GPU, no
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 and caches on first run (typically under
23
- `~/.cache/huggingface` or fastembed's cache directory).
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, point mrplex at the `mrplex-embedder` binary:
34
+ After a global install:
34
35
 
35
36
  ```bash
36
37
  # Serve with the hook — every write auto-embeds.
37
- mrplex serve --unsafe --embed-cmd "mrplex-embedder --stdio"
38
+ mrplex serve --unsafe --embedder mrplex-embedder
38
39
 
39
40
  # One-off backfill of an existing repo.
40
- mrplex embed backfill -r notes --embed-cmd "mrplex-embedder --stdio"
41
+ mrplex embed backfill -r notes --embedder mrplex-embedder
41
42
 
42
- # Or make it ambient.
43
- export MRPLEX_EMBED_CMD="mrplex-embedder --stdio"
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 MRPLEX_EMBED_CMD="mrplex-embedder --stdio --model fast-bge-base-en-v1.5"
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 MRPLEX_EMBED_CMD="mrplex-embedder --stdio --dim 256"
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 `--embed-cmd` hook.
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 --embed-cmd "mrplex-embedder --stdio"
12
- * mrplex embed backfill -r notes --embed-cmd "mrplex-embedder --stdio"
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 --embed-cmd hook.
46
+ Local CPU embedding provider for mrplex's --embedder hook.
39
47
 
40
48
  Usage:
41
- mrplex-embedder --stdio [--model KEY] [--dim N]
49
+ mrplex-embedder [--model KEY] [--dim N] [--cache-dir PATH]
42
50
 
43
51
  Options:
44
- --stdio required transport (one JSON line per batch over stdin/stdout)
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.0",
4
- "description": "Local CPU embedding provider for mrplex's --embed-cmd hook (bge-small-en-v1.5 via fastembed). Isolated from mrplex core so fastembed/tar stay out of the core dependency graph.",
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
- "start": "node embedder.mjs --stdio",
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": {