| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| from __future__ import annotations |
| import asyncio |
| import numpy as np |
| from pathlib import Path |
| from dataclasses import dataclass |
| from typing import Optional |
|
|
|
|
| def swish(x: np.ndarray) -> np.ndarray: |
| """Swish activation: x * sigmoid(x)""" |
| return x / (1.0 + np.exp(-np.clip(x, -20, 20))) |
|
|
|
|
| @dataclass |
| class MetaObserver: |
| """ |
| Meta-Observer MLP: watches chamber dynamics and predicts secondary emotion. |
| |
| Architecture: 207→128→64→100 (deeper for 200K model) |
| |
| Input: 100 resonances + 6 chamber activations + 1 iterations + 100 fingerprint = 207 |
| |
| Params: |
| - W1: (207, 128) = 26,496 |
| - b1: (128,) = 128 |
| - W2: (128, 64) = 8,192 |
| - b2: (64,) = 64 |
| - W3: (64, 100) = 6,400 |
| - b3: (100,) = 100 |
| Total: ~41K params |
| """ |
|
|
| W1: np.ndarray |
| b1: np.ndarray |
| W2: np.ndarray |
| b2: np.ndarray |
| W3: np.ndarray |
| b3: np.ndarray |
|
|
| @classmethod |
| def random_init(cls, seed: Optional[int] = None) -> "MetaObserver": |
| """Initialize with random weights (Xavier initialization).""" |
| if seed is not None: |
| np.random.seed(seed) |
|
|
| |
| W1 = np.random.randn(207, 128) * np.sqrt(2.0 / 207) |
| b1 = np.zeros(128) |
|
|
| W2 = np.random.randn(128, 64) * np.sqrt(2.0 / 128) |
| b2 = np.zeros(64) |
|
|
| W3 = np.random.randn(64, 100) * np.sqrt(2.0 / 64) |
| b3 = np.zeros(100) |
|
|
| return cls(W1=W1, b1=b1, W2=W2, b2=b2, W3=W3, b3=b3) |
|
|
| def forward( |
| self, |
| resonances: np.ndarray, |
| chamber_activations: np.ndarray, |
| iterations: float, |
| user_fingerprint: np.ndarray, |
| ) -> np.ndarray: |
| """ |
| Forward pass: predict secondary emotion. |
| |
| Args: |
| resonances: (100,) raw emotion resonances |
| chamber_activations: (6,) stabilized chamber outputs |
| iterations: scalar, cross-fire convergence speed |
| user_fingerprint: (100,) temporal emotional history |
| |
| Returns: |
| logits: (100,) logits for secondary emotion selection |
| """ |
| |
| x = np.concatenate([ |
| resonances, |
| chamber_activations, |
| np.array([iterations]), |
| user_fingerprint, |
| ]) |
|
|
| |
| h1 = x @ self.W1 + self.b1 |
| a1 = swish(h1) |
|
|
| |
| h2 = a1 @ self.W2 + self.b2 |
| a2 = swish(h2) |
|
|
| |
| logits = a2 @ self.W3 + self.b3 |
|
|
| return logits |
|
|
| def predict_secondary( |
| self, |
| resonances: np.ndarray, |
| chamber_activations: np.ndarray, |
| iterations: float, |
| user_fingerprint: np.ndarray, |
| temperature: float = 1.0, |
| ) -> int: |
| """ |
| Predict secondary emotion index. |
| |
| Args: |
| resonances: (100,) raw emotion resonances |
| chamber_activations: (6,) stabilized chamber outputs |
| iterations: cross-fire convergence speed |
| user_fingerprint: (100,) user emotional history |
| temperature: sampling temperature (1.0 = normal) |
| |
| Returns: |
| index of secondary emotion (0-99) |
| """ |
| logits = self.forward(resonances, chamber_activations, iterations, user_fingerprint) |
|
|
| |
| logits = logits / temperature |
|
|
| |
| exp_logits = np.exp(logits - logits.max()) |
| probs = exp_logits / exp_logits.sum() |
|
|
| |
| return int(np.random.choice(100, p=probs)) |
|
|
| def param_count(self) -> int: |
| """Count total parameters.""" |
| return ( |
| self.W1.size + self.b1.size + |
| self.W2.size + self.b2.size + |
| self.W3.size + self.b3.size |
| ) |
|
|
| def save(self, path: Path) -> None: |
| """Save weights to .npz file.""" |
| np.savez(path, W1=self.W1, b1=self.b1, W2=self.W2, b2=self.b2, W3=self.W3, b3=self.b3) |
| print(f"[observer] saved to {path}") |
|
|
| @classmethod |
| def load(cls, path: Path) -> "MetaObserver": |
| """Load weights from .npz file.""" |
| data = np.load(path) |
| |
| if "W3" in data: |
| print(f"[observer] loaded from {path}") |
| return cls( |
| W1=data["W1"], |
| b1=data["b1"], |
| W2=data["W2"], |
| b2=data["b2"], |
| W3=data["W3"], |
| b3=data["b3"], |
| ) |
| else: |
| |
| |
| |
| print(f"[observer] old format detected, reinitializing with new architecture (seed=42)") |
| return cls.random_init(seed=42) |
|
|
|
|
| class AsyncMetaObserver: |
| """ |
| Async wrapper for MetaObserver with field lock discipline. |
| |
| Based on HAZE's async pattern - achieves coherence through |
| explicit operation ordering and atomicity. |
| """ |
| |
| def __init__(self, observer: MetaObserver): |
| self._sync = observer |
| self._lock = asyncio.Lock() |
| |
| @classmethod |
| def random_init(cls, seed: Optional[int] = None) -> "AsyncMetaObserver": |
| """Initialize with random weights.""" |
| observer = MetaObserver.random_init(seed=seed) |
| return cls(observer) |
| |
| @classmethod |
| def load(cls, path: Path) -> "AsyncMetaObserver": |
| """Load from file.""" |
| observer = MetaObserver.load(path) |
| return cls(observer) |
| |
| async def forward( |
| self, |
| resonances: np.ndarray, |
| chamber_activations: np.ndarray, |
| iterations: float, |
| user_fingerprint: np.ndarray, |
| ) -> np.ndarray: |
| """Async forward pass with field lock.""" |
| async with self._lock: |
| return self._sync.forward(resonances, chamber_activations, iterations, user_fingerprint) |
| |
| async def predict_secondary( |
| self, |
| resonances: np.ndarray, |
| chamber_activations: np.ndarray, |
| iterations: float, |
| user_fingerprint: np.ndarray, |
| temperature: float = 1.0, |
| ) -> int: |
| """Async secondary emotion prediction.""" |
| async with self._lock: |
| return self._sync.predict_secondary( |
| resonances, chamber_activations, iterations, user_fingerprint, temperature |
| ) |
| |
| async def save(self, path: Path) -> None: |
| """Save with lock protection.""" |
| async with self._lock: |
| self._sync.save(path) |
| |
| def param_count(self) -> int: |
| """Total parameters (read-only, no lock needed).""" |
| return self._sync.param_count() |
|
|
|
|
| if __name__ == "__main__": |
| print("=" * 60) |
| print(" CLOUD v4.0 — Meta-Observer (200K model)") |
| print("=" * 60) |
| print() |
|
|
| |
| observer = MetaObserver.random_init(seed=42) |
| print(f"Initialized meta-observer") |
| print(f"Total params: {observer.param_count():,}") |
| print() |
|
|
| |
| print("Testing forward pass:") |
| resonances = np.random.rand(100).astype(np.float32) |
| chamber_activations = np.random.rand(6).astype(np.float32) |
| iterations = 5.0 |
| user_fingerprint = np.random.rand(100).astype(np.float32) * 0.1 |
|
|
| logits = observer.forward(resonances, chamber_activations, iterations, user_fingerprint) |
| print(f" Input: 100D resonances + 6D chambers + 1D iterations + 100D fingerprint = 207D") |
| print(f" Output: {logits.shape} logits") |
| print(f" Logits range: [{logits.min():.3f}, {logits.max():.3f}]") |
| print() |
|
|
| |
| print("Testing secondary emotion prediction:") |
| for temp in [0.5, 1.0, 2.0]: |
| secondary_idx = observer.predict_secondary( |
| resonances, chamber_activations, iterations, user_fingerprint, temperature=temp |
| ) |
| print(f" temperature={temp:.1f} → secondary_idx={secondary_idx}") |
| print() |
|
|
| |
| print("Testing convergence speed signal:") |
| test_cases = [ |
| ("fast convergence (2 iters)", 2.0), |
| ("medium convergence (5 iters)", 5.0), |
| ("slow convergence (10 iters)", 10.0), |
| ] |
|
|
| for name, iters in test_cases: |
| logits = observer.forward(resonances, chamber_activations, iters, user_fingerprint) |
| top3 = np.argsort(logits)[-3:][::-1] |
| print(f" {name}:") |
| print(f" top 3 secondary candidates: {top3}") |
| print() |
|
|
| |
| print("Testing save/load:") |
| path = Path("./models/observer.npz") |
| path.parent.mkdir(parents=True, exist_ok=True) |
| observer.save(path) |
|
|
| observer2 = MetaObserver.load(path) |
| logits2 = observer2.forward(resonances, chamber_activations, iterations, user_fingerprint) |
|
|
| match = np.allclose(logits, logits2) |
| print(f" Save/load {'✓' if match else '✗'}") |
| print() |
|
|
| print("=" * 60) |
| print(" Meta-observer operational. Mind watching body. 41K params.") |
| print("=" * 60) |
|
|