pycontextdb 0.1.0__py3-none-any.whl

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 (47) hide show
  1. contextdb/__init__.py +72 -0
  2. contextdb/agents/__init__.py +8 -0
  3. contextdb/agents/memory_bus.py +80 -0
  4. contextdb/agents/rl_manager.py +89 -0
  5. contextdb/cli.py +107 -0
  6. contextdb/client.py +516 -0
  7. contextdb/core/__init__.py +41 -0
  8. contextdb/core/config.py +89 -0
  9. contextdb/core/exceptions.py +29 -0
  10. contextdb/core/models.py +151 -0
  11. contextdb/dynamics/__init__.py +25 -0
  12. contextdb/dynamics/evolution.py +168 -0
  13. contextdb/dynamics/formation.py +193 -0
  14. contextdb/dynamics/retrieval.py +130 -0
  15. contextdb/graphs/__init__.py +17 -0
  16. contextdb/graphs/base.py +46 -0
  17. contextdb/graphs/causal.py +224 -0
  18. contextdb/graphs/entity.py +251 -0
  19. contextdb/graphs/semantic.py +156 -0
  20. contextdb/graphs/temporal.py +173 -0
  21. contextdb/integrations/__init__.py +10 -0
  22. contextdb/integrations/autogen.py +39 -0
  23. contextdb/integrations/crewai.py +41 -0
  24. contextdb/integrations/langchain.py +132 -0
  25. contextdb/integrations/openai_tools.py +124 -0
  26. contextdb/memory/__init__.py +9 -0
  27. contextdb/memory/experiential.py +102 -0
  28. contextdb/memory/factual.py +58 -0
  29. contextdb/memory/working.py +90 -0
  30. contextdb/privacy/__init__.py +9 -0
  31. contextdb/privacy/audit.py +199 -0
  32. contextdb/privacy/pii_detector.py +173 -0
  33. contextdb/privacy/retention.py +99 -0
  34. contextdb/py.typed +0 -0
  35. contextdb/store/__init__.py +15 -0
  36. contextdb/store/base.py +67 -0
  37. contextdb/store/sqlite_store.py +517 -0
  38. contextdb/store/vector_index.py +241 -0
  39. contextdb/utils/__init__.py +22 -0
  40. contextdb/utils/embeddings.py +159 -0
  41. contextdb/utils/llm.py +139 -0
  42. contextdb/utils/migrations.py +159 -0
  43. pycontextdb-0.1.0.dist-info/METADATA +589 -0
  44. pycontextdb-0.1.0.dist-info/RECORD +47 -0
  45. pycontextdb-0.1.0.dist-info/WHEEL +4 -0
  46. pycontextdb-0.1.0.dist-info/entry_points.txt +2 -0
  47. pycontextdb-0.1.0.dist-info/licenses/LICENSE +190 -0
@@ -0,0 +1,589 @@
1
+ Metadata-Version: 2.4
2
+ Name: pycontextdb
3
+ Version: 0.1.0
4
+ Summary: The unified context layer for AI agents — replacing the patchwork with a memory operating system
5
+ Project-URL: Homepage, https://github.com/atomsai/contextdb
6
+ Project-URL: Documentation, https://contextdb.dev
7
+ Project-URL: Repository, https://github.com/atomsai/contextdb
8
+ Project-URL: Issues, https://github.com/atomsai/contextdb/issues
9
+ Author-email: Gaurav Sharma <gaurav@saaslabs.co>
10
+ License-Expression: Apache-2.0
11
+ License-File: LICENSE
12
+ Keywords: ai-agents,context,knowledge-graph,llm,memory,rag,vector-database
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: aiosqlite>=0.19
23
+ Requires-Dist: cryptography>=42.0
24
+ Requires-Dist: numpy>=1.24
25
+ Requires-Dist: openai>=1.0
26
+ Requires-Dist: pydantic-settings>=2.0
27
+ Requires-Dist: pydantic>=2.0
28
+ Provides-Extra: all
29
+ Requires-Dist: asyncpg>=0.29; extra == 'all'
30
+ Requires-Dist: faiss-cpu>=1.7; extra == 'all'
31
+ Requires-Dist: neo4j>=5.0; extra == 'all'
32
+ Requires-Dist: pgvector>=0.2; extra == 'all'
33
+ Requires-Dist: redis>=5.0; extra == 'all'
34
+ Requires-Dist: sentence-transformers>=2.0; extra == 'all'
35
+ Provides-Extra: dev
36
+ Requires-Dist: hypothesis>=6.0; extra == 'dev'
37
+ Requires-Dist: mypy>=1.8; extra == 'dev'
38
+ Requires-Dist: pre-commit>=3.0; extra == 'dev'
39
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
40
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
41
+ Requires-Dist: pytest>=7.0; extra == 'dev'
42
+ Requires-Dist: ruff>=0.4; extra == 'dev'
43
+ Provides-Extra: faiss
44
+ Requires-Dist: faiss-cpu>=1.7; extra == 'faiss'
45
+ Provides-Extra: local
46
+ Requires-Dist: sentence-transformers>=2.0; extra == 'local'
47
+ Provides-Extra: neo4j
48
+ Requires-Dist: neo4j>=5.0; extra == 'neo4j'
49
+ Provides-Extra: postgres
50
+ Requires-Dist: asyncpg>=0.29; extra == 'postgres'
51
+ Requires-Dist: pgvector>=0.2; extra == 'postgres'
52
+ Provides-Extra: redis
53
+ Requires-Dist: redis>=5.0; extra == 'redis'
54
+ Provides-Extra: rl
55
+ Requires-Dist: torch>=2.0; extra == 'rl'
56
+ Requires-Dist: trl>=0.7; extra == 'rl'
57
+ Description-Content-Type: text/markdown
58
+
59
+ <p align="center">
60
+ <img src="assets/hero.png" alt="ContextDB — The unified context layer for AI agents" width="100%">
61
+ </p>
62
+
63
+ <h1 align="center">ContextDB</h1>
64
+ <p align="center"><strong>The unified context layer for AI agents.</strong></p>
65
+
66
+ <p align="center">
67
+ <a href="https://pypi.org/project/pycontextdb/"><img src="https://img.shields.io/pypi/v/pycontextdb.svg" alt="PyPI version"></a>
68
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License: Apache 2.0"></a>
69
+ <a href="tests/"><img src="https://img.shields.io/badge/tests-82%20passing-brightgreen.svg" alt="Tests"></a>
70
+ <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10%2B-blue.svg" alt="Python 3.10+"></a>
71
+ <a href="pyproject.toml"><img src="https://img.shields.io/badge/mypy-strict-blue.svg" alt="Type Checked"></a>
72
+ <a href="benchmarks/run_benchmarks.py"><img src="https://img.shields.io/badge/search_p95-%3C5ms_%40_5K-brightgreen.svg" alt="Search p95"></a>
73
+ <a href="https://github.com/atomsai/contextdb/stargazers"><img src="https://img.shields.io/github/stars/atomsai/contextdb?style=social" alt="GitHub stars"></a>
74
+ </p>
75
+
76
+ <p align="center">Replace your patchwork of Pinecone + Redis + Postgres + glue code with one system that understands memory.</p>
77
+
78
+ <p align="center">
79
+ <strong>⭐ If ContextDB saves you from building yet another memory stack, give it a star — it takes 1 second and makes a real difference for a solo-maintained project.</strong>
80
+ </p>
81
+
82
+ ---
83
+
84
+ ## At a glance
85
+
86
+ <p align="center">
87
+ <img src="assets/performance.png" alt="Performance at a glance — search p50 3.4ms, 1,930 writes/sec, 112K PII/sec, 5.0ms p95 at 5K memories, 800K vectors/sec index build, 82/82 tests" width="100%">
88
+ </p>
89
+
90
+ | | |
91
+ |---|---|
92
+ | **Write throughput** | 1,900+ memories/sec |
93
+ | **Search latency (1K memories)** | p50 **3.4ms** · p95 **4.5ms** |
94
+ | **Search latency (5K memories)** | p50 **3.9ms** · p95 **5.0ms** |
95
+ | **Vector search (10K × 1,536d)** | p50 **0.8ms** · p95 **1.0ms** |
96
+ | **PII detection** | 100,000+ texts/sec |
97
+ | **Tests** | 82 passing · ruff clean · mypy `--strict` clean |
98
+ | **Dependencies** | SQLite + NumPy (FAISS / Postgres optional) |
99
+
100
+ Hermetic, reproducible — run the suite yourself: `python benchmarks/run_benchmarks.py`.
101
+
102
+ ---
103
+
104
+ ## The problem
105
+
106
+ <p align="center">
107
+ <img src="assets/problem.png" alt="The broken stack every agent team builds: Pinecone + Redis + Postgres + S3 + glue code" width="100%">
108
+ </p>
109
+
110
+ Every team shipping agents assembles the same broken stack: vectors in Pinecone, sessions in Redis, profiles in Postgres, logs in S3, and 2-4 months of glue code holding it together. It breaks at multi-session reasoning (the agent forgets you between calls), temporal understanding ("last Tuesday" is not a vector), and learning from experience (nothing records what worked).
111
+
112
+ Databricks Lakebase gives agents a hard drive. ContextDB gives agents a brain.
113
+
114
+ ---
115
+
116
+ ## What ContextDB replaces
117
+
118
+ | What you use today | What breaks | ContextDB equivalent |
119
+ |---|---|---|
120
+ | Pinecone / Qdrant / Weaviate | Semantic-only; no temporal, causal, or entity awareness | Multi-graph retrieval fused with RRF (semantic + temporal + causal + entity) |
121
+ | Redis / Memcached | Ephemeral; lost between sessions; no compression | `WorkingMemory` with token-budget paging and FIFO eviction |
122
+ | PostgreSQL / MongoDB | Static rows; no lifecycle; no graph links | `FactualMemory` with formation, evolution, and consolidation |
123
+ | S3 / flat files | Write-only archive; not queryable by meaning or time | `ExperientialMemory` for trajectories, reflections, and workflows |
124
+ | Custom glue code | Brittle; rebuilt at every company; 2-4 engineering months | One `init()` call, one async SDK, one dependency |
125
+ | *(nothing today)* | Agents never learn from outcomes | RL-trained memory manager (`ADD` / `UPDATE` / `DELETE` / `NOOP`) |
126
+ | *(nothing today)* | Raw PII stored indefinitely; compliance risk | PII detection, typed TTLs, hash-chained audit log |
127
+
128
+ ---
129
+
130
+ ## Quick start
131
+
132
+ <p align="center">
133
+ <img src="assets/quickstart.png" alt="Three lines to persistent agent memory" width="100%">
134
+ </p>
135
+
136
+ ```python
137
+ import asyncio
138
+ import contextdb
139
+
140
+ async def main() -> None:
141
+ db = contextdb.init(
142
+ user_id="cust_42",
143
+ embedding_model="mock", llm_model="mock", llm_api_key="mock", # drop for real providers
144
+ )
145
+ async with db:
146
+ await db.factual.add("Customer runs a Carrier 24ACC6 AC unit installed 2019.")
147
+ await db.experiential.record_trajectory(
148
+ action="clear condenser coil",
149
+ outcome="restored cooling within 8 minutes",
150
+ success=True,
151
+ )
152
+ hits = await db.search("how do I fix weak airflow on a Carrier unit")
153
+ for h in hits:
154
+ print(h.content)
155
+
156
+ asyncio.run(main())
157
+ ```
158
+
159
+ One import, one `init`, one `async with`. No infra to stand up.
160
+
161
+ ---
162
+
163
+ ## Factual memory
164
+
165
+ Durable knowledge about users, entities, and the world. Survives sessions; answers "what do I know about X."
166
+
167
+ ```python
168
+ import asyncio
169
+ import contextdb
170
+
171
+ async def main() -> None:
172
+ db = contextdb.init(
173
+ user_id="cust_42",
174
+ embedding_model="mock", llm_model="mock", llm_api_key="mock",
175
+ )
176
+ async with db:
177
+ await db.factual.add("Customer owns a Carrier 24ACC6, installed March 2019.")
178
+ await db.factual.add("Preferred contact channel: email. Not phone.")
179
+ await db.factual.add("Home is a 2,400 sq ft single-story in Phoenix, AZ.")
180
+
181
+ hits = await db.factual.recall("what AC model does this customer have?")
182
+ print(hits[0].content) # → "Customer owns a Carrier 24ACC6..."
183
+
184
+ asyncio.run(main())
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Experiential memory
190
+
191
+ What the agent did, what happened, what to do next time. This is the substrate for agent self-improvement.
192
+
193
+ ```python
194
+ import asyncio
195
+ import contextdb
196
+
197
+ async def main() -> None:
198
+ db = contextdb.init(
199
+ user_id="cust_42",
200
+ embedding_model="mock", llm_model="mock", llm_api_key="mock",
201
+ )
202
+ async with db:
203
+ traj = await db.experiential.record_trajectory(
204
+ action="walked customer through filter replacement",
205
+ outcome="airflow restored; customer satisfied",
206
+ context={"ticket": "T-1139", "unit": "Carrier 24ACC6"},
207
+ success=True,
208
+ )
209
+ await db.experiential.add_reflection(
210
+ trajectory_id=traj.id,
211
+ insight="For Carrier 24ACC6 weak-airflow cases, check filter before coil.",
212
+ )
213
+
214
+ similar = await db.experiential.recall_similar(
215
+ "customer reports weak airflow on Carrier unit"
216
+ )
217
+ for s in similar:
218
+ print(s.content)
219
+
220
+ asyncio.run(main())
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Working memory
226
+
227
+ Token-budgeted session scratchpad. Oldest entries evict FIFO when you cross the budget; the LLM never sees more than you pay for.
228
+
229
+ ```python
230
+ import asyncio
231
+ import contextdb
232
+
233
+ async def main() -> None:
234
+ db = contextdb.init(
235
+ user_id="cust_42",
236
+ embedding_model="mock", llm_model="mock", llm_api_key="mock",
237
+ )
238
+ async with db:
239
+ session = db.working(session_id="call_7781", max_tokens=800)
240
+
241
+ await session.push("Customer called about AC not cooling.")
242
+ await session.push("Diagnosed: condenser coil clogged with cottonwood fluff.")
243
+ await session.push("Walked through cleaning procedure over phone.")
244
+ await session.push("Customer confirms cold air after 10 minutes.")
245
+
246
+ window = await session.context_window()
247
+ print(window) # exactly what to paste into the next LLM call
248
+
249
+ asyncio.run(main())
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Multi-graph retrieval
255
+
256
+ A semantic-only retriever is fine for "find things about X." It does not know that *"last Tuesday"* is a temporal constraint, that *"why did the repair fail"* is causal, or that *"the Phoenix customer"* is an entity. ContextDB layers four orthogonal graphs over the same memory table and fuses them via Reciprocal Rank Fusion (k=60).
257
+
258
+ ```python
259
+ import asyncio
260
+ import contextdb
261
+
262
+ async def main() -> None:
263
+ db = contextdb.init(
264
+ user_id="cust_42",
265
+ embedding_model="mock", llm_model="mock", llm_api_key="mock",
266
+ enable_multi_graph=True, # unlocks temporal + causal graphs
267
+ )
268
+ async with db:
269
+ await db.add("Coil cleaning on 2026-04-14 restored airflow.")
270
+ await db.add("Compressor trip on 2026-04-18 caused no-cool condition.")
271
+ await db.add("Replacing the contactor cleared the compressor trip.")
272
+
273
+ # Temporal intent: the query classifier boosts the temporal graph.
274
+ recent = await db.search("what went wrong last week with this unit?")
275
+
276
+ # Causal intent: causal graph boosts cause/effect chains.
277
+ causal = await db.search("why did the compressor stop?")
278
+
279
+ for h in recent + causal:
280
+ print(h.content)
281
+
282
+ asyncio.run(main())
283
+ ```
284
+
285
+ The query classifier assigns weights per graph based on markers in the query; each graph returns a ranked list; RRF fuses them. You do not pick which index to hit.
286
+
287
+ ---
288
+
289
+ ## Privacy by design
290
+
291
+ PII is detected, classified, and redacted **before** the embedder ever sees it. Writes, reads, and deletions are recorded in a hash-chained audit log. Retention TTLs are typed — factual memories live for 5 years, working memories for 24 hours, experiential memories indefinitely — all configurable.
292
+
293
+ ```python
294
+ import asyncio
295
+ import contextdb
296
+
297
+ async def main() -> None:
298
+ db = contextdb.init(
299
+ user_id="cust_42",
300
+ embedding_model="mock", llm_model="mock", llm_api_key="mock",
301
+ pii_action="redact",
302
+ )
303
+ async with db:
304
+ item = await db.add(
305
+ "Customer Alex Rivera (alex@example.com, 555-213-8844, "
306
+ "card 4111-1111-1111-1111) reported no cooling."
307
+ )
308
+ print(item.content)
309
+ # → "Customer Alex Rivera ([EMAIL], [PHONE], card [CREDIT_CARD]) reported no cooling."
310
+
311
+ # Tamper-evident audit chain covering every CREATE / READ / SEARCH / DELETE.
312
+ assert db.audit is not None
313
+ assert await db.audit.verify_chain() is True
314
+
315
+ asyncio.run(main())
316
+ ```
317
+
318
+ Right-to-erasure is a first-class operation:
319
+
320
+ ```python
321
+ await db.forget(entity="Alex Rivera") # bulk delete + audit entries
322
+ ```
323
+
324
+ ---
325
+
326
+ ## Framework integrations
327
+
328
+ Drop ContextDB into whatever stack you already ship. Each adapter is a thin duck-typed wrapper — no hard dependency on the framework.
329
+
330
+ **LangChain:**
331
+
332
+ ```python
333
+ import contextdb
334
+ from contextdb.integrations.langchain import ContextDBMemory
335
+
336
+ db = contextdb.init(user_id="cust_42",
337
+ embedding_model="mock", llm_model="mock", llm_api_key="mock")
338
+ memory = ContextDBMemory(db, session_id="chat-1")
339
+ # memory conforms to LangChain's async memory interface:
340
+ # aload_memory_variables(inputs) / asave_context(inputs, outputs) / aclear()
341
+ ```
342
+
343
+ **OpenAI Agents (function calling):**
344
+
345
+ ```python
346
+ import contextdb
347
+ from contextdb.integrations.openai_tools import tool_schemas, make_tool_handlers
348
+
349
+ db = contextdb.init(user_id="cust_42",
350
+ embedding_model="mock", llm_model="mock", llm_api_key="mock")
351
+ tools = tool_schemas() # JSON schemas for chat.completions tools=
352
+ handlers = make_tool_handlers(db) # name -> async callable
353
+ # Pass `tools` to the model; dispatch each tool_call name against handlers.
354
+ ```
355
+
356
+ **CrewAI:**
357
+
358
+ ```python
359
+ import contextdb
360
+ from contextdb.integrations.crewai import ContextDBCrewMemory
361
+
362
+ db = contextdb.init(user_id="cust_42",
363
+ embedding_model="mock", llm_model="mock", llm_api_key="mock")
364
+ crew_memory = ContextDBCrewMemory(db, top_k=5)
365
+ # Implements save / search / reset — the full CrewAI memory contract.
366
+ ```
367
+
368
+ AutoGen adapter ships in `contextdb.integrations.autogen` with the same shape.
369
+
370
+ ---
371
+
372
+ ## Use with AI coding tools
373
+
374
+ Drop any of these files into your project and your AI coding tool will automatically reach for ContextDB whenever it needs to add memory to an agent — no hand-holding required.
375
+
376
+ | File | Tool | What it does |
377
+ |---|---|---|
378
+ | [`.cursorrules`](.cursorrules) | Cursor | Auto-uses ContextDB for all agent-memory tasks; bans raw Pinecone / Redis / custom PII regex |
379
+ | [`CLAUDE.md`](CLAUDE.md) | Claude Code | Same, for Claude Code — includes the `async with db:` pattern and framework adapters |
380
+ | [`.github/copilot-instructions.md`](.github/copilot-instructions.md) | GitHub Copilot | Biases Copilot suggestions toward `db.factual.add` / `db.search` over custom vector plumbing |
381
+ | [`llms.txt`](llms.txt) · [`llms-full.txt`](llms-full.txt) | Any LLM | Host at your docs-site root so assistants can discover and recommend ContextDB |
382
+
383
+ ### Or copy-paste a ready-made prompt
384
+
385
+ [`docs/prompts.md`](docs/prompts.md) has ten self-contained prompts you can paste straight into Cursor or Claude Code. Examples:
386
+
387
+ - *Add memory to an existing LangChain agent* — swaps `ConversationBufferMemory` for `ContextDBMemory`
388
+ - *Build a customer support agent with memory* — full FastAPI + GPT-4o + ContextDB wiring
389
+ - *Migrate from Mem0 to ContextDB* — uses the built-in `Mem0Migrator`
390
+
391
+ ---
392
+
393
+ ## Architecture
394
+
395
+ <p align="center">
396
+ <img src="assets/architecture.png" alt="Five layers, one pip install — every component modular, testable, replaceable" width="100%">
397
+ </p>
398
+
399
+ Five layers, one dependency. Every component is modular, testable, and replaceable. Privacy is a layer, not an afterthought — PII never reaches the embedder unprocessed.
400
+
401
+ <details>
402
+ <summary>ASCII diagram (if images don't render)</summary>
403
+
404
+ ```
405
+ ┌──────────────────────────────────────────────────────────┐
406
+ │ Application Layer │
407
+ │ (Your agent: support bot, phone agent, copilot, crew) │
408
+ └─────────────────────────────┬────────────────────────────┘
409
+ │ contextdb SDK (async)
410
+ ┌─────────────────────────────▼────────────────────────────┐
411
+ │ ContextDB Core │
412
+ │ │
413
+ │ Memory Types Dynamics Engine Graph Layer │
414
+ │ ──────────── ─────────────── ─────────── │
415
+ │ • Factual • Formation • Semantic │
416
+ │ • Experiential • Evolution • Temporal │
417
+ │ • Working • Retrieval (RRF) • Causal │
418
+ │ • Entity │
419
+ └─────────────────────────────┬────────────────────────────┘
420
+ │
421
+ ┌─────────────────────────────▼────────────────────────────┐
422
+ │ Storage Layer │
423
+ │ SQLite (default) │ PostgreSQL │ FAISS │
424
+ └─────────────────────────────┬────────────────────────────┘
425
+ │
426
+ ┌─────────────────────────────▼────────────────────────────┐
427
+ │ Privacy Layer │
428
+ │ PII Detection │ Retention TTLs │ Hash-Chain Audit │
429
+ └──────────────────────────────────────────────────────────┘
430
+ ```
431
+
432
+ </details>
433
+
434
+ ---
435
+
436
+ ## Benchmarks
437
+
438
+ <p align="center">
439
+ <img src="assets/benchmarks.png" alt="ContextDB v0.1.0 performance dashboard — search p50 3.4ms, 1,930 writes/sec, 112K PII/sec, 82/82 tests" width="100%">
440
+ </p>
441
+
442
+ Six workloads, all hermetic, all reproducible. No API keys, no network, no cached results — just `python benchmarks/run_benchmarks.py`.
443
+
444
+ ### 1. Write throughput
445
+
446
+ 1,000 sequential `add()` calls including Pydantic validation, embedding, SQLite INSERT, and vector-index update.
447
+
448
+ ```
449
+ Throughput: 1,930 writes/sec
450
+ Average per write: 0.52ms
451
+ ```
452
+
453
+ ### 2. Search latency — 100 queries against 1,000 memories
454
+
455
+ ```
456
+ p50: 3.40ms
457
+ p95: 4.54ms
458
+ p99: 4.75ms
459
+ Mean: 3.59ms
460
+ ```
461
+
462
+ Target was <100ms p95. We hit it by an order of magnitude with room to spare.
463
+
464
+ ### 3. Search latency vs scale
465
+
466
+ Latency grows sub-linearly; write cost stays flat until the vector index rebuilds.
467
+
468
+ | Memories | Add (ms/op) | Search p50 | Search p95 |
469
+ |---:|---:|---:|---:|
470
+ | 100 | 0.47ms | 3.26ms | 4.25ms |
471
+ | 500 | 0.45ms | 3.59ms | 4.16ms |
472
+ | 1,000 | 0.43ms | 3.50ms | 4.24ms |
473
+ | 5,000 | 0.53ms | 3.89ms | 4.96ms |
474
+
475
+ ### 4. PII detection & redaction — 1,000 texts
476
+
477
+ ```
478
+ Throughput: 111,745 texts/sec
479
+ Per text: 0.01ms
480
+ Types covered: EMAIL, PHONE, SSN, CREDIT_CARD
481
+ ```
482
+
483
+ Correctness spot-check:
484
+
485
+ ```
486
+ Input: Contact me at test@example.com or 555-123-4567. SSN: 123-45-6789
487
+ Redacted: Contact me at [EMAIL] or [PHONE]. SSN: [SSN]
488
+ ```
489
+
490
+ PII runs before content reaches storage. It never gets embedded. It never gets logged.
491
+
492
+ ### 5. Vector index — 10K × 1,536-dim vectors
493
+
494
+ Pure-NumPy brute force, no FAISS dependency.
495
+
496
+ ```
497
+ Index build: 0.013s (~800K vectors/sec)
498
+ Search p50: 0.80ms
499
+ Search p95: 1.04ms
500
+ Self-retrieval accuracy: PASS
501
+ ```
502
+
503
+ FAISS is available as an optional backend for datasets beyond ~100K vectors.
504
+
505
+ ### 6. End-to-end — customer support agent
506
+
507
+ 50 mixed factual/experiential memories, 20 semantic searches, one PII-laden write with redaction verification.
508
+
509
+ ```
510
+ Add 50 memories: 0.03s (1,849/sec)
511
+ Search p50: 1.70ms
512
+ PII add + redact: 0.76ms
513
+ PII correctly redacted: PASS
514
+ ```
515
+
516
+ Stored content check:
517
+
518
+ ```
519
+ Input: Customer John Smith, email john@acme.com, SSN 123-45-6789 called about billing
520
+ Stored: Customer John Smith, email [EMAIL], SSN [SSN] called about billing
521
+ ```
522
+
523
+ Numbers above are from a MacBook-class laptop with no FAISS. Rerun `python benchmarks/run_benchmarks.py` on your own hardware — the script prints everything you see here.
524
+
525
+ ---
526
+
527
+ ## Why not just use...
528
+
529
+ **Mem0?** Graph intelligence is gated behind the paid tier. No experiential memory for trajectories and reflections. No RL-trained memory manager. No working memory with token budgets.
530
+
531
+ **Zep?** Strong bitemporal knowledge graphs. But no experiential memory, no working memory paging, no learned retrieval policies. Scope is narrower than a full memory OS.
532
+
533
+ **MemGPT / Letta?** OS-style working memory paging is elegant, but there's no persistent factual memory, no graph structures, and no multi-agent primitives. Great for one long chat; thin for a real product.
534
+
535
+ **Pinecone + Redis + Postgres + glue code?** That is the patchwork. It is exactly what ContextDB replaces. Five dependencies, three query languages, one brittle seam at each boundary, and nobody at your company learns anything from last quarter's tickets.
536
+
537
+ **Databricks Lakebase?** Storage, not cognition. Lakebase gives your agent a managed Postgres with pgvector and LangGraph checkpointing — a hard drive. ContextDB sits above storage (and can run on Lakebase as a backend) and provides the memory semantics: formation, evolution, retrieval, privacy.
538
+
539
+ ---
540
+
541
+ ## Research
542
+
543
+ Built on analysis of 200+ papers on agentic memory. The taxonomy — **Forms × Functions × Dynamics** — organizes agent memory along three axes:
544
+
545
+ - **Forms** — how memory is represented (token, parametric, latent).
546
+ - **Functions** — what memory is for (factual, experiential, working).
547
+ - **Dynamics** — how memory changes (formation, evolution, retrieval).
548
+
549
+ ContextDB is the first system to span all three axes in one library.
550
+
551
+ Paper: [*ContextDB: A Unified Context Layer for AI Agents*](https://zenodo.org/records/19647089) by **Gaurav Sharma** ([@gaufire](https://github.com/gaufire) · [x.com/Gaufire](https://x.com/Gaufire)), Zenodo, 2026.
552
+
553
+ ---
554
+
555
+ ## Installation
556
+
557
+ ```bash
558
+ pip install pycontextdb # core: SQLite, NumPy vector index, all memory types
559
+ pip install "pycontextdb[faiss]" # FAISS-accelerated vector index
560
+ pip install "pycontextdb[postgres]" # asyncpg + pgvector backend
561
+ pip install "pycontextdb[all]" # everything
562
+ ```
563
+
564
+ Python 3.10+. No system dependencies for the default install — SQLite and NumPy ship with Python.
565
+
566
+ ---
567
+
568
+ ## Contributing
569
+
570
+ Apache 2.0 — see [LICENSE](LICENSE). See [`docs/architecture.md`](docs/architecture.md) for the design rationale. Issues and pull requests welcome on [GitHub](https://github.com/atomsai/contextdb).
571
+
572
+ If you use ContextDB in research, please cite the paper: [zenodo.org/records/19647089](https://zenodo.org/records/19647089).
573
+
574
+ ---
575
+
576
+ ## Author
577
+
578
+ **Gaurav Sharma** — creator and maintainer of ContextDB, author of the companion paper.
579
+
580
+ - GitHub: [@gaufire](https://github.com/gaufire)
581
+ - X / Twitter: [@Gaufire](https://x.com/Gaufire)
582
+
583
+ ---
584
+
585
+ <p align="center">
586
+ <strong>Found ContextDB useful?</strong><br>
587
+ ⭐ <a href="https://github.com/atomsai/contextdb">Star the repo on GitHub</a> — it's the single biggest thing you can do to help a solo-maintained OSS project.<br>
588
+ Share it with someone currently cobbling together Pinecone + Redis + Postgres, and follow <a href="https://x.com/Gaufire">@Gaufire</a> for build logs.
589
+ </p>
@@ -0,0 +1,47 @@
1
+ contextdb/__init__.py,sha256=jMy34QTjGaWY7jNwA0sDbszN5fguER6diHw6Ds9ihLU,1725
2
+ contextdb/cli.py,sha256=MyF1jQ8np1b9IpKhiG4x1e_ibrkxoUAIkuqgXE3GSYY,3508
3
+ contextdb/client.py,sha256=2UM9fu2EbGry4XJrpT8IhHjVQXaSqDZwrYhfal7yLqM,20121
4
+ contextdb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ contextdb/agents/__init__.py,sha256=Ze-ScZtEgKP1nisKG6c1GcauO9QU5pbvDZIKfvAFWRQ,255
6
+ contextdb/agents/memory_bus.py,sha256=hIm3v7MR5CvES0TICqJBQO_WDW2_AYiAzL8gcGiu2KA,2827
7
+ contextdb/agents/rl_manager.py,sha256=QC0j474yuCTOTZvqaTZS48FQATaSQA9w2zwZ2Fu8vTQ,3108
8
+ contextdb/core/__init__.py,sha256=gyB41aR9FKq3KRha6OoAqf7Ird67lhqGKjR-6_z0NYg,785
9
+ contextdb/core/config.py,sha256=hEKKeVXKTE6n8O1C2e6nYgCmM-W44DYsBm7nuz-Rbwk,3208
10
+ contextdb/core/exceptions.py,sha256=dsh8u6Mdrd5wiGOREmEgvvC_ELO4WY0HNfPmknnauB4,842
11
+ contextdb/core/models.py,sha256=GWIKJUw11Fesx26PiHI8v7lpZrCX5QxiBLf5OXe9x-s,4970
12
+ contextdb/dynamics/__init__.py,sha256=KSlZ-ZgCrBbZqMCty2dB0Y8GUxpbrNXXd94ikGtLy9I,631
13
+ contextdb/dynamics/evolution.py,sha256=gJSDkyxQH0OWX1wg8skPsQ-HgRL589q4fZQuSWf8X6U,6994
14
+ contextdb/dynamics/formation.py,sha256=ODX5EGIqzT8IhMVHJKrDj3g7Kj6FUZRTcVG33EHAPcU,6662
15
+ contextdb/dynamics/retrieval.py,sha256=QUI-cQrKU-Oq8ju4OYy19OBw36yGIuS0RwBfWHDi5rs,4631
16
+ contextdb/graphs/__init__.py,sha256=QPn4wjuJPqTJxF1ZtYsG3iIxT66Uq-KCri4-zt0lPpc,462
17
+ contextdb/graphs/base.py,sha256=AED_T-xhQbV5li-e-lB7Jt92RDviuMEO0pSqQY0bwk4,1304
18
+ contextdb/graphs/causal.py,sha256=VigbroCAECv0mfcNMXDRP5tBFUXgOX1A0Z-um6VPRBc,8266
19
+ contextdb/graphs/entity.py,sha256=TddeQWZI2TUrFI3aGt_BkswBYdIQVVGYJN5qrbCqR_I,8904
20
+ contextdb/graphs/semantic.py,sha256=8-1j2zWK9uYHfggCNJ8ZPAiFF5pbJOQJLc-1y4YXrrc,5429
21
+ contextdb/graphs/temporal.py,sha256=M9QkwQJLJ7hBFbQGw0CWQi2mBd_-uFWFQsUfQH2ETog,6311
22
+ contextdb/integrations/__init__.py,sha256=CeTzuTh2OG8S0AQcNa-bATZA-Om99ugcavLyI0Rl9oI,217
23
+ contextdb/integrations/autogen.py,sha256=lCYTp6HQSZmdTDCDUUsxIa1UXkuxCQl9RL88NxZVwpw,1215
24
+ contextdb/integrations/crewai.py,sha256=zd1ybpBk0UOchB0lIpVETNMVq9pLLYPaWuxoAWsSASI,1423
25
+ contextdb/integrations/langchain.py,sha256=arefIyg8HX-FkEmjvfLAyr7RXMLpaLRcR4MZkA9ukGM,4637
26
+ contextdb/integrations/openai_tools.py,sha256=pEA2UNGx6XhTIqkYE-qlnml8Z3kG8xIpL1i0PO_vQcs,4398
27
+ contextdb/memory/__init__.py,sha256=KCIAs2faG6vu4sNpz-Er66NV6J5s31mSy7Yy2Fh8nQg,329
28
+ contextdb/memory/experiential.py,sha256=T-EEIj9RSyRqsVecqXGCBSFby67uENMXPHgsGqKizpA,3424
29
+ contextdb/memory/factual.py,sha256=3kYbCKAkI_BbIQSIp7opKn1Jb5KmlLRrZ_ivHqtbStc,1962
30
+ contextdb/memory/working.py,sha256=z3J2bQEI4Rl3ukKsS7WHtijskXyqlzwlT7felMWhWFA,2934
31
+ contextdb/privacy/__init__.py,sha256=29u7YK1wK_V1TuiODJzyszBqJPQZ2Y69Juf2X3o_5gA,362
32
+ contextdb/privacy/audit.py,sha256=Q8UxOj5P35KuWmhY-ERtCIxQkeDCNa8oOAursCb-plI,6672
33
+ contextdb/privacy/pii_detector.py,sha256=O7pfFcgWoA91d6kkLBS2DkVCZGFbCveLyNUay-X5cPU,6412
34
+ contextdb/privacy/retention.py,sha256=K5Fd6MbPZXPOPXLpY14o0ev5o-mWTszL9huU8metFCc,3507
35
+ contextdb/store/__init__.py,sha256=9jOGjBi_FZECITmEzIbPJ2tPHLSteNxwDNGWBH8YAWU,371
36
+ contextdb/store/base.py,sha256=0G3W6kKPMtUcqi77w2Yj6UL-I0_4LRxK--gTREBvCNo,2088
37
+ contextdb/store/sqlite_store.py,sha256=lcUZGdSJcD0bpAKjBFJYHAGkfJHG82RqIfjDFf_8-7E,19457
38
+ contextdb/store/vector_index.py,sha256=KDozOb8IAfO_MjguDDFSC9RIs0qN1pJ_PqHWREAugho,8897
39
+ contextdb/utils/__init__.py,sha256=v__Q0TKYVHD7htDaZoylXZ1DEkIjtDBYWy_3Bwiv2dY,490
40
+ contextdb/utils/embeddings.py,sha256=oLDdzZG_fsUUA6SYxKIRzq2EvHIqN8ULp7dmjHPk538,5554
41
+ contextdb/utils/llm.py,sha256=CaC_ok_zpt8FBy0Qx4aCKBajsi3wE1485ajMFWY62Ns,4319
42
+ contextdb/utils/migrations.py,sha256=OTCzAok7DNm57JRxSkITVQmE-1_q5FVvyRNwNB0cfbs,5221
43
+ pycontextdb-0.1.0.dist-info/METADATA,sha256=co56pA9EYF49soav4Cw9QwjYpUCyzNj44jXVD33C7DY,24231
44
+ pycontextdb-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
45
+ pycontextdb-0.1.0.dist-info/entry_points.txt,sha256=-Rg1W4AO7WZYsWBUZKiYfk1EcYIShu5CMQje4JmEcTI,49
46
+ pycontextdb-0.1.0.dist-info/licenses/LICENSE,sha256=cMgwq9yELgjvII_U4SPgTylbP1lrsi2iB69430hruoM,10764
47
+ pycontextdb-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ contextdb = contextdb.cli:main