Files
Florian Hartmann b83546d833 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.
2026-06-03 22:51:50 +00:00

97 lines
3.2 KiB
Python

"""RelationStore — Relationen-Management für Tier 2."""
import sqlite3
import time
import uuid as uuid_mod
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class Relation:
uuid: str
from_entity_id: str
to_entity_id: str
relation_type: str
strength: float
evidence_fact_id: Optional[str]
created_at: float
updated_at: float
class RelationStore:
def __init__(self, conn: sqlite3.Connection):
self.conn = conn
def link(
self,
from_entity_id: str,
to_entity_id: str,
relation_type: str,
strength: float = 1.0,
evidence_fact_id: Optional[str] = None,
) -> Relation:
existing = self.conn.execute(
"SELECT uuid FROM relations WHERE from_entity_id = ? AND to_entity_id = ? AND relation_type = ?",
(from_entity_id, to_entity_id, relation_type),
).fetchone()
now = time.time()
if existing:
self.conn.execute(
"UPDATE relations SET strength = MAX(strength, ?), updated_at = ? WHERE uuid = ?",
(strength, now, existing["uuid"]),
)
self.conn.commit()
return self.get_by_uuid(existing["uuid"])
rel_uuid = str(uuid_mod.uuid4())
self.conn.execute(
"""
INSERT INTO relations (uuid, from_entity_id, to_entity_id, relation_type, strength, evidence_fact_id, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""",
(rel_uuid, from_entity_id, to_entity_id, relation_type, strength, evidence_fact_id, now, now),
)
self.conn.commit()
return self.get_by_uuid(rel_uuid)
def get_by_uuid(self, rel_uuid: str) -> Optional[Relation]:
row = self.conn.execute("SELECT * FROM relations WHERE uuid = ? LIMIT 1", (rel_uuid,)).fetchone()
return self._row_to_relation(row) if row else None
def query(
self,
from_entity_id: Optional[str] = None,
to_entity_id: Optional[str] = None,
relation_type: Optional[str] = None,
limit: int = 50,
) -> List[Relation]:
sql = "SELECT * FROM relations WHERE 1=1"
params: List = []
if from_entity_id:
sql += " AND from_entity_id = ?"
params.append(from_entity_id)
if to_entity_id:
sql += " AND to_entity_id = ?"
params.append(to_entity_id)
if relation_type:
sql += " AND relation_type = ?"
params.append(relation_type)
sql += " ORDER BY strength DESC, updated_at DESC LIMIT ?"
params.append(limit)
rows = self.conn.execute(sql, params).fetchall()
return [self._row_to_relation(r) for r in rows]
def _row_to_relation(self, row: sqlite3.Row) -> Relation:
return Relation(
uuid=row["uuid"],
from_entity_id=row["from_entity_id"],
to_entity_id=row["to_entity_id"],
relation_type=row["relation_type"],
strength=row["strength"],
evidence_fact_id=row["evidence_fact_id"],
created_at=row["created_at"],
updated_at=row["updated_at"],
)