wavemind 2.1.0__tar.gz → 2.1.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.
- {wavemind-2.1.0 → wavemind-2.1.1}/CONTRIBUTING.md +2 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/MANIFEST.in +6 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/PKG-INFO +238 -125
- {wavemind-2.1.0 → wavemind-2.1.1}/README.md +237 -124
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/ann_index_curve_benchmark.py +7 -4
- {wavemind-2.1.0 → wavemind-2.1.1}/docker-compose.yml +1 -1
- wavemind-2.1.1/docs/CHROMA_MIGRATION.md +412 -0
- wavemind-2.1.1/docs/DEMO_SCRIPT.md +116 -0
- wavemind-2.1.1/docs/LAUNCH_KIT.md +361 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/docs/PROJECT_BOARD.md +6 -1
- {wavemind-2.1.0 → wavemind-2.1.1}/docs/ROADMAP.md +4 -2
- wavemind-2.1.1/docs/RU_LAUNCH_POSTS.md +192 -0
- wavemind-2.1.1/docs/USE_CASES.md +274 -0
- wavemind-2.1.1/docs/assets/wavemind-social-card.svg +104 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/examples/demo.py +2 -2
- wavemind-2.1.1/examples/dynamic_memory_demo.py +134 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/pyproject.toml +1 -1
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_api.py +14 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_cli_smoke.py +29 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_core_persistence.py +26 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_examples.py +25 -3
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_indexes_encoders.py +17 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_packaging_files.py +7 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/__init__.py +1 -1
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/api.py +13 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/cli.py +73 -1
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/core.py +62 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/indexes.py +199 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/PKG-INFO +238 -125
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/SOURCES.txt +7 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/Dockerfile +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/LICENSE +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/SECURITY.md +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/SUPPORT.md +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/BENCHMARK_REPORT.md +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/agent_memory_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/agent_memory_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/ann_index_curve_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/benchmark_matrix_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/benchmark_registry.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/dynamic_memory_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/dynamic_memory_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/field_memory_dynamics_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/field_memory_dynamics_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/locomo_evidence_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/locomo_memory_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/locomo_sentence_evidence_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/long_memory_evidence_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/long_memory_evidence_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_answer_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_answer_extractive_20_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_evidence_50_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_evidence_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_memory_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/open_retrieval_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/open_retrieval_scifact_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/render_benchmark_charts.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/render_benchmark_report.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/ru_sentences_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/wavemind_capacity_results.json +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/docs/RELEASE.md +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/docs/assets/benchmark-summary.svg +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/examples/agent_with_memory.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/examples/framework_integrations.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/examples/langchain_memory.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/examples/sharded_memory.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/install.bat +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/install.sh +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/requirements-optional.txt +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/requirements.txt +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/setup.cfg +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_agent_memory_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_ann_index_curve_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_api_process_persistence.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_benchmark_charts.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_benchmark_registry.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_benchmark_report.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_dynamic_memory_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_field_graph.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_field_graph_integration.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_field_memory_dynamics_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_framework_adapters.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_import_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_langchain_integration.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_locomo_memory_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_long_memory_evidence_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_longmemeval_answer_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_longmemeval_memory_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_observability.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_open_retrieval_benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_postgres_storage.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_semantic_and_latency.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_sharding.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/__main__.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/benchmark.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/encoders.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/field_graph.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/importers.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/__init__.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/autogen.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/crewai.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/langchain.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/langgraph.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/llamaindex.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/observability.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/sharding.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/storage.py +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/dependency_links.txt +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/entry_points.txt +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/requires.txt +0 -0
- {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/top_level.txt +0 -0
|
@@ -92,6 +92,8 @@ Current scale roadmap:
|
|
|
92
92
|
|
|
93
93
|
See [`docs/ROADMAP.md`](docs/ROADMAP.md) for the full roadmap.
|
|
94
94
|
See [`docs/RELEASE.md`](docs/RELEASE.md) for release mechanics.
|
|
95
|
+
See [`docs/LAUNCH_KIT.md`](docs/LAUNCH_KIT.md) for public positioning,
|
|
96
|
+
benchmark-claim guardrails, and community launch drafts.
|
|
95
97
|
|
|
96
98
|
## Pull Request Style
|
|
97
99
|
|
|
@@ -12,7 +12,13 @@ include requirements-optional.txt
|
|
|
12
12
|
include docs/ROADMAP.md
|
|
13
13
|
include docs/RELEASE.md
|
|
14
14
|
include docs/PROJECT_BOARD.md
|
|
15
|
+
include docs/DEMO_SCRIPT.md
|
|
16
|
+
include docs/LAUNCH_KIT.md
|
|
17
|
+
include docs/CHROMA_MIGRATION.md
|
|
18
|
+
include docs/RU_LAUNCH_POSTS.md
|
|
19
|
+
include docs/USE_CASES.md
|
|
15
20
|
include docs/assets/benchmark-summary.svg
|
|
21
|
+
include docs/assets/wavemind-social-card.svg
|
|
16
22
|
include benchmarks/*.py
|
|
17
23
|
include benchmarks/*.json
|
|
18
24
|
include benchmarks/*.md
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wavemind
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: Local-first dynamic memory field with vector search and wave-field re-ranking
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/CaspianG/wavemind
|
|
@@ -52,25 +52,28 @@ Dynamic: license-file
|
|
|
52
52
|
|
|
53
53
|
# WaveMind
|
|
54
54
|
|
|
55
|
-
**
|
|
55
|
+
**Local-first dynamic memory for apps, agents, notebooks, and tools.**
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
It stores text, vectors, metadata, and recall state in SQLite. A wave-field
|
|
62
|
-
priority layer then reinforces useful memories, lets stale facts fade, respects
|
|
63
|
-
namespaces, and keeps the final recall set small enough for real applications.
|
|
57
|
+
WaveMind stores memories in SQLite, finds relevant candidates with vector
|
|
58
|
+
search, then uses a wave-field priority layer to decide what still matters:
|
|
59
|
+
hot facts rise, stale facts fade, temporary facts expire, and namespaces keep
|
|
60
|
+
users or projects isolated.
|
|
64
61
|
|
|
65
62
|

|
|
66
63
|
[](https://pypi.org/project/wavemind/)
|
|
67
64
|
[](https://github.com/CaspianG/wavemind/actions/workflows/tests.yml)
|
|
68
65
|

|
|
69
66
|
|
|
70
|
-
|
|
67
|
+
<img src="https://raw.githubusercontent.com/CaspianG/wavemind/main/docs/assets/wavemind-social-card.svg" alt="WaveMind dynamic memory overview" width="820">
|
|
68
|
+
|
|
71
69
|
[Quick Start](#quick-start) |
|
|
70
|
+
[CLI](#cli-cheat-sheet) |
|
|
71
|
+
[Python Example](#python-example) |
|
|
72
|
+
[HTTP Example](#http-example) |
|
|
73
|
+
[Where Data Lives](#where-data-lives) |
|
|
72
74
|
[LangChain](#langchain-memory) |
|
|
73
|
-
[
|
|
75
|
+
[Chroma Migration](docs/CHROMA_MIGRATION.md) |
|
|
76
|
+
[Use Cases](docs/USE_CASES.md) |
|
|
74
77
|
[HTTP API](#http-api) |
|
|
75
78
|
[Benchmarks](#benchmark) |
|
|
76
79
|
[Roadmap](#roadmap) |
|
|
@@ -79,38 +82,212 @@ namespaces, and keeps the final recall set small enough for real applications.
|
|
|
79
82
|
|
|
80
83
|
</div>
|
|
81
84
|
|
|
82
|
-
##
|
|
85
|
+
## What Is WaveMind?
|
|
86
|
+
|
|
87
|
+
WaveMind is a dynamic memory engine you can embed in a product.
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
small-to-medium knowledge stream where "latest", "repeated", "expired", and
|
|
88
|
-
"scoped to this user/project" matter.
|
|
89
|
+
Use it when your app needs to remember things like user preferences, decisions,
|
|
90
|
+
corrections, notes, research snippets, support history, agent context, or
|
|
91
|
+
temporary facts.
|
|
89
92
|
|
|
90
|
-
The
|
|
93
|
+
The short version:
|
|
91
94
|
|
|
92
95
|
```text
|
|
93
|
-
|
|
94
|
-
WaveMind:
|
|
96
|
+
normal vector search: find the nearest text
|
|
97
|
+
WaveMind: find the nearest useful memory
|
|
95
98
|
```
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
and optional
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
WaveMind is not trying to replace every vector database. It is the memory layer
|
|
101
|
+
around retrieval: persistence, namespaces, TTL, hotness, priority, decay,
|
|
102
|
+
explicit forgetting, audit events, and optional graph dynamics.
|
|
103
|
+
|
|
104
|
+
## 60-Second Version
|
|
105
|
+
|
|
106
|
+
| Question | Answer |
|
|
107
|
+
|---|---|
|
|
108
|
+
| What does it store? | Text memories, vectors, metadata, tags, TTL, priority, and recall state. |
|
|
109
|
+
| Where does it store data? | A local SQLite file by default; Postgres is available for production state. |
|
|
110
|
+
| How do I use it? | CLI, Python API, FastAPI HTTP server, LangChain memory, or framework adapters. |
|
|
111
|
+
| What is different from Chroma/Qdrant? | WaveMind adds memory policy: hotness, decay, TTL, correction handling, and scoped recall. |
|
|
112
|
+
| When should I not use it? | For huge static document search where a mature vector DB is already the right tool. |
|
|
113
|
+
| What is the simplest install? | `python -m pip install wavemind` |
|
|
102
114
|
|
|
103
|
-
##
|
|
115
|
+
## Why Use It?
|
|
104
116
|
|
|
105
117
|
| If you need... | WaveMind gives you... |
|
|
106
118
|
|---|---|
|
|
107
|
-
| Memory that survives restarts | SQLite
|
|
108
|
-
|
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
119
|
+
| Memory that survives restarts | One SQLite file stores text, vectors, metadata, TTL, and recall state. |
|
|
120
|
+
| Per-user or per-project recall | Namespaces and tags keep memories separated. |
|
|
121
|
+
| Temporary facts | `ttl_seconds` lets facts expire automatically. |
|
|
122
|
+
| Corrections and changing preferences | Newer or reinforced memories can outrank stale ones. |
|
|
123
|
+
| A simple integration path | Python API, CLI, FastAPI server, and LangChain memory class. |
|
|
124
|
+
| Production hygiene | Backups, audit log, API keys, rate limits, Prometheus metrics, and OpenTelemetry traces. |
|
|
125
|
+
|
|
126
|
+
## Quick Start
|
|
127
|
+
|
|
128
|
+
The shortest path from install to first recall:
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
python -m pip install wavemind
|
|
132
|
+
wavemind remember "Andrey is a trader" --namespace demo
|
|
133
|
+
wavemind query "What does Andrey do?" --namespace demo
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Need a reminder after install?
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
wavemind quickstart
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
By default, WaveMind creates `wavemind.sqlite3` in the current working
|
|
143
|
+
directory. That file is the local source of truth. Keep it out of git and back
|
|
144
|
+
it up like application state.
|
|
145
|
+
|
|
146
|
+
## CLI Cheat Sheet
|
|
147
|
+
|
|
148
|
+
Start here if you only want to use WaveMind from the terminal:
|
|
149
|
+
|
|
150
|
+
| Goal | Command |
|
|
151
|
+
|---|---|
|
|
152
|
+
| Show first-run help | `wavemind quickstart` |
|
|
153
|
+
| Store a memory | `wavemind remember "Andrey prefers short answers" --namespace user:42` |
|
|
154
|
+
| Search memory | `wavemind query "answer style" --namespace user:42` |
|
|
155
|
+
| See stored state | `wavemind stats --namespace user:42` |
|
|
156
|
+
| Delete a namespace | `wavemind forget --namespace user:42` |
|
|
157
|
+
| Import notes | `wavemind import ./notes.txt --namespace project:alpha` |
|
|
158
|
+
| Use another database file | `wavemind --db ./state/memory.sqlite3 query "budget" --namespace user:42` |
|
|
159
|
+
| Start the HTTP API | `wavemind --db ./state/memory.sqlite3 serve --host 127.0.0.1 --port 8000` |
|
|
160
|
+
|
|
161
|
+
After this point, choose the integration path you need: Python, HTTP, LangChain,
|
|
162
|
+
framework adapters, benchmarks, or production deployment.
|
|
163
|
+
|
|
164
|
+
## Python Example
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from wavemind import WaveMind
|
|
168
|
+
|
|
169
|
+
memory = WaveMind(db_path="./state/wavemind.sqlite3")
|
|
170
|
+
|
|
171
|
+
memory.remember(
|
|
172
|
+
"The user prefers short practical answers.",
|
|
173
|
+
namespace="user:42",
|
|
174
|
+
tags=["preference"],
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
hits = memory.query("How should I answer this user?", namespace="user:42", top_k=3)
|
|
178
|
+
for hit in hits:
|
|
179
|
+
print(hit.score, hit.text)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The integration pattern is intentionally small:
|
|
183
|
+
|
|
184
|
+
1. Call `query()` before your app, agent, tool, or UI needs context.
|
|
185
|
+
2. Pass the returned memories into your prompt, screen, search result, or
|
|
186
|
+
decision function.
|
|
187
|
+
3. Call `remember()` after something worth keeping happens.
|
|
188
|
+
|
|
189
|
+
## HTTP Example
|
|
190
|
+
|
|
191
|
+
The FastAPI server is included in the base install:
|
|
192
|
+
|
|
193
|
+
```sh
|
|
194
|
+
wavemind --db ./state/wavemind.sqlite3 serve --host 127.0.0.1 --port 8000
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Then use WaveMind from any language:
|
|
198
|
+
|
|
199
|
+
```sh
|
|
200
|
+
curl -X POST http://127.0.0.1:8000/remember \
|
|
201
|
+
-H "Content-Type: application/json" \
|
|
202
|
+
-d "{\"text\":\"Andrey prefers short answers\",\"namespace\":\"user:42\",\"tags\":[\"preference\"]}"
|
|
203
|
+
|
|
204
|
+
curl -X POST http://127.0.0.1:8000/query \
|
|
205
|
+
-H "Content-Type: application/json" \
|
|
206
|
+
-d "{\"query\":\"How should I answer?\",\"namespace\":\"user:42\",\"top_k\":3}"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Where Data Lives
|
|
210
|
+
|
|
211
|
+
WaveMind is local-first. The SQLite database stores memories, vectors, metadata,
|
|
212
|
+
namespaces, tags, TTL, hotness, priority, and audit events.
|
|
213
|
+
|
|
214
|
+
| runtime | Suggested database path |
|
|
215
|
+
|---|---|
|
|
216
|
+
| quick CLI experiment | `./wavemind.sqlite3` |
|
|
217
|
+
| Python app or agent | `./state/wavemind.sqlite3` |
|
|
218
|
+
| desktop app | user data directory, for example `%APPDATA%` or `~/.local/share` |
|
|
219
|
+
| server daemon | `/var/lib/wavemind/wavemind.sqlite3` |
|
|
220
|
+
| Docker | mounted volume, for example `/data/wavemind.sqlite3` |
|
|
221
|
+
|
|
222
|
+
Explicit path:
|
|
223
|
+
|
|
224
|
+
```sh
|
|
225
|
+
wavemind --db ./state/app_memory.sqlite3 remember "Andrey prefers short answers" --namespace user:42
|
|
226
|
+
wavemind --db ./state/app_memory.sqlite3 query "answer style" --namespace user:42
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Common Ways To Use It
|
|
230
|
+
|
|
231
|
+
| You are building... | Start with... |
|
|
232
|
+
|---|---|
|
|
233
|
+
| Python app | `from wavemind import WaveMind` |
|
|
234
|
+
| LangChain agent | `WaveMindMemory` from `wavemind.integrations.langchain` |
|
|
235
|
+
| LangGraph workflow | `make_recall_node()` and `make_persist_node()` |
|
|
236
|
+
| LlamaIndex pipeline | `WaveMindRetriever` |
|
|
237
|
+
| CrewAI or AutoGen loop | The adapters in `wavemind.integrations` |
|
|
238
|
+
| Node, Go, Ruby, PHP, or no-code app | `wavemind serve` and the HTTP API |
|
|
239
|
+
| Personal knowledge base | Store notes by project namespace and query locally |
|
|
240
|
+
| Support or CRM workflow | Store customer issues, resolutions, preferences, and corrections |
|
|
241
|
+
| Research or trading notebook | Store observations with source metadata and TTL for temporary hypotheses |
|
|
242
|
+
|
|
243
|
+
For migrations from existing local vector memory, start with
|
|
244
|
+
[`docs/CHROMA_MIGRATION.md`](docs/CHROMA_MIGRATION.md).
|
|
245
|
+
|
|
246
|
+
## Minimal Agent Loop
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
from wavemind import WaveMind
|
|
250
|
+
|
|
251
|
+
memory = WaveMind(db_path="./state/agent.sqlite3")
|
|
252
|
+
|
|
253
|
+
def run_turn(user_id: str, user_text: str) -> str:
|
|
254
|
+
namespace = f"user:{user_id}"
|
|
255
|
+
hits = memory.query(user_text, namespace=namespace, top_k=5, min_score=0.25)
|
|
256
|
+
recalled = "\n".join(f"- {hit.text}" for hit in hits)
|
|
257
|
+
|
|
258
|
+
answer = call_your_llm(f"Relevant memory:\n{recalled}\n\nUser: {user_text}")
|
|
259
|
+
|
|
260
|
+
memory.remember(f"User said: {user_text}", namespace=namespace, tags=["conversation"])
|
|
261
|
+
memory.remember(f"Assistant answered: {answer}", namespace=namespace, tags=["conversation"])
|
|
262
|
+
return answer
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Terminal Demo
|
|
266
|
+
|
|
267
|
+
From a cloned repository:
|
|
268
|
+
|
|
269
|
+
```text
|
|
270
|
+
$ python examples/demo.py
|
|
271
|
+
[ok] Remembered: "Andrey is a trader who tracks market breakouts."
|
|
272
|
+
[ok] Remembered: "Andrey prefers short practical answers about product decisions."
|
|
273
|
+
|
|
274
|
+
Query: "Andrey trader preferences"
|
|
275
|
+
-> Result 1 (0.60): "Andrey is a trader who tracks market breakouts."
|
|
276
|
+
-> Result 2 (0.30): "Andrey prefers short practical answers about product decisions."
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The demo is offline, keyless, and uses the built-in hash encoder.
|
|
280
|
+
|
|
281
|
+
To see the behavior that plain vector search does not provide:
|
|
282
|
+
|
|
283
|
+
```sh
|
|
284
|
+
python examples/dynamic_memory_demo.py
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
That demo shows corrected facts outranking stale facts, temporary memory
|
|
288
|
+
expiring, namespace isolation, and index-health reporting.
|
|
289
|
+
|
|
290
|
+
## How The Memory Field Works
|
|
114
291
|
|
|
115
292
|
```mermaid
|
|
116
293
|
flowchart LR
|
|
@@ -125,10 +302,9 @@ flowchart LR
|
|
|
125
302
|
F --> D
|
|
126
303
|
```
|
|
127
304
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
marketing name for embeddings.
|
|
305
|
+
The wave field is the dynamic layer around stored memories. It is not a
|
|
306
|
+
replacement for embeddings; it is the policy that decides which candidate
|
|
307
|
+
memories should still matter.
|
|
132
308
|
|
|
133
309
|
| signal | Plain meaning | Effect |
|
|
134
310
|
|---|---|---|
|
|
@@ -145,39 +321,6 @@ memories, not a continuous mathematical physics field. That honesty matters:
|
|
|
145
321
|
WaveMind is useful today as a dynamic memory engine, while the research path is
|
|
146
322
|
to make the field dynamics more explicit, measurable, and scalable.
|
|
147
323
|
|
|
148
|
-
## Terminal Demo
|
|
149
|
-
|
|
150
|
-
From a cloned repository:
|
|
151
|
-
|
|
152
|
-
```text
|
|
153
|
-
$ python examples/demo.py
|
|
154
|
-
[ok] Remembered: "Andrey is a trader who tracks market breakouts."
|
|
155
|
-
[ok] Remembered: "Andrey prefers short practical answers about product decisions."
|
|
156
|
-
|
|
157
|
-
Query: "Andrey trader preferences"
|
|
158
|
-
-> Result 1 (0.60): "Andrey is a trader who tracks market breakouts."
|
|
159
|
-
-> Result 2 (0.30): "Andrey prefers short practical answers about product decisions."
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
The demo is offline, keyless, and uses the built-in hash encoder.
|
|
163
|
-
|
|
164
|
-
## Quick Start
|
|
165
|
-
|
|
166
|
-
Install from PyPI and create your first local memory:
|
|
167
|
-
|
|
168
|
-
```sh
|
|
169
|
-
python -m pip install wavemind
|
|
170
|
-
wavemind remember "Andrey is a trader" --namespace demo
|
|
171
|
-
wavemind query "trader" --namespace demo
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
What happens here:
|
|
175
|
-
|
|
176
|
-
- `remember` writes the text and its vector pattern into a local SQLite database.
|
|
177
|
-
- By default, the database file is `wavemind.sqlite3` in your current working directory.
|
|
178
|
-
- `--namespace demo` keeps this memory separate from other users, agents, or projects.
|
|
179
|
-
- `query` reads from the same SQLite file and returns the closest remembered texts.
|
|
180
|
-
|
|
181
324
|
## Optional Embeddings
|
|
182
325
|
|
|
183
326
|
For sentence-transformer embeddings:
|
|
@@ -215,6 +358,16 @@ wavemind --index faiss-persisted query "trader" --namespace demo
|
|
|
215
358
|
SQLite or Postgres remains the source of truth. The persisted FAISS files are a
|
|
216
359
|
candidate-index snapshot and are validated against the current memory ids on
|
|
217
360
|
load. If the snapshot does not match the stored memories, WaveMind rebuilds it.
|
|
361
|
+
You can also check and rebuild the candidate index explicitly:
|
|
362
|
+
|
|
363
|
+
```sh
|
|
364
|
+
wavemind --index faiss-persisted index-health --json
|
|
365
|
+
wavemind --index faiss-persisted rebuild-index
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Index health compares durable memory ids against the candidate index. Local
|
|
369
|
+
indexes report exact missing/extra ids; service backends report exact ids when
|
|
370
|
+
the backend exposes an id scan and otherwise fall back to count-based health.
|
|
218
371
|
|
|
219
372
|
pgvector setup:
|
|
220
373
|
|
|
@@ -250,38 +403,6 @@ production latency and durability should be measured against a real Qdrant
|
|
|
250
403
|
service. If `WAVEMIND_QDRANT_URL` is missing, WaveMind raises a clear error
|
|
251
404
|
instead of silently falling back to another backend.
|
|
252
405
|
|
|
253
|
-
## Data Location
|
|
254
|
-
|
|
255
|
-
For an explicit database path, put global options before the command:
|
|
256
|
-
|
|
257
|
-
```sh
|
|
258
|
-
wavemind --db ./app_memory.sqlite3 remember "Andrey is a trader" --namespace demo
|
|
259
|
-
wavemind --db ./app_memory.sqlite3 query "trader" --namespace demo
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
WaveMind is local-first. One SQLite file is the source of truth for texts,
|
|
263
|
-
metadata, vectors, namespaces, tags, TTL, and recall state. For real agents,
|
|
264
|
-
prefer an explicit path under your application's state directory:
|
|
265
|
-
|
|
266
|
-
```python
|
|
267
|
-
from wavemind import WaveMind
|
|
268
|
-
|
|
269
|
-
memory = WaveMind(db_path="./state/wavemind.sqlite3")
|
|
270
|
-
memory.remember("The user prefers short answers.", namespace="user:42", tags=["preference"])
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
Useful storage patterns:
|
|
274
|
-
|
|
275
|
-
| runtime | Suggested database path |
|
|
276
|
-
|---|---|
|
|
277
|
-
| local CLI experiment | `./wavemind.sqlite3` |
|
|
278
|
-
| Python app or agent | `./state/wavemind.sqlite3` |
|
|
279
|
-
| OpenClaw sidecar | `~/.openclaw/wavemind/<agent-id>.sqlite3` |
|
|
280
|
-
| server daemon | `/var/lib/wavemind/wavemind.sqlite3` |
|
|
281
|
-
| Docker | mounted volume, for example `/data/wavemind.sqlite3` |
|
|
282
|
-
|
|
283
|
-
Keep the SQLite file out of git. Back it up like any other application state.
|
|
284
|
-
|
|
285
406
|
## Storage Backends
|
|
286
407
|
|
|
287
408
|
SQLite is the default source of truth. For multi-tenant production deployments,
|
|
@@ -355,6 +476,8 @@ curl http://127.0.0.1:8000/stats?namespace=demo
|
|
|
355
476
|
curl http://127.0.0.1:8000/audit?namespace=demo
|
|
356
477
|
curl http://127.0.0.1:8000/metrics
|
|
357
478
|
curl http://127.0.0.1:8000/observability
|
|
479
|
+
curl http://127.0.0.1:8000/index/health
|
|
480
|
+
curl -X POST http://127.0.0.1:8000/index/rebuild
|
|
358
481
|
curl -X POST http://127.0.0.1:8000/backup -H "Content-Type: application/json" -d '{"path":"./backups","keep_last":7}'
|
|
359
482
|
```
|
|
360
483
|
|
|
@@ -362,6 +485,9 @@ curl -X POST http://127.0.0.1:8000/backup -H "Content-Type: application/json" -d
|
|
|
362
485
|
`purge_expired`. Query audit is opt-in with `WAVEMIND_AUDIT_QUERIES=1` because
|
|
363
486
|
writing an audit row for every query changes latency. `/metrics` returns a
|
|
364
487
|
Prometheus-compatible text payload without adding a required dependency.
|
|
488
|
+
`/index/health` reports source-of-truth versus candidate-index consistency.
|
|
489
|
+
`/index/rebuild` rebuilds the candidate index from stored active memories and
|
|
490
|
+
logs an `index_rebuild` audit event.
|
|
365
491
|
|
|
366
492
|
OpenTelemetry traces are optional and off by default:
|
|
367
493
|
|
|
@@ -392,9 +518,9 @@ Role behavior:
|
|
|
392
518
|
|
|
393
519
|
| role | Env var | Allows |
|
|
394
520
|
|---|---|---|
|
|
395
|
-
| read | `WAVEMIND_READ_KEYS` | `/query`, `/stats`, `/metrics` |
|
|
521
|
+
| read | `WAVEMIND_READ_KEYS` | `/query`, `/stats`, `/metrics`, `/index/health` |
|
|
396
522
|
| write | `WAVEMIND_WRITE_KEYS` | read actions plus `/remember` and `/import` |
|
|
397
|
-
| admin | `WAVEMIND_ADMIN_KEYS` or `WAVEMIND_API_KEYS` | all actions, including `/audit`, `/backup`, and `/forget` |
|
|
523
|
+
| admin | `WAVEMIND_ADMIN_KEYS` or `WAVEMIND_API_KEYS` | all actions, including `/audit`, `/backup`, `/index/rebuild`, and `/forget` |
|
|
398
524
|
|
|
399
525
|
Keys are accepted through `Authorization: Bearer <key>` or `X-API-Key: <key>`.
|
|
400
526
|
If no key env vars are set, authentication is disabled for local development.
|
|
@@ -442,7 +568,7 @@ Offline runnable example from a cloned repository:
|
|
|
442
568
|
python examples/langchain_memory.py
|
|
443
569
|
```
|
|
444
570
|
|
|
445
|
-
##
|
|
571
|
+
## Framework Integrations
|
|
446
572
|
|
|
447
573
|
WaveMind only needs two touch points in an agent, service, notebook, or app:
|
|
448
574
|
|
|
@@ -471,6 +597,9 @@ That makes it usable in more than LangChain:
|
|
|
471
597
|
| Preference/profile memory | Store with tags such as `profile`, `preference`, `project`, `decision`. |
|
|
472
598
|
| Corrections/privacy | Use `forget()` or namespace deletion workflows. |
|
|
473
599
|
|
|
600
|
+
More examples: [`docs/USE_CASES.md`](docs/USE_CASES.md).
|
|
601
|
+
Migrating from a Chroma memory store: [`docs/CHROMA_MIGRATION.md`](docs/CHROMA_MIGRATION.md).
|
|
602
|
+
|
|
474
603
|
Framework examples in this repository:
|
|
475
604
|
|
|
476
605
|
| Framework / pattern | Example |
|
|
@@ -483,26 +612,6 @@ Framework examples in this repository:
|
|
|
483
612
|
| AutoGen-style hooks | `wavemind.integrations.autogen`, `examples/framework_integrations.py` |
|
|
484
613
|
| Namespace sharding | `examples/sharded_memory.py` |
|
|
485
614
|
|
|
486
|
-
Minimal custom agent loop:
|
|
487
|
-
|
|
488
|
-
```python
|
|
489
|
-
from wavemind import WaveMind
|
|
490
|
-
|
|
491
|
-
memory = WaveMind(db_path="./state/wavemind.sqlite3")
|
|
492
|
-
|
|
493
|
-
def run_turn(user_id: str, user_text: str, history: list[str]) -> str:
|
|
494
|
-
namespace = f"user:{user_id}"
|
|
495
|
-
hits = memory.query(user_text, namespace=namespace, top_k=5, min_score=0.25)
|
|
496
|
-
recalled = "\n".join(f"- {hit.text}" for hit in hits)
|
|
497
|
-
|
|
498
|
-
prompt = f"Relevant memory:\n{recalled}\n\nUser: {user_text}"
|
|
499
|
-
answer = call_your_llm(prompt, history)
|
|
500
|
-
|
|
501
|
-
memory.remember(f"User said: {user_text}", namespace=namespace, tags=["conversation"])
|
|
502
|
-
memory.remember(f"Assistant answered: {answer}", namespace=namespace, tags=["conversation"])
|
|
503
|
-
return answer
|
|
504
|
-
```
|
|
505
|
-
|
|
506
615
|
## OpenClaw Integration
|
|
507
616
|
|
|
508
617
|
[OpenClaw memory](https://docs.openclaw.ai/concepts/memory) is file-centered:
|
|
@@ -1071,6 +1180,9 @@ python benchmarks/dynamic_memory_benchmark.py --engines wavemind chroma --memori
|
|
|
1071
1180
|
|
|
1072
1181
|
WaveMind is not trying to replace dedicated vector databases at scale. The intended product gap is dynamic priority: frequently used memories can become hotter while old or low-priority memories fade. For static RAG over large document collections, use a mature vector database. For memory that needs persistence, scoped recall, TTL, forgetting, and reinforcement, WaveMind is designed to sit above or beside the vector index.
|
|
1073
1182
|
|
|
1183
|
+
If you already use Chroma for local memory, see the practical migration guide:
|
|
1184
|
+
[`docs/CHROMA_MIGRATION.md`](docs/CHROMA_MIGRATION.md).
|
|
1185
|
+
|
|
1074
1186
|
## Known Limitations
|
|
1075
1187
|
|
|
1076
1188
|
- Optimal capacity on the current NumPy exact index is up to 1000 records.
|
|
@@ -1107,6 +1219,7 @@ WaveMind is not trying to replace dedicated vector databases at scale. The inten
|
|
|
1107
1219
|
## Roadmap
|
|
1108
1220
|
|
|
1109
1221
|
Full roadmap: [`docs/ROADMAP.md`](docs/ROADMAP.md).
|
|
1222
|
+
Launch and positioning kit: [`docs/LAUNCH_KIT.md`](docs/LAUNCH_KIT.md).
|
|
1110
1223
|
|
|
1111
1224
|
Near-term priorities:
|
|
1112
1225
|
|