memnet-llm 0.2.6__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.
- memnet_llm-0.2.6/.gitignore +36 -0
- memnet_llm-0.2.6/LICENSE +21 -0
- memnet_llm-0.2.6/PKG-INFO +257 -0
- memnet_llm-0.2.6/README.md +227 -0
- memnet_llm-0.2.6/pyproject.toml +71 -0
- memnet_llm-0.2.6/src/memnet/__init__.py +3 -0
- memnet_llm-0.2.6/src/memnet/__main__.py +4 -0
- memnet_llm-0.2.6/src/memnet/cli.py +795 -0
- memnet_llm-0.2.6/src/memnet/config.py +71 -0
- memnet_llm-0.2.6/src/memnet/examples/relations.seed.txt +4 -0
- memnet_llm-0.2.6/src/memnet/examples/schema.example.txt +8 -0
- memnet_llm-0.2.6/src/memnet/examples/workflow.example.txt +15 -0
- memnet_llm-0.2.6/src/memnet/exceptions.py +19 -0
- memnet_llm-0.2.6/src/memnet/filter.py +38 -0
- memnet_llm-0.2.6/src/memnet/fixed_tags.py +17 -0
- memnet_llm-0.2.6/src/memnet/help_text.py +117 -0
- memnet_llm-0.2.6/src/memnet/housekeep.py +105 -0
- memnet_llm-0.2.6/src/memnet/mem_store.py +352 -0
- memnet_llm-0.2.6/src/memnet/models.py +54 -0
- memnet_llm-0.2.6/src/memnet/output.py +98 -0
- memnet_llm-0.2.6/src/memnet/py.typed +0 -0
- memnet_llm-0.2.6/src/memnet/registry.py +69 -0
- memnet_llm-0.2.6/src/memnet/sanitiser.py +55 -0
- memnet_llm-0.2.6/src/memnet/serve.py +116 -0
- memnet_llm-0.2.6/src/memnet/serve_client.py +54 -0
- memnet_llm-0.2.6/src/memnet/session.py +189 -0
- memnet_llm-0.2.6/src/memnet/snapshot.py +178 -0
- memnet_llm-0.2.6/src/memnet/tag_map.py +203 -0
- memnet_llm-0.2.6/src/memnet/warnings.py +59 -0
- memnet_llm-0.2.6/src/memnet/wire.py +47 -0
- memnet_llm-0.2.6/tests/conftest.py +30 -0
- memnet_llm-0.2.6/tests/test_add_update.py +39 -0
- memnet_llm-0.2.6/tests/test_cli.py +44 -0
- memnet_llm-0.2.6/tests/test_efficiency.py +82 -0
- memnet_llm-0.2.6/tests/test_housekeep.py +25 -0
- memnet_llm-0.2.6/tests/test_mem_store.py +75 -0
- memnet_llm-0.2.6/tests/test_mission_warm.py +42 -0
- memnet_llm-0.2.6/tests/test_read_filter.py +106 -0
- memnet_llm-0.2.6/tests/test_schemes.py +39 -0
- memnet_llm-0.2.6/tests/test_session.py +54 -0
- memnet_llm-0.2.6/tests/test_session_modified.py +61 -0
- memnet_llm-0.2.6/tests/test_snapshot.py +75 -0
- memnet_llm-0.2.6/tests/test_tag_map.py +60 -0
- memnet_llm-0.2.6/tests/test_wire.py +20 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.eggs/
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
|
|
16
|
+
# Tooling
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
htmlcov/
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
|
|
23
|
+
# MemNet data (local graph stores)
|
|
24
|
+
*.db
|
|
25
|
+
.memnet/
|
|
26
|
+
|
|
27
|
+
# Environment
|
|
28
|
+
.env
|
|
29
|
+
.env.local
|
|
30
|
+
|
|
31
|
+
# IDE / OS
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
*.swp
|
|
35
|
+
.DS_Store
|
|
36
|
+
Thumbs.db
|
memnet_llm-0.2.6/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MemNet contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: memnet-llm
|
|
3
|
+
Version: 0.2.6
|
|
4
|
+
Summary: In-memory working-memory graph CLI for LLM agents (goldfish brain scratch space)
|
|
5
|
+
Project-URL: Homepage, https://github.com/chouswei/MemNet
|
|
6
|
+
Project-URL: Repository, https://github.com/chouswei/MemNet
|
|
7
|
+
Project-URL: Changelog, https://github.com/chouswei/MemNet/blob/master/CHANGELOG.md
|
|
8
|
+
Project-URL: Documentation, https://github.com/chouswei/MemNet/blob/master/LLM-GUIDE.md
|
|
9
|
+
Author: MemNet contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agent,cli,knowledge-graph,llm,memory,working-memory
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: pydantic>=2.10
|
|
23
|
+
Requires-Dist: rich>=13.9
|
|
24
|
+
Requires-Dist: typer>=0.15
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.3; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.9; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# MemNet
|
|
32
|
+
|
|
33
|
+
**Pure in-memory working-memory graph for LLM "goldfish brains"** — structured state an agent writes once and re-reads each turn because the model forgets.
|
|
34
|
+
|
|
35
|
+
MemNet is **scratch memory for the current task**, not a durable knowledge base or vector store. Sessions live in RAM, expire by TTL, and disappear on `session close`. There is **no automatic disk state**; persistence is explicit and user-controlled via `session save` / `session load`.
|
|
36
|
+
|
|
37
|
+
## The problem it solves
|
|
38
|
+
|
|
39
|
+
LLMs lose track of entities, state, and rules between tool calls. MemNet gives the agent a small, typed, queryable graph it can:
|
|
40
|
+
|
|
41
|
+
- add facts, tasks, and relations once; update them when state changes,
|
|
42
|
+
- pull back only the live slice on the next turn (`query warm --anchor`),
|
|
43
|
+
- settle or expire missions so they stop polluting the prompt,
|
|
44
|
+
- keep hard limits and produce machine-readable warnings instead of silent bloat.
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```powershell
|
|
49
|
+
pip install memnet-llm
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
From source (development):
|
|
53
|
+
|
|
54
|
+
```powershell
|
|
55
|
+
pip install -e ".[dev]"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The CLI command is still **`memnet`**. PyPI package name is **`memnet-llm`** (the name `memnet` on [PyPI](https://pypi.org/project/memnet/) is a different project — memristive neural networks).
|
|
59
|
+
|
|
60
|
+
Requires Python ≥ 3.11.
|
|
61
|
+
|
|
62
|
+
## Quick start
|
|
63
|
+
|
|
64
|
+
You need two terminals. One runs the in-memory server that holds the graph; the other runs the CLI client.
|
|
65
|
+
|
|
66
|
+
**Terminal 1 (server):**
|
|
67
|
+
|
|
68
|
+
```powershell
|
|
69
|
+
memnet serve
|
|
70
|
+
# prints: MEMNET_SERVE=127.0.0.1:18765
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Terminal 2 (client):**
|
|
74
|
+
|
|
75
|
+
```powershell
|
|
76
|
+
# See the cheat sheet
|
|
77
|
+
memnet guide --loose
|
|
78
|
+
|
|
79
|
+
# Start a session with the bundled schema
|
|
80
|
+
memnet session open --map-file src/memnet/examples/schema.example.txt
|
|
81
|
+
# stderr also prints: MEMNET_SESSION=mn_xxxxxxxx
|
|
82
|
+
$env:MEMNET_SESSION = "mn_xxxxxxxx"
|
|
83
|
+
|
|
84
|
+
# Ingest a small world (LAW rules + world state + missions)
|
|
85
|
+
memnet add --file src/memnet/examples/workflow.example.txt
|
|
86
|
+
|
|
87
|
+
# Preferred read for the next LLM turn: only live mission state
|
|
88
|
+
memnet query warm --anchor PLR01
|
|
89
|
+
|
|
90
|
+
# When done
|
|
91
|
+
memnet session close $env:MEMNET_SESSION
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Without `memnet serve` running, any stateful command returns `@ERR: serve_required`.
|
|
95
|
+
|
|
96
|
+
For one-off scripting or tests you can set `MEMNET_TEST_INLINE=1` to run in-process (no server), but this is not the normal multi-turn agent mode.
|
|
97
|
+
|
|
98
|
+
**LLM agents:** read `LLM-GUIDE.md` (in this repo) for the full agent playbook, the goldfish loop, settlement pattern, and disciplines. It is written to be consumed by models.
|
|
99
|
+
|
|
100
|
+
## The goldfish loop (recommended pattern)
|
|
101
|
+
|
|
102
|
+
A typical agent turn:
|
|
103
|
+
|
|
104
|
+
1. `add` new rows or `update` existing ones (`@TAG:` lines, batch via `--stdin` or `--file` is best).
|
|
105
|
+
2. `query warm --anchor <focus>` — returns only active (non-recyclable) rows, always includes LAW.
|
|
106
|
+
3. Paste the wire lines into the prompt, reason, decide on next adds/updates or a mission settle.
|
|
107
|
+
4. On mission complete: **update** the `TSK` (or equivalent) with both `status=settled` **and** `recycle=delete_on_settle`. Mission edges usually use `delete_on_expire` or `delete_on_settle`.
|
|
108
|
+
5. Optionally `housekeep prune stale --apply` to physically remove settled rows.
|
|
109
|
+
6. Next turn starts again at step 1 with a (usually new) anchor.
|
|
110
|
+
|
|
111
|
+
`query context` (cold) returns everything and emits `@WRN: stale_in_store|…` on stderr when recyclable rows exist. Prefer `warm`.
|
|
112
|
+
|
|
113
|
+
## Wire format
|
|
114
|
+
|
|
115
|
+
One record per line:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
@TAG: field|field|...
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- Pipe inside a value must be escaped: `note\|extra` (or `\\|` in some shells).
|
|
122
|
+
- Always quote the whole line in PowerShell or bash when it contains special characters.
|
|
123
|
+
- Reserved output tags: `@SESSION`, `@ERR`, `@WRN`, `@STAT`, `@REL`, `@DEL`.
|
|
124
|
+
- Errors and advisories go to **stderr**; data rows to **stdout**.
|
|
125
|
+
|
|
126
|
+
Example multi-line ingest (PowerShell):
|
|
127
|
+
|
|
128
|
+
```powershell
|
|
129
|
+
memnet add --stdin @"
|
|
130
|
+
@NPC: N01|Shen Tiexin|female(12)|0|traditional|80|active|persistent
|
|
131
|
+
@EDG: E01|N01|seeks_help|PLR01|unlock|delete_on_expire
|
|
132
|
+
"@
|
|
133
|
+
|
|
134
|
+
memnet update --stdin @"
|
|
135
|
+
@NPC: N01|Shen Tiexin|female(12)|0|traditional|90|active|persistent
|
|
136
|
+
"@
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
See `memnet guide`, `memnet examples map`, and `memnet tagmap fields --tag <TAG>` for the current schema.
|
|
140
|
+
|
|
141
|
+
## Commands
|
|
142
|
+
|
|
143
|
+
Run any command with `--help` for full flags.
|
|
144
|
+
|
|
145
|
+
### Session lifecycle
|
|
146
|
+
| Command | Purpose |
|
|
147
|
+
|--------------------------|---------|
|
|
148
|
+
| `session open --map-file` | Create a new session (prints `@SESSION:` and `MEMNET_SESSION=...` on stderr) |
|
|
149
|
+
| `session resume <id>` | Attach to an existing session |
|
|
150
|
+
| `session current` | Show the id from `$env:MEMNET_SESSION` (or "none") |
|
|
151
|
+
| `session list` | List live sessions (id, expires, minutes left, last modified) |
|
|
152
|
+
| `session save --file` | **Optional** export of the current graph to a user-chosen snapshot file (wire format) |
|
|
153
|
+
| `session load --file` | Restore a snapshot into RAM (new session id by default; `--keep-id` to reuse) |
|
|
154
|
+
| `session close <id>` | Destroy the session (graph is gone) |
|
|
155
|
+
|
|
156
|
+
Default TTL is 60 minutes (`MEMNET_SESSION_TTL_MINUTES` or `--ttl`).
|
|
157
|
+
|
|
158
|
+
### Add, update & delete
|
|
159
|
+
- `add [line] [--file PATH] [--stdin] [--dry-run] [--allow-new-relation] [--agent NAME] [--session]`
|
|
160
|
+
- Create **new** rows only. Fails with `id_exists` if the id is already in the graph.
|
|
161
|
+
- `update [line] [--file PATH] [--stdin] [--dry-run] [--allow-new-relation] [--agent NAME] [--session]`
|
|
162
|
+
- Replace **existing** rows only. Fails with `not_found` if the id is missing (catches update typos).
|
|
163
|
+
- Batch via `--stdin` or `--file` is strongly preferred. `--dry-run` parses without mutating.
|
|
164
|
+
- `delete --id ID`
|
|
165
|
+
|
|
166
|
+
### Query (graph reads)
|
|
167
|
+
- `query warm --anchor ID [--depth N] [--max-rows M]` — **the normal read for agents**. `active_only` is forced; anchor is required. LAW rows are always included.
|
|
168
|
+
- `query context [--anchor] [--depth] [--max-rows] [--active-only]` — cold/full view (use for audit; warns on stale rows).
|
|
169
|
+
- `query neighbors <id> [--depth]`
|
|
170
|
+
- `query path <src> <dst>`
|
|
171
|
+
|
|
172
|
+
### Direct reads
|
|
173
|
+
- `read list [--tag T] [--active-only] [--where field=value ...]`
|
|
174
|
+
- `read get --id ID [--tag T]`
|
|
175
|
+
|
|
176
|
+
`--where` filters by field value (exact match). Repeat for AND. Use `*` or `?` wildcards for glob match (e.g. `--where name=*Tiexin*`).
|
|
177
|
+
|
|
178
|
+
### Housekeeping
|
|
179
|
+
- `housekeep stats` — `@STAT` rows + caps for rows/edges/relations/orphans/dangling/recyclable/**modified**.
|
|
180
|
+
- `housekeep stale|orphans|dangling|recyclable` — list the respective sets.
|
|
181
|
+
- `housekeep prune stale|... --apply` — actually delete (emits `@DEL` lines and a summary on stderr).
|
|
182
|
+
|
|
183
|
+
`stale` = recyclable + dangling + orphans.
|
|
184
|
+
|
|
185
|
+
### Schema & relations
|
|
186
|
+
- `tagmap fields [--tag T]` / `map fields` — reference field lists.
|
|
187
|
+
- `tagmap show` / `map show` — current session's effective tag map.
|
|
188
|
+
- `relations list` — allowed EDG relation names for this session.
|
|
189
|
+
- New relations are rejected unless `add` or `update` uses `--allow-new-relation` (subject to `max_relations`).
|
|
190
|
+
|
|
191
|
+
### Examples & server
|
|
192
|
+
- `examples map|workflow|add <tag>|path`
|
|
193
|
+
- `serve [--host] [--port]` — the in-memory graph host. Required for normal CLI use across processes.
|
|
194
|
+
- `version`, `guide`, `guide --loose`
|
|
195
|
+
|
|
196
|
+
## Session model & optional snapshots
|
|
197
|
+
|
|
198
|
+
- One `session open` per task. Agents should `resume` rather than open duplicates.
|
|
199
|
+
- The graph is **RAM only** while the session is live.
|
|
200
|
+
- `session save --file my.snap` writes a plain-text wire-format snapshot that *you* own. `session load --file my.snap` brings it back into a (usually new) RAM session.
|
|
201
|
+
- On `close` or TTL expiry the session is dropped from the server; no server-side files remain.
|
|
202
|
+
- Snapshots are a user convenience, not MemNet's durability layer.
|
|
203
|
+
|
|
204
|
+
## Housekeeping, warnings, and signals
|
|
205
|
+
|
|
206
|
+
On every stateful command the server emits advisory `@WRN` lines on stderr (capped per call):
|
|
207
|
+
|
|
208
|
+
- `near_cap*`, `ttl_expiring`
|
|
209
|
+
- `stale_in_store`, `stale_dangling`, `stale_orphans`, `stale_graph`
|
|
210
|
+
- `mission_settled`
|
|
211
|
+
- `fanout_clamped`, `dangling_endpoint`, etc.
|
|
212
|
+
|
|
213
|
+
`@STAT` lines report counts vs caps. `@DEL` lines are emitted after successful `prune --apply` or `delete`.
|
|
214
|
+
|
|
215
|
+
## Environment variables
|
|
216
|
+
|
|
217
|
+
| Variable | Effect |
|
|
218
|
+
|---------------------------------|--------|
|
|
219
|
+
| `MEMNET_SESSION` | Default session id when `--session` is omitted |
|
|
220
|
+
| `MEMNET_SESSION_TTL_MINUTES` | Default TTL for new sessions (1..1440) |
|
|
221
|
+
| `MEMNET_AGENT` | Default agent name stamped on written records |
|
|
222
|
+
| `MEMNET_SERVE_HOST`, `MEMNET_SERVE_PORT` | Bind address for `memnet serve` (client discovery is implicit via the same vars) |
|
|
223
|
+
| `MEMNET_MAX_ROWS` / `MAX_LAW` / `MAX_RELATIONS` / ... | Hard caps (see `Caps` in config) |
|
|
224
|
+
| `MEMNET_TEST_INLINE` | When set, CLI runs in-process (tests, one-off scripts). Not for normal agent use. |
|
|
225
|
+
|
|
226
|
+
All caps have `MEMNET_MAX_*` names; see source for the full list and defaults.
|
|
227
|
+
|
|
228
|
+
## Architecture (one minute)
|
|
229
|
+
|
|
230
|
+
- `tagMap` — merged fixed + user schema loaded at `session open`. Drives parsing and field order on output.
|
|
231
|
+
- `memStore` — in-memory nodes + directed edges (EDG). Write-order index, simple BFS for neighbours / paths / warm packs.
|
|
232
|
+
- `LAW` rows — special, usually exempt from orphan/dangling accounting and always surface in warm reads.
|
|
233
|
+
- `recycle` field — `persistent` (default for active world) vs `delete_on_settle` / `delete_on_expire` (missions). `query warm` hides the latter.
|
|
234
|
+
- Server holds a registry of live `SessionEntry`s. CLI is a stateless client that talks over localhost TCP (or in-process in tests).
|
|
235
|
+
|
|
236
|
+
No JSON on the wire for LLM consumption — only the `@TAG:` lines plus a handful of control records on stderr.
|
|
237
|
+
|
|
238
|
+
## Application notes
|
|
239
|
+
|
|
240
|
+
Rich, document-style worked examples live under `application-notes/`. These are self-contained narratives (one `.md` per note) showing complete usage patterns with all data — including background, configurations, bibles, rules, and user preferences — kept inside MemNet.
|
|
241
|
+
|
|
242
|
+
See [application-notes/llm-novel-writer.md](application-notes/llm-novel-writer.md) for the first example: an interactive LLM novel writer driven by the explicit 6-step read → context → user-input-as-data → analyse → update → loop pipeline.
|
|
243
|
+
|
|
244
|
+
See [application-notes/llm-sysml-v2-modeling.md](application-notes/llm-sysml-v2-modeling.md) for the second: LLM-assisted SysML v2 textual modeling (6U CubeSat PDU controller) with the same 6-step pipeline, a SysML v2 syntax reference table, a deployable "whole model as rows" block, explicit demonstration that models living in different .sysml files are easily referred to together via @PKG rows + declaredIn / cross-package EDG, and concrete examples of using the graph to help build the system (allocations, ports and connections driving wiring, implementation tasks and deployment), write the system model docs (interconnection views, behaviour specs, traceability matrices generated from the rows), and evaluate runtime behaviour (BEHD + timing/power + allocations for analysis, latency and power budgeting). Warm + EDG + settlement still keeps every turn's slice small, granular and on-demand.
|
|
245
|
+
|
|
246
|
+
## Development
|
|
247
|
+
|
|
248
|
+
```powershell
|
|
249
|
+
.\scripts\dev.ps1 # setup / test / lint / fmt / cli
|
|
250
|
+
pytest
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Tests run with `MEMNET_TEST_INLINE=1` so they do not require a separate `serve` process.
|
|
254
|
+
|
|
255
|
+
## Licence
|
|
256
|
+
|
|
257
|
+
MIT
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# MemNet
|
|
2
|
+
|
|
3
|
+
**Pure in-memory working-memory graph for LLM "goldfish brains"** — structured state an agent writes once and re-reads each turn because the model forgets.
|
|
4
|
+
|
|
5
|
+
MemNet is **scratch memory for the current task**, not a durable knowledge base or vector store. Sessions live in RAM, expire by TTL, and disappear on `session close`. There is **no automatic disk state**; persistence is explicit and user-controlled via `session save` / `session load`.
|
|
6
|
+
|
|
7
|
+
## The problem it solves
|
|
8
|
+
|
|
9
|
+
LLMs lose track of entities, state, and rules between tool calls. MemNet gives the agent a small, typed, queryable graph it can:
|
|
10
|
+
|
|
11
|
+
- add facts, tasks, and relations once; update them when state changes,
|
|
12
|
+
- pull back only the live slice on the next turn (`query warm --anchor`),
|
|
13
|
+
- settle or expire missions so they stop polluting the prompt,
|
|
14
|
+
- keep hard limits and produce machine-readable warnings instead of silent bloat.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```powershell
|
|
19
|
+
pip install memnet-llm
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
From source (development):
|
|
23
|
+
|
|
24
|
+
```powershell
|
|
25
|
+
pip install -e ".[dev]"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The CLI command is still **`memnet`**. PyPI package name is **`memnet-llm`** (the name `memnet` on [PyPI](https://pypi.org/project/memnet/) is a different project — memristive neural networks).
|
|
29
|
+
|
|
30
|
+
Requires Python ≥ 3.11.
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
You need two terminals. One runs the in-memory server that holds the graph; the other runs the CLI client.
|
|
35
|
+
|
|
36
|
+
**Terminal 1 (server):**
|
|
37
|
+
|
|
38
|
+
```powershell
|
|
39
|
+
memnet serve
|
|
40
|
+
# prints: MEMNET_SERVE=127.0.0.1:18765
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Terminal 2 (client):**
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
# See the cheat sheet
|
|
47
|
+
memnet guide --loose
|
|
48
|
+
|
|
49
|
+
# Start a session with the bundled schema
|
|
50
|
+
memnet session open --map-file src/memnet/examples/schema.example.txt
|
|
51
|
+
# stderr also prints: MEMNET_SESSION=mn_xxxxxxxx
|
|
52
|
+
$env:MEMNET_SESSION = "mn_xxxxxxxx"
|
|
53
|
+
|
|
54
|
+
# Ingest a small world (LAW rules + world state + missions)
|
|
55
|
+
memnet add --file src/memnet/examples/workflow.example.txt
|
|
56
|
+
|
|
57
|
+
# Preferred read for the next LLM turn: only live mission state
|
|
58
|
+
memnet query warm --anchor PLR01
|
|
59
|
+
|
|
60
|
+
# When done
|
|
61
|
+
memnet session close $env:MEMNET_SESSION
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Without `memnet serve` running, any stateful command returns `@ERR: serve_required`.
|
|
65
|
+
|
|
66
|
+
For one-off scripting or tests you can set `MEMNET_TEST_INLINE=1` to run in-process (no server), but this is not the normal multi-turn agent mode.
|
|
67
|
+
|
|
68
|
+
**LLM agents:** read `LLM-GUIDE.md` (in this repo) for the full agent playbook, the goldfish loop, settlement pattern, and disciplines. It is written to be consumed by models.
|
|
69
|
+
|
|
70
|
+
## The goldfish loop (recommended pattern)
|
|
71
|
+
|
|
72
|
+
A typical agent turn:
|
|
73
|
+
|
|
74
|
+
1. `add` new rows or `update` existing ones (`@TAG:` lines, batch via `--stdin` or `--file` is best).
|
|
75
|
+
2. `query warm --anchor <focus>` — returns only active (non-recyclable) rows, always includes LAW.
|
|
76
|
+
3. Paste the wire lines into the prompt, reason, decide on next adds/updates or a mission settle.
|
|
77
|
+
4. On mission complete: **update** the `TSK` (or equivalent) with both `status=settled` **and** `recycle=delete_on_settle`. Mission edges usually use `delete_on_expire` or `delete_on_settle`.
|
|
78
|
+
5. Optionally `housekeep prune stale --apply` to physically remove settled rows.
|
|
79
|
+
6. Next turn starts again at step 1 with a (usually new) anchor.
|
|
80
|
+
|
|
81
|
+
`query context` (cold) returns everything and emits `@WRN: stale_in_store|…` on stderr when recyclable rows exist. Prefer `warm`.
|
|
82
|
+
|
|
83
|
+
## Wire format
|
|
84
|
+
|
|
85
|
+
One record per line:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
@TAG: field|field|...
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- Pipe inside a value must be escaped: `note\|extra` (or `\\|` in some shells).
|
|
92
|
+
- Always quote the whole line in PowerShell or bash when it contains special characters.
|
|
93
|
+
- Reserved output tags: `@SESSION`, `@ERR`, `@WRN`, `@STAT`, `@REL`, `@DEL`.
|
|
94
|
+
- Errors and advisories go to **stderr**; data rows to **stdout**.
|
|
95
|
+
|
|
96
|
+
Example multi-line ingest (PowerShell):
|
|
97
|
+
|
|
98
|
+
```powershell
|
|
99
|
+
memnet add --stdin @"
|
|
100
|
+
@NPC: N01|Shen Tiexin|female(12)|0|traditional|80|active|persistent
|
|
101
|
+
@EDG: E01|N01|seeks_help|PLR01|unlock|delete_on_expire
|
|
102
|
+
"@
|
|
103
|
+
|
|
104
|
+
memnet update --stdin @"
|
|
105
|
+
@NPC: N01|Shen Tiexin|female(12)|0|traditional|90|active|persistent
|
|
106
|
+
"@
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
See `memnet guide`, `memnet examples map`, and `memnet tagmap fields --tag <TAG>` for the current schema.
|
|
110
|
+
|
|
111
|
+
## Commands
|
|
112
|
+
|
|
113
|
+
Run any command with `--help` for full flags.
|
|
114
|
+
|
|
115
|
+
### Session lifecycle
|
|
116
|
+
| Command | Purpose |
|
|
117
|
+
|--------------------------|---------|
|
|
118
|
+
| `session open --map-file` | Create a new session (prints `@SESSION:` and `MEMNET_SESSION=...` on stderr) |
|
|
119
|
+
| `session resume <id>` | Attach to an existing session |
|
|
120
|
+
| `session current` | Show the id from `$env:MEMNET_SESSION` (or "none") |
|
|
121
|
+
| `session list` | List live sessions (id, expires, minutes left, last modified) |
|
|
122
|
+
| `session save --file` | **Optional** export of the current graph to a user-chosen snapshot file (wire format) |
|
|
123
|
+
| `session load --file` | Restore a snapshot into RAM (new session id by default; `--keep-id` to reuse) |
|
|
124
|
+
| `session close <id>` | Destroy the session (graph is gone) |
|
|
125
|
+
|
|
126
|
+
Default TTL is 60 minutes (`MEMNET_SESSION_TTL_MINUTES` or `--ttl`).
|
|
127
|
+
|
|
128
|
+
### Add, update & delete
|
|
129
|
+
- `add [line] [--file PATH] [--stdin] [--dry-run] [--allow-new-relation] [--agent NAME] [--session]`
|
|
130
|
+
- Create **new** rows only. Fails with `id_exists` if the id is already in the graph.
|
|
131
|
+
- `update [line] [--file PATH] [--stdin] [--dry-run] [--allow-new-relation] [--agent NAME] [--session]`
|
|
132
|
+
- Replace **existing** rows only. Fails with `not_found` if the id is missing (catches update typos).
|
|
133
|
+
- Batch via `--stdin` or `--file` is strongly preferred. `--dry-run` parses without mutating.
|
|
134
|
+
- `delete --id ID`
|
|
135
|
+
|
|
136
|
+
### Query (graph reads)
|
|
137
|
+
- `query warm --anchor ID [--depth N] [--max-rows M]` — **the normal read for agents**. `active_only` is forced; anchor is required. LAW rows are always included.
|
|
138
|
+
- `query context [--anchor] [--depth] [--max-rows] [--active-only]` — cold/full view (use for audit; warns on stale rows).
|
|
139
|
+
- `query neighbors <id> [--depth]`
|
|
140
|
+
- `query path <src> <dst>`
|
|
141
|
+
|
|
142
|
+
### Direct reads
|
|
143
|
+
- `read list [--tag T] [--active-only] [--where field=value ...]`
|
|
144
|
+
- `read get --id ID [--tag T]`
|
|
145
|
+
|
|
146
|
+
`--where` filters by field value (exact match). Repeat for AND. Use `*` or `?` wildcards for glob match (e.g. `--where name=*Tiexin*`).
|
|
147
|
+
|
|
148
|
+
### Housekeeping
|
|
149
|
+
- `housekeep stats` — `@STAT` rows + caps for rows/edges/relations/orphans/dangling/recyclable/**modified**.
|
|
150
|
+
- `housekeep stale|orphans|dangling|recyclable` — list the respective sets.
|
|
151
|
+
- `housekeep prune stale|... --apply` — actually delete (emits `@DEL` lines and a summary on stderr).
|
|
152
|
+
|
|
153
|
+
`stale` = recyclable + dangling + orphans.
|
|
154
|
+
|
|
155
|
+
### Schema & relations
|
|
156
|
+
- `tagmap fields [--tag T]` / `map fields` — reference field lists.
|
|
157
|
+
- `tagmap show` / `map show` — current session's effective tag map.
|
|
158
|
+
- `relations list` — allowed EDG relation names for this session.
|
|
159
|
+
- New relations are rejected unless `add` or `update` uses `--allow-new-relation` (subject to `max_relations`).
|
|
160
|
+
|
|
161
|
+
### Examples & server
|
|
162
|
+
- `examples map|workflow|add <tag>|path`
|
|
163
|
+
- `serve [--host] [--port]` — the in-memory graph host. Required for normal CLI use across processes.
|
|
164
|
+
- `version`, `guide`, `guide --loose`
|
|
165
|
+
|
|
166
|
+
## Session model & optional snapshots
|
|
167
|
+
|
|
168
|
+
- One `session open` per task. Agents should `resume` rather than open duplicates.
|
|
169
|
+
- The graph is **RAM only** while the session is live.
|
|
170
|
+
- `session save --file my.snap` writes a plain-text wire-format snapshot that *you* own. `session load --file my.snap` brings it back into a (usually new) RAM session.
|
|
171
|
+
- On `close` or TTL expiry the session is dropped from the server; no server-side files remain.
|
|
172
|
+
- Snapshots are a user convenience, not MemNet's durability layer.
|
|
173
|
+
|
|
174
|
+
## Housekeeping, warnings, and signals
|
|
175
|
+
|
|
176
|
+
On every stateful command the server emits advisory `@WRN` lines on stderr (capped per call):
|
|
177
|
+
|
|
178
|
+
- `near_cap*`, `ttl_expiring`
|
|
179
|
+
- `stale_in_store`, `stale_dangling`, `stale_orphans`, `stale_graph`
|
|
180
|
+
- `mission_settled`
|
|
181
|
+
- `fanout_clamped`, `dangling_endpoint`, etc.
|
|
182
|
+
|
|
183
|
+
`@STAT` lines report counts vs caps. `@DEL` lines are emitted after successful `prune --apply` or `delete`.
|
|
184
|
+
|
|
185
|
+
## Environment variables
|
|
186
|
+
|
|
187
|
+
| Variable | Effect |
|
|
188
|
+
|---------------------------------|--------|
|
|
189
|
+
| `MEMNET_SESSION` | Default session id when `--session` is omitted |
|
|
190
|
+
| `MEMNET_SESSION_TTL_MINUTES` | Default TTL for new sessions (1..1440) |
|
|
191
|
+
| `MEMNET_AGENT` | Default agent name stamped on written records |
|
|
192
|
+
| `MEMNET_SERVE_HOST`, `MEMNET_SERVE_PORT` | Bind address for `memnet serve` (client discovery is implicit via the same vars) |
|
|
193
|
+
| `MEMNET_MAX_ROWS` / `MAX_LAW` / `MAX_RELATIONS` / ... | Hard caps (see `Caps` in config) |
|
|
194
|
+
| `MEMNET_TEST_INLINE` | When set, CLI runs in-process (tests, one-off scripts). Not for normal agent use. |
|
|
195
|
+
|
|
196
|
+
All caps have `MEMNET_MAX_*` names; see source for the full list and defaults.
|
|
197
|
+
|
|
198
|
+
## Architecture (one minute)
|
|
199
|
+
|
|
200
|
+
- `tagMap` — merged fixed + user schema loaded at `session open`. Drives parsing and field order on output.
|
|
201
|
+
- `memStore` — in-memory nodes + directed edges (EDG). Write-order index, simple BFS for neighbours / paths / warm packs.
|
|
202
|
+
- `LAW` rows — special, usually exempt from orphan/dangling accounting and always surface in warm reads.
|
|
203
|
+
- `recycle` field — `persistent` (default for active world) vs `delete_on_settle` / `delete_on_expire` (missions). `query warm` hides the latter.
|
|
204
|
+
- Server holds a registry of live `SessionEntry`s. CLI is a stateless client that talks over localhost TCP (or in-process in tests).
|
|
205
|
+
|
|
206
|
+
No JSON on the wire for LLM consumption — only the `@TAG:` lines plus a handful of control records on stderr.
|
|
207
|
+
|
|
208
|
+
## Application notes
|
|
209
|
+
|
|
210
|
+
Rich, document-style worked examples live under `application-notes/`. These are self-contained narratives (one `.md` per note) showing complete usage patterns with all data — including background, configurations, bibles, rules, and user preferences — kept inside MemNet.
|
|
211
|
+
|
|
212
|
+
See [application-notes/llm-novel-writer.md](application-notes/llm-novel-writer.md) for the first example: an interactive LLM novel writer driven by the explicit 6-step read → context → user-input-as-data → analyse → update → loop pipeline.
|
|
213
|
+
|
|
214
|
+
See [application-notes/llm-sysml-v2-modeling.md](application-notes/llm-sysml-v2-modeling.md) for the second: LLM-assisted SysML v2 textual modeling (6U CubeSat PDU controller) with the same 6-step pipeline, a SysML v2 syntax reference table, a deployable "whole model as rows" block, explicit demonstration that models living in different .sysml files are easily referred to together via @PKG rows + declaredIn / cross-package EDG, and concrete examples of using the graph to help build the system (allocations, ports and connections driving wiring, implementation tasks and deployment), write the system model docs (interconnection views, behaviour specs, traceability matrices generated from the rows), and evaluate runtime behaviour (BEHD + timing/power + allocations for analysis, latency and power budgeting). Warm + EDG + settlement still keeps every turn's slice small, granular and on-demand.
|
|
215
|
+
|
|
216
|
+
## Development
|
|
217
|
+
|
|
218
|
+
```powershell
|
|
219
|
+
.\scripts\dev.ps1 # setup / test / lint / fmt / cli
|
|
220
|
+
pytest
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Tests run with `MEMNET_TEST_INLINE=1` so they do not require a separate `serve` process.
|
|
224
|
+
|
|
225
|
+
## Licence
|
|
226
|
+
|
|
227
|
+
MIT
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "memnet-llm"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "In-memory working-memory graph CLI for LLM agents (goldfish brain scratch space)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{ name = "MemNet contributors" }]
|
|
13
|
+
keywords = ["knowledge-graph", "llm", "cli", "memory", "agent", "working-memory"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"pydantic>=2.10",
|
|
26
|
+
"rich>=13.9",
|
|
27
|
+
"typer>=0.15",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/chouswei/MemNet"
|
|
32
|
+
Repository = "https://github.com/chouswei/MemNet"
|
|
33
|
+
Changelog = "https://github.com/chouswei/MemNet/blob/master/CHANGELOG.md"
|
|
34
|
+
Documentation = "https://github.com/chouswei/MemNet/blob/master/LLM-GUIDE.md"
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = [
|
|
38
|
+
"pytest>=8.3",
|
|
39
|
+
"pytest-cov>=6.0",
|
|
40
|
+
"ruff>=0.9",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.scripts]
|
|
44
|
+
memnet = "memnet.cli:main"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.version]
|
|
47
|
+
path = "src/memnet/__init__.py"
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.wheel]
|
|
50
|
+
packages = ["src/memnet"]
|
|
51
|
+
|
|
52
|
+
[tool.hatch.build.targets.sdist]
|
|
53
|
+
only-include = ["src/memnet", "tests", "README.md", "LICENSE", "pyproject.toml"]
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
testpaths = ["tests"]
|
|
57
|
+
addopts = "-q"
|
|
58
|
+
markers = [
|
|
59
|
+
"scheme(id): integration scheme identifier from plan S01-S115",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
[tool.ruff]
|
|
63
|
+
target-version = "py311"
|
|
64
|
+
line-length = 100
|
|
65
|
+
src = ["src", "tests"]
|
|
66
|
+
|
|
67
|
+
[tool.ruff.lint]
|
|
68
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
69
|
+
|
|
70
|
+
[tool.ruff.format]
|
|
71
|
+
quote-style = "double"
|