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.
Files changed (111) hide show
  1. {wavemind-2.1.0 → wavemind-2.1.1}/CONTRIBUTING.md +2 -0
  2. {wavemind-2.1.0 → wavemind-2.1.1}/MANIFEST.in +6 -0
  3. {wavemind-2.1.0 → wavemind-2.1.1}/PKG-INFO +238 -125
  4. {wavemind-2.1.0 → wavemind-2.1.1}/README.md +237 -124
  5. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/ann_index_curve_benchmark.py +7 -4
  6. {wavemind-2.1.0 → wavemind-2.1.1}/docker-compose.yml +1 -1
  7. wavemind-2.1.1/docs/CHROMA_MIGRATION.md +412 -0
  8. wavemind-2.1.1/docs/DEMO_SCRIPT.md +116 -0
  9. wavemind-2.1.1/docs/LAUNCH_KIT.md +361 -0
  10. {wavemind-2.1.0 → wavemind-2.1.1}/docs/PROJECT_BOARD.md +6 -1
  11. {wavemind-2.1.0 → wavemind-2.1.1}/docs/ROADMAP.md +4 -2
  12. wavemind-2.1.1/docs/RU_LAUNCH_POSTS.md +192 -0
  13. wavemind-2.1.1/docs/USE_CASES.md +274 -0
  14. wavemind-2.1.1/docs/assets/wavemind-social-card.svg +104 -0
  15. {wavemind-2.1.0 → wavemind-2.1.1}/examples/demo.py +2 -2
  16. wavemind-2.1.1/examples/dynamic_memory_demo.py +134 -0
  17. {wavemind-2.1.0 → wavemind-2.1.1}/pyproject.toml +1 -1
  18. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_api.py +14 -0
  19. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_cli_smoke.py +29 -0
  20. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_core_persistence.py +26 -0
  21. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_examples.py +25 -3
  22. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_indexes_encoders.py +17 -0
  23. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_packaging_files.py +7 -0
  24. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/__init__.py +1 -1
  25. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/api.py +13 -0
  26. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/cli.py +73 -1
  27. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/core.py +62 -0
  28. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/indexes.py +199 -0
  29. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/PKG-INFO +238 -125
  30. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/SOURCES.txt +7 -0
  31. {wavemind-2.1.0 → wavemind-2.1.1}/Dockerfile +0 -0
  32. {wavemind-2.1.0 → wavemind-2.1.1}/LICENSE +0 -0
  33. {wavemind-2.1.0 → wavemind-2.1.1}/SECURITY.md +0 -0
  34. {wavemind-2.1.0 → wavemind-2.1.1}/SUPPORT.md +0 -0
  35. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/BENCHMARK_REPORT.md +0 -0
  36. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/agent_memory_benchmark.py +0 -0
  37. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/agent_memory_results.json +0 -0
  38. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/ann_index_curve_results.json +0 -0
  39. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/benchmark_matrix_results.json +0 -0
  40. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/benchmark_registry.py +0 -0
  41. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/dynamic_memory_benchmark.py +0 -0
  42. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/dynamic_memory_results.json +0 -0
  43. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/field_memory_dynamics_benchmark.py +0 -0
  44. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/field_memory_dynamics_results.json +0 -0
  45. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/locomo_evidence_results.json +0 -0
  46. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/locomo_memory_benchmark.py +0 -0
  47. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/locomo_sentence_evidence_results.json +0 -0
  48. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/long_memory_evidence_benchmark.py +0 -0
  49. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/long_memory_evidence_results.json +0 -0
  50. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_answer_benchmark.py +0 -0
  51. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_answer_extractive_20_results.json +0 -0
  52. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_evidence_50_results.json +0 -0
  53. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_evidence_results.json +0 -0
  54. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/longmemeval_memory_benchmark.py +0 -0
  55. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/open_retrieval_benchmark.py +0 -0
  56. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/open_retrieval_scifact_results.json +0 -0
  57. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/render_benchmark_charts.py +0 -0
  58. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/render_benchmark_report.py +0 -0
  59. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/ru_sentences_benchmark.py +0 -0
  60. {wavemind-2.1.0 → wavemind-2.1.1}/benchmarks/wavemind_capacity_results.json +0 -0
  61. {wavemind-2.1.0 → wavemind-2.1.1}/docs/RELEASE.md +0 -0
  62. {wavemind-2.1.0 → wavemind-2.1.1}/docs/assets/benchmark-summary.svg +0 -0
  63. {wavemind-2.1.0 → wavemind-2.1.1}/examples/agent_with_memory.py +0 -0
  64. {wavemind-2.1.0 → wavemind-2.1.1}/examples/framework_integrations.py +0 -0
  65. {wavemind-2.1.0 → wavemind-2.1.1}/examples/langchain_memory.py +0 -0
  66. {wavemind-2.1.0 → wavemind-2.1.1}/examples/sharded_memory.py +0 -0
  67. {wavemind-2.1.0 → wavemind-2.1.1}/install.bat +0 -0
  68. {wavemind-2.1.0 → wavemind-2.1.1}/install.sh +0 -0
  69. {wavemind-2.1.0 → wavemind-2.1.1}/requirements-optional.txt +0 -0
  70. {wavemind-2.1.0 → wavemind-2.1.1}/requirements.txt +0 -0
  71. {wavemind-2.1.0 → wavemind-2.1.1}/setup.cfg +0 -0
  72. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_agent_memory_benchmark.py +0 -0
  73. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_ann_index_curve_benchmark.py +0 -0
  74. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_api_process_persistence.py +0 -0
  75. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_benchmark_charts.py +0 -0
  76. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_benchmark_registry.py +0 -0
  77. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_benchmark_report.py +0 -0
  78. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_dynamic_memory_benchmark.py +0 -0
  79. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_field_graph.py +0 -0
  80. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_field_graph_integration.py +0 -0
  81. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_field_memory_dynamics_benchmark.py +0 -0
  82. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_framework_adapters.py +0 -0
  83. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_import_benchmark.py +0 -0
  84. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_langchain_integration.py +0 -0
  85. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_locomo_memory_benchmark.py +0 -0
  86. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_long_memory_evidence_benchmark.py +0 -0
  87. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_longmemeval_answer_benchmark.py +0 -0
  88. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_longmemeval_memory_benchmark.py +0 -0
  89. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_observability.py +0 -0
  90. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_open_retrieval_benchmark.py +0 -0
  91. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_postgres_storage.py +0 -0
  92. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_semantic_and_latency.py +0 -0
  93. {wavemind-2.1.0 → wavemind-2.1.1}/tests/test_sharding.py +0 -0
  94. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/__main__.py +0 -0
  95. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/benchmark.py +0 -0
  96. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/encoders.py +0 -0
  97. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/field_graph.py +0 -0
  98. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/importers.py +0 -0
  99. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/__init__.py +0 -0
  100. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/autogen.py +0 -0
  101. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/crewai.py +0 -0
  102. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/langchain.py +0 -0
  103. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/langgraph.py +0 -0
  104. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/integrations/llamaindex.py +0 -0
  105. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/observability.py +0 -0
  106. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/sharding.py +0 -0
  107. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind/storage.py +0 -0
  108. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/dependency_links.txt +0 -0
  109. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/entry_points.txt +0 -0
  110. {wavemind-2.1.0 → wavemind-2.1.1}/wavemind.egg-info/requires.txt +0 -0
  111. {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.0
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
- **A local-first dynamic memory field for software that needs to remember.**
55
+ **Local-first dynamic memory for apps, agents, notebooks, and tools.**
56
56
 
57
- Most storage systems answer one question: "what record is closest to this
58
- query?" WaveMind adds a second question: "what information still matters right
59
- now?"
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
  ![Python](https://img.shields.io/badge/python-3.10%2B-blue)
66
63
  [![PyPI](https://img.shields.io/pypi/v/wavemind.svg)](https://pypi.org/project/wavemind/)
67
64
  [![Tests](https://github.com/CaspianG/wavemind/actions/workflows/tests.yml/badge.svg)](https://github.com/CaspianG/wavemind/actions/workflows/tests.yml)
68
65
  ![License](https://img.shields.io/badge/license-MIT-green)
69
66
 
70
- [Concept](#concept) |
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
- [OpenClaw](#openclaw-integration) |
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
- ## Concept
85
+ ## What Is WaveMind?
86
+
87
+ WaveMind is a dynamic memory engine you can embed in a product.
83
88
 
84
- WaveMind is not a replacement for every database. It is a memory layer for
85
- information that changes in importance over time: preferences, decisions,
86
- corrections, notes, research snippets, support history, agent context, or any
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 simple version:
93
+ The short version:
91
94
 
92
95
  ```text
93
- ordinary vector search: find the nearest text
94
- WaveMind: find the nearest useful memory
96
+ normal vector search: find the nearest text
97
+ WaveMind: find the nearest useful memory
95
98
  ```
96
99
 
97
- Under the hood, WaveMind still starts with normal vector search. The difference
98
- is the memory state around it: hotness, priority, decay, TTL, tags, namespaces,
99
- and optional memory-to-memory graph dynamics. That state is why the same stored
100
- fact can become stronger after repeated use, weaker after time passes, or
101
- disappear from recall after expiry.
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
- ## At a Glance
115
+ ## Why Use It?
104
116
 
105
117
  | If you need... | WaveMind gives you... |
106
118
  |---|---|
107
- | Memory that survives restarts | SQLite-backed `remember()`, `query()`, and `forget()`. |
108
- | Scoped recall per user, app, agent, or project | Namespaces and tags on every record. |
109
- | Information that changes importance over time | Hotness, priority, TTL, and decay-aware ranking. |
110
- | A local data source you can inspect and back up | One SQLite file is the source of truth. |
111
- | Easy integration | Python API, CLI, FastAPI server, and LangChain memory class. |
112
- | Honest benchmarks | Public LoCoMo, LongMemEval, BEIR/SciFact, and local policy checks. |
113
- | Production hooks | API keys, rate limits, audit log, Prometheus metrics, OpenTelemetry traces, backups, and optional external indexes. |
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
- ## What The Wave Field Does
129
-
130
- The "field" is the dynamic layer around stored memories. It is not just a
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
- ## Integration Patterns
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