Skip to content

Commit 8d730c9

Browse files
author
STARGA Inc
committed
release: v3.10.3 — mm install-model + GGUF on HuggingFace
Adds `mm install-model` subcommand that downloads mind-mem-4b-Q4_K_M.gguf (~2.5 GB) from HF, writes a Modelfile, runs ollama create, sets keep-alive to -1, and smoke-tests. Idempotent. Also publishes the GGUF to HF (model card commit c5d08750) so end users don't need llama.cpp's convert_hf_to_gguf.py (which had Qwen3.5 tokenizer issues until very recent versions). End-user setup is now: pip install mind-mem && mm install-all --force && mm install-model. Three commands, ~3 minutes, working local LLM. The 8.4 GB full-fp16 safetensors stays on HF for researchers fine-tuners and vLLM/exllamav2 serving.
1 parent 433be90 commit 8d730c9

5 files changed

Lines changed: 194 additions & 6 deletions

File tree

ANATOMY.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
> Re-generate with: `anatomy .`
66
77
**Project:** `mind-mem`
8-
**Files:** 739 | **Est. tokens:** ~1,508,637
9-
**Generated:** 2026-05-09 00:39 UTC
8+
**Files:** 739 | **Est. tokens:** ~1,510,011
9+
**Generated:** 2026-05-09 00:56 UTC
1010

1111
## Token Budget Guide
1212

@@ -56,7 +56,7 @@
5656
| `skills/integrity-scan/` | 1 | ~376 |
5757
| `skills/memory-recall/` | 1 | ~549 |
5858
| `src/` | 1 | ~280 |
59-
| `src/mind_mem/` | 155 | ~536,208 |
59+
| `src/mind_mem/` | 155 | ~537,582 |
6060
| `src/mind_mem/api/` | 5 | ~15,751 |
6161
| `src/mind_mem/mcp/` | 3 | ~3,960 |
6262
| `src/mind_mem/mcp/infra/` | 8 | ~6,924 |
@@ -528,7 +528,7 @@
528528
- `mind_ffi.py` (~5481 tok, huge) — mind-mem FFI bridge — loads compiled MIND .so and exposes scoring functions.
529529
- `mind_filelock.py` (~1844 tok, huge) — mind-mem file locking — cross-platform advisory locks. Zero external deps.
530530
- `mind_kernels.py` (~1706 tok, huge) — # Copyright 2026 STARGA, Inc.
531-
- `mm_cli.py` (~17919 tok, huge) — # Copyright 2026 STARGA, Inc.
531+
- `mm_cli.py` (~19293 tok, huge) — # Copyright 2026 STARGA, Inc.
532532
- `model_audit.py` (~4370 tok, huge) — Model checkpoint audit — scan for remote-code hooks, unsafe pickle, tokenizer injection.
533533
- `model_gate.py` (~2549 tok, huge) — Load-gate registry for ``mm audit-model`` checkpoints.
534534
- `model_provenance.py` (~1751 tok, huge) — Provenance allowlist check for ``mm audit-model`` checkpoints.

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,41 @@
22

33
All notable changes to MIND-Mem are documented in this file.
44

5+
## v3.10.3 — `mm install-model` + GGUF on HuggingFace
6+
7+
Released 2026-05-08. Closes the public-user setup gap: `pip install
8+
mind-mem` now gets you to a running local LLM in two commands.
9+
10+
### Added
11+
- `mm install-model` subcommand — downloads the canonical
12+
`mind-mem-4b-Q4_K_M.gguf` (~2.5 GB) from HuggingFace, writes a
13+
Modelfile, runs `ollama create mind-mem:4b`, sets
14+
`OLLAMA_KEEP_ALIVE=-1`, and smoke-tests the model. Idempotent.
15+
Flags: `--model`, `--name`, `--dest`, `--keep-alive`, `--dry-run`.
16+
- **GGUF Q4_K_M now published to HuggingFace**:
17+
https://huggingface.co/star-ga/mind-mem-4b/blob/main/mind-mem-4b-Q4_K_M.gguf
18+
Q4_K_M quantization fits in **6 GB VRAM** (vs 16+ GB for the
19+
full-fp16 safetensors), runs on a consumer RTX 3060.
20+
21+
### Two-command setup for end users
22+
```bash
23+
pip install mind-mem
24+
mm install-all --force # wires every detected CLI (10 supported)
25+
mm install-model # pulls GGUF + imports into Ollama
26+
```
27+
28+
The full-precision `model.safetensors` (8.4 GB) stays on HF for
29+
researchers, fine-tuners, and high-perf serving (vLLM / exllamav2).
30+
End users running Ollama use the GGUF — 70 % less bandwidth.
31+
32+
### Notes
33+
- Requires `ollama` on PATH; otherwise the command exits with a
34+
clear hint pointing at https://ollama.com/download.
35+
- Skips re-download if the destination file already matches the
36+
HF Content-Length (re-runs are no-ops).
37+
- `--keep-alive -1` matches the systemd `OLLAMA_KEEP_ALIVE=-1`
38+
setting documented in `docs/mind-mem-4b-setup.md`.
39+
540
## v3.10.2 — Canonical Memory Protocol injected on `mm install-all`
641

742
Released 2026-05-08. Closes a gap discovered during a sibling product

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "mind-mem"
3-
version = "3.10.2"
3+
version = "3.10.3"
44
description = "Drop-in memory for Claude Code, OpenClaw, and any MCP-compatible agent."
55
readme = "README.md"
66
license = { text = "Apache-2.0" }

src/mind_mem/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
)
4444
from .storage import get_block_store
4545

46-
__version__ = "3.10.2"
46+
__version__ = "3.10.3"
4747

4848
# Best-effort import-time integrity check. Fails open unless
4949
# MIND_MEM_INTEGRITY=strict, so editable installs and source checkouts

src/mind_mem/mm_cli.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,128 @@ def _cmd_install(args: argparse.Namespace) -> int:
374374
return 0
375375

376376

377+
def _cmd_install_model(args: argparse.Namespace) -> int:
378+
"""Download mind-mem-4b GGUF from HF and import into Ollama.
379+
380+
Idempotent — safe to re-run. Skips download if file already
381+
present with matching size; skips Ollama import if tag already
382+
present (unless --force on the parent command).
383+
"""
384+
import shutil
385+
import subprocess
386+
import urllib.request
387+
388+
hf_repo = "star-ga/mind-mem-4b"
389+
gguf_url = f"https://huggingface.co/{hf_repo}/resolve/main/{args.model}"
390+
dest = os.path.expanduser(args.dest)
391+
392+
output: dict[str, Any] = {
393+
"model_file": args.model,
394+
"ollama_tag": args.name,
395+
"dest": dest,
396+
"keep_alive": args.keep_alive,
397+
"dry_run": bool(args.dry_run),
398+
}
399+
400+
if args.dry_run:
401+
output["plan"] = [
402+
f"would download {gguf_url} -> {dest}",
403+
f"would write Modelfile with FROM {dest}",
404+
f"would run `ollama create {args.name} -f Modelfile`",
405+
f"would set OLLAMA_KEEP_ALIVE={args.keep_alive}",
406+
]
407+
print(json.dumps(output, indent=2))
408+
return 0
409+
410+
# 1. Check ollama on PATH (graceful skip if absent)
411+
if not shutil.which("ollama"):
412+
output["error"] = "ollama not found on PATH"
413+
output["hint"] = "install ollama from https://ollama.com/download then re-run `mm install-model`"
414+
print(json.dumps(output, indent=2))
415+
return 2
416+
417+
# 2. Download GGUF (skip if dest already correct size)
418+
os.makedirs(os.path.dirname(dest), exist_ok=True)
419+
expected_size = None
420+
try:
421+
with urllib.request.urlopen(gguf_url) as resp:
422+
expected_size = int(resp.headers.get("Content-Length") or 0)
423+
except Exception as exc:
424+
output["error"] = f"could not query HF for {args.model}: {exc}"
425+
print(json.dumps(output, indent=2))
426+
return 3
427+
428+
if os.path.exists(dest) and expected_size and os.path.getsize(dest) == expected_size:
429+
output["downloaded"] = False
430+
output["reason"] = "dest already present with matching size"
431+
else:
432+
try:
433+
urllib.request.urlretrieve(gguf_url, dest)
434+
output["downloaded"] = True
435+
output["bytes"] = os.path.getsize(dest)
436+
except Exception as exc:
437+
output["error"] = f"download failed: {exc}"
438+
print(json.dumps(output, indent=2))
439+
return 4
440+
441+
# 3. Build Modelfile next to the GGUF (idempotent)
442+
modelfile = os.path.join(os.path.dirname(dest), "Modelfile")
443+
modelfile_body = (
444+
f"FROM {dest}\n"
445+
"PARAMETER temperature 0.6\n"
446+
"PARAMETER top_p 0.95\n"
447+
"PARAMETER num_ctx 8192\n"
448+
f'PARAMETER stop "<|im_end|>"\n'
449+
)
450+
with open(modelfile, "w", encoding="utf-8") as fh:
451+
fh.write(modelfile_body)
452+
output["modelfile"] = modelfile
453+
454+
# 4. Ollama import
455+
try:
456+
result = subprocess.run(
457+
["ollama", "create", args.name, "-f", modelfile],
458+
capture_output=True,
459+
text=True,
460+
timeout=180,
461+
check=False,
462+
)
463+
output["ollama_create_returncode"] = result.returncode
464+
if result.returncode != 0:
465+
output["ollama_stderr"] = result.stderr[-500:]
466+
print(json.dumps(output, indent=2))
467+
return 5
468+
except subprocess.TimeoutExpired:
469+
output["error"] = "`ollama create` timed out after 180s"
470+
print(json.dumps(output, indent=2))
471+
return 6
472+
473+
# 5. Smoke test (warm the model + keep-alive)
474+
try:
475+
smoke = subprocess.run(
476+
["ollama", "run", args.name, "test"],
477+
input="hi\n",
478+
capture_output=True,
479+
text=True,
480+
timeout=60,
481+
check=False,
482+
env={**os.environ, "OLLAMA_KEEP_ALIVE": args.keep_alive},
483+
)
484+
output["smoke_returncode"] = smoke.returncode
485+
if smoke.returncode == 0:
486+
output["smoke_response_first_60"] = smoke.stdout.strip()[:60]
487+
except subprocess.TimeoutExpired:
488+
output["smoke_response"] = "(timeout — model likely importing in background; run `ollama list` to verify)"
489+
490+
output["status"] = "ok"
491+
output["next_steps"] = [
492+
f"ollama run {args.name} # test the model",
493+
"mm status # confirm mind-mem.json is configured",
494+
]
495+
print(json.dumps(output, indent=2))
496+
return 0
497+
498+
377499
def _cmd_install_all(args: argparse.Namespace) -> int:
378500
"""Auto-detect installed AI clients and configure all of them."""
379501
from mind_mem.hook_installer import detect_installed_agents, install_all
@@ -1525,6 +1647,37 @@ def build_parser() -> argparse.ArgumentParser:
15251647
)
15261648
p_install_all.set_defaults(func=_cmd_install_all)
15271649

1650+
# install-model — pull mind-mem-4b GGUF from HF + import to Ollama
1651+
p_install_model = sub.add_parser(
1652+
"install-model",
1653+
help=(
1654+
"Download `mind-mem-4b` GGUF (~2.5GB) from HuggingFace and "
1655+
"import into Ollama as `mind-mem:4b`. Idempotent."
1656+
),
1657+
)
1658+
p_install_model.add_argument(
1659+
"--model",
1660+
default="mind-mem-4b-Q4_K_M.gguf",
1661+
help="GGUF filename on HF. Default: mind-mem-4b-Q4_K_M.gguf",
1662+
)
1663+
p_install_model.add_argument(
1664+
"--name",
1665+
default="mind-mem:4b",
1666+
help="Ollama tag to register. Default: mind-mem:4b",
1667+
)
1668+
p_install_model.add_argument(
1669+
"--dest",
1670+
default=os.path.expanduser("~/.cache/mind-mem/mind-mem-4b-Q4_K_M.gguf"),
1671+
help="Local path to download into. Default: ~/.cache/mind-mem/",
1672+
)
1673+
p_install_model.add_argument(
1674+
"--keep-alive",
1675+
default="-1",
1676+
help="Ollama keep-alive value. -1 = forever (default), 30m, etc.",
1677+
)
1678+
p_install_model.add_argument("--dry-run", action="store_true")
1679+
p_install_model.set_defaults(func=_cmd_install_model)
1680+
15281681
# vault namespace
15291682
p_vault = sub.add_parser("vault", help="Vault sync subcommands.")
15301683
vsub = p_vault.add_subparsers(dest="vault_cmd", required=True)

0 commit comments

Comments
 (0)