consolidation-memory 0.1.0__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.
- consolidation_memory-0.1.0/LICENSE +21 -0
- consolidation_memory-0.1.0/PKG-INFO +305 -0
- consolidation_memory-0.1.0/README.md +261 -0
- consolidation_memory-0.1.0/pyproject.toml +58 -0
- consolidation_memory-0.1.0/setup.cfg +4 -0
- consolidation_memory-0.1.0/src/consolidation_memory/__init__.py +24 -0
- consolidation_memory-0.1.0/src/consolidation_memory/__main__.py +5 -0
- consolidation_memory-0.1.0/src/consolidation_memory/backends/__init__.py +142 -0
- consolidation_memory-0.1.0/src/consolidation_memory/backends/base.py +32 -0
- consolidation_memory-0.1.0/src/consolidation_memory/backends/fastembed_backend.py +52 -0
- consolidation_memory-0.1.0/src/consolidation_memory/backends/lmstudio.py +117 -0
- consolidation_memory-0.1.0/src/consolidation_memory/backends/ollama.py +96 -0
- consolidation_memory-0.1.0/src/consolidation_memory/backends/openai_backend.py +83 -0
- consolidation_memory-0.1.0/src/consolidation_memory/cli.py +440 -0
- consolidation_memory-0.1.0/src/consolidation_memory/client.py +477 -0
- consolidation_memory-0.1.0/src/consolidation_memory/config.py +158 -0
- consolidation_memory-0.1.0/src/consolidation_memory/consolidation.py +698 -0
- consolidation_memory-0.1.0/src/consolidation_memory/context_assembler.py +170 -0
- consolidation_memory-0.1.0/src/consolidation_memory/database.py +458 -0
- consolidation_memory-0.1.0/src/consolidation_memory/defaults/__init__.py +0 -0
- consolidation_memory-0.1.0/src/consolidation_memory/rest.py +143 -0
- consolidation_memory-0.1.0/src/consolidation_memory/schemas.py +273 -0
- consolidation_memory-0.1.0/src/consolidation_memory/server.py +161 -0
- consolidation_memory-0.1.0/src/consolidation_memory/topic_cache.py +60 -0
- consolidation_memory-0.1.0/src/consolidation_memory/types.py +71 -0
- consolidation_memory-0.1.0/src/consolidation_memory/vector_store.py +309 -0
- consolidation_memory-0.1.0/src/consolidation_memory.egg-info/PKG-INFO +305 -0
- consolidation_memory-0.1.0/src/consolidation_memory.egg-info/SOURCES.txt +34 -0
- consolidation_memory-0.1.0/src/consolidation_memory.egg-info/dependency_links.txt +1 -0
- consolidation_memory-0.1.0/src/consolidation_memory.egg-info/entry_points.txt +2 -0
- consolidation_memory-0.1.0/src/consolidation_memory.egg-info/requires.txt +27 -0
- consolidation_memory-0.1.0/src/consolidation_memory.egg-info/top_level.txt +1 -0
- consolidation_memory-0.1.0/tests/test_client.py +241 -0
- consolidation_memory-0.1.0/tests/test_core.py +943 -0
- consolidation_memory-0.1.0/tests/test_rest.py +117 -0
- consolidation_memory-0.1.0/tests/test_schemas.py +109 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Charlie Wright
|
|
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,305 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: consolidation-memory
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local-first persistent memory for AI agents — store, recall, and consolidate knowledge across sessions using FAISS, SQLite, and any LLM
|
|
5
|
+
Author: Charlie Wright
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/charliee1w/consolidation-memory
|
|
8
|
+
Project-URL: Repository, https://github.com/charliee1w/consolidation-memory
|
|
9
|
+
Project-URL: Issues, https://github.com/charliee1w/consolidation-memory/issues
|
|
10
|
+
Keywords: mcp,memory,ai,semantic-search,faiss,claude
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: mcp[cli]>=1.26.0
|
|
24
|
+
Requires-Dist: httpx>=0.28.0
|
|
25
|
+
Requires-Dist: faiss-cpu>=1.9.0
|
|
26
|
+
Requires-Dist: scipy>=1.14.0
|
|
27
|
+
Requires-Dist: numpy>=2.0.0
|
|
28
|
+
Requires-Dist: platformdirs>=4.0.0
|
|
29
|
+
Requires-Dist: tomli>=2.0.0; python_version < "3.11"
|
|
30
|
+
Provides-Extra: fastembed
|
|
31
|
+
Requires-Dist: fastembed>=0.4.0; extra == "fastembed"
|
|
32
|
+
Provides-Extra: openai
|
|
33
|
+
Requires-Dist: openai>=1.0.0; extra == "openai"
|
|
34
|
+
Provides-Extra: rest
|
|
35
|
+
Requires-Dist: fastapi>=0.115.0; extra == "rest"
|
|
36
|
+
Requires-Dist: uvicorn[standard]>=0.34.0; extra == "rest"
|
|
37
|
+
Provides-Extra: all
|
|
38
|
+
Requires-Dist: consolidation-memory[fastembed,openai,rest]; extra == "all"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
41
|
+
Requires-Dist: ruff>=0.7.0; extra == "dev"
|
|
42
|
+
Requires-Dist: httpx>=0.28.0; extra == "dev"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# consolidation-memory
|
|
46
|
+
|
|
47
|
+
Local-first persistent memory for AI agents. Store facts, solutions, and preferences as episodes — then a local LLM automatically clusters and distills them into structured knowledge documents. Your AI remembers what it learned, not just what you said.
|
|
48
|
+
|
|
49
|
+
Works with **any LLM** (LM Studio, Ollama, OpenAI) and **any interface** — MCP (Claude Desktop/Code/Cursor), Python API, REST API, or OpenAI function calling.
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install consolidation-memory[fastembed]
|
|
55
|
+
consolidation-memory init
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### MCP (Claude Desktop / Claude Code / Cursor)
|
|
59
|
+
|
|
60
|
+
Add to your Claude Desktop config (`claude_desktop_config.json`):
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"mcpServers": {
|
|
65
|
+
"consolidation_memory": {
|
|
66
|
+
"command": "consolidation-memory"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Python API
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from consolidation_memory import MemoryClient
|
|
76
|
+
|
|
77
|
+
with MemoryClient() as mem:
|
|
78
|
+
# Store
|
|
79
|
+
result = mem.store("User prefers dark mode", content_type="preference", tags=["ui"])
|
|
80
|
+
print(result.id) # UUID of stored episode
|
|
81
|
+
|
|
82
|
+
# Recall
|
|
83
|
+
result = mem.recall("user interface preferences")
|
|
84
|
+
for ep in result.episodes:
|
|
85
|
+
print(ep["content"], ep["similarity"])
|
|
86
|
+
for doc in result.knowledge:
|
|
87
|
+
print(doc["title"])
|
|
88
|
+
|
|
89
|
+
# Status
|
|
90
|
+
stats = mem.status()
|
|
91
|
+
print(stats.episodic_buffer["total"])
|
|
92
|
+
print(stats.knowledge_base["total_topics"])
|
|
93
|
+
|
|
94
|
+
# Forget
|
|
95
|
+
mem.forget(episode_id="some-uuid")
|
|
96
|
+
|
|
97
|
+
# Export
|
|
98
|
+
export = mem.export()
|
|
99
|
+
print(export.path) # backup JSON file
|
|
100
|
+
|
|
101
|
+
# Correct knowledge
|
|
102
|
+
mem.correct("vr_setup.md", "SteamVR version is now 2.7, not 2.5")
|
|
103
|
+
|
|
104
|
+
# Manual consolidation
|
|
105
|
+
mem.consolidate()
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### OpenAI Function Calling (any OpenAI-compatible LLM)
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import json
|
|
112
|
+
from openai import OpenAI
|
|
113
|
+
from consolidation_memory import MemoryClient
|
|
114
|
+
from consolidation_memory.schemas import openai_tools, dispatch_tool_call
|
|
115
|
+
|
|
116
|
+
client = OpenAI(base_url="http://localhost:1234/v1", api_key="lm-studio")
|
|
117
|
+
mem = MemoryClient()
|
|
118
|
+
|
|
119
|
+
messages = [{"role": "user", "content": "What do you remember about my VR setup?"}]
|
|
120
|
+
|
|
121
|
+
response = client.chat.completions.create(
|
|
122
|
+
model="qwen2.5-7b-instruct",
|
|
123
|
+
messages=messages,
|
|
124
|
+
tools=openai_tools,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
for call in response.choices[0].message.tool_calls or []:
|
|
128
|
+
result = dispatch_tool_call(mem, call.function.name, json.loads(call.function.arguments))
|
|
129
|
+
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
|
|
130
|
+
|
|
131
|
+
mem.close()
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Works with LM Studio, Ollama, OpenAI, Azure, any OpenAI-compatible API.
|
|
135
|
+
|
|
136
|
+
### REST API
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
pip install consolidation-memory[rest]
|
|
140
|
+
consolidation-memory serve --rest --port 8080
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Store
|
|
145
|
+
curl -X POST http://localhost:8080/memory/store \
|
|
146
|
+
-H "Content-Type: application/json" \
|
|
147
|
+
-d '{"content": "User runs SteamVR on Windows 11", "content_type": "fact"}'
|
|
148
|
+
|
|
149
|
+
# Recall
|
|
150
|
+
curl -X POST http://localhost:8080/memory/recall \
|
|
151
|
+
-H "Content-Type: application/json" \
|
|
152
|
+
-d '{"query": "VR setup"}'
|
|
153
|
+
|
|
154
|
+
# Status
|
|
155
|
+
curl http://localhost:8080/memory/status
|
|
156
|
+
|
|
157
|
+
# Health
|
|
158
|
+
curl http://localhost:8080/health
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
All endpoints:
|
|
162
|
+
|
|
163
|
+
| Method | Path | Description |
|
|
164
|
+
|--------|------|-------------|
|
|
165
|
+
| GET | `/health` | Version + status |
|
|
166
|
+
| POST | `/memory/store` | Store episode |
|
|
167
|
+
| POST | `/memory/recall` | Semantic search |
|
|
168
|
+
| GET | `/memory/status` | System statistics |
|
|
169
|
+
| DELETE | `/memory/episodes/{id}` | Forget episode |
|
|
170
|
+
| POST | `/memory/consolidate` | Run consolidation |
|
|
171
|
+
| POST | `/memory/correct` | Correct knowledge doc |
|
|
172
|
+
| POST | `/memory/export` | Export to JSON |
|
|
173
|
+
|
|
174
|
+
## How It Works
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
Store → Embed → FAISS Index
|
|
178
|
+
↓
|
|
179
|
+
Recall (semantic search + priority scoring)
|
|
180
|
+
↓
|
|
181
|
+
Consolidation (cluster → LLM synthesis → knowledge docs)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
1. **Store**: Episodes (facts, solutions, preferences) are embedded and stored in SQLite + FAISS
|
|
185
|
+
2. **Recall**: Queries are embedded and matched against episodes using cosine similarity, weighted by surprise score, recency, and access frequency
|
|
186
|
+
3. **Consolidate**: Background thread clusters related episodes via agglomerative clustering, then synthesizes them into structured markdown knowledge documents using a local LLM
|
|
187
|
+
|
|
188
|
+
## MCP Tools
|
|
189
|
+
|
|
190
|
+
| Tool | Description |
|
|
191
|
+
|------|-------------|
|
|
192
|
+
| `memory_store` | Store a memory episode |
|
|
193
|
+
| `memory_recall` | Semantic search over episodes + knowledge |
|
|
194
|
+
| `memory_status` | System statistics |
|
|
195
|
+
| `memory_forget` | Remove an episode |
|
|
196
|
+
| `memory_export` | Export to JSON snapshot |
|
|
197
|
+
| `memory_correct` | Correct a knowledge document |
|
|
198
|
+
|
|
199
|
+
## CLI Commands
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
consolidation-memory serve # Start MCP server (default)
|
|
203
|
+
consolidation-memory serve --rest # Start REST API on 127.0.0.1:8080
|
|
204
|
+
consolidation-memory serve --rest --port 9000 --host 0.0.0.0
|
|
205
|
+
consolidation-memory init # Interactive setup
|
|
206
|
+
consolidation-memory status # Show statistics
|
|
207
|
+
consolidation-memory consolidate # Run consolidation manually
|
|
208
|
+
consolidation-memory export # Export to JSON
|
|
209
|
+
consolidation-memory import PATH # Import from JSON export
|
|
210
|
+
consolidation-memory reindex # Re-embed with current backend
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Embedding Backends
|
|
214
|
+
|
|
215
|
+
| Backend | Config Value | Model | Dimensions | Requirements |
|
|
216
|
+
|---------|-------------|-------|-----------|--------------|
|
|
217
|
+
| **FastEmbed** (default) | `fastembed` | bge-small-en-v1.5 | 384 | `pip install consolidation-memory[fastembed]` |
|
|
218
|
+
| LM Studio | `lmstudio` | nomic-embed-text-v1.5 | 768 | LM Studio running |
|
|
219
|
+
| OpenAI | `openai` | text-embedding-3-small | 1536 | API key |
|
|
220
|
+
| Ollama | `ollama` | nomic-embed-text | 768 | Ollama running |
|
|
221
|
+
|
|
222
|
+
## LLM Backends (Consolidation)
|
|
223
|
+
|
|
224
|
+
Consolidation requires an LLM to synthesize episode clusters into knowledge documents. Set `backend = "disabled"` under `[llm]` to use store/recall without consolidation.
|
|
225
|
+
|
|
226
|
+
| Backend | Config Value | Requirements |
|
|
227
|
+
|---------|-------------|--------------|
|
|
228
|
+
| LM Studio (default) | `lmstudio` | LM Studio running with chat model |
|
|
229
|
+
| OpenAI | `openai` | API key |
|
|
230
|
+
| Ollama | `ollama` | Ollama running with chat model |
|
|
231
|
+
| Disabled | `disabled` | None (no consolidation) |
|
|
232
|
+
|
|
233
|
+
## Configuration
|
|
234
|
+
|
|
235
|
+
Config file location:
|
|
236
|
+
- **Linux/macOS**: `~/.config/consolidation_memory/config.toml`
|
|
237
|
+
- **Windows**: `%APPDATA%\consolidation_memory\config.toml`
|
|
238
|
+
- **Override**: `CONSOLIDATION_MEMORY_CONFIG` env var
|
|
239
|
+
|
|
240
|
+
```toml
|
|
241
|
+
[embedding]
|
|
242
|
+
backend = "fastembed"
|
|
243
|
+
|
|
244
|
+
[llm]
|
|
245
|
+
backend = "lmstudio"
|
|
246
|
+
api_base = "http://localhost:1234/v1"
|
|
247
|
+
model = "qwen2.5-7b-instruct"
|
|
248
|
+
|
|
249
|
+
[consolidation]
|
|
250
|
+
auto_run = true
|
|
251
|
+
interval_hours = 6
|
|
252
|
+
cluster_threshold = 0.72
|
|
253
|
+
|
|
254
|
+
[dedup]
|
|
255
|
+
enabled = true
|
|
256
|
+
similarity_threshold = 0.95
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Run `consolidation-memory init` to generate a config interactively.
|
|
260
|
+
|
|
261
|
+
## Data Directory
|
|
262
|
+
|
|
263
|
+
- **Linux**: `~/.local/share/consolidation_memory/`
|
|
264
|
+
- **macOS**: `~/Library/Application Support/consolidation_memory/`
|
|
265
|
+
- **Windows**: `%LOCALAPPDATA%\consolidation_memory\`
|
|
266
|
+
|
|
267
|
+
Override with `data_dir` under `[paths]` in config.
|
|
268
|
+
|
|
269
|
+
## Migrating from Existing Installation
|
|
270
|
+
|
|
271
|
+
If you have an existing data directory, point your config at it:
|
|
272
|
+
|
|
273
|
+
```toml
|
|
274
|
+
[paths]
|
|
275
|
+
data_dir = "C:\\Users\\you\\Documents\\consolidation_memory\\data"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
If switching embedding backends (different dimensions), run:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
consolidation-memory reindex
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Installation Extras
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
pip install consolidation-memory # Core (MCP + Python API)
|
|
288
|
+
pip install consolidation-memory[fastembed] # + FastEmbed (recommended)
|
|
289
|
+
pip install consolidation-memory[openai] # + OpenAI SDK
|
|
290
|
+
pip install consolidation-memory[rest] # + REST API (FastAPI + Uvicorn)
|
|
291
|
+
pip install consolidation-memory[all] # Everything
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Development
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
git clone https://github.com/charliee1w/consolidation-memory
|
|
298
|
+
cd consolidation-memory
|
|
299
|
+
pip install -e ".[fastembed,dev]"
|
|
300
|
+
python -m pytest tests/ -v # 88 tests
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## License
|
|
304
|
+
|
|
305
|
+
MIT
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# consolidation-memory
|
|
2
|
+
|
|
3
|
+
Local-first persistent memory for AI agents. Store facts, solutions, and preferences as episodes — then a local LLM automatically clusters and distills them into structured knowledge documents. Your AI remembers what it learned, not just what you said.
|
|
4
|
+
|
|
5
|
+
Works with **any LLM** (LM Studio, Ollama, OpenAI) and **any interface** — MCP (Claude Desktop/Code/Cursor), Python API, REST API, or OpenAI function calling.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install consolidation-memory[fastembed]
|
|
11
|
+
consolidation-memory init
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### MCP (Claude Desktop / Claude Code / Cursor)
|
|
15
|
+
|
|
16
|
+
Add to your Claude Desktop config (`claude_desktop_config.json`):
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"mcpServers": {
|
|
21
|
+
"consolidation_memory": {
|
|
22
|
+
"command": "consolidation-memory"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Python API
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from consolidation_memory import MemoryClient
|
|
32
|
+
|
|
33
|
+
with MemoryClient() as mem:
|
|
34
|
+
# Store
|
|
35
|
+
result = mem.store("User prefers dark mode", content_type="preference", tags=["ui"])
|
|
36
|
+
print(result.id) # UUID of stored episode
|
|
37
|
+
|
|
38
|
+
# Recall
|
|
39
|
+
result = mem.recall("user interface preferences")
|
|
40
|
+
for ep in result.episodes:
|
|
41
|
+
print(ep["content"], ep["similarity"])
|
|
42
|
+
for doc in result.knowledge:
|
|
43
|
+
print(doc["title"])
|
|
44
|
+
|
|
45
|
+
# Status
|
|
46
|
+
stats = mem.status()
|
|
47
|
+
print(stats.episodic_buffer["total"])
|
|
48
|
+
print(stats.knowledge_base["total_topics"])
|
|
49
|
+
|
|
50
|
+
# Forget
|
|
51
|
+
mem.forget(episode_id="some-uuid")
|
|
52
|
+
|
|
53
|
+
# Export
|
|
54
|
+
export = mem.export()
|
|
55
|
+
print(export.path) # backup JSON file
|
|
56
|
+
|
|
57
|
+
# Correct knowledge
|
|
58
|
+
mem.correct("vr_setup.md", "SteamVR version is now 2.7, not 2.5")
|
|
59
|
+
|
|
60
|
+
# Manual consolidation
|
|
61
|
+
mem.consolidate()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### OpenAI Function Calling (any OpenAI-compatible LLM)
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import json
|
|
68
|
+
from openai import OpenAI
|
|
69
|
+
from consolidation_memory import MemoryClient
|
|
70
|
+
from consolidation_memory.schemas import openai_tools, dispatch_tool_call
|
|
71
|
+
|
|
72
|
+
client = OpenAI(base_url="http://localhost:1234/v1", api_key="lm-studio")
|
|
73
|
+
mem = MemoryClient()
|
|
74
|
+
|
|
75
|
+
messages = [{"role": "user", "content": "What do you remember about my VR setup?"}]
|
|
76
|
+
|
|
77
|
+
response = client.chat.completions.create(
|
|
78
|
+
model="qwen2.5-7b-instruct",
|
|
79
|
+
messages=messages,
|
|
80
|
+
tools=openai_tools,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
for call in response.choices[0].message.tool_calls or []:
|
|
84
|
+
result = dispatch_tool_call(mem, call.function.name, json.loads(call.function.arguments))
|
|
85
|
+
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
|
|
86
|
+
|
|
87
|
+
mem.close()
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Works with LM Studio, Ollama, OpenAI, Azure, any OpenAI-compatible API.
|
|
91
|
+
|
|
92
|
+
### REST API
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pip install consolidation-memory[rest]
|
|
96
|
+
consolidation-memory serve --rest --port 8080
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Store
|
|
101
|
+
curl -X POST http://localhost:8080/memory/store \
|
|
102
|
+
-H "Content-Type: application/json" \
|
|
103
|
+
-d '{"content": "User runs SteamVR on Windows 11", "content_type": "fact"}'
|
|
104
|
+
|
|
105
|
+
# Recall
|
|
106
|
+
curl -X POST http://localhost:8080/memory/recall \
|
|
107
|
+
-H "Content-Type: application/json" \
|
|
108
|
+
-d '{"query": "VR setup"}'
|
|
109
|
+
|
|
110
|
+
# Status
|
|
111
|
+
curl http://localhost:8080/memory/status
|
|
112
|
+
|
|
113
|
+
# Health
|
|
114
|
+
curl http://localhost:8080/health
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
All endpoints:
|
|
118
|
+
|
|
119
|
+
| Method | Path | Description |
|
|
120
|
+
|--------|------|-------------|
|
|
121
|
+
| GET | `/health` | Version + status |
|
|
122
|
+
| POST | `/memory/store` | Store episode |
|
|
123
|
+
| POST | `/memory/recall` | Semantic search |
|
|
124
|
+
| GET | `/memory/status` | System statistics |
|
|
125
|
+
| DELETE | `/memory/episodes/{id}` | Forget episode |
|
|
126
|
+
| POST | `/memory/consolidate` | Run consolidation |
|
|
127
|
+
| POST | `/memory/correct` | Correct knowledge doc |
|
|
128
|
+
| POST | `/memory/export` | Export to JSON |
|
|
129
|
+
|
|
130
|
+
## How It Works
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
Store → Embed → FAISS Index
|
|
134
|
+
↓
|
|
135
|
+
Recall (semantic search + priority scoring)
|
|
136
|
+
↓
|
|
137
|
+
Consolidation (cluster → LLM synthesis → knowledge docs)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
1. **Store**: Episodes (facts, solutions, preferences) are embedded and stored in SQLite + FAISS
|
|
141
|
+
2. **Recall**: Queries are embedded and matched against episodes using cosine similarity, weighted by surprise score, recency, and access frequency
|
|
142
|
+
3. **Consolidate**: Background thread clusters related episodes via agglomerative clustering, then synthesizes them into structured markdown knowledge documents using a local LLM
|
|
143
|
+
|
|
144
|
+
## MCP Tools
|
|
145
|
+
|
|
146
|
+
| Tool | Description |
|
|
147
|
+
|------|-------------|
|
|
148
|
+
| `memory_store` | Store a memory episode |
|
|
149
|
+
| `memory_recall` | Semantic search over episodes + knowledge |
|
|
150
|
+
| `memory_status` | System statistics |
|
|
151
|
+
| `memory_forget` | Remove an episode |
|
|
152
|
+
| `memory_export` | Export to JSON snapshot |
|
|
153
|
+
| `memory_correct` | Correct a knowledge document |
|
|
154
|
+
|
|
155
|
+
## CLI Commands
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
consolidation-memory serve # Start MCP server (default)
|
|
159
|
+
consolidation-memory serve --rest # Start REST API on 127.0.0.1:8080
|
|
160
|
+
consolidation-memory serve --rest --port 9000 --host 0.0.0.0
|
|
161
|
+
consolidation-memory init # Interactive setup
|
|
162
|
+
consolidation-memory status # Show statistics
|
|
163
|
+
consolidation-memory consolidate # Run consolidation manually
|
|
164
|
+
consolidation-memory export # Export to JSON
|
|
165
|
+
consolidation-memory import PATH # Import from JSON export
|
|
166
|
+
consolidation-memory reindex # Re-embed with current backend
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Embedding Backends
|
|
170
|
+
|
|
171
|
+
| Backend | Config Value | Model | Dimensions | Requirements |
|
|
172
|
+
|---------|-------------|-------|-----------|--------------|
|
|
173
|
+
| **FastEmbed** (default) | `fastembed` | bge-small-en-v1.5 | 384 | `pip install consolidation-memory[fastembed]` |
|
|
174
|
+
| LM Studio | `lmstudio` | nomic-embed-text-v1.5 | 768 | LM Studio running |
|
|
175
|
+
| OpenAI | `openai` | text-embedding-3-small | 1536 | API key |
|
|
176
|
+
| Ollama | `ollama` | nomic-embed-text | 768 | Ollama running |
|
|
177
|
+
|
|
178
|
+
## LLM Backends (Consolidation)
|
|
179
|
+
|
|
180
|
+
Consolidation requires an LLM to synthesize episode clusters into knowledge documents. Set `backend = "disabled"` under `[llm]` to use store/recall without consolidation.
|
|
181
|
+
|
|
182
|
+
| Backend | Config Value | Requirements |
|
|
183
|
+
|---------|-------------|--------------|
|
|
184
|
+
| LM Studio (default) | `lmstudio` | LM Studio running with chat model |
|
|
185
|
+
| OpenAI | `openai` | API key |
|
|
186
|
+
| Ollama | `ollama` | Ollama running with chat model |
|
|
187
|
+
| Disabled | `disabled` | None (no consolidation) |
|
|
188
|
+
|
|
189
|
+
## Configuration
|
|
190
|
+
|
|
191
|
+
Config file location:
|
|
192
|
+
- **Linux/macOS**: `~/.config/consolidation_memory/config.toml`
|
|
193
|
+
- **Windows**: `%APPDATA%\consolidation_memory\config.toml`
|
|
194
|
+
- **Override**: `CONSOLIDATION_MEMORY_CONFIG` env var
|
|
195
|
+
|
|
196
|
+
```toml
|
|
197
|
+
[embedding]
|
|
198
|
+
backend = "fastembed"
|
|
199
|
+
|
|
200
|
+
[llm]
|
|
201
|
+
backend = "lmstudio"
|
|
202
|
+
api_base = "http://localhost:1234/v1"
|
|
203
|
+
model = "qwen2.5-7b-instruct"
|
|
204
|
+
|
|
205
|
+
[consolidation]
|
|
206
|
+
auto_run = true
|
|
207
|
+
interval_hours = 6
|
|
208
|
+
cluster_threshold = 0.72
|
|
209
|
+
|
|
210
|
+
[dedup]
|
|
211
|
+
enabled = true
|
|
212
|
+
similarity_threshold = 0.95
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Run `consolidation-memory init` to generate a config interactively.
|
|
216
|
+
|
|
217
|
+
## Data Directory
|
|
218
|
+
|
|
219
|
+
- **Linux**: `~/.local/share/consolidation_memory/`
|
|
220
|
+
- **macOS**: `~/Library/Application Support/consolidation_memory/`
|
|
221
|
+
- **Windows**: `%LOCALAPPDATA%\consolidation_memory\`
|
|
222
|
+
|
|
223
|
+
Override with `data_dir` under `[paths]` in config.
|
|
224
|
+
|
|
225
|
+
## Migrating from Existing Installation
|
|
226
|
+
|
|
227
|
+
If you have an existing data directory, point your config at it:
|
|
228
|
+
|
|
229
|
+
```toml
|
|
230
|
+
[paths]
|
|
231
|
+
data_dir = "C:\\Users\\you\\Documents\\consolidation_memory\\data"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
If switching embedding backends (different dimensions), run:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
consolidation-memory reindex
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Installation Extras
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
pip install consolidation-memory # Core (MCP + Python API)
|
|
244
|
+
pip install consolidation-memory[fastembed] # + FastEmbed (recommended)
|
|
245
|
+
pip install consolidation-memory[openai] # + OpenAI SDK
|
|
246
|
+
pip install consolidation-memory[rest] # + REST API (FastAPI + Uvicorn)
|
|
247
|
+
pip install consolidation-memory[all] # Everything
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Development
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
git clone https://github.com/charliee1w/consolidation-memory
|
|
254
|
+
cd consolidation-memory
|
|
255
|
+
pip install -e ".[fastembed,dev]"
|
|
256
|
+
python -m pytest tests/ -v # 88 tests
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## License
|
|
260
|
+
|
|
261
|
+
MIT
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "consolidation-memory"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Local-first persistent memory for AI agents — store, recall, and consolidate knowledge across sessions using FAISS, SQLite, and any LLM"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{name = "Charlie Wright"}]
|
|
13
|
+
keywords = ["mcp", "memory", "ai", "semantic-search", "faiss", "claude"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"mcp[cli]>=1.26.0",
|
|
27
|
+
"httpx>=0.28.0",
|
|
28
|
+
"faiss-cpu>=1.9.0",
|
|
29
|
+
"scipy>=1.14.0",
|
|
30
|
+
"numpy>=2.0.0",
|
|
31
|
+
"platformdirs>=4.0.0",
|
|
32
|
+
"tomli>=2.0.0; python_version < '3.11'",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
fastembed = ["fastembed>=0.4.0"]
|
|
37
|
+
openai = ["openai>=1.0.0"]
|
|
38
|
+
rest = ["fastapi>=0.115.0", "uvicorn[standard]>=0.34.0"]
|
|
39
|
+
all = ["consolidation-memory[fastembed,openai,rest]"]
|
|
40
|
+
dev = ["pytest>=8.0.0", "ruff>=0.7.0", "httpx>=0.28.0"]
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
consolidation-memory = "consolidation_memory.cli:main"
|
|
44
|
+
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://github.com/charliee1w/consolidation-memory"
|
|
47
|
+
Repository = "https://github.com/charliee1w/consolidation-memory"
|
|
48
|
+
Issues = "https://github.com/charliee1w/consolidation-memory/issues"
|
|
49
|
+
|
|
50
|
+
[tool.setuptools.packages.find]
|
|
51
|
+
where = ["src"]
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
target-version = "py310"
|
|
55
|
+
line-length = 100
|
|
56
|
+
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Consolidation Memory — persistent semantic memory for AI conversations."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.1.0"
|
|
4
|
+
|
|
5
|
+
# Lazy imports to avoid pulling in heavy deps (faiss, numpy) on bare import.
|
|
6
|
+
_LAZY_IMPORTS = {
|
|
7
|
+
"MemoryClient": "consolidation_memory.client",
|
|
8
|
+
"StoreResult": "consolidation_memory.types",
|
|
9
|
+
"RecallResult": "consolidation_memory.types",
|
|
10
|
+
"ForgetResult": "consolidation_memory.types",
|
|
11
|
+
"StatusResult": "consolidation_memory.types",
|
|
12
|
+
"ExportResult": "consolidation_memory.types",
|
|
13
|
+
"CorrectResult": "consolidation_memory.types",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
__all__ = ["__version__", *_LAZY_IMPORTS]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def __getattr__(name: str):
|
|
20
|
+
if name in _LAZY_IMPORTS:
|
|
21
|
+
import importlib
|
|
22
|
+
module = importlib.import_module(_LAZY_IMPORTS[name])
|
|
23
|
+
return getattr(module, name)
|
|
24
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|