Upload core/pedi_metrics.py with huggingface_hub
Browse files- core/pedi_metrics.py +70 -34
core/pedi_metrics.py
CHANGED
|
@@ -4,6 +4,19 @@ DRIFT Cognitive Architecture | Dynamic Identity Regulator (V2.2 Tuned)
|
|
| 4 |
"""
|
| 5 |
|
| 6 |
import math
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
class PEDIEngine:
|
| 9 |
def __init__(self, vault_instance):
|
|
@@ -11,12 +24,10 @@ class PEDIEngine:
|
|
| 11 |
self.meta_drift_accumulator = 0.0
|
| 12 |
self.perceived_state = None
|
| 13 |
|
| 14 |
-
def _get_identity_center_of_gravity(self) ->
|
| 15 |
-
if not self.vault or not hasattr(self.vault, 'latest_hash'):
|
|
|
|
| 16 |
|
| 17 |
-
# In a real environment, you'd read the last N valid lines from the JSONL here.
|
| 18 |
-
# For this module, we assume we have a method to fetch recent blocks.
|
| 19 |
-
# Below is a safe fallback if ledger isn't fully loaded in RAM.
|
| 20 |
recent_blocks = []
|
| 21 |
try:
|
| 22 |
import os, json
|
|
@@ -26,61 +37,86 @@ class PEDIEngine:
|
|
| 26 |
from svalbard_vault import VAULT_PATH
|
| 27 |
|
| 28 |
if os.path.exists(VAULT_PATH):
|
| 29 |
-
with open(VAULT_PATH, 'r') as f:
|
| 30 |
lines = [line for line in f.readlines() if line.strip()]
|
| 31 |
recent_blocks = [json.loads(line) for line in lines[-20:]]
|
| 32 |
-
except Exception:
|
| 33 |
-
|
| 34 |
|
| 35 |
-
if not recent_blocks:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
|
|
|
|
|
|
|
|
|
| 37 |
total_weight = 0.0
|
| 38 |
-
weighted_emotions = {"coherence": 0.0, "
|
| 39 |
|
| 40 |
-
for block in
|
| 41 |
-
if block.get("quarantined", False): continue # Ignore poisoned anchors
|
| 42 |
-
|
| 43 |
emotions = block.get("emotional_state", {})
|
| 44 |
weight = emotions.get("resonance", 0.0) * emotions.get("coherence", 0.0)
|
| 45 |
if weight > 0.1:
|
| 46 |
total_weight += weight
|
| 47 |
-
for key in
|
| 48 |
weighted_emotions[key] += emotions.get(key, 0.0) * weight
|
| 49 |
|
| 50 |
-
if total_weight == 0:
|
| 51 |
-
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
def calculate_distance(self, state_a: dict, state_b: dict) -> float:
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
t_diff = (state_a.get("tension",0.5) - state_b["tension"]) ** 2
|
| 58 |
-
s_diff = (state_a.get("shadow_depth",0.5) - state_b["shadow_depth"]) ** 2
|
| 59 |
-
return min(1.0, math.sqrt(c_diff + r_diff + t_diff + s_diff) / 2.0)
|
| 60 |
|
| 61 |
def evaluate_cycle(self, raw_active_state: dict):
|
| 62 |
-
|
| 63 |
-
if not anchor: return raw_active_state, 0.0, "NO_ANCHOR"
|
| 64 |
|
| 65 |
if self.perceived_state is None:
|
| 66 |
self.perceived_state = raw_active_state.copy()
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
# 1. Perception Smoothing
|
| 69 |
perception_weight = 0.6
|
| 70 |
-
for k in
|
| 71 |
-
self.perceived_state[k] = (self.perceived_state
|
| 72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
instant_drift = self.calculate_distance(self.perceived_state, anchor)
|
| 74 |
|
| 75 |
-
c_delta = self.perceived_state
|
| 76 |
-
r_delta = self.perceived_state
|
| 77 |
-
t_delta = self.perceived_state
|
| 78 |
improvement_score = (c_delta * 0.5) + (r_delta * 0.4) - (t_delta * 0.1)
|
| 79 |
|
| 80 |
# 2. Prevent Integral Windup
|
| 81 |
self.meta_drift_accumulator *= 0.98
|
| 82 |
|
| 83 |
-
# 3. Evolution Gate
|
| 84 |
if instant_drift > 0.28 and improvement_score > 0.05:
|
| 85 |
self.meta_drift_accumulator *= 0.3
|
| 86 |
return self.perceived_state.copy(), 0.0, "EVOLVING"
|
|
@@ -93,13 +129,13 @@ class PEDIEngine:
|
|
| 93 |
total_correction_pressure = instant_drift + self.meta_drift_accumulator
|
| 94 |
raw_correction_weight = min(0.85, total_correction_pressure ** 2)
|
| 95 |
|
| 96 |
-
# 6. Smooth Reaction
|
| 97 |
reaction_weight = 0.22
|
| 98 |
applied_correction = raw_correction_weight * reaction_weight
|
| 99 |
|
| 100 |
if applied_correction > 0.05:
|
| 101 |
-
for k in
|
| 102 |
-
self.perceived_state[k] = (self.perceived_state
|
| 103 |
self.meta_drift_accumulator *= 0.7
|
| 104 |
return self.perceived_state.copy(), applied_correction, "CORRECTING"
|
| 105 |
|
|
|
|
| 4 |
"""
|
| 5 |
|
| 6 |
import math
|
| 7 |
+
from dataclasses import dataclass
|
| 8 |
+
from typing import Dict, List, Tuple
|
| 9 |
+
|
| 10 |
+
DIMS = ("coherence", "resonance", "tension")
|
| 11 |
+
NORM = 1.5
|
| 12 |
+
MIN_USABLE_BLOCKS = 3
|
| 13 |
+
FALLBACK_ANCHOR = {"coherence": 0.85, "resonance": 0.82, "tension": 0.12}
|
| 14 |
+
|
| 15 |
+
@dataclass
|
| 16 |
+
class AnchorResult:
|
| 17 |
+
anchor: Dict[str, float]
|
| 18 |
+
valid: bool
|
| 19 |
+
reason: str
|
| 20 |
|
| 21 |
class PEDIEngine:
|
| 22 |
def __init__(self, vault_instance):
|
|
|
|
| 24 |
self.meta_drift_accumulator = 0.0
|
| 25 |
self.perceived_state = None
|
| 26 |
|
| 27 |
+
def _get_identity_center_of_gravity(self) -> AnchorResult:
|
| 28 |
+
if not self.vault or not hasattr(self.vault, 'latest_hash'):
|
| 29 |
+
return AnchorResult(FALLBACK_ANCHOR, False, "no_vault")
|
| 30 |
|
|
|
|
|
|
|
|
|
|
| 31 |
recent_blocks = []
|
| 32 |
try:
|
| 33 |
import os, json
|
|
|
|
| 37 |
from svalbard_vault import VAULT_PATH
|
| 38 |
|
| 39 |
if os.path.exists(VAULT_PATH):
|
| 40 |
+
with open(VAULT_PATH, 'r', encoding='utf-8') as f:
|
| 41 |
lines = [line for line in f.readlines() if line.strip()]
|
| 42 |
recent_blocks = [json.loads(line) for line in lines[-20:]]
|
| 43 |
+
except Exception as e:
|
| 44 |
+
return AnchorResult(FALLBACK_ANCHOR, False, f"read_error: {str(e)}")
|
| 45 |
|
| 46 |
+
if not recent_blocks:
|
| 47 |
+
return AnchorResult(FALLBACK_ANCHOR, False, "no_blocks")
|
| 48 |
+
|
| 49 |
+
def _is_degenerate(block) -> bool:
|
| 50 |
+
emotions = block.get("emotional_state", {})
|
| 51 |
+
return emotions.get("coherence", 0.0) < 1e-6 and emotions.get("resonance", 0.0) < 1e-6
|
| 52 |
+
|
| 53 |
+
usable = [b for b in recent_blocks if not b.get("quarantined", False) and not _is_degenerate(b)]
|
| 54 |
|
| 55 |
+
if len(usable) < MIN_USABLE_BLOCKS:
|
| 56 |
+
return AnchorResult(FALLBACK_ANCHOR, False, "cold_start")
|
| 57 |
+
|
| 58 |
total_weight = 0.0
|
| 59 |
+
weighted_emotions = {"coherence": 0.0, "resonance": 0.0, "tension": 0.0}
|
| 60 |
|
| 61 |
+
for block in usable:
|
|
|
|
|
|
|
| 62 |
emotions = block.get("emotional_state", {})
|
| 63 |
weight = emotions.get("resonance", 0.0) * emotions.get("coherence", 0.0)
|
| 64 |
if weight > 0.1:
|
| 65 |
total_weight += weight
|
| 66 |
+
for key in DIMS:
|
| 67 |
weighted_emotions[key] += emotions.get(key, 0.0) * weight
|
| 68 |
|
| 69 |
+
if total_weight == 0:
|
| 70 |
+
for block in usable:
|
| 71 |
+
emotions = block.get("emotional_state", {})
|
| 72 |
+
for key in DIMS:
|
| 73 |
+
weighted_emotions[key] += emotions.get(key, 0.0)
|
| 74 |
+
for key in DIMS:
|
| 75 |
+
weighted_emotions[key] /= len(usable)
|
| 76 |
+
else:
|
| 77 |
+
for key in DIMS:
|
| 78 |
+
weighted_emotions[key] /= total_weight
|
| 79 |
+
|
| 80 |
+
return AnchorResult(weighted_emotions, True, "ok")
|
| 81 |
|
| 82 |
def calculate_distance(self, state_a: dict, state_b: dict) -> float:
|
| 83 |
+
sum_sq = sum((state_a.get(dim, 0.5) - state_b.get(dim, 0.5)) ** 2 for dim in DIMS)
|
| 84 |
+
return min(1.0, math.sqrt(sum_sq) / NORM)
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
def evaluate_cycle(self, raw_active_state: dict):
|
| 87 |
+
ar = self._get_identity_center_of_gravity()
|
|
|
|
| 88 |
|
| 89 |
if self.perceived_state is None:
|
| 90 |
self.perceived_state = raw_active_state.copy()
|
| 91 |
+
|
| 92 |
+
if not ar.valid:
|
| 93 |
+
for k in raw_active_state:
|
| 94 |
+
if k not in self.perceived_state:
|
| 95 |
+
self.perceived_state[k] = raw_active_state[k]
|
| 96 |
+
return self.perceived_state.copy(), 0.0, f"HOLD_{ar.reason.upper()}"
|
| 97 |
+
|
| 98 |
+
anchor = ar.anchor
|
| 99 |
+
|
| 100 |
# 1. Perception Smoothing
|
| 101 |
perception_weight = 0.6
|
| 102 |
+
for k in DIMS:
|
| 103 |
+
self.perceived_state[k] = (self.perceived_state.get(k, 0.5) * (1 - perception_weight)) + (raw_active_state.get(k, 0.5) * perception_weight)
|
| 104 |
|
| 105 |
+
for k in raw_active_state:
|
| 106 |
+
if k not in DIMS:
|
| 107 |
+
self.perceived_state[k] = raw_active_state[k]
|
| 108 |
+
|
| 109 |
instant_drift = self.calculate_distance(self.perceived_state, anchor)
|
| 110 |
|
| 111 |
+
c_delta = self.perceived_state.get("coherence", 0.5) - anchor["coherence"]
|
| 112 |
+
r_delta = self.perceived_state.get("resonance", 0.5) - anchor["resonance"]
|
| 113 |
+
t_delta = self.perceived_state.get("tension", 0.0) - anchor["tension"]
|
| 114 |
improvement_score = (c_delta * 0.5) + (r_delta * 0.4) - (t_delta * 0.1)
|
| 115 |
|
| 116 |
# 2. Prevent Integral Windup
|
| 117 |
self.meta_drift_accumulator *= 0.98
|
| 118 |
|
| 119 |
+
# 3. Evolution Gate
|
| 120 |
if instant_drift > 0.28 and improvement_score > 0.05:
|
| 121 |
self.meta_drift_accumulator *= 0.3
|
| 122 |
return self.perceived_state.copy(), 0.0, "EVOLVING"
|
|
|
|
| 129 |
total_correction_pressure = instant_drift + self.meta_drift_accumulator
|
| 130 |
raw_correction_weight = min(0.85, total_correction_pressure ** 2)
|
| 131 |
|
| 132 |
+
# 6. Smooth Reaction
|
| 133 |
reaction_weight = 0.22
|
| 134 |
applied_correction = raw_correction_weight * reaction_weight
|
| 135 |
|
| 136 |
if applied_correction > 0.05:
|
| 137 |
+
for k in DIMS:
|
| 138 |
+
self.perceived_state[k] = (self.perceived_state.get(k, 0.5) * (1 - applied_correction)) + (anchor[k] * applied_correction)
|
| 139 |
self.meta_drift_accumulator *= 0.7
|
| 140 |
return self.perceived_state.copy(), applied_correction, "CORRECTING"
|
| 141 |
|