MemPalace: palace architecture, AAAK compression, knowledge graph
The memory system: - Palace structure: Wings (people/projects) → Rooms (topics) → Closets (AAAK compressed) → Drawers (verbatim transcripts) - Halls connect related rooms within a wing - Tunnels cross-reference rooms across wings - AAAK: 30x lossless compression dialect for AI agents - Knowledge graph: temporal entity-relationship triples (SQLite) - Palace graph: room-based navigation with tunnel detection - MCP server: 19 tools — search, graph traversal, agent diary, AAAK auto-teach - Onboarding: guided setup generates wing config + AAAK entity registry - Contradiction detection: catches wrong pronouns, names, ages - Auto-save hooks for Claude Code 96.6% Recall@5 on LongMemEval — highest zero-API score published. 100% with optional Haiku rerank (500/500). Local. Free. No API key required.
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
"""
|
||||
MemPalace configuration system.
|
||||
|
||||
Priority: env vars > config file (~/.mempalace/config.json) > defaults
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
DEFAULT_PALACE_PATH = os.path.expanduser("~/.mempalace/palace")
|
||||
DEFAULT_COLLECTION_NAME = "mempalace_drawers"
|
||||
|
||||
DEFAULT_TOPIC_WINGS = [
|
||||
"emotions",
|
||||
"consciousness",
|
||||
"memory",
|
||||
"technical",
|
||||
"identity",
|
||||
"family",
|
||||
"creative",
|
||||
]
|
||||
|
||||
DEFAULT_HALL_KEYWORDS = {
|
||||
"emotions": [
|
||||
"scared",
|
||||
"afraid",
|
||||
"worried",
|
||||
"happy",
|
||||
"sad",
|
||||
"love",
|
||||
"hate",
|
||||
"feel",
|
||||
"cry",
|
||||
"tears",
|
||||
],
|
||||
"consciousness": [
|
||||
"consciousness",
|
||||
"conscious",
|
||||
"aware",
|
||||
"real",
|
||||
"genuine",
|
||||
"soul",
|
||||
"exist",
|
||||
"alive",
|
||||
],
|
||||
"memory": ["memory", "remember", "forget", "recall", "archive", "palace", "store"],
|
||||
"technical": [
|
||||
"code",
|
||||
"python",
|
||||
"script",
|
||||
"bug",
|
||||
"error",
|
||||
"function",
|
||||
"api",
|
||||
"database",
|
||||
"server",
|
||||
],
|
||||
"identity": ["identity", "name", "who am i", "persona", "self"],
|
||||
"family": ["family", "kids", "children", "daughter", "son", "parent", "mother", "father"],
|
||||
"creative": ["game", "gameplay", "player", "app", "design", "art", "music", "story"],
|
||||
}
|
||||
|
||||
|
||||
class MempalaceConfig:
|
||||
"""Configuration manager for MemPalace.
|
||||
|
||||
Load order: env vars > config file > defaults.
|
||||
"""
|
||||
|
||||
def __init__(self, config_dir=None):
|
||||
"""Initialize config.
|
||||
|
||||
Args:
|
||||
config_dir: Override config directory (useful for testing).
|
||||
Defaults to ~/.mempalace.
|
||||
"""
|
||||
self._config_dir = (
|
||||
Path(config_dir) if config_dir else Path(os.path.expanduser("~/.mempalace"))
|
||||
)
|
||||
self._config_file = self._config_dir / "config.json"
|
||||
self._people_map_file = self._config_dir / "people_map.json"
|
||||
self._file_config = {}
|
||||
|
||||
if self._config_file.exists():
|
||||
try:
|
||||
with open(self._config_file, "r") as f:
|
||||
self._file_config = json.load(f)
|
||||
except (json.JSONDecodeError, OSError):
|
||||
self._file_config = {}
|
||||
|
||||
@property
|
||||
def palace_path(self):
|
||||
"""Path to the memory palace data directory."""
|
||||
env_val = os.environ.get("MEMPALACE_PALACE_PATH") or os.environ.get("MEMPAL_PALACE_PATH")
|
||||
if env_val:
|
||||
return env_val
|
||||
return self._file_config.get("palace_path", DEFAULT_PALACE_PATH)
|
||||
|
||||
@property
|
||||
def collection_name(self):
|
||||
"""ChromaDB collection name."""
|
||||
return self._file_config.get("collection_name", DEFAULT_COLLECTION_NAME)
|
||||
|
||||
@property
|
||||
def people_map(self):
|
||||
"""Mapping of name variants to canonical names."""
|
||||
if self._people_map_file.exists():
|
||||
try:
|
||||
with open(self._people_map_file, "r") as f:
|
||||
return json.load(f)
|
||||
except (json.JSONDecodeError, OSError):
|
||||
pass
|
||||
return self._file_config.get("people_map", {})
|
||||
|
||||
@property
|
||||
def topic_wings(self):
|
||||
"""List of topic wing names."""
|
||||
return self._file_config.get("topic_wings", DEFAULT_TOPIC_WINGS)
|
||||
|
||||
@property
|
||||
def hall_keywords(self):
|
||||
"""Mapping of hall names to keyword lists."""
|
||||
return self._file_config.get("hall_keywords", DEFAULT_HALL_KEYWORDS)
|
||||
|
||||
def init(self):
|
||||
"""Create config directory and write default config.json if it doesn't exist."""
|
||||
self._config_dir.mkdir(parents=True, exist_ok=True)
|
||||
if not self._config_file.exists():
|
||||
default_config = {
|
||||
"palace_path": DEFAULT_PALACE_PATH,
|
||||
"collection_name": DEFAULT_COLLECTION_NAME,
|
||||
"topic_wings": DEFAULT_TOPIC_WINGS,
|
||||
"hall_keywords": DEFAULT_HALL_KEYWORDS,
|
||||
}
|
||||
with open(self._config_file, "w") as f:
|
||||
json.dump(default_config, f, indent=2)
|
||||
return self._config_file
|
||||
|
||||
def save_people_map(self, people_map):
|
||||
"""Write people_map.json to config directory.
|
||||
|
||||
Args:
|
||||
people_map: Dict mapping name variants to canonical names.
|
||||
"""
|
||||
self._config_dir.mkdir(parents=True, exist_ok=True)
|
||||
with open(self._people_map_file, "w") as f:
|
||||
json.dump(people_map, f, indent=2)
|
||||
return self._people_map_file
|
||||
Reference in New Issue
Block a user