mnemo-engine 0.4.1__tar.gz → 0.5.1__tar.gz
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.
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/PKG-INFO +60 -1
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/README.md +59 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/Cargo.lock +332 -70
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/Cargo.toml +58 -1
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/README.md +123 -5
- mnemo_engine-0.5.1/mnemo/benches/cache.rs +218 -0
- mnemo_engine-0.5.1/mnemo/benches/corpus.rs +227 -0
- mnemo_engine-0.5.1/mnemo/benches/embed_overhead.rs +154 -0
- mnemo_engine-0.5.1/mnemo/benches/open.rs +111 -0
- mnemo_engine-0.5.1/mnemo/benches/recall.rs +121 -0
- mnemo_engine-0.5.1/mnemo/benches/write.rs +107 -0
- mnemo_engine-0.5.1/mnemo/examples/ann_recall_grid.rs +258 -0
- mnemo_engine-0.5.1/mnemo/examples/embedder_server.py +51 -0
- mnemo_engine-0.5.1/mnemo/examples/file_size_breakdown.rs +157 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/bin/mnemo.rs +289 -15
- mnemo_engine-0.5.1/mnemo/src/embed.rs +280 -0
- mnemo_engine-0.5.1/mnemo/src/embed_cmd.rs +572 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/lib.rs +136 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/mcp.rs +273 -82
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/memory.rs +13 -1
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/pager.rs +2 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/store.rs +196 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/wal.rs +1 -0
- mnemo_engine-0.5.1/mnemo/tests/cli_smoke.rs +1336 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/tests/integration.rs +370 -10
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo-python/Cargo.lock +2 -2
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo-python/Cargo.toml +11 -1
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo-python/README.md +59 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo-python/src/lib.rs +281 -7
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo-python/test_mnemo.py +164 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/pyproject.toml +1 -1
- mnemo_engine-0.4.1/mnemo/tests/cli_smoke.rs +0 -553
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/.gitignore +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/deny.toml +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/examples/quickstart.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/examples/session.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/cache.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/crypto.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/error.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/format.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/index.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/result_cache.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/src/session.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/tests/proptest_store.proptest-regressions +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo/tests/proptest_store.rs +0 -0
- {mnemo_engine-0.4.1 → mnemo_engine-0.5.1}/mnemo-python/.gitignore +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mnemo-engine
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: 3
|
|
6
6
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -161,6 +161,10 @@ its own agent.
|
|
|
161
161
|
| `memories()` | Enumerate every live (non-deleted, non-expired) memory as a list of dicts |
|
|
162
162
|
| `dimensions()` | Embedding dimensionality this database was created with (also on `stats()["dimensions"]`) |
|
|
163
163
|
| `rekey(new_passphrase, fast=False)` | Change the passphrase. Re-derives the KEK and re-wraps the DEK; encrypted pages are not rewritten (O(1) in db size). `fast=True` uses the cheap-Argon2 test params — omit for production |
|
|
164
|
+
| `set_embedder(fn, *, name, dimensions, normalize=True)` | Register a Python callable `embed(texts: list[str]) -> list[list[float]]` as this handle's text embedder (Phase 3). Dimension-checks against the database's width; identity-checks against (and on first use upserts) the scaffold manifest's `embedder_name` / `embedder_dimensions` / `embedder_normalize` keys, so swapping embedders between opens fails loudly |
|
|
165
|
+
| `remember_text(content, memory_type, **kwargs)` | Embed `content` via the registered embedder and `remember` the result. Accepts the same per-memory kwargs as `remember` (`agent_id`, `importance`, `session_id`, `ttl_secs`, `shared`, `metadata`) |
|
|
166
|
+
| `recall_text(query, top_k=10, memory_types=None, agent_id=None, track_access=True)` | Embed `query` via the registered embedder and run `recall`. Same return shape as `recall` |
|
|
167
|
+
| `cache_get_semantic_text(namespace, text, threshold=0.97)` | Text-side semantic cache lookup; uses the embedder's `name` as the semantic cache's `model` component |
|
|
164
168
|
| `stats()` | Summary statistics |
|
|
165
169
|
| `export_encrypted(dest)` | Copy the (already-encrypted) file elsewhere |
|
|
166
170
|
| `len(db)` | Live memory count |
|
|
@@ -370,6 +374,61 @@ your embedder's output — `text-embedding-3-small` is 1536-dim,
|
|
|
370
374
|
consistent across hosts (use Redis / DynamoDB DAX). MNemo's cache is
|
|
371
375
|
optimized for a single-host agent that owns its cache file.
|
|
372
376
|
|
|
377
|
+
### Recipe: `set_embedder` + text-only `remember` / `recall`
|
|
378
|
+
|
|
379
|
+
Phase 3 ships a per-handle embedder hook so callers never have to
|
|
380
|
+
pass vectors by hand. Register once at open time; every subsequent
|
|
381
|
+
`remember_text` / `recall_text` / `cache_get_semantic_text` call on
|
|
382
|
+
the handle uses it.
|
|
383
|
+
|
|
384
|
+
```python
|
|
385
|
+
import mnemo
|
|
386
|
+
from sentence_transformers import SentenceTransformer
|
|
387
|
+
|
|
388
|
+
model = SentenceTransformer("all-MiniLM-L6-v2") # 384-dim, normalized
|
|
389
|
+
|
|
390
|
+
def embed(texts: list[str]) -> list[list[float]]:
|
|
391
|
+
return model.encode(texts, normalize_embeddings=True).tolist()
|
|
392
|
+
|
|
393
|
+
db = mnemo.open("agent.mnemo", "pw", dimensions=384)
|
|
394
|
+
db.set_embedder(embed, name="all-MiniLM-L6-v2",
|
|
395
|
+
dimensions=384, normalize=True)
|
|
396
|
+
|
|
397
|
+
db.remember_text("the user prefers tea", "semantic",
|
|
398
|
+
importance=0.8, agent_id="assistant")
|
|
399
|
+
hits = db.recall_text("how does the user like their drinks?", top_k=5)
|
|
400
|
+
for h in hits:
|
|
401
|
+
print(h["score"], h["content"])
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Or with OpenAI's hosted embeddings:
|
|
405
|
+
|
|
406
|
+
```python
|
|
407
|
+
from openai import OpenAI
|
|
408
|
+
client = OpenAI()
|
|
409
|
+
|
|
410
|
+
def embed(texts: list[str]) -> list[list[float]]:
|
|
411
|
+
r = client.embeddings.create(model="text-embedding-3-small", input=texts)
|
|
412
|
+
return [item.embedding for item in r.data]
|
|
413
|
+
|
|
414
|
+
db = mnemo.open("agent.mnemo", "pw", dimensions=1536)
|
|
415
|
+
db.set_embedder(embed, name="text-embedding-3-small",
|
|
416
|
+
dimensions=1536, normalize=False)
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
The identity (`name`, `dimensions`, `normalize`) is persisted on the
|
|
420
|
+
scaffold manifest the first time you `set_embedder`. Reopening with a
|
|
421
|
+
*different* embedder — say you swap MiniLM for BGE on the same file —
|
|
422
|
+
raises `RuntimeError: embedder identity mismatch: database manifest
|
|
423
|
+
records embedder (name="all-MiniLM-L6-v2", …), but this handle was
|
|
424
|
+
passed embedder (name="bge-large-en-v1.5", …). Mixing embedders
|
|
425
|
+
silently corrupts recall quality — open the file with the original
|
|
426
|
+
embedder, or create a fresh database for the new one.`
|
|
427
|
+
|
|
428
|
+
Mnemo also now refuses any `remember` call with an all-zero vector,
|
|
429
|
+
so a mis-wired embedder (returning `[0.0] * dims`) fails loudly on
|
|
430
|
+
the first write instead of polluting recall silently.
|
|
431
|
+
|
|
373
432
|
## License
|
|
374
433
|
|
|
375
434
|
Apache-2.0.
|
|
@@ -147,6 +147,10 @@ its own agent.
|
|
|
147
147
|
| `memories()` | Enumerate every live (non-deleted, non-expired) memory as a list of dicts |
|
|
148
148
|
| `dimensions()` | Embedding dimensionality this database was created with (also on `stats()["dimensions"]`) |
|
|
149
149
|
| `rekey(new_passphrase, fast=False)` | Change the passphrase. Re-derives the KEK and re-wraps the DEK; encrypted pages are not rewritten (O(1) in db size). `fast=True` uses the cheap-Argon2 test params — omit for production |
|
|
150
|
+
| `set_embedder(fn, *, name, dimensions, normalize=True)` | Register a Python callable `embed(texts: list[str]) -> list[list[float]]` as this handle's text embedder (Phase 3). Dimension-checks against the database's width; identity-checks against (and on first use upserts) the scaffold manifest's `embedder_name` / `embedder_dimensions` / `embedder_normalize` keys, so swapping embedders between opens fails loudly |
|
|
151
|
+
| `remember_text(content, memory_type, **kwargs)` | Embed `content` via the registered embedder and `remember` the result. Accepts the same per-memory kwargs as `remember` (`agent_id`, `importance`, `session_id`, `ttl_secs`, `shared`, `metadata`) |
|
|
152
|
+
| `recall_text(query, top_k=10, memory_types=None, agent_id=None, track_access=True)` | Embed `query` via the registered embedder and run `recall`. Same return shape as `recall` |
|
|
153
|
+
| `cache_get_semantic_text(namespace, text, threshold=0.97)` | Text-side semantic cache lookup; uses the embedder's `name` as the semantic cache's `model` component |
|
|
150
154
|
| `stats()` | Summary statistics |
|
|
151
155
|
| `export_encrypted(dest)` | Copy the (already-encrypted) file elsewhere |
|
|
152
156
|
| `len(db)` | Live memory count |
|
|
@@ -356,6 +360,61 @@ your embedder's output — `text-embedding-3-small` is 1536-dim,
|
|
|
356
360
|
consistent across hosts (use Redis / DynamoDB DAX). MNemo's cache is
|
|
357
361
|
optimized for a single-host agent that owns its cache file.
|
|
358
362
|
|
|
363
|
+
### Recipe: `set_embedder` + text-only `remember` / `recall`
|
|
364
|
+
|
|
365
|
+
Phase 3 ships a per-handle embedder hook so callers never have to
|
|
366
|
+
pass vectors by hand. Register once at open time; every subsequent
|
|
367
|
+
`remember_text` / `recall_text` / `cache_get_semantic_text` call on
|
|
368
|
+
the handle uses it.
|
|
369
|
+
|
|
370
|
+
```python
|
|
371
|
+
import mnemo
|
|
372
|
+
from sentence_transformers import SentenceTransformer
|
|
373
|
+
|
|
374
|
+
model = SentenceTransformer("all-MiniLM-L6-v2") # 384-dim, normalized
|
|
375
|
+
|
|
376
|
+
def embed(texts: list[str]) -> list[list[float]]:
|
|
377
|
+
return model.encode(texts, normalize_embeddings=True).tolist()
|
|
378
|
+
|
|
379
|
+
db = mnemo.open("agent.mnemo", "pw", dimensions=384)
|
|
380
|
+
db.set_embedder(embed, name="all-MiniLM-L6-v2",
|
|
381
|
+
dimensions=384, normalize=True)
|
|
382
|
+
|
|
383
|
+
db.remember_text("the user prefers tea", "semantic",
|
|
384
|
+
importance=0.8, agent_id="assistant")
|
|
385
|
+
hits = db.recall_text("how does the user like their drinks?", top_k=5)
|
|
386
|
+
for h in hits:
|
|
387
|
+
print(h["score"], h["content"])
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Or with OpenAI's hosted embeddings:
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
from openai import OpenAI
|
|
394
|
+
client = OpenAI()
|
|
395
|
+
|
|
396
|
+
def embed(texts: list[str]) -> list[list[float]]:
|
|
397
|
+
r = client.embeddings.create(model="text-embedding-3-small", input=texts)
|
|
398
|
+
return [item.embedding for item in r.data]
|
|
399
|
+
|
|
400
|
+
db = mnemo.open("agent.mnemo", "pw", dimensions=1536)
|
|
401
|
+
db.set_embedder(embed, name="text-embedding-3-small",
|
|
402
|
+
dimensions=1536, normalize=False)
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
The identity (`name`, `dimensions`, `normalize`) is persisted on the
|
|
406
|
+
scaffold manifest the first time you `set_embedder`. Reopening with a
|
|
407
|
+
*different* embedder — say you swap MiniLM for BGE on the same file —
|
|
408
|
+
raises `RuntimeError: embedder identity mismatch: database manifest
|
|
409
|
+
records embedder (name="all-MiniLM-L6-v2", …), but this handle was
|
|
410
|
+
passed embedder (name="bge-large-en-v1.5", …). Mixing embedders
|
|
411
|
+
silently corrupts recall quality — open the file with the original
|
|
412
|
+
embedder, or create a fresh database for the new one.`
|
|
413
|
+
|
|
414
|
+
Mnemo also now refuses any `remember` call with an all-zero vector,
|
|
415
|
+
so a mis-wired embedder (returning `[0.0] * dims`) fails loudly on
|
|
416
|
+
the first write instead of polluting recall silently.
|
|
417
|
+
|
|
359
418
|
## License
|
|
360
419
|
|
|
361
420
|
Apache-2.0.
|