Skip to content

Commit 1fa773c

Browse files
committed
1.0.1
1 parent aab0bca commit 1fa773c

19 files changed

Lines changed: 860 additions & 1849 deletions

ARCHITECTURE.md

Lines changed: 100 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -62,30 +62,31 @@ OpenMemory is a self-hosted AI memory engine implementing **Hierarchical Memory
6262

6363
**Key Endpoints:**
6464

65-
| Method | Endpoint | Description |
66-
|--------|----------|-------------|
67-
| `GET` | `/health` | Health check and version info |
68-
| `GET` | `/sectors` | List available sectors and stats |
69-
| `POST` | `/memory/add` | Add a new memory |
70-
| `POST` | `/memory/query` | Query memories by similarity |
71-
| `POST` | `/memory/ingest` | Ingest document (PDF/DOCX/TXT) |
72-
| `POST` | `/memory/ingest/url` | Ingest URL content |
73-
| `POST` | `/memory/reinforce` | Boost memory salience |
74-
| `GET` | `/memory/all` | List all memories (paginated) |
75-
| `GET` | `/memory/:id` | Get specific memory details |
76-
| `DELETE` | `/memory/:id` | Delete a memory |
65+
| Method | Endpoint | Description |
66+
| -------- | -------------------- | -------------------------------- |
67+
| `GET` | `/health` | Health check and version info |
68+
| `GET` | `/sectors` | List available sectors and stats |
69+
| `POST` | `/memory/add` | Add a new memory |
70+
| `POST` | `/memory/query` | Query memories by similarity |
71+
| `POST` | `/memory/ingest` | Ingest document (PDF/DOCX/TXT) |
72+
| `POST` | `/memory/ingest/url` | Ingest URL content |
73+
| `POST` | `/memory/reinforce` | Boost memory salience |
74+
| `GET` | `/memory/all` | List all memories (paginated) |
75+
| `GET` | `/memory/:id` | Get specific memory details |
76+
| `DELETE` | `/memory/:id` | Delete a memory |
7777

7878
**LangGraph Mode Endpoints** (when `OM_MODE=langgraph`):
7979

80-
| Method | Endpoint | Description |
81-
|--------|----------|-------------|
82-
| `POST` | `/lgm/store` | Store LangGraph node output |
83-
| `POST` | `/lgm/retrieve` | Retrieve memories for graph session |
84-
| `POST` | `/lgm/context` | Get summarized multi-sector context |
85-
| `POST` | `/lgm/reflection` | Generate and store reflections |
86-
| `GET` | `/lgm/config` | Inspect LangGraph configuration |
80+
| Method | Endpoint | Description |
81+
| ------ | ----------------- | ----------------------------------- |
82+
| `POST` | `/lgm/store` | Store LangGraph node output |
83+
| `POST` | `/lgm/retrieve` | Retrieve memories for graph session |
84+
| `POST` | `/lgm/context` | Get summarized multi-sector context |
85+
| `POST` | `/lgm/reflection` | Generate and store reflections |
86+
| `GET` | `/lgm/config` | Inspect LangGraph configuration |
8787

8888
**Features:**
89+
8990
- CORS support for cross-origin requests
9091
- Bearer token authentication (optional)
9192
- Scheduled decay process (every 24 hours)
@@ -134,6 +135,7 @@ SECTORS = {
134135
#### 2.2 Memory Operations
135136

136137
**Add Memory Flow:**
138+
137139
```
138140
1. Content → classifyContent() → {primary, additional}
139141
2. For each sector → embedMultiSector() → vectors[]
@@ -144,6 +146,7 @@ SECTORS = {
144146
```
145147

146148
**Query Memory Flow:**
149+
147150
```
148151
1. Query text → classifyContent() → candidate sectors
149152
2. For each sector → embedForSector() → query vector
@@ -181,14 +184,17 @@ Memory A ──0.85──> Memory B
181184
```
182185

183186
**Creation:**
187+
184188
- During add: find single best match (cosine > 0.75)
185189
- Bidirectional if cross-sector
186190

187191
**Reinforcement:**
192+
188193
- On query: boost weight by 0.05 per traversal
189194
- Max weight: 1.0
190195

191196
**Pruning:**
197+
192198
- Every 7 days: remove weights < 0.05
193199

194200
---
@@ -199,22 +205,24 @@ Memory A ──0.85──> Memory B
199205

200206
#### 3.1 Supported Providers
201207

202-
| Provider | Models | Batch Support | Cost |
203-
|----------|--------|---------------|------|
204-
| **OpenAI** | `text-embedding-3-small`, `text-embedding-3-large` || ~$0.02/1M tokens |
205-
| **Gemini** | `embedding-001` || ~$0.01/1M tokens |
206-
| **Ollama** | `nomic-embed-text`, `bge-small`, `bge-large` || Free (local) |
207-
| **Local** | Custom models || Free (local) |
208-
| **Synthetic** | Hash-based || Free |
208+
| Provider | Models | Batch Support | Cost |
209+
| ------------- | -------------------------------------------------- | ------------- | ---------------- |
210+
| **OpenAI** | `text-embedding-3-small`, `text-embedding-3-large` | | ~$0.02/1M tokens |
211+
| **Gemini** | `embedding-001` | | ~$0.01/1M tokens |
212+
| **Ollama** | `nomic-embed-text`, `bge-small`, `bge-large` | | Free (local) |
213+
| **Local** | Custom models | | Free (local) |
214+
| **Synthetic** | Hash-based | | Free |
209215

210216
#### 3.2 Embedding Modes
211217

212218
**Simple Mode** (`OM_EMBED_MODE=simple`):
219+
213220
- One batch call per memory (all sectors at once)
214221
- Faster for OpenAI/Gemini
215222
- Lower API overhead
216223

217224
**Advanced Mode** (`OM_EMBED_MODE=advanced`):
225+
218226
- Sector-specific model selection
219227
- Optional parallel embedding
220228
- Chunking support for long texts
@@ -223,6 +231,7 @@ Memory A ──0.85──> Memory B
223231
#### 3.3 Chunking Strategy
224232

225233
For texts > 512 tokens:
234+
226235
```
227236
1. Split text into overlapping chunks (512 tokens, 50 overlap)
228237
2. Embed each chunk separately
@@ -239,6 +248,7 @@ For texts > 512 tokens:
239248
#### 4.1 Schema
240249

241250
**memories table:**
251+
242252
```sql
243253
CREATE TABLE memories (
244254
id TEXT PRIMARY KEY, -- UUID
@@ -258,6 +268,7 @@ CREATE TABLE memories (
258268
```
259269

260270
**vectors table:**
271+
261272
```sql
262273
CREATE TABLE vectors (
263274
id TEXT NOT NULL, -- Memory ID
@@ -269,6 +280,7 @@ CREATE TABLE vectors (
269280
```
270281

271282
**waypoints table:**
283+
272284
```sql
273285
CREATE TABLE waypoints (
274286
src_id TEXT PRIMARY KEY, -- Source memory
@@ -280,6 +292,7 @@ CREATE TABLE waypoints (
280292
```
281293

282294
**embed_logs table:**
295+
283296
```sql
284297
CREATE TABLE embed_logs (
285298
id TEXT PRIMARY KEY,
@@ -293,15 +306,15 @@ CREATE TABLE embed_logs (
293306
#### 4.2 Transaction Support
294307

295308
```typescript
296-
transaction.begin()
309+
transaction.begin();
297310
try {
298311
// Insert memory
299312
// Insert vectors
300313
// Create waypoints
301-
transaction.commit()
314+
transaction.commit();
302315
} catch (e) {
303-
transaction.rollback()
304-
throw e
316+
transaction.rollback();
317+
throw e;
305318
}
306319
```
307320

@@ -313,12 +326,12 @@ try {
313326

314327
#### 5.1 Supported Formats
315328

316-
| Format | Parser | Features |
317-
|--------|--------|----------|
318-
| **PDF** | `pdf-parse` | Text extraction, metadata |
319-
| **DOCX** | `mammoth` | Convert to markdown |
320-
| **TXT** | Native | Direct read |
321-
| **URL** | `fetch` + `turndown` | HTML → Markdown |
329+
| Format | Parser | Features |
330+
| -------- | -------------------- | ------------------------- |
331+
| **PDF** | `pdf-parse` | Text extraction, metadata |
332+
| **DOCX** | `mammoth` | Convert to markdown |
333+
| **TXT** | Native | Direct read |
334+
| **URL** | `fetch` + `turndown` | HTML → Markdown |
322335

323336
#### 5.2 Processing Flow
324337

@@ -332,6 +345,7 @@ Document → Extract text → Chunk if needed →
332345
```
333346

334347
**Configuration:**
348+
335349
```typescript
336350
{
337351
chunk_size: 2048, // Max tokens per chunk
@@ -350,12 +364,12 @@ Document → Extract text → Chunk if needed →
350364

351365
```typescript
352366
NODE_SECTOR_MAP = {
353-
observe: 'episodic', // Observations
354-
plan: 'semantic', // Plans and strategies
355-
reflect: 'reflective', // Reflections
356-
act: 'procedural', // Actions taken
357-
emotion: 'emotional' // Emotional state
358-
}
367+
observe: 'episodic', // Observations
368+
plan: 'semantic', // Plans and strategies
369+
reflect: 'reflective', // Reflections
370+
act: 'procedural', // Actions taken
371+
emotion: 'emotional', // Emotional state
372+
};
359373
```
360374

361375
#### 6.2 Context Assembly
@@ -543,33 +557,33 @@ OM_LG_REFLECTIVE=true
543557

544558
### Latency (100k memories)
545559

546-
| Operation | Latency | Notes |
547-
|-----------|---------|-------|
548-
| Add memory | 80-120 ms | Depends on embedding provider |
549-
| Query (simple) | 110-130 ms | Single-sector search |
550-
| Query (multi-sector) | 150-200 ms | 2-3 sector fusion |
551-
| Waypoint expansion | +30-50 ms | Per hop |
552-
| Decay process | ~10 sec | Background, every 24h |
560+
| Operation | Latency | Notes |
561+
| -------------------- | ---------- | ----------------------------- |
562+
| Add memory | 80-120 ms | Depends on embedding provider |
563+
| Query (simple) | 110-130 ms | Single-sector search |
564+
| Query (multi-sector) | 150-200 ms | 2-3 sector fusion |
565+
| Waypoint expansion | +30-50 ms | Per hop |
566+
| Decay process | ~10 sec | Background, every 24h |
553567

554568
### Storage (SQLite)
555569

556-
| Item | Size | Notes |
557-
|------|------|-------|
558-
| Memory metadata | ~500 bytes | Per memory |
559-
| Vector (768d) | ~3 KB | Per sector |
560-
| Waypoint | ~100 bytes | Per link |
561-
| **Total per memory** | ~4-6 KB | Depends on sectors |
562-
| **100k memories** | ~500 MB | Typical |
563-
| **1M memories** | ~5 GB | With indexing |
570+
| Item | Size | Notes |
571+
| -------------------- | ---------- | ------------------ |
572+
| Memory metadata | ~500 bytes | Per memory |
573+
| Vector (768d) | ~3 KB | Per sector |
574+
| Waypoint | ~100 bytes | Per link |
575+
| **Total per memory** | ~4-6 KB | Depends on sectors |
576+
| **100k memories** | ~500 MB | Typical |
577+
| **1M memories** | ~5 GB | With indexing |
564578

565579
### Throughput
566580

567-
| Operation | Rate | Notes |
568-
|-----------|------|-------|
569-
| Add (synthetic) | ~40 ops/s | No external API |
570-
| Add (OpenAI) | ~10-15 ops/s | Rate limited |
571-
| Add (Ollama) | ~8-12 ops/s | CPU bound |
572-
| Query | ~30-50 ops/s | In-memory vectors |
581+
| Operation | Rate | Notes |
582+
| --------------- | ------------ | ----------------- |
583+
| Add (synthetic) | ~40 ops/s | No external API |
584+
| Add (OpenAI) | ~10-15 ops/s | Rate limited |
585+
| Add (Ollama) | ~8-12 ops/s | CPU bound |
586+
| Query | ~30-50 ops/s | In-memory vectors |
573587

574588
---
575589

@@ -591,22 +605,26 @@ OM_LG_REFLECTIVE=true
591605
```
592606

593607
**Benefits:**
608+
594609
- Sector-specific optimization
595610
- Independent scaling per sector
596611
- Reduced contention
597612

598613
**Trade-offs:**
614+
599615
- Cross-sector queries need aggregation
600616
- Waypoints may span instances
601617

602618
### Vertical Scaling
603619

604620
**Bottlenecks:**
621+
605622
1. Embedding API rate limits → Use batch mode
606623
2. SQLite write contention → Use WAL mode
607624
3. Vector similarity computation → Use SIMD
608625

609626
**Optimizations:**
627+
610628
- Enable WAL mode (write-ahead logging)
611629
- Use connection pooling
612630
- Cache mean vectors in memory
@@ -617,17 +635,20 @@ OM_LG_REFLECTIVE=true
617635
## Security
618636

619637
### Authentication
638+
620639
- Optional bearer token (`OM_API_KEY`)
621640
- All write endpoints check auth
622641
- Read endpoints can be public
623642

624643
### Data Privacy
644+
625645
- 100% local storage (no vendor lock-in)
626646
- Optional content encryption at rest
627647
- PII scrubbing hooks available
628648
- Tenant isolation support
629649

630650
### Best Practices
651+
631652
1. Use HTTPS in production
632653
2. Set `OM_API_KEY` for write protection
633654
3. Run behind reverse proxy (nginx/caddy)
@@ -645,6 +666,7 @@ docker compose up -d
645666
```
646667

647668
Ports:
669+
648670
- `8080` → API server
649671
- Data persisted in `/data/openmemory.sqlite`
650672

@@ -664,6 +686,7 @@ npm start
664686
```
665687

666688
**Systemd service:**
689+
667690
```ini
668691
[Unit]
669692
Description=OpenMemory Service
@@ -720,6 +743,7 @@ Response:
720743
### Embedding Logs
721744

722745
Query `embed_logs` table for:
746+
723747
- Failed embedding attempts
724748
- Rate limit issues
725749
- Provider errors
@@ -729,16 +753,19 @@ Query `embed_logs` table for:
729753
## Future Architecture Enhancements
730754

731755
### v1.3: Learned Sector Classifier
756+
732757
- Replace regex patterns with Tiny Transformer
733758
- Train on user data for better classification
734759
- Adaptive sector weighting
735760

736761
### v1.4: Federated Multi-Node
762+
737763
- Distributed waypoint graph
738764
- Consensus protocol for salience
739765
- Cross-node query federation
740766

741767
### v1.5: Pluggable Vector Backends
768+
742769
- Support pgvector (PostgreSQL)
743770
- Support Weaviate/Qdrant
744771
- Abstraction layer for vector ops
@@ -747,16 +774,16 @@ Query `embed_logs` table for:
747774

748775
## Glossary
749776

750-
| Term | Definition |
751-
|------|------------|
752-
| **HMD** | Hierarchical Memory Decomposition - the core architecture |
753-
| **Sector** | Memory type (episodic, semantic, procedural, emotional, reflective) |
754-
| **Salience** | Importance score (0-1) that decays over time |
755-
| **Waypoint** | Associative link between memories (single strongest only) |
756-
| **Decay** | Time-based reduction in salience (sector-specific) |
757-
| **Reinforcement** | Boosting salience/waypoint strength on recall |
758-
| **Mean Vector** | Weighted average of all sector vectors (for waypoint matching) |
759-
| **Composite Score** | 0.6×similarity + 0.2×salience + 0.1×recency + 0.1×waypoint |
777+
| Term | Definition |
778+
| ------------------- | ------------------------------------------------------------------- |
779+
| **HMD** | Hierarchical Memory Decomposition - the core architecture |
780+
| **Sector** | Memory type (episodic, semantic, procedural, emotional, reflective) |
781+
| **Salience** | Importance score (0-1) that decays over time |
782+
| **Waypoint** | Associative link between memories (single strongest only) |
783+
| **Decay** | Time-based reduction in salience (sector-specific) |
784+
| **Reinforcement** | Boosting salience/waypoint strength on recall |
785+
| **Mean Vector** | Weighted average of all sector vectors (for waypoint matching) |
786+
| **Composite Score** | 0.6×similarity + 0.2×salience + 0.1×recency + 0.1×waypoint |
760787

761788
---
762789

0 commit comments

Comments
 (0)