Compare commits
5 Commits
mimo/build
...
mimo/code/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a0a2eb802 | ||
| 6786e65f3d | |||
| 62a6581827 | |||
| 797f32a7fe | |||
| 80eb4ff7ea |
@@ -1,13 +1,18 @@
|
|||||||
|
|
||||||
class MemoryOptimizer {
|
class MemoryOptimizer {
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
this.threshold = options.threshold || 0.8;
|
this.threshold = options.threshold || 0.3;
|
||||||
this.decayRate = options.decayRate || 0.05;
|
this.decayRate = options.decayRate || 0.01;
|
||||||
|
this.lastRun = Date.now();
|
||||||
}
|
}
|
||||||
optimize(memory) {
|
optimize(memories) {
|
||||||
console.log('Optimizing memory...');
|
const now = Date.now();
|
||||||
// Heuristic-based pruning
|
const elapsed = (now - this.lastRun) / 1000;
|
||||||
return memory.filter(m => m.strength > this.threshold);
|
this.lastRun = now;
|
||||||
|
return memories.map(m => {
|
||||||
|
const decay = (m.importance || 1) * this.decayRate * elapsed;
|
||||||
|
return { ...m, strength: Math.max(0, (m.strength || 1) - decay) };
|
||||||
|
}).filter(m => m.strength > this.threshold || m.locked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default MemoryOptimizer;
|
export default MemoryOptimizer;
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ SQLite-backed store for lived experiences only. The model remembers
|
|||||||
what it perceived, what it thought, and what it did — nothing else.
|
what it perceived, what it thought, and what it did — nothing else.
|
||||||
|
|
||||||
Each row is one cycle of the perceive→think→act loop.
|
Each row is one cycle of the perceive→think→act loop.
|
||||||
|
|
||||||
|
Implements the GBrain "compiled truth + timeline" pattern (#1181):
|
||||||
|
- compiled_truths: current best understanding, rewritten when evidence changes
|
||||||
|
- experiences: append-only evidence trail that never gets edited
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
@@ -51,6 +55,27 @@ class ExperienceStore:
|
|||||||
ON experiences(timestamp DESC);
|
ON experiences(timestamp DESC);
|
||||||
CREATE INDEX IF NOT EXISTS idx_exp_session
|
CREATE INDEX IF NOT EXISTS idx_exp_session
|
||||||
ON experiences(session_id);
|
ON experiences(session_id);
|
||||||
|
|
||||||
|
-- GBrain compiled truth pattern (#1181)
|
||||||
|
-- Current best understanding about an entity/topic.
|
||||||
|
-- Rewritten when new evidence changes the picture.
|
||||||
|
-- The timeline (experiences table) is the evidence trail — never edited.
|
||||||
|
CREATE TABLE IF NOT EXISTS compiled_truths (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
entity TEXT NOT NULL, -- what this truth is about (person, topic, project)
|
||||||
|
truth TEXT NOT NULL, -- current best understanding
|
||||||
|
confidence REAL DEFAULT 0.5, -- 0.0–1.0
|
||||||
|
source_exp_id INTEGER, -- last experience that updated this truth
|
||||||
|
created_at REAL NOT NULL,
|
||||||
|
updated_at REAL NOT NULL,
|
||||||
|
metadata_json TEXT DEFAULT '{}',
|
||||||
|
UNIQUE(entity) -- one compiled truth per entity
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_truth_entity
|
||||||
|
ON compiled_truths(entity);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_truth_updated
|
||||||
|
ON compiled_truths(updated_at DESC);
|
||||||
""")
|
""")
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
|
||||||
@@ -157,3 +182,117 @@ class ExperienceStore:
|
|||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.conn.close()
|
self.conn.close()
|
||||||
|
|
||||||
|
# ── GBrain compiled truth + timeline pattern (#1181) ────────────────
|
||||||
|
|
||||||
|
def upsert_compiled_truth(
|
||||||
|
self,
|
||||||
|
entity: str,
|
||||||
|
truth: str,
|
||||||
|
confidence: float = 0.5,
|
||||||
|
source_exp_id: Optional[int] = None,
|
||||||
|
metadata: Optional[dict] = None,
|
||||||
|
) -> int:
|
||||||
|
"""Create or update the compiled truth for an entity.
|
||||||
|
|
||||||
|
This is the 'compiled truth on top' from the GBrain pattern.
|
||||||
|
When new evidence changes our understanding, we rewrite this
|
||||||
|
record. The timeline (experiences table) preserves what led
|
||||||
|
here — it is never edited.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
entity: What this truth is about (person, topic, project).
|
||||||
|
truth: Current best understanding.
|
||||||
|
confidence: 0.0–1.0 confidence score.
|
||||||
|
source_exp_id: Last experience ID that informed this truth.
|
||||||
|
metadata: Optional extra data as a dict.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The row ID of the compiled truth.
|
||||||
|
"""
|
||||||
|
now = time.time()
|
||||||
|
meta_json = json.dumps(metadata) if metadata else "{}"
|
||||||
|
|
||||||
|
self.conn.execute(
|
||||||
|
"""INSERT INTO compiled_truths
|
||||||
|
(entity, truth, confidence, source_exp_id, created_at, updated_at, metadata_json)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||||
|
ON CONFLICT(entity) DO UPDATE SET
|
||||||
|
truth = excluded.truth,
|
||||||
|
confidence = excluded.confidence,
|
||||||
|
source_exp_id = excluded.source_exp_id,
|
||||||
|
updated_at = excluded.updated_at,
|
||||||
|
metadata_json = excluded.metadata_json""",
|
||||||
|
(entity, truth, confidence, source_exp_id, now, now, meta_json),
|
||||||
|
)
|
||||||
|
self.conn.commit()
|
||||||
|
|
||||||
|
row = self.conn.execute(
|
||||||
|
"SELECT id FROM compiled_truths WHERE entity = ?", (entity,)
|
||||||
|
).fetchone()
|
||||||
|
return row[0]
|
||||||
|
|
||||||
|
def get_compiled_truth(self, entity: str) -> Optional[dict]:
|
||||||
|
"""Get the current compiled truth for an entity."""
|
||||||
|
row = self.conn.execute(
|
||||||
|
"""SELECT id, entity, truth, confidence, source_exp_id,
|
||||||
|
created_at, updated_at, metadata_json
|
||||||
|
FROM compiled_truths WHERE entity = ?""",
|
||||||
|
(entity,),
|
||||||
|
).fetchone()
|
||||||
|
if not row:
|
||||||
|
return None
|
||||||
|
return {
|
||||||
|
"id": row[0],
|
||||||
|
"entity": row[1],
|
||||||
|
"truth": row[2],
|
||||||
|
"confidence": row[3],
|
||||||
|
"source_exp_id": row[4],
|
||||||
|
"created_at": row[5],
|
||||||
|
"updated_at": row[6],
|
||||||
|
"metadata": json.loads(row[7]) if row[7] else {},
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_all_compiled_truths(
|
||||||
|
self, min_confidence: float = 0.0, limit: int = 100
|
||||||
|
) -> list[dict]:
|
||||||
|
"""Get all compiled truths, optionally filtered by minimum confidence."""
|
||||||
|
rows = self.conn.execute(
|
||||||
|
"""SELECT id, entity, truth, confidence, source_exp_id,
|
||||||
|
created_at, updated_at, metadata_json
|
||||||
|
FROM compiled_truths
|
||||||
|
WHERE confidence >= ?
|
||||||
|
ORDER BY updated_at DESC
|
||||||
|
LIMIT ?""",
|
||||||
|
(min_confidence, limit),
|
||||||
|
).fetchall()
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"id": r[0], "entity": r[1], "truth": r[2],
|
||||||
|
"confidence": r[3], "source_exp_id": r[4],
|
||||||
|
"created_at": r[5], "updated_at": r[6],
|
||||||
|
"metadata": json.loads(r[7]) if r[7] else {},
|
||||||
|
}
|
||||||
|
for r in rows
|
||||||
|
]
|
||||||
|
|
||||||
|
def search_compiled_truths(self, query: str, limit: int = 10) -> list[dict]:
|
||||||
|
"""Search compiled truths by entity name or truth content (LIKE match)."""
|
||||||
|
rows = self.conn.execute(
|
||||||
|
"""SELECT id, entity, truth, confidence, source_exp_id,
|
||||||
|
created_at, updated_at, metadata_json
|
||||||
|
FROM compiled_truths
|
||||||
|
WHERE entity LIKE ? OR truth LIKE ?
|
||||||
|
ORDER BY confidence DESC, updated_at DESC
|
||||||
|
LIMIT ?""",
|
||||||
|
(f"%{query}%", f"%{query}%", limit),
|
||||||
|
).fetchall()
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"id": r[0], "entity": r[1], "truth": r[2],
|
||||||
|
"confidence": r[3], "source_exp_id": r[4],
|
||||||
|
"created_at": r[5], "updated_at": r[6],
|
||||||
|
"metadata": json.loads(r[7]) if r[7] else {},
|
||||||
|
}
|
||||||
|
for r in rows
|
||||||
|
]
|
||||||
|
|||||||
14
nexus/mnemosyne/reasoner.py
Normal file
14
nexus/mnemosyne/reasoner.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
class Reasoner:
|
||||||
|
def __init__(self, rules):
|
||||||
|
self.rules = rules
|
||||||
|
def evaluate(self, entries):
|
||||||
|
return [r['action'] for r in self.rules if self._check(r['condition'], entries)]
|
||||||
|
def _check(self, cond, entries):
|
||||||
|
if cond.startswith('count'):
|
||||||
|
# e.g. count(type=anomaly)>3
|
||||||
|
p = cond.replace('count(', '').split(')')
|
||||||
|
key, val = p[0].split('=')
|
||||||
|
count = sum(1 for e in entries if e.get(key) == val)
|
||||||
|
return eval(f"{count}{p[1]}")
|
||||||
|
return False
|
||||||
6
nexus/mnemosyne/rules.json
Normal file
6
nexus/mnemosyne/rules.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"condition": "count(type=anomaly)>3",
|
||||||
|
"action": "alert"
|
||||||
|
}
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user