@gorlitzer-labs/seldon 0.1.9 → 0.1.10

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 +13 -2
  2. package/bin/seldon.js +31 -6
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -41,8 +41,19 @@ seldon down # stop everything
41
41
  ```
42
42
 
43
43
  `seldon up` only starts what's installed. demerzel serves the voice UI on
44
- `http://localhost:8770`; its first run needs a one-time model fetch (~25 GB) and
45
- `up` prints the exact command if they're missing. Logs live in `~/.seldon/run/`.
44
+ `http://localhost:8770`. Its model set (~25 GB) is a one-time download —
45
+ `seldon install demerzel` **offers to fetch it right there** ([y/N]), and `seldon up`
46
+ offers again if it's still missing. Nothing that big is ever pulled silently.
47
+ Logs live in `~/.seldon/run/`.
48
+
49
+ **Try a different LLM** (e.g. PrismML's Bonsai 2, ~5.9 GB, much smaller than the
50
+ default): set `DEMERZEL_LLM` to any MLX-compatible HF repo before install/up, and
51
+ both the fetch and the runtime follow it:
52
+
53
+ ```bash
54
+ DEMERZEL_LLM=mlx-community/<bonsai-2-repo> seldon install demerzel # fetch that model
55
+ DEMERZEL_LLM=mlx-community/<bonsai-2-repo> seldon up # run it
56
+ ```
46
57
 
47
58
  ## Uninstall
48
59
 
package/bin/seldon.js CHANGED
@@ -184,7 +184,7 @@ function installOne(m, dev) {
184
184
  return ok;
185
185
  }
186
186
 
187
- function doInstall(ids, { dev } = {}) {
187
+ async function doInstall(ids, { dev } = {}) {
188
188
  ids = withRequires(ids);
189
189
  console.log(C.bold(`\nInstalling: `) + ids.join(", ") + (dev ? C.dim(" (dev: link from checkout)") : ""));
190
190
  console.log(C.bold("\nPreflight:"));
@@ -194,6 +194,8 @@ function doInstall(ids, { dev } = {}) {
194
194
  const good = results.filter(([, r]) => r).map(([i]) => i);
195
195
  const bad = results.filter(([, r]) => !r).map(([i]) => i);
196
196
  console.log("\n" + C.bold("Done. ") + C.green(good.join(", ") || "—") + (bad.length ? " " + C.red("failed: " + bad.join(", ")) : ""));
197
+ // demerzel's models are the heavy part — offer to pull them now, at install time.
198
+ if (good.includes("demerzel")) await ensureDemerzelModels({ ask: true });
197
199
  }
198
200
 
199
201
  // ---- uninstall --------------------------------------------------------------
@@ -314,7 +316,26 @@ function demerzelModelsReady() {
314
316
  }
315
317
  const demerzelInstalled = () => fs.existsSync(path.join(SELDON_HOME, "demerzel", ".venv", "bin", "python"));
316
318
 
317
- function up() {
319
+ // Fetch demerzel's model set (~25 GB) — offered, never silent. Respects the
320
+ // chosen LLM (DEMERZEL_LLM) so `seldon install demerzel` / `seldon up` pull the
321
+ // model you'll actually run. --models forces yes, --no-models forces skip.
322
+ async function ensureDemerzelModels({ ask = true } = {}) {
323
+ if (!demerzelInstalled() || !platformOk(byId.demerzel)) return false;
324
+ if (demerzelModelsReady()) return true;
325
+ const home = path.join(SELDON_HOME, "demerzel");
326
+ const force = process.argv.includes("--models");
327
+ const skip = process.argv.includes("--no-models");
328
+ let doit = force;
329
+ if (!doit && !skip) doit = process.stdin.isTTY
330
+ ? await confirm(C.gold("\n Download Demerzel's voice models now (~25 GB, one time)? [y/N] "))
331
+ : false; // never pull 25 GB non-interactively without --models
332
+ if (!doit) { console.log(C.dim(" models not fetched — the voice stays off until they are (seldon up will offer again).")); return false; }
333
+ const llm = process.env.DEMERZEL_LLM;
334
+ console.log(C.dim(` fetching Demerzel models${llm ? ` (LLM ${llm})` : ""} — ~25 GB, resumable…`));
335
+ return run(path.join(home, ".venv/bin/python"), [path.join(home, "scripts/fetch-models.py")], { cwd: home, env: { ...process.env } });
336
+ }
337
+
338
+ async function up() {
318
339
  console.log(C.gold("\n seldon — bringing the stack up\n"));
319
340
  const go = []; // where-to-go lines
320
341
  const later = []; // things that need one action first
@@ -324,10 +345,14 @@ function up() {
324
345
  if (demerzelInstalled()) {
325
346
  const home = path.join(SELDON_HOME, "demerzel");
326
347
  if (!platformOk(dem)) later.push("Voice (demerzel) needs macOS on Apple silicon — skipped here.");
327
- else if (!demerzelModelsReady()) later.push(`Voice (demerzel) needs its models once (~25 GB):\n ${path.join(home, ".venv/bin/python")} ${path.join(home, "scripts/fetch-models.py")}\n then re-run seldon up`);
328
348
  else {
329
- const r = startDaemon("demerzel", path.join(home, ".venv/bin/python"), ["-m", "demerzel.server"], { cwd: home });
330
- go.push(`${C.bold("Voice")} ${C.cyan("http://localhost:8770")} ${C.dim(r.already ? "(already up)" : "(starting — models load, ~30s)")}`);
349
+ if (!demerzelModelsReady()) await ensureDemerzelModels({ ask: true }); // offer the fetch inline
350
+ if (demerzelModelsReady()) {
351
+ const r = startDaemon("demerzel", path.join(home, ".venv/bin/python"), ["-m", "demerzel.server"], { cwd: home, env: { ...process.env } });
352
+ go.push(`${C.bold("Voice")} ${C.cyan("http://localhost:8770")} ${C.dim(r.already ? "(already up)" : "(starting — models load, ~30s)")}`);
353
+ } else {
354
+ later.push("Voice (demerzel): models not fetched yet — run `seldon up` again when you're ready to pull them.");
355
+ }
331
356
  }
332
357
  }
333
358
 
@@ -484,5 +509,5 @@ const ids = tokens.filter((id) => byId[id]); // only the valid module
484
509
  const picked = await tui();
485
510
  if (!picked) { console.log(C.dim("nothing installed.")); return; }
486
511
  if (!picked.length) { console.log(C.dim("nothing selected.")); return; }
487
- doInstall(picked, { dev });
512
+ await doInstall(picked, { dev });
488
513
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gorlitzer-labs/seldon",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Install the Seldon stack — pick your tools from a checklist; each installs via its native method.",
5
5
  "type": "module",
6
6
  "bin": {