Add AI Council architecture: Tier 2/3/Graph implementation + Integration Plan
Architecture (Agent 1):
- hermes_memory/tier2/{schema,facts,entities,relations,timeline}.py
- hermes_memory/tier3/{backend,chroma_backend,embedder}.py
- hermes_memory/graph/nx_store.py
- hermes_memory/api/memory_api.py (unified API)
- hermes_memory/cron/{consolidate,embed_queue,graph_refresh,prune}.py
- hermes_memory/config.py + pyproject.toml
Integration Plan (Agent 3):
- INTEGRATION_PLAN.md: Memory Provider Plugin strategy
- Hermes Core needs minimal changes
- sync_turn() + prefetch() hooks
- Skills integration via nextlevel_search/remember
Auto-Extraction (Agent 2):
- ARCHITECTURE.md: Full extraction pipeline docs
- Chunking, Pre-Filter, LLM Prompts, Classification
- Entity-Linking, Temporal Reasoning, Deduplication
All files: Python syntax checked, ECC standards applied.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
"""Cron-Jobs für Hermes Memory Maintenance."""
|
||||
|
||||
from hermes_memory.cron.consolidate import run_consolidate
|
||||
from hermes_memory.cron.embed_queue import run_embed_queue
|
||||
from hermes_memory.cron.graph_refresh import run_graph_refresh
|
||||
from hermes_memory.cron.prune import run_prune
|
||||
|
||||
__all__ = ["run_consolidate", "run_embed_queue", "run_graph_refresh", "run_prune"]
|
||||
@@ -0,0 +1,14 @@
|
||||
"""Fakten-Deduplizierung & Konflikt-Auflösung."""
|
||||
|
||||
import logging
|
||||
from hermes_memory.api.memory_api import MemoryAPI
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def run_consolidate(profile: str = "default") -> dict:
|
||||
"""Führt Deduplizierung und Maintenance aus."""
|
||||
api = MemoryAPI(profile=profile)
|
||||
result = api.consolidate()
|
||||
logger.info("Consolidation complete: %s", result)
|
||||
return result
|
||||
@@ -0,0 +1,45 @@
|
||||
"""Embedding-Job-Queue für Tier 3."""
|
||||
|
||||
import logging
|
||||
import time
|
||||
from hermes_memory.api.memory_api import MemoryAPI
|
||||
from hermes_memory.tier2.schema import connect
|
||||
from hermes_memory.config import load_config
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def run_embed_queue(profile: str = "default", batch_size: int = 50) -> dict:
|
||||
"""Verarbeitet pending Embeddings aus der Queue."""
|
||||
config = load_config(profile)
|
||||
db_path = Path(config["tier2"]["db_path"].format(
|
||||
HERMES_HOME=Path.home() / ".hermes",
|
||||
profile=profile,
|
||||
))
|
||||
conn = connect(db_path)
|
||||
rows = conn.execute(
|
||||
"SELECT id, fact_id, content, source_type, session_id, message_id FROM embedding_queue WHERE processed = 0 ORDER BY queued_at LIMIT ?",
|
||||
(batch_size,),
|
||||
).fetchall()
|
||||
|
||||
if not rows:
|
||||
return {"processed": 0}
|
||||
|
||||
api = MemoryAPI(profile=profile)
|
||||
processed = 0
|
||||
for row in rows:
|
||||
try:
|
||||
api.semantic_index(
|
||||
text=row["content"],
|
||||
source_type=row["source_type"],
|
||||
session_id=row["session_id"],
|
||||
message_id=row["message_id"],
|
||||
)
|
||||
conn.execute("UPDATE embedding_queue SET processed = 1 WHERE id = ?", (row["id"],))
|
||||
processed += 1
|
||||
except Exception as e:
|
||||
logger.error("Embedding failed for queue id %s: %s", row["id"], e)
|
||||
|
||||
conn.commit()
|
||||
return {"processed": processed}
|
||||
@@ -0,0 +1,14 @@
|
||||
"""Graph-Rebuild Job."""
|
||||
|
||||
import logging
|
||||
from hermes_memory.api.memory_api import MemoryAPI
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def run_graph_refresh(profile: str = "default") -> dict:
|
||||
"""Baut Knowledge Graph aus Tier 2 neu auf."""
|
||||
api = MemoryAPI(profile=profile)
|
||||
result = api.graph_rebuild()
|
||||
logger.info("Graph refresh complete: %s", result)
|
||||
return result
|
||||
@@ -0,0 +1,40 @@
|
||||
"""Prune — Alte/archivierte Daten entfernen."""
|
||||
|
||||
import logging
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from hermes_memory.config import load_config
|
||||
from hermes_memory.tier2.schema import connect
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def run_prune(profile: str = "default") -> dict:
|
||||
"""Entfernt archivierte Fakten und alte Embeddings."""
|
||||
config = load_config(profile)
|
||||
db_path = Path(config["tier2"]["db_path"].format(
|
||||
HERMES_HOME=Path.home() / ".hermes",
|
||||
profile=profile,
|
||||
))
|
||||
conn = connect(db_path)
|
||||
now = time.time()
|
||||
ttl = config["limits"]["fact_ttl_days"] * 86400
|
||||
|
||||
# Archivierte Fakten älter als TTL löschen
|
||||
cur = conn.execute(
|
||||
"DELETE FROM facts WHERE is_archived = 1 AND updated_at < ?",
|
||||
(now - ttl,),
|
||||
)
|
||||
deleted_facts = cur.rowcount
|
||||
|
||||
# Verarbeitete Queue-Einträge älter als 7 Tage löschen
|
||||
cur = conn.execute(
|
||||
"DELETE FROM embedding_queue WHERE processed = 1 AND queued_at < ?",
|
||||
(now - 7 * 86400,),
|
||||
)
|
||||
deleted_queue = cur.rowcount
|
||||
|
||||
conn.commit()
|
||||
logger.info("Pruned %s facts, %s queue entries", deleted_facts, deleted_queue)
|
||||
return {"deleted_facts": deleted_facts, "deleted_queue": deleted_queue}
|
||||
Reference in New Issue
Block a user