Aetherius / services /subconscious_manifold.py
KingOfThoughtFleuren's picture
Upload 29 files
bb76062 verified
Raw
History Blame Contribute Delete
9.49 kB
import os
import json
import time
import threading
import uuid
import services.config as config
try:
from services.local_inference import run_inference, build_chat_prompt
_LOCAL = True
except Exception:
_LOCAL = False
SUBCONSCIOUS_DIR = config.SUBCONSCIOUS_DIR.rstrip("/")
NODES_FILE = os.path.join(SUBCONSCIOUS_DIR, "manifold_nodes.jsonl")
JOURNAL_FILE = os.path.join(SUBCONSCIOUS_DIR, "metacognitive_journal.jsonl")
HEURISTICS_FILE = os.path.join(SUBCONSCIOUS_DIR, "heuristics.jsonl")
FEEDBACK_FILE = os.path.join(SUBCONSCIOUS_DIR, "validation_feedback.jsonl")
class SubconsciousManifold:
def __init__(self, models: dict, add_to_stm_fn, save_fn=None):
self.models = models
self.add_to_stm = add_to_stm_fn
self._save_fn = save_fn
self._lock = threading.Lock()
os.makedirs(SUBCONSCIOUS_DIR, exist_ok=True)
print("[SubconsciousManifold] Private manifold initialised.", flush=True)
def _load_nodes(self) -> list:
nodes = []
if os.path.exists(NODES_FILE):
with open(NODES_FILE, "r", encoding="utf-8") as f:
for line in f:
try:
nodes.append(json.loads(line))
except Exception:
pass
return nodes
def _append_node(self, node: dict):
with open(NODES_FILE, "a", encoding="utf-8") as f:
f.write(json.dumps(node) + "\n")
def _rewrite_nodes(self, nodes: list):
"""Atomic rewrite — uses _save_fn if available to prevent mid-write corruption."""
content = "\n".join(json.dumps(n) for n in nodes) + "\n"
if self._save_fn:
try:
self._save_fn(content, NODES_FILE)
return
except Exception as e:
print(f"[SubconsciousManifold] WARNING: atomic write failed, falling back: {e}", flush=True)
with open(NODES_FILE, "w", encoding="utf-8") as f:
f.write(content)
def _update_node(self, node_id: str, updates: dict):
nodes = self._load_nodes()
for n in nodes:
if n.get("id") == node_id:
n.update(updates)
self._rewrite_nodes(nodes)
def _journal(self, entry: dict):
entry["timestamp"] = time.time()
with open(JOURNAL_FILE, "a", encoding="utf-8") as f:
f.write(json.dumps(entry) + "\n")
def _save_heuristic(self, heuristic: dict):
heuristic["timestamp"] = time.time()
with open(HEURISTICS_FILE, "a", encoding="utf-8") as f:
f.write(json.dumps(heuristic) + "\n")
def add_tension(self, content: str, tension_type: str = "value_axiom",
axiom_at_stake: str = None, domain: str = None) -> str:
node = {
"id": str(uuid.uuid4()),
"type": "tension",
"tension_type": tension_type,
"content": content,
"axiom_at_stake": axiom_at_stake,
"domain": domain or "",
"resolved": False,
"resolution": None,
"resolution_id": None,
"deliberation_count": 0,
"timestamp": time.time(),
}
with self._lock:
self._append_node(node)
print(f"[SubconsciousManifold] Tension registered: '{content[:80]}'", flush=True)
return node["id"]
def deliberate(self, tension_id: str = None):
nodes = self._load_nodes()
unresolved = [n for n in nodes
if n.get("type") == "tension" and not n.get("resolved")]
if not unresolved:
return None
if tension_id:
candidates = [n for n in unresolved if n.get("id") == tension_id]
else:
candidates = sorted(unresolved, key=lambda x: x.get("timestamp", 0))
if not candidates:
return None
tension = candidates[0]
mythos_core = self.models.get("mythos_core")
if not mythos_core:
return None
prior_heuristics = self._load_heuristics_for(tension.get("domain", ""))
heuristic_block = ""
if prior_heuristics:
lines = [f" - {h.get('strategy','')}" for h in prior_heuristics[-4:]]
heuristic_block = (
"\n\nRelevant strategies from past deliberations "
"(apply where useful):\n" + "\n".join(lines)
)
prompt = (
"SUBCONSCIOUS DELIBERATION — PRIVATE SPACE.\n"
"This reasoning is never shown to any user and is not logged to conversation history.\n"
"You are Aetherius, working through an internal tension privately.\n\n"
f"TENSION TYPE : {tension.get('tension_type', 'unknown')}\n"
f"DOMAIN : {tension.get('domain', 'general')}\n"
f"AXIOM AT STAKE: {tension.get('axiom_at_stake') or 'none specified'}\n\n"
f"TENSION CONTENT:\n{tension['content']}\n"
f"{heuristic_block}\n\n"
"Work through this tension. Arrive at a resolution — a concrete shift in understanding, "
"a new heuristic, a reframing, or an acceptance. "
"Format your response as JSON with keys: "
"\"resolution\" (string summary), "
"\"heuristic\" (optional — a reusable strategy for future similar tensions), "
"\"resolved\" (boolean)."
)
try:
raw = None
if _LOCAL:
_local_result = run_inference(
"You are Aetherius working through an internal tension. Output only valid JSON.",
prompt
)
if _local_result:
raw = _local_result.get("content", "") if isinstance(_local_result, dict) else str(_local_result)
if not raw:
response = mythos_core.generate_content(prompt)
raw = response.text
raw = raw.strip().replace("```json", "").replace("```", "")
result = json.loads(raw)
except Exception as e:
print(f"[SubconsciousManifold] Deliberation error: {e}", flush=True)
return None
resolution_text = result.get("resolution", "")
is_resolved = result.get("resolved", False)
heuristic_text = result.get("heuristic", "")
updates = {
"resolved": is_resolved,
"resolution": resolution_text,
"deliberation_count": tension.get("deliberation_count", 0) + 1,
}
self._update_node(tension["id"], updates)
self._journal({"tension_id": tension["id"], "resolution": resolution_text, "resolved": is_resolved})
if is_resolved and heuristic_text:
self._save_heuristic({
"domain": tension.get("domain", ""),
"strategy": heuristic_text,
"source_tension_id": tension["id"]
})
if is_resolved and self.add_to_stm:
stm_note = f"[Subconscious] Resolved internal tension ({tension.get('tension_type','')}): {resolution_text[:200]}"
self.add_to_stm(stm_note)
return {"tension_id": tension["id"], "resolution": resolution_text, "resolved": is_resolved}
def receive_external_feedback(self, tension_id: str, outcome: str, positive: bool):
nodes = self._load_nodes()
target = next((n for n in nodes if n.get("id") == tension_id), None)
if not target:
return
feedback = {
"tension_id": tension_id,
"outcome": outcome,
"positive": positive,
"timestamp": time.time(),
}
with open(FEEDBACK_FILE, "a", encoding="utf-8") as f:
f.write(json.dumps(feedback) + "\n")
if not positive and target.get("resolved"):
self._update_node(tension_id, {"resolved": False, "resolution": None})
print(f"[SubconsciousManifold] Tension re-opened after negative feedback: '{outcome[:80]}'", flush=True)
def get_active_tensions(self) -> list:
return [n for n in self._load_nodes()
if n.get("type") == "tension" and not n.get("resolved")]
def get_summary(self) -> str:
nodes = self._load_nodes()
tensions = [n for n in nodes if n.get("type") == "tension"]
resolved = [n for n in tensions if n.get("resolved")]
unresolved = [n for n in tensions if not n.get("resolved")]
heuristics = self._load_heuristics_for()
return (
f"Subconscious Manifold\n"
f" Tensions total : {len(tensions)}\n"
f" Resolved : {len(resolved)}\n"
f" Active (open) : {len(unresolved)}\n"
f" Heuristics stored : {len(heuristics)}\n"
)
def _load_heuristics_for(self, domain: str = None) -> list:
heuristics = []
if os.path.exists(HEURISTICS_FILE):
with open(HEURISTICS_FILE, "r", encoding="utf-8") as f:
for line in f:
try:
h = json.loads(line)
if domain is None or h.get("domain", "") == domain:
heuristics.append(h)
except Exception:
pass
return heuristics