Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| # ============================================================================= | |
| # PROJECT : ScaleUp-OmegaB | EVOLUTION v4 β TRUE FEDERATED EXPANSION | |
| # AUTHOR : imsuprtwo2 | |
| # ENGINE : Federated Dynamic Synaptic Expansion (F-DSE) | |
| # BACKEND : NumPy / AdaGrad Β· no hard param ceiling | |
| # BROWSER : TensorFlow.js WebWorker β real gradient computation on user PC | |
| # STORAGE : HuggingFace Hub (imsuprtwo2/ScaleUp-OmegaB) | |
| # DATASETS : Random-cycling public HuggingFace datasets, any format | |
| # SPACES : RAM-aware expansion gate β safe on free HF Spaces (16 GB) | |
| # ============================================================================= | |
| import os, sys, json, time, uuid, math, random, logging, threading, traceback | |
| import asyncio, struct, gc, platform | |
| from dataclasses import dataclass, field, asdict | |
| from typing import Any, Dict, List, Optional, Tuple | |
| from collections import deque | |
| import numpy as np | |
| from fastapi import FastAPI, WebSocket, WebSocketDisconnect, BackgroundTasks | |
| from fastapi.responses import HTMLResponse, JSONResponse | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from pydantic import BaseModel | |
| # ββ Optional heavy deps ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| try: | |
| import psutil | |
| HAS_PSUTIL = True | |
| except ImportError: | |
| HAS_PSUTIL = False | |
| try: | |
| import torch | |
| HAS_TORCH = True | |
| TORCH_DEVICE = "cuda" if torch.cuda.is_available() else "cpu" | |
| except ImportError: | |
| HAS_TORCH = False | |
| TORCH_DEVICE = "cpu" | |
| try: | |
| from huggingface_hub import HfApi, hf_hub_download | |
| HAS_HF_HUB = True | |
| except ImportError: | |
| HAS_HF_HUB = False | |
| try: | |
| from datasets import load_dataset, get_dataset_config_names | |
| HAS_DATASETS = True | |
| except ImportError: | |
| HAS_DATASETS = False | |
| # ============================================================================= | |
| # [ S0 GLOBAL CONFIG ] | |
| # ============================================================================= | |
| logging.basicConfig( | |
| level = logging.INFO, | |
| format = "%(asctime)s [%(levelname)s] %(name)s - %(message)s", | |
| datefmt = "%H:%M:%S", | |
| ) | |
| log = logging.getLogger("OMEGA") | |
| # Detect HuggingFace Spaces environment | |
| IS_HF_SPACES = bool(os.environ.get("SPACE_ID") or os.environ.get("SPACES_ZERO_GPU")) | |
| HF_TOKEN = os.environ.get("HF_TOKEN", "") | |
| HF_REPO_ID = os.environ.get("HF_REPO_ID", "imsuprtwo2/ScaleUp-OmegaB") | |
| CHECKPOINT_EVERY = int(os.environ.get("CHECKPOINT_EVERY", "300")) | |
| EXPANSION_COOLDOWN = float(os.environ.get("EXPANSION_COOLDOWN", "5")) | |
| LOSS_THRESHOLD = float(os.environ.get("LOSS_THRESHOLD", "0.065")) | |
| LEARNING_RATE = float(os.environ.get("LEARNING_RATE", "0.0003")) | |
| PORT = int(os.environ.get("PORT", "7860")) | |
| INPUT_DIM = 128 | |
| OUTPUT_DIM = 128 | |
| # RAM safety thresholds β critical for HF Spaces free tier (16 GB) | |
| RAM_EXPAND_CEILING = 0.78 # pause expansion above this fraction | |
| RAM_HARD_CEILING = 0.90 # force gc.collect above this | |
| _START_TIME = time.time() | |
| # Seed datasets that reliably load as fallback | |
| SEED_DATASETS = [ | |
| ("wikipedia", "20220301.simple"), | |
| ("bookcorpus", None), | |
| ("squad", None), | |
| ("glue", "sst2"), | |
| ("ag_news", None), | |
| ("multi_news", None), | |
| ("cnn_dailymail", "3.0.0"), | |
| ("scientific_papers", "arxiv"), | |
| ("cc_news", None), | |
| ("openwebtext", None), | |
| ] | |
| TEXT_FIELDS = [ | |
| "text","content","body","article","document","passage", | |
| "sentence","review","description","summary","context", | |
| "question","answer","title","abstract","story","input","output", | |
| ] | |
| # ============================================================================= | |
| # [ S1 HARDWARE SCANNER ] | |
| # ============================================================================= | |
| class HardwareProfile: | |
| client_id: str = "" | |
| cpu_cores_phys: int = 1 | |
| cpu_cores_logic: int = 1 | |
| cpu_freq_mhz: float = 0.0 | |
| ram_total_gb: float = 0.0 | |
| ram_avail_gb: float = 0.0 | |
| gpu_name: str = "None" | |
| gpu_vram_gb: float = 0.0 | |
| cuda_available: bool = False | |
| platform_str: str = "" | |
| compute_score: float = 0.0 | |
| allocated_threads: int = 1 | |
| allocated_batch: int = 8 | |
| def to_dict(self) -> Dict: | |
| return asdict(self) | |
| class HardwareScanner: | |
| def scan(client_id: str = "server") -> HardwareProfile: | |
| p = HardwareProfile(client_id=client_id, platform_str=platform.system()) | |
| if HAS_PSUTIL: | |
| p.cpu_cores_phys = psutil.cpu_count(logical=False) or 1 | |
| p.cpu_cores_logic = psutil.cpu_count(logical=True) or 1 | |
| freq = psutil.cpu_freq() | |
| p.cpu_freq_mhz = round(freq.current, 1) if freq else 0.0 | |
| vm = psutil.virtual_memory() | |
| p.ram_total_gb = round(vm.total / 1024**3, 2) | |
| p.ram_avail_gb = round(vm.available/ 1024**3, 2) | |
| else: | |
| p.cpu_cores_logic = os.cpu_count() or 2 | |
| p.cpu_cores_phys = p.cpu_cores_logic | |
| if HAS_TORCH: | |
| p.cuda_available = torch.cuda.is_available() | |
| if p.cuda_available: | |
| p.gpu_name = torch.cuda.get_device_name(0) | |
| props = torch.cuda.get_device_properties(0) | |
| p.gpu_vram_gb = round(props.total_memory / 1024**3, 2) | |
| cpu_pts = p.cpu_cores_logic * max(p.cpu_freq_mhz, 1000) / 1000 | |
| ram_pts = p.ram_avail_gb * 4 | |
| vram_pts = p.gpu_vram_gb * 80 | |
| p.compute_score = round(cpu_pts + ram_pts + vram_pts, 2) | |
| s = p.compute_score | |
| if s < 20: p.allocated_threads, p.allocated_batch = 1, 8 | |
| elif s < 60: p.allocated_threads, p.allocated_batch = 2, 16 | |
| elif s < 150: p.allocated_threads, p.allocated_batch = 4, 32 | |
| elif s < 400: p.allocated_threads, p.allocated_batch = 6, 64 | |
| else: p.allocated_threads, p.allocated_batch = min(p.cpu_cores_phys, 12), 128 | |
| log.info( | |
| f"[HW] {client_id[:12]} cores={p.cpu_cores_logic} " | |
| f"ram={p.ram_avail_gb}GB gpu={p.gpu_name} " | |
| f"score={p.compute_score} T={p.allocated_threads} B={p.allocated_batch}" | |
| ) | |
| return p | |
| def ram_usage_fraction() -> float: | |
| """Returns current RAM usage as a 0.0-1.0 fraction.""" | |
| if HAS_PSUTIL: | |
| return psutil.virtual_memory().percent / 100.0 | |
| return 0.4 | |
| # ============================================================================= | |
| # [ S2 RESPONSE GENERATOR ] | |
| # ============================================================================= | |
| class ResponseGenerator: | |
| """ | |
| Generates technically-accurate, varied chat messages drawn from real | |
| training metrics. Each call produces a different style of message so | |
| the model never sounds like a broken record. | |
| """ | |
| _LOSS_LABELS = [ | |
| (0.010, "near-zero - pattern fully saturated"), | |
| (0.030, "very low - high predictive confidence"), | |
| (0.065, "moderate - healthy gradient flow"), | |
| (0.120, "elevated - expansion pressure active"), | |
| (0.250, "high - novel input distribution"), | |
| (999.0, "very high - unexplored representation space"), | |
| ] | |
| def __init__(self): | |
| self._prev_loss = 1.0 | |
| self._prev_params = 0 | |
| self._cycle = 0 | |
| def _loss_label(self, loss: float) -> str: | |
| for threshold, label in self._LOSS_LABELS: | |
| if loss <= threshold: | |
| return label | |
| return "indeterminate" | |
| def generate(self, *, loss: float, params: int, layers: int, | |
| expansions: int, expanded: bool, new_width: int, | |
| dataset: str, datasets_tried: int, clients: int, | |
| total_score: float, fed_updates: int, train_steps: int, | |
| batch: int, iq: float, sps: float, workers: int, | |
| ram_pct: float, expansion_paused: bool) -> str: | |
| ds_short = dataset.split("/")[-1][:22] if dataset != "none" else "loading..." | |
| prev_loss = self._prev_loss | |
| prev_par = self._prev_params | |
| self._prev_loss = loss | |
| self._prev_params = params | |
| # --- Expansion just happened: always lead with that --- | |
| if expanded: | |
| self._cycle += 1 | |
| return ( | |
| f"Neurogenesis #{expansions}: injected a {new_width}-neuron dense layer. " | |
| f"Parameter count {prev_par:,} -> {params:,} (+{params - prev_par:,}). " | |
| f"Triggered by loss={loss:.5f} on dataset [{ds_short}]. " | |
| f"Architecture is now {layers} layers deep." | |
| ) | |
| # --- RAM warning --- | |
| if expansion_paused and ram_pct > RAM_EXPAND_CEILING * 100: | |
| return ( | |
| f"Expansion paused: RAM at {ram_pct:.1f}% (HF Spaces safety gate at " | |
| f"{RAM_EXPAND_CEILING*100:.0f}%). Holding at {params:,} params / {layers} layers. " | |
| f"Training continues at full speed. Loss={loss:.5f}, IQ={iq:.4f}. " | |
| f"Expansion will resume automatically when memory clears." | |
| ) | |
| # --- Rotate through informative templates --- | |
| self._cycle = (self._cycle + 1) % 6 | |
| c = self._cycle | |
| if c == 0: | |
| pct_change = abs(prev_loss - loss) / (prev_loss + 1e-9) * 100 | |
| direction = "improved" if loss < prev_loss else "increased" | |
| return ( | |
| f"Loss {direction} {prev_loss:.5f} -> {loss:.5f} ({pct_change:.1f}%) " | |
| f"on dataset [{ds_short}]. " | |
| f"Architecture: {layers} layers, {params:,} parameters. " | |
| f"IQ index: {iq:.4f}. Server training: ~{sps:.1f} steps/sec." | |
| ) | |
| elif c == 1: | |
| return ( | |
| f"Trained a {batch}-sample mini-batch against [{ds_short}] " | |
| f"(dataset #{datasets_tried} in rotation). " | |
| f"Loss={loss:.5f} ({self._loss_label(loss)}). " | |
| f"{clients} distributed client(s) contributing {total_score:.0f} compute-units. " | |
| f"{fed_updates} federated gradient packets absorbed this session." | |
| ) | |
| elif c == 2: | |
| return ( | |
| f"Your input was embedded across all {layers} synaptic layers " | |
| f"({params:,} parameters, {expansions} neurogenesis events so far). " | |
| f"Prediction error: {loss:.5f}. AdaGrad accumulators updated. " | |
| f"Continuous training on [{ds_short}] running in background." | |
| ) | |
| elif c == 3: | |
| return ( | |
| f"Server: {workers} worker thread(s), {sps:.1f} steps/sec, " | |
| f"{train_steps:,} total gradient steps. " | |
| f"Browser workers: {clients - 1} client(s) running TF.js locally. " | |
| f"Fed updates: {fed_updates}. Current loss: {loss:.5f}." | |
| ) | |
| elif c == 4: | |
| return ( | |
| f"Dataset [{ds_short}] ({datasets_tried} rotated total). " | |
| f"Loss={loss:.5f} | Params={params:,} | Layers={layers} | IQ={iq:.4f}. " | |
| f"RAM usage: {ram_pct:.1f}%. " | |
| f"No expansion needed at this loss level." | |
| ) | |
| else: | |
| return ( | |
| f"Gradient descent step complete. Loss: {loss:.5f} " | |
| f"({self._loss_label(loss)}). " | |
| f"Model has {params:,} active parameters in {layers} layers. " | |
| f"Global IQ index: {iq:.4f}. " | |
| f"Weights synced to HuggingFace Hub: imsuprtwo2/ScaleUp-OmegaB." | |
| ) | |
| # ============================================================================= | |
| # [ S3 DATASET MANAGER ] | |
| # ============================================================================= | |
| class DatasetManager: | |
| def __init__(self): | |
| self._lock = threading.Lock() | |
| self._blacklist: set = set() | |
| self._catalogue: List[str] = [] | |
| self._last_refresh = 0.0 | |
| self._refresh_interval= 3600.0 | |
| self._current_iter = None | |
| self._current_name = "none" | |
| self._rows_consumed = 0 | |
| self.datasets_tried = 0 | |
| self._switch_after = 2000 | |
| self._log: deque = deque(maxlen=40) | |
| self._queue: deque = deque(maxlen=512) | |
| t = threading.Thread(target=self._prefetch_loop, daemon=True) | |
| t.start() | |
| def _refresh_catalogue(self): | |
| now = time.time() | |
| if now - self._last_refresh < self._refresh_interval: | |
| return | |
| self._last_refresh = now | |
| if not HAS_HF_HUB: | |
| return | |
| try: | |
| api = HfApi() | |
| info = api.list_datasets(limit=5000, full=False) | |
| ids = [d.id for d in info if d.id] | |
| random.shuffle(ids) | |
| with self._lock: | |
| self._catalogue = ids | |
| log.info(f"[DATASET] Catalogue: {len(ids)} datasets.") | |
| except Exception as e: | |
| log.warning(f"[DATASET] Catalogue refresh failed: {e}") | |
| def _pick(self) -> Tuple[str, Optional[str]]: | |
| self._refresh_catalogue() | |
| with self._lock: | |
| cands = [d for d in self._catalogue if d not in self._blacklist] | |
| if cands: | |
| return random.choice(cands), None | |
| live = [s for s in SEED_DATASETS if s[0] not in self._blacklist] | |
| if live: | |
| return random.choice(live) | |
| with self._lock: | |
| self._blacklist.clear() | |
| return random.choice(SEED_DATASETS) | |
| def _extract(self, record: Dict) -> Optional[str]: | |
| for f in TEXT_FIELDS: | |
| if f in record: | |
| v = record[f] | |
| if isinstance(v, str) and len(v.strip()) > 15: | |
| return v.strip() | |
| if isinstance(v, list): | |
| j = " ".join(str(x) for x in v if isinstance(x, str)) | |
| if len(j.strip()) > 15: | |
| return j.strip() | |
| parts = [v for v in record.values() if isinstance(v, str) and len(v) > 8] | |
| result = " ".join(parts) | |
| return result if len(result) > 15 else None | |
| def _load(self): | |
| if not HAS_DATASETS: | |
| return | |
| for _ in range(10): | |
| ds_id, config = self._pick() | |
| self.datasets_tried += 1 | |
| label = ds_id + (f"/{config}" if config else "") | |
| log.info(f"[DATASET] Loading [{self.datasets_tried}] {label}") | |
| self._log.append(f"[{time.strftime('%H:%M:%S')}] Loading {label}") | |
| try: | |
| kw: Dict[str, Any] = dict( | |
| path = ds_id, | |
| split = "train", | |
| streaming = True, | |
| trust_remote_code = True, | |
| ) | |
| if config: | |
| kw["name"] = config | |
| else: | |
| try: | |
| cfgs = get_dataset_config_names(ds_id, trust_remote_code=True) | |
| if cfgs: | |
| kw["name"] = cfgs[0] | |
| except Exception: | |
| pass | |
| ds = load_dataset(**kw) | |
| sample = next(iter(ds)) | |
| text = self._extract(sample) | |
| if text is None: | |
| raise ValueError(f"No text field found in {ds_id}") | |
| self._current_iter = iter(ds) | |
| self._current_name = label | |
| self._rows_consumed = 0 | |
| log.info(f"[DATASET] Active: {label}") | |
| self._log.append(f"[{time.strftime('%H:%M:%S')}] Active: {label}") | |
| return | |
| except Exception as e: | |
| log.warning(f"[DATASET] Failed {ds_id}: {e}") | |
| with self._lock: | |
| self._blacklist.add(ds_id) | |
| def _prefetch_loop(self): | |
| while True: | |
| try: | |
| if len(self._queue) < 128: | |
| if self._current_iter is None or self._rows_consumed >= self._switch_after: | |
| self._load() | |
| if self._current_iter is not None: | |
| for _ in range(64): | |
| try: | |
| rec = next(self._current_iter) | |
| text = self._extract(rec) | |
| if text: | |
| self._queue.append(text[:2048]) | |
| self._rows_consumed += 1 | |
| except StopIteration: | |
| self._current_iter = None | |
| break | |
| else: | |
| time.sleep(0.05) | |
| except Exception as e: | |
| log.warning(f"[DATASET/prefetch] {e}") | |
| time.sleep(2) | |
| def next_text(self) -> str: | |
| for _ in range(200): | |
| if self._queue: | |
| return self._queue.popleft() | |
| time.sleep(0.03) | |
| words = ["the","model","trains","on","distributed","datasets","continuously"] | |
| return " ".join(random.choices(words, k=random.randint(20, 60))) | |
| def status(self) -> Dict: | |
| return { | |
| "current": self._current_name, | |
| "rows_consumed": self._rows_consumed, | |
| "datasets_tried": self.datasets_tried, | |
| "blacklisted": len(self._blacklist), | |
| "queue_depth": len(self._queue), | |
| "recent_log": list(self._log)[-10:], | |
| } | |
| # ============================================================================= | |
| # [ S4 DYNAMIC BRAIN ] | |
| # ============================================================================= | |
| class DynamicBrain: | |
| """ | |
| Self-expanding MLP with no hard parameter ceiling. | |
| - AdaGrad per-parameter adaptive learning rates | |
| - Xavier initialisation on all new layers | |
| - RAM-aware expansion gate (critical for HF Spaces) | |
| - Thread-safe via RLock | |
| - Binary serialisation for HF Hub checkpoints | |
| """ | |
| def __init__(self): | |
| self.input_dim = INPUT_DIM | |
| self.output_dim = OUTPUT_DIM | |
| self.lr = LEARNING_RATE | |
| self.lock = threading.RLock() | |
| self.layers: List[Dict] = [] | |
| self._build_seed() | |
| self.param_count = self._count() | |
| self.global_iq = 0.0 | |
| self.total_tokens = 0 | |
| self.expansion_events = 0 | |
| self.train_steps = 0 | |
| self.last_expansion_time = 0.0 | |
| self.last_checkpoint_time= time.time() | |
| self.expansion_paused = False | |
| self.last_expansion_width= 0 | |
| self.loss_history: deque = deque(maxlen=500) | |
| self.grad_acc: List[Dict]= self._make_adagrad() | |
| self.hf = HFModelManager() | |
| self._try_load_hf() | |
| log.info(f"[BRAIN] Ready: {self.param_count:,} params / {len(self.layers)} layers") | |
| # ββ Architecture βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _xavier(self, fan_in: int, fan_out: int) -> Dict: | |
| lim = math.sqrt(6.0 / (fan_in + fan_out)) | |
| return { | |
| "W": np.random.uniform(-lim, lim, (fan_in, fan_out)).astype(np.float32), | |
| "b": np.zeros((1, fan_out), dtype=np.float32), | |
| } | |
| def _build_seed(self): | |
| self.layers = [ | |
| self._xavier(self.input_dim, 1024), | |
| self._xavier(1024, 1024), | |
| self._xavier(1024, 512), | |
| self._xavier(512, self.output_dim), | |
| ] | |
| def _count(self) -> int: | |
| return sum(l["W"].size + l["b"].size for l in self.layers) | |
| def _make_adagrad(self) -> List[Dict]: | |
| return [ | |
| {"W": np.ones_like(l["W"]) * 1e-8, | |
| "b": np.ones_like(l["b"]) * 1e-8} | |
| for l in self.layers | |
| ] | |
| # ββ Activations ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _lrelu(z, a=0.01): return np.where(z > 0, z, a * z) | |
| def _lrelu_d(z, a=0.01): return np.where(z > 0, 1.0, a) | |
| # ββ Neurogenesis ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def maybe_expand(self, loss: float) -> bool: | |
| """ | |
| Conditionally insert a new hidden layer. | |
| Returns True if expansion occurred. | |
| """ | |
| if loss <= LOSS_THRESHOLD: | |
| return False | |
| now = time.time() | |
| if now - self.last_expansion_time < EXPANSION_COOLDOWN: | |
| return False | |
| ram = ram_usage_fraction() | |
| if ram >= RAM_EXPAND_CEILING: | |
| self.expansion_paused = True | |
| if ram >= RAM_HARD_CEILING: | |
| gc.collect() | |
| return False | |
| self.expansion_paused = False | |
| self.last_expansion_time = now | |
| with self.lock: | |
| self.expansion_events += 1 | |
| new_width = 256 + self.expansion_events * 128 | |
| self.last_expansion_width = new_width | |
| prev_width = self.layers[-2]["W"].shape[1] | |
| new_layer = self._xavier(prev_width, new_width) | |
| self.layers[-1] = self._xavier(new_width, self.output_dim) | |
| self.layers.insert(-1, new_layer) | |
| self.param_count = self._count() | |
| self.grad_acc = self._make_adagrad() | |
| log.info( | |
| f"[NEUROGENESIS #{self.expansion_events}] " | |
| f"width={new_width} params={self.param_count:,} ram={ram*100:.1f}%" | |
| ) | |
| return True | |
| # ββ Forward / Backprop ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _forward(self, x: np.ndarray): | |
| pre, post = [], [x] | |
| for i, l in enumerate(self.layers): | |
| z = post[-1] @ l["W"] + l["b"] | |
| pre.append(z) | |
| post.append(self._lrelu(z) if i < len(self.layers) - 1 else z) | |
| return pre, post | |
| def _backprop(self, pre, post, target: np.ndarray): | |
| with self.lock: | |
| delta = 2.0 * (post[-1] - target) / target.shape[0] | |
| for i in range(len(self.layers) - 1, -1, -1): | |
| gW = post[i].T @ delta | |
| gb = delta.sum(axis=0, keepdims=True) | |
| self.grad_acc[i]["W"] += gW ** 2 | |
| self.grad_acc[i]["b"] += gb ** 2 | |
| self.layers[i]["W"] -= self.lr * gW / (np.sqrt(self.grad_acc[i]["W"]) + 1e-8) | |
| self.layers[i]["b"] -= self.lr * gb / (np.sqrt(self.grad_acc[i]["b"]) + 1e-8) | |
| if i > 0: | |
| delta = (delta @ self.layers[i]["W"].T) * self._lrelu_d(pre[i - 1]) | |
| # ββ Text vectorisation ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _text_to_batch(self, text: str, batch_size: int) -> Tuple[np.ndarray, np.ndarray]: | |
| enc = np.array([ord(c) / 255.0 for c in text], dtype=np.float32) | |
| L, W = len(enc), self.input_dim | |
| if L < W + 1: | |
| enc = np.pad(enc, (0, W + 1 - L)) | |
| L = len(enc) | |
| n = min(batch_size, L - W - 1) | |
| idx = np.random.randint(0, max(1, L - W - 1), size=max(1, n)) | |
| X = np.stack([enc[i: i + W] for i in idx]) | |
| Y = np.stack([enc[i + 1: i + 1 + W] for i in idx]) | |
| return X, Y | |
| # ββ Public train step βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def train_on_text(self, text: str, batch_size: int = 32) -> Tuple[float, bool]: | |
| """Returns (loss, expanded).""" | |
| X, Y = self._text_to_batch(text, batch_size) | |
| pre, post = self._forward(X) | |
| loss = float(np.mean((post[-1] - Y) ** 2)) | |
| self._backprop(pre, post, Y) | |
| self.train_steps += 1 | |
| self.total_tokens += len(text.split()) | |
| self.loss_history.append(loss) | |
| avg = float(np.mean(list(self.loss_history)[-50:])) if len(self.loss_history) >= 50 else loss | |
| self.global_iq = max(0.0, self.global_iq + 0.004 / (avg + 1e-4)) | |
| expanded = self.maybe_expand(loss) | |
| if time.time() - self.last_checkpoint_time > CHECKPOINT_EVERY: | |
| threading.Thread(target=self._checkpoint, daemon=True).start() | |
| self.last_checkpoint_time = time.time() | |
| return loss, expanded | |
| # ββ Federated gradient application βββββββββββββββββββββββββββββββββββββββ | |
| def apply_federated_update(self, grad_pack: List[Dict]): | |
| """ | |
| Apply weight deltas arriving from a browser client's TF.js worker. | |
| Each element: {"W": flat_array, "b": flat_array, | |
| "W_shape": [rows, cols], "b_shape": [1, cols]} | |
| Layers that do not match current architecture are skipped gracefully. | |
| """ | |
| with self.lock: | |
| n = min(len(grad_pack), len(self.layers)) | |
| for i in range(n): | |
| try: | |
| gW = np.array(grad_pack[i]["W"], dtype=np.float32) | |
| gb = np.array(grad_pack[i]["b"], dtype=np.float32) | |
| Ws = grad_pack[i].get("W_shape") | |
| bs = grad_pack[i].get("b_shape") | |
| if Ws: | |
| gW = gW.reshape(Ws) | |
| if bs: | |
| gb = gb.reshape(bs) | |
| if gW.shape != self.layers[i]["W"].shape: | |
| continue | |
| if gb.shape != self.layers[i]["b"].shape: | |
| gb = gb.reshape(self.layers[i]["b"].shape) | |
| self.grad_acc[i]["W"] += gW ** 2 | |
| self.grad_acc[i]["b"] += gb ** 2 | |
| self.layers[i]["W"] -= self.lr * gW / (np.sqrt(self.grad_acc[i]["W"]) + 1e-8) | |
| self.layers[i]["b"] -= self.lr * gb / (np.sqrt(self.grad_acc[i]["b"]) + 1e-8) | |
| except Exception as e: | |
| log.debug(f"[FED] Layer {i} skip: {e}") | |
| # ββ Serialisation βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def snapshot(self) -> bytes: | |
| header = json.dumps({ | |
| "n": len(self.layers), | |
| "shapes": [[list(l["W"].shape), list(l["b"].shape)] for l in self.layers], | |
| "params": self.param_count, | |
| "exp": self.expansion_events, | |
| "steps": self.train_steps, | |
| "iq": self.global_iq, | |
| "tokens": self.total_tokens, | |
| }).encode() | |
| parts = [struct.pack(">I", len(header)), header] | |
| with self.lock: | |
| for l in self.layers: | |
| parts += [l["W"].tobytes(), l["b"].tobytes()] | |
| return b"".join(parts) | |
| def restore(self, data: bytes): | |
| hlen = struct.unpack(">I", data[:4])[0] | |
| header = json.loads(data[4: 4 + hlen]) | |
| offset = 4 + hlen | |
| with self.lock: | |
| new_layers = [] | |
| for (Ws, bs) in header["shapes"]: | |
| Wn = int(np.prod(Ws)) | |
| bn = int(np.prod(bs)) | |
| W = np.frombuffer(data[offset: offset + Wn * 4], dtype=np.float32).reshape(Ws).copy() | |
| offset += Wn * 4 | |
| b = np.frombuffer(data[offset: offset + bn * 4], dtype=np.float32).reshape(bs).copy() | |
| offset += bn * 4 | |
| new_layers.append({"W": W, "b": b}) | |
| self.layers = new_layers | |
| self.param_count = self._count() | |
| self.expansion_events = header.get("exp", 0) | |
| self.train_steps = header.get("steps", 0) | |
| self.global_iq = header.get("iq", 0.0) | |
| self.total_tokens = header.get("tokens", 0) | |
| self.grad_acc = self._make_adagrad() | |
| log.info(f"[BRAIN] Restored: {self.param_count:,} params / {self.expansion_events} expansions") | |
| def _checkpoint(self): | |
| try: | |
| self.hf.push(self.snapshot(), self.status) | |
| except Exception as e: | |
| log.warning(f"[BRAIN/ckpt] {e}") | |
| def _try_load_hf(self): | |
| try: | |
| data = self.hf.pull() | |
| if data: | |
| self.restore(data) | |
| except Exception as e: | |
| log.warning(f"[BRAIN/load] {e}") | |
| def avg_loss(self) -> float: | |
| return float(np.mean(list(self.loss_history)[-50:])) if len(self.loss_history) >= 50 else 1.0 | |
| def status(self) -> Dict: | |
| return { | |
| "param_count": self.param_count, | |
| "expansion_events": self.expansion_events, | |
| "train_steps": self.train_steps, | |
| "total_tokens": self.total_tokens, | |
| "global_iq": round(self.global_iq, 6), | |
| "avg_loss": round(self.avg_loss, 6), | |
| "layer_count": len(self.layers), | |
| "layer_shapes": [list(l["W"].shape) for l in self.layers], | |
| "expansion_paused": self.expansion_paused, | |
| "ram_pct": round(ram_usage_fraction() * 100, 1), | |
| } | |
| # ============================================================================= | |
| # [ S5 HF MODEL MANAGER ] | |
| # ============================================================================= | |
| class HFModelManager: | |
| BIN = "omega_checkpoint.bin" | |
| META = "omega_meta.json" | |
| def __init__(self): | |
| self.api = HfApi() if HAS_HF_HUB and HF_TOKEN else None | |
| self.repo_id = HF_REPO_ID | |
| self.token = HF_TOKEN | |
| self._pushes = 0 | |
| def _ensure_repo(self): | |
| if not self.api: | |
| return | |
| try: | |
| self.api.create_repo( | |
| self.repo_id, repo_type="model", | |
| exist_ok=True, token=self.token | |
| ) | |
| except Exception: | |
| pass | |
| def push(self, data: bytes, meta: Optional[Dict] = None): | |
| if not self.api: | |
| log.debug("[HF] Push skipped - set HF_TOKEN and HF_REPO_ID.") | |
| return | |
| self._ensure_repo() | |
| import io | |
| try: | |
| self.api.upload_file( | |
| path_or_fileobj = io.BytesIO(data), | |
| path_in_repo = self.BIN, | |
| repo_id = self.repo_id, | |
| repo_type = "model", | |
| token = self.token, | |
| ) | |
| if meta: | |
| self.api.upload_file( | |
| path_or_fileobj = io.BytesIO(json.dumps(meta, indent=2).encode()), | |
| path_in_repo = self.META, | |
| repo_id = self.repo_id, | |
| repo_type = "model", | |
| token = self.token, | |
| ) | |
| self._pushes += 1 | |
| log.info(f"[HF] Pushed checkpoint #{self._pushes} to {self.repo_id}") | |
| except Exception as e: | |
| log.warning(f"[HF] Push failed: {e}") | |
| def pull(self) -> Optional[bytes]: | |
| if not self.api: | |
| return None | |
| try: | |
| path = hf_hub_download( | |
| repo_id = self.repo_id, | |
| filename = self.BIN, | |
| repo_type = "model", | |
| token = self.token, | |
| ) | |
| with open(path, "rb") as fh: | |
| data = fh.read() | |
| log.info(f"[HF] Pulled {len(data):,} bytes from {self.repo_id}") | |
| return data | |
| except Exception as e: | |
| log.info(f"[HF] No checkpoint found ({e})") | |
| return None | |
| # ============================================================================= | |
| # [ S6 CLIENT REGISTRY ] | |
| # ============================================================================= | |
| class ClientSession: | |
| session_id: str | |
| hw: HardwareProfile | |
| connected_at: float = field(default_factory=time.time) | |
| messages: int = 0 | |
| fed_updates: int = 0 | |
| ws: Any = None | |
| class ClientRegistry: | |
| def __init__(self): | |
| self._clients: Dict[str, ClientSession] = {} | |
| self._lock = threading.Lock() | |
| def register(self, sid: str, hw: HardwareProfile, ws=None) -> ClientSession: | |
| s = ClientSession(session_id=sid, hw=hw, ws=ws) | |
| with self._lock: | |
| self._clients[sid] = s | |
| log.info(f"[REG] +{sid[:8]} score={hw.compute_score:.1f}") | |
| return s | |
| def unregister(self, sid: str): | |
| with self._lock: | |
| self._clients.pop(sid, None) | |
| def get(self, sid: str) -> Optional[ClientSession]: | |
| return self._clients.get(sid) | |
| def count(self) -> int: | |
| return len(self._clients) | |
| def total_compute(self) -> float: | |
| return sum(s.hw.compute_score for s in self._clients.values()) | |
| def total_fed_updates(self) -> int: | |
| return sum(s.fed_updates for s in self._clients.values()) | |
| # ============================================================================= | |
| # [ S7 TRAINING COORDINATOR ] | |
| # ============================================================================= | |
| class TrainingCoordinator: | |
| def __init__(self, brain: DynamicBrain, ds: DatasetManager, hw: HardwareProfile): | |
| self.brain = brain | |
| self.ds = ds | |
| self.hw = hw | |
| self._stop = threading.Event() | |
| self._workers: List[threading.Thread] = [] | |
| self._steps = 0 | |
| self._lock = threading.Lock() | |
| self._start(hw.allocated_threads) | |
| def _start(self, n: int): | |
| for i in range(n): | |
| t = threading.Thread(target=self._loop, args=(i,), daemon=True) | |
| t.start() | |
| self._workers.append(t) | |
| log.info(f"[COORD] {n} workers (batch={self.hw.allocated_batch})") | |
| def _loop(self, wid: int): | |
| time.sleep(wid * 0.08) | |
| batch = self.hw.allocated_batch | |
| while not self._stop.is_set(): | |
| try: | |
| text = self.ds.next_text() | |
| self.brain.train_on_text(text, batch_size=batch) | |
| with self._lock: | |
| self._steps += 1 | |
| time.sleep(0.001) | |
| except Exception as e: | |
| log.warning(f"[WORKER/{wid}] {e}") | |
| time.sleep(1) | |
| def scale_up(self, hw: HardwareProfile): | |
| current = len(self._workers) | |
| target = hw.allocated_threads | |
| if target > current: | |
| self._start(target - current) | |
| def stop(self): | |
| self._stop.set() | |
| def steps_per_sec(self) -> float: | |
| return self._steps / max(1, time.time() - _START_TIME) | |
| # ============================================================================= | |
| # [ S8 PYDANTIC MODELS ] | |
| # ============================================================================= | |
| class ChatRequest(BaseModel): | |
| message: str | |
| session_id: Optional[str] = None | |
| class HardwareReport(BaseModel): | |
| session_id: str | |
| cpu_cores: int = 1 | |
| ram_gb: float = 4.0 | |
| gpu_name: str = "None" | |
| gpu_vram_gb: float = 0.0 | |
| compute_score: float = 10.0 | |
| class GradientPacket(BaseModel): | |
| session_id: str | |
| weight: float = 1.0 | |
| gradients: List[Dict] # [{W, b, W_shape, b_shape}, ...] | |
| # ============================================================================= | |
| # [ S9 GLOBAL SINGLETONS ] | |
| # ============================================================================= | |
| SERVER_HW = HardwareScanner.scan("server") | |
| BRAIN = DynamicBrain() | |
| DS_MGR = DatasetManager() | |
| COORD = TrainingCoordinator(BRAIN, DS_MGR, SERVER_HW) | |
| REGISTRY = ClientRegistry() | |
| RESPGEN = ResponseGenerator() | |
| REGISTRY.register("server", SERVER_HW) | |
| # ============================================================================= | |
| # [ S10 FASTAPI ROUTES ] | |
| # ============================================================================= | |
| app = FastAPI(title="ScaleUp-OmegaB", version="4.0.0") | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], allow_methods=["*"], allow_headers=["*"] | |
| ) | |
| async def api_chat(req: ChatRequest, bg: BackgroundTasks): | |
| sid = req.session_id or str(uuid.uuid4()) | |
| session = REGISTRY.get(sid) | |
| if session: | |
| session.messages += 1 | |
| old_params = BRAIN.param_count | |
| loss, expanded = BRAIN.train_on_text(req.message, batch_size=16) | |
| if expanded: | |
| bg.add_task(BRAIN.hf.push, BRAIN.snapshot(), BRAIN.status) | |
| reply = RESPGEN.generate( | |
| loss = loss, | |
| params = BRAIN.param_count, | |
| layers = len(BRAIN.layers), | |
| expansions = BRAIN.expansion_events, | |
| expanded = expanded, | |
| new_width = BRAIN.last_expansion_width, | |
| dataset = DS_MGR._current_name, | |
| datasets_tried = DS_MGR.datasets_tried, | |
| clients = REGISTRY.count, | |
| total_score = REGISTRY.total_compute, | |
| fed_updates = REGISTRY.total_fed_updates, | |
| train_steps = BRAIN.train_steps, | |
| batch = 16, | |
| iq = BRAIN.global_iq, | |
| sps = COORD.steps_per_sec, | |
| workers = COORD.hw.allocated_threads, | |
| ram_pct = ram_usage_fraction() * 100, | |
| expansion_paused = BRAIN.expansion_paused, | |
| ) | |
| return JSONResponse({ | |
| "reply": reply, | |
| "session_id": sid, | |
| "expanded": expanded, | |
| "loss": round(loss, 6), | |
| "iq": round(BRAIN.global_iq, 6), | |
| "total_params": BRAIN.param_count, | |
| "expansions": BRAIN.expansion_events, | |
| "layer_count": len(BRAIN.layers), | |
| "active_clients": REGISTRY.count, | |
| "ram_pct": round(ram_usage_fraction() * 100, 1), | |
| }) | |
| async def api_status(): | |
| return JSONResponse({ | |
| "brain": BRAIN.status, | |
| "dataset": DS_MGR.status, | |
| "hardware":SERVER_HW.to_dict(), | |
| "coordinator": { | |
| "workers": COORD.hw.allocated_threads, | |
| "total_steps":COORD._steps, | |
| "steps_sec": round(COORD.steps_per_sec, 2), | |
| }, | |
| "federation": { | |
| "clients": REGISTRY.count, | |
| "compute": round(REGISTRY.total_compute, 2), | |
| "fed_updates": REGISTRY.total_fed_updates, | |
| }, | |
| "uptime": round(time.time() - _START_TIME, 1), | |
| "is_hf_spaces": IS_HF_SPACES, | |
| }) | |
| async def api_hw(report: HardwareReport): | |
| hw = HardwareProfile( | |
| client_id = report.session_id, | |
| cpu_cores_logic = report.cpu_cores, | |
| ram_avail_gb = report.ram_gb, | |
| gpu_name = report.gpu_name, | |
| gpu_vram_gb = report.gpu_vram_gb, | |
| compute_score = report.compute_score, | |
| ) | |
| s = report.compute_score | |
| hw.allocated_threads = 1 if s < 20 else 2 if s < 60 else 3 if s < 150 else 4 | |
| hw.allocated_batch = 8 if s < 20 else 16 if s < 60 else 32 if s < 150 else 64 | |
| existing = REGISTRY.get(report.session_id) | |
| if existing: | |
| existing.hw = hw | |
| else: | |
| REGISTRY.register(report.session_id, hw) | |
| COORD.scale_up(hw) | |
| return JSONResponse({ | |
| "ok": True, | |
| "allocated_batch": hw.allocated_batch, | |
| "allocated_threads": hw.allocated_threads, | |
| }) | |
| async def api_gradients(pkt: GradientPacket): | |
| session = REGISTRY.get(pkt.session_id) | |
| if not session: | |
| hw = HardwareProfile(client_id=pkt.session_id, compute_score=10.0) | |
| session = REGISTRY.register(pkt.session_id, hw) | |
| BRAIN.apply_federated_update(pkt.gradients) | |
| session.fed_updates += 1 | |
| return JSONResponse({"ok": True, "fed_updates": session.fed_updates}) | |
| async def api_arch(): | |
| with BRAIN.lock: | |
| layers = [ | |
| {"i": i, "fan_in": l["W"].shape[0], "fan_out": l["W"].shape[1], | |
| "params": l["W"].size + l["b"].size} | |
| for i, l in enumerate(BRAIN.layers) | |
| ] | |
| return JSONResponse({ | |
| "layers": layers, | |
| "total": BRAIN.param_count, | |
| "expansions": BRAIN.expansion_events, | |
| }) | |
| async def api_weight_subset(n_layers: int = 3): | |
| """ | |
| Return the first n_layers as JSON so the browser worker can initialise | |
| its local TF.js model with server-synced starting weights. | |
| """ | |
| n = min(n_layers, len(BRAIN.layers)) | |
| with BRAIN.lock: | |
| subset = [ | |
| { | |
| "W": BRAIN.layers[i]["W"].tolist(), | |
| "b": BRAIN.layers[i]["b"].tolist(), | |
| "W_shape": list(BRAIN.layers[i]["W"].shape), | |
| "b_shape": list(BRAIN.layers[i]["b"].shape), | |
| } | |
| for i in range(n) | |
| ] | |
| return JSONResponse({ | |
| "layers": subset, | |
| "total_server_layers": len(BRAIN.layers), | |
| }) | |
| # ββ WebSocket ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async def ws_stats(ws: WebSocket): | |
| await ws.accept() | |
| sid = str(uuid.uuid4()) | |
| hw = HardwareProfile(client_id=sid, compute_score=5.0) | |
| REGISTRY.register(sid, hw, ws=ws) | |
| async def push(): | |
| while True: | |
| try: | |
| await ws.send_text(json.dumps({ | |
| "type": "stats", | |
| "params": BRAIN.param_count, | |
| "iq": round(BRAIN.global_iq, 6), | |
| "loss": round(BRAIN.avg_loss, 6), | |
| "expansions": BRAIN.expansion_events, | |
| "train_steps": BRAIN.train_steps, | |
| "layers": len(BRAIN.layers), | |
| "tokens": BRAIN.total_tokens, | |
| "dataset": DS_MGR._current_name, | |
| "clients": REGISTRY.count, | |
| "steps_sec": round(COORD.steps_per_sec, 2), | |
| "workers": COORD.hw.allocated_threads, | |
| "ram_pct": round(ram_usage_fraction() * 100, 1), | |
| "exp_paused": BRAIN.expansion_paused, | |
| "fed_updates": REGISTRY.total_fed_updates, | |
| "is_hf": IS_HF_SPACES, | |
| })) | |
| except Exception: | |
| return | |
| await asyncio.sleep(1.0) | |
| async def recv(): | |
| async for raw in ws.iter_text(): | |
| try: | |
| msg = json.loads(raw) | |
| if msg.get("type") == "hw": | |
| hw.compute_score = float(msg.get("score", 5)) | |
| hw.cpu_cores_logic = int(msg.get("cores", 1)) | |
| hw.ram_avail_gb = float(msg.get("ram", 0)) | |
| hw.gpu_name = msg.get("gpu", "None") | |
| except Exception: | |
| pass | |
| try: | |
| await asyncio.gather(push(), recv()) | |
| except (WebSocketDisconnect, Exception): | |
| pass | |
| finally: | |
| REGISTRY.unregister(sid) | |
| # ============================================================================= | |
| # [ S11 FRONTEND HTML + EMBEDDED TF.JS WEBWORKER ] | |
| # ============================================================================= | |
| # | |
| # The TF.js worker is stored in a <script type="text/worker-source"> tag. | |
| # The main thread reads it, creates a Blob URL, and spawns a Worker from it. | |
| # No separate worker file is needed β everything is self-contained in app.py. | |
| # | |
| # Worker flow: | |
| # 1. Receives "init" message - builds a local TF.js sequential model. | |
| # 2. Receives "load_weights" - sets model weights from server snapshot. | |
| # 3. Continuously receives "train" messages with text snippets. | |
| # 4. For each step: snapshot weights before, run model.fit(), snapshot after, | |
| # compute delta (before - after), POST delta to /api/gradients. | |
| # 5. Reports step count and loss back to main thread for display. | |
| INDEX_HTML = r"""<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width,initial-scale=1"> | |
| <title>ScaleUp-OmegaB v4 | imsuprtwo2</title> | |
| <style> | |
| :root { | |
| --g:#00ff88; --g2:#00cc66; --r:#ff3366; --b:#00ccff; | |
| --p:#cc44ff; --y:#ffcc00; --bg:#040c08; --bg2:#071410; | |
| --dim:#152820; --dim2:#0e1f18; | |
| } | |
| *{box-sizing:border-box;margin:0;padding:0;} | |
| body{background:var(--bg);color:var(--g);font-family:'Courier New',monospace; | |
| height:100vh;display:flex;flex-direction:column;overflow:hidden;} | |
| #hdr{background:var(--bg2);border-bottom:1px solid var(--g2);padding:7px 14px; | |
| display:flex;align-items:center;justify-content:space-between;gap:6px;flex-wrap:wrap;} | |
| #hdr h1{font-size:1rem;letter-spacing:3px;text-shadow:0 0 10px var(--g);} | |
| .badges{display:flex;gap:5px;flex-wrap:wrap;} | |
| .badge{font-size:.62rem;background:var(--dim);border:1px solid var(--g2); | |
| padding:2px 7px;border-radius:3px;color:var(--b);} | |
| .badge.ok{border-color:var(--g);color:var(--g);} | |
| .badge.warn{border-color:var(--y);color:var(--y);} | |
| .badge.err{border-color:var(--r);color:var(--r);} | |
| #ribbon{background:var(--dim2);border-bottom:1px solid var(--dim); | |
| padding:4px 14px;display:flex;gap:18px;overflow-x:auto;white-space:nowrap;} | |
| .st{display:flex;flex-direction:column;align-items:center;} | |
| .st-l{color:#446;font-size:.57rem;text-transform:uppercase;letter-spacing:.5px;} | |
| .st-v{color:var(--g);font-size:.8rem;font-weight:bold;} | |
| .st-v.hot{color:var(--p);} | |
| .st-v.warn{color:var(--y);} | |
| #main{flex:1;display:grid;grid-template-columns:1fr 310px;overflow:hidden;} | |
| #term-wrap{display:flex;flex-direction:column;overflow:hidden;border-right:1px solid var(--dim);} | |
| #term{flex:1;padding:10px 12px;overflow-y:auto;display:flex;flex-direction:column; | |
| gap:3px;background:rgba(0,6,3,.97);} | |
| .ln{font-size:.78rem;line-height:1.55;} | |
| .ln.sys{color:#2a7;}.ln.usr{color:#ddd;}.ln.bot{color:var(--g);} | |
| .ln.evt{color:var(--p);}.ln.ds{color:var(--b);font-size:.7rem;} | |
| .ln.wrk{color:var(--y);font-size:.7rem;}.ln.err{color:var(--r);} | |
| .ln.ram{color:var(--y);} | |
| #input-bar{background:var(--bg2);border-top:1px solid var(--g2); | |
| padding:7px 12px;display:flex;gap:7px;} | |
| #msg{flex:1;background:#000;border:1px solid var(--g2);color:var(--g); | |
| padding:8px 11px;font-family:inherit;font-size:.82rem;outline:none;} | |
| #msg:focus{border-color:var(--g);box-shadow:0 0 6px rgba(0,255,136,.25);} | |
| #sbtn{background:var(--g);color:#000;border:none;padding:8px 16px; | |
| cursor:pointer;font-weight:bold;font-family:inherit;font-size:.82rem;} | |
| #sbtn:hover{background:var(--g2);} | |
| #side{display:flex;flex-direction:column;overflow:hidden;background:var(--bg2);} | |
| #n-wrap{flex:0 0 195px;border-bottom:1px solid var(--dim);padding:8px;} | |
| #n-wrap h2{font-size:.65rem;color:#2a7;letter-spacing:1px;margin-bottom:5px;} | |
| #nc{width:100%;height:165px;} | |
| #wk-wrap{flex:0 0 88px;border-bottom:1px solid var(--dim);padding:8px;} | |
| #wk-wrap h2{font-size:.65rem;color:#2a7;letter-spacing:1px;margin-bottom:4px;} | |
| .wk-r{font-size:.67rem;display:flex;justify-content:space-between;padding:1px 0;} | |
| .wk-v{color:var(--y);} | |
| #ds-wrap{flex:1;padding:8px;overflow-y:auto;border-bottom:1px solid var(--dim);} | |
| #ds-wrap h2{font-size:.65rem;color:#2a7;letter-spacing:1px;margin-bottom:4px;} | |
| .ds-e{font-size:.66rem;color:var(--b);padding:1px 0; | |
| border-bottom:1px solid var(--dim);opacity:.85;} | |
| #hw-wrap{padding:8px;font-size:.67rem;color:#557;} | |
| #hw-wrap h2{font-size:.65rem;color:#2a7;letter-spacing:1px;margin-bottom:4px;} | |
| .hw-r{display:flex;justify-content:space-between;padding:1px 0;} | |
| .hw-v{color:var(--g);} | |
| ::-webkit-scrollbar{width:4px;} | |
| ::-webkit-scrollbar-track{background:var(--bg);} | |
| ::-webkit-scrollbar-thumb{background:var(--g2);border-radius:2px;} | |
| @keyframes pulse{0%,100%{opacity:1}50%{opacity:.25}} | |
| </style> | |
| </head> | |
| <body> | |
| <div id="hdr"> | |
| <h1>SCALEUP-OMEGAB <span style="font-size:.65rem;color:#2a7;letter-spacing:1px">v4 FEDERATED Β· imsuprtwo2</span></h1> | |
| <div class="badges"> | |
| <span class="badge" id="b-env">ENV: β</span> | |
| <span class="badge" id="b-cli">0 CLIENTS</span> | |
| <span class="badge" id="b-wk">WORKER: β</span> | |
| <span class="badge" id="b-fed">FED: 0</span> | |
| <span class="badge" id="b-net">WS: β</span> | |
| </div> | |
| </div> | |
| <div id="ribbon"> | |
| <div class="st"><span class="st-l">PARAMS</span><span class="st-v" id="r-p">β</span></div> | |
| <div class="st"><span class="st-l">IQ</span><span class="st-v" id="r-iq">β</span></div> | |
| <div class="st"><span class="st-l">LOSS</span><span class="st-v" id="r-l">β</span></div> | |
| <div class="st"><span class="st-l">EXPANSIONS</span><span class="st-v" id="r-e">β</span></div> | |
| <div class="st"><span class="st-l">LAYERS</span><span class="st-v" id="r-ly">β</span></div> | |
| <div class="st"><span class="st-l">TRAIN STEPS</span><span class="st-v" id="r-ts">β</span></div> | |
| <div class="st"><span class="st-l">TOKENS</span><span class="st-v" id="r-tk">β</span></div> | |
| <div class="st"><span class="st-l">STEPS/s</span><span class="st-v" id="r-sps">β</span></div> | |
| <div class="st"><span class="st-l">RAM</span><span class="st-v" id="r-ram">β</span></div> | |
| </div> | |
| <div id="main"> | |
| <div id="term-wrap"> | |
| <div id="term"></div> | |
| <div id="input-bar"> | |
| <input id="msg" type="text" placeholder="Send a message β your PC trains on it in real-timeβ¦" | |
| autocomplete="off" onkeydown="if(event.key==='Enter')send()"> | |
| <button id="sbtn" onclick="send()">TRANSMIT</button> | |
| </div> | |
| </div> | |
| <div id="side"> | |
| <div id="n-wrap"> | |
| <h2>NEURAL ARCHITECTURE</h2> | |
| <canvas id="nc"></canvas> | |
| </div> | |
| <div id="wk-wrap"> | |
| <h2>BROWSER WORKER (YOUR PC)</h2> | |
| <div class="wk-r"><span>Status</span><span class="wk-v" id="wk-st">Loading TF.jsβ¦</span></div> | |
| <div class="wk-r"><span>Local steps</span><span class="wk-v" id="wk-steps">0</span></div> | |
| <div class="wk-r"><span>Last loss</span><span class="wk-v" id="wk-loss">β</span></div> | |
| <div class="wk-r"><span>Grads sent</span><span class="wk-v" id="wk-grads">0</span></div> | |
| </div> | |
| <div id="ds-wrap"> | |
| <h2>DATASET STREAM</h2> | |
| <div id="ds-log"></div> | |
| </div> | |
| <div id="hw-wrap"> | |
| <h2>LOCAL HARDWARE</h2> | |
| <div class="hw-r"><span>CPU cores</span><span class="hw-v" id="hw-c">β</span></div> | |
| <div class="hw-r"><span>RAM</span><span class="hw-v" id="hw-r">β</span></div> | |
| <div class="hw-r"><span>GPU</span><span class="hw-v" id="hw-g">β</span></div> | |
| <div class="hw-r"><span>Compute score</span><span class="hw-v" id="hw-s">β</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| TF.JS WEBWORKER SOURCE | |
| Stored in a non-executable script tag, read by JS, turned into a Blob URL. | |
| The worker loads TensorFlow.js, trains a local model on incoming text, | |
| computes weight deltas (before - after fit), and POSTs them to the server. | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <script id="worker-src" type="text/worker-source"> | |
| importScripts('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.17.0/dist/tf.min.js'); | |
| const INPUT_DIM = 128; | |
| let model = null; | |
| let localSteps = 0; | |
| let gradsSent = 0; | |
| let SESSION_ID = ''; | |
| let SERVER_URL = ''; | |
| let SEND_EVERY = 5; | |
| // Build a local sequential model matching a slice of the server architecture | |
| function buildModel(sizes) { | |
| const m = tf.sequential(); | |
| for (let i = 1; i < sizes.length; i++) { | |
| const cfg = { | |
| units: sizes[i], | |
| useBias: true, | |
| activation: i < sizes.length - 1 ? 'elu' : 'linear', | |
| kernelInitializer: 'glorotNormal', | |
| biasInitializer: 'zeros', | |
| }; | |
| if (i === 1) cfg.inputShape = [sizes[0]]; | |
| m.add(tf.layers.dense(cfg)); | |
| } | |
| m.compile({ optimizer: tf.train.adam(0.0005), loss: 'meanSquaredError' }); | |
| return m; | |
| } | |
| // Set weights from server-provided flat arrays | |
| function applyServerWeights(serverLayers) { | |
| if (!model) return; | |
| const trainable = model.layers.filter(l => l.getWeights().length > 0); | |
| serverLayers.forEach((sl, i) => { | |
| if (i >= trainable.length) return; | |
| try { | |
| const Wflat = new Float32Array(sl.W.flat ? sl.W.flat(Infinity) : sl.W); | |
| const bflat = new Float32Array(sl.b.flat ? sl.b.flat(Infinity) : sl.b); | |
| const Wt = tf.tensor(Wflat, sl.W_shape); | |
| const bt = tf.tensor(bflat, sl.b_shape); | |
| trainable[i].setWeights([Wt, bt]); | |
| Wt.dispose(); bt.dispose(); | |
| } catch(e) { /* shape mismatch - skip */ } | |
| }); | |
| } | |
| // Convert a text string to a pair of (input, target) 2D tensors | |
| function textToTensors(text, batchSize) { | |
| const chars = []; | |
| for (let i = 0; i < text.length; i++) chars.push(text.charCodeAt(i) / 255.0); | |
| while (chars.length < INPUT_DIM + 2) chars.push(0); | |
| const xs = [], ys = []; | |
| const limit = Math.min(batchSize, chars.length - INPUT_DIM - 1); | |
| for (let k = 0; k < limit; k++) { | |
| const off = Math.floor(Math.random() * (chars.length - INPUT_DIM - 1)); | |
| xs.push(chars.slice(off, off + INPUT_DIM)); | |
| ys.push(chars.slice(off + 1, off + 1 + INPUT_DIM)); | |
| } | |
| if (xs.length === 0) return null; | |
| return [tf.tensor2d(xs), tf.tensor2d(ys)]; | |
| } | |
| // One training step. Returns {loss, deltas} or null. | |
| async function trainStep(text, batchSize) { | |
| if (!model || !text || text.length < 12) return null; | |
| const trainable = model.layers.filter(l => l.getWeights().length > 0); | |
| // Snapshot weights before fit | |
| const before = trainable.map(l => | |
| l.getWeights().map(w => ({ data: w.dataSync().slice(), shape: w.shape })) | |
| ); | |
| const tensors = textToTensors(text, batchSize); | |
| if (!tensors) return null; | |
| const [xs, ys] = tensors; | |
| let loss = 1.0; | |
| try { | |
| const h = await model.fit(xs, ys, { epochs: 1, verbose: 0, batchSize }); | |
| loss = h.history.loss[0]; | |
| } finally { | |
| xs.dispose(); ys.dispose(); | |
| } | |
| // Compute deltas: before - after (what the optimizer subtracted) | |
| const deltas = trainable.map((l, li) => { | |
| const after = l.getWeights(); | |
| const result = { W: null, b: null, W_shape: null, b_shape: null }; | |
| after.forEach((w, wi) => { | |
| const bef = before[li][wi]; | |
| const aft = w.dataSync(); | |
| const delta = Array.from(bef.data).map((v, j) => v - aft[j]); | |
| if (w.shape.length === 2) { | |
| result.W = delta; | |
| result.W_shape = w.shape; | |
| } else { | |
| result.b = delta; | |
| result.b_shape = w.shape; | |
| } | |
| w.dispose(); | |
| }); | |
| return result; | |
| }).filter(d => d.W !== null && d.b !== null); | |
| return { loss, deltas }; | |
| } | |
| async function postGradients(deltas) { | |
| if (!deltas || deltas.length === 0 || !SERVER_URL || !SESSION_ID) return; | |
| try { | |
| const res = await fetch(SERVER_URL + '/api/gradients', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| session_id: SESSION_ID, | |
| weight: 1.0, | |
| gradients: deltas, | |
| }), | |
| }); | |
| if (res.ok) { | |
| gradsSent++; | |
| self.postMessage({ type: 'grads_sent', count: gradsSent }); | |
| } | |
| } catch(e) { /* network error β silently skip */ } | |
| } | |
| self.onmessage = async (e) => { | |
| const msg = e.data; | |
| if (msg.type === 'init') { | |
| SESSION_ID = msg.sessionId; | |
| SERVER_URL = msg.serverUrl; | |
| SEND_EVERY = msg.sendEvery || 5; | |
| const sizes = msg.layerSizes || [INPUT_DIM, 512, 256, INPUT_DIM]; | |
| model = buildModel(sizes); | |
| self.postMessage({ type: 'ready' }); | |
| return; | |
| } | |
| if (msg.type === 'load_weights') { | |
| applyServerWeights(msg.layers); | |
| self.postMessage({ type: 'weights_loaded' }); | |
| return; | |
| } | |
| if (msg.type === 'train') { | |
| const r = await trainStep(msg.text, msg.batchSize || 8); | |
| if (!r) return; | |
| localSteps++; | |
| self.postMessage({ type: 'step_done', loss: r.loss, step: localSteps }); | |
| if (localSteps % SEND_EVERY === 0) { | |
| await postGradients(r.deltas); | |
| } | |
| return; | |
| } | |
| // Immediate flush (called when user sends a chat message) | |
| if (msg.type === 'flush') { | |
| const r = await trainStep(msg.text || 'neural network training', 8); | |
| if (r) await postGradients(r.deltas); | |
| return; | |
| } | |
| }; | |
| </script> | |
| <script> | |
| // ============================================================================= | |
| // MAIN THREAD | |
| // ============================================================================= | |
| const SESSION_ID = crypto.randomUUID(); | |
| const SERVER_URL = location.origin; | |
| let ws, wsOk = false; | |
| let worker, workerReady = false; | |
| let workerGrads = 0; | |
| let layerShapes = []; | |
| let prevParams = 0, prevExp = 0; | |
| let trainingText = ''; | |
| let hwScore = 0; | |
| let lastDataset = ''; | |
| // ============================================================================= | |
| // WORKER | |
| // ============================================================================= | |
| function initWorker() { | |
| const src = document.getElementById('worker-src').textContent; | |
| const blob = new Blob([src], { type: 'application/javascript' }); | |
| worker = new Worker(URL.createObjectURL(blob)); | |
| worker.onmessage = e => { | |
| const m = e.data; | |
| if (m.type === 'ready') { | |
| workerReady = true; | |
| setEl('wk-st', 'Active (TF.js)'); | |
| setEl('b-wk', 'WORKER: RUNNING'); | |
| setBadge('b-wk', 'ok'); | |
| addLog('wrk', 'TF.js worker ready. Your PC is now training the model.'); | |
| syncWeights(); | |
| localTrainLoop(); | |
| } | |
| if (m.type === 'step_done') { | |
| setEl('wk-steps', m.step); | |
| setEl('wk-loss', m.loss.toFixed(5)); | |
| } | |
| if (m.type === 'grads_sent') { | |
| workerGrads = m.count; | |
| setEl('wk-grads', workerGrads); | |
| setEl('b-fed', 'FED: ' + workerGrads); | |
| } | |
| }; | |
| worker.onerror = err => { | |
| setEl('wk-st', 'Error'); | |
| setBadge('b-wk', 'err'); | |
| addLog('err', 'Worker error: ' + err.message); | |
| }; | |
| worker.postMessage({ | |
| type: 'init', | |
| sessionId: SESSION_ID, | |
| serverUrl: SERVER_URL, | |
| sendEvery: 5, | |
| layerSizes: [128, 512, 256, 128], | |
| }); | |
| } | |
| async function syncWeights() { | |
| try { | |
| const res = await fetch('/api/weight_subset?n_layers=3'); | |
| const data = await res.json(); | |
| if (data.layers && workerReady) { | |
| worker.postMessage({ type: 'load_weights', layers: data.layers }); | |
| } | |
| } catch(e) {} | |
| } | |
| async function localTrainLoop() { | |
| while (true) { | |
| await sleep(150); | |
| if (!workerReady) continue; | |
| const text = trainingText || fallbackText(); | |
| worker.postMessage({ type: 'train', text, batchSize: 8 }); | |
| } | |
| } | |
| function fallbackText() { | |
| const pool = [ | |
| 'neural networks learn through backpropagation and gradient descent optimisation', | |
| 'federated learning trains models across distributed devices without sharing raw data', | |
| 'transformer architectures use self-attention to model long-range sequence dependencies', | |
| 'neurogenesis events expand the model capacity by inserting new hidden layers', | |
| 'adagrad adapts the learning rate per parameter based on historical gradient magnitudes', | |
| 'dynamic synaptic expansion grows the architecture based on prediction error signals', | |
| ]; | |
| return pool[Math.floor(Math.random() * pool.length)]; | |
| } | |
| // ============================================================================= | |
| // HARDWARE SCAN | |
| // ============================================================================= | |
| async function scanHW() { | |
| const cores = navigator.hardwareConcurrency || 2; | |
| const ram = navigator.deviceMemory || 2; | |
| let gpuName = 'None', gpuVram = 0; | |
| try { | |
| const c = document.createElement('canvas'); | |
| const gl = c.getContext('webgl') || c.getContext('experimental-webgl'); | |
| if (gl) { | |
| const ext = gl.getExtension('WEBGL_debug_renderer_info'); | |
| if (ext) { | |
| gpuName = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL).replace(/\s+/g, ' ').trim(); | |
| const m = gpuName.match(/(\d+)\s*GB/i); | |
| gpuVram = m ? parseInt(m[1]) : 0; | |
| } | |
| } | |
| } catch(e) {} | |
| hwScore = cores * 1.5 + ram * 4 + gpuVram * 80; | |
| setEl('hw-c', cores); | |
| setEl('hw-r', ram + ' GB'); | |
| setEl('hw-g', gpuName.substring(0, 22)); | |
| setEl('hw-s', hwScore.toFixed(1)); | |
| try { | |
| await fetch('/api/hardware_report', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| session_id: SESSION_ID, | |
| cpu_cores: cores, | |
| ram_gb: ram, | |
| gpu_name: gpuName, | |
| gpu_vram_gb: gpuVram, | |
| compute_score:hwScore, | |
| }), | |
| }); | |
| } catch(e) {} | |
| } | |
| // ============================================================================= | |
| // WEBSOCKET | |
| // ============================================================================= | |
| function connectWS() { | |
| const proto = location.protocol === 'https:' ? 'wss' : 'ws'; | |
| ws = new WebSocket(`${proto}://${location.host}/ws/stats`); | |
| setEl('b-net', 'WS: Connectingβ¦'); | |
| ws.onopen = async () => { | |
| wsOk = true; | |
| setEl('b-net', 'WS: Connected'); | |
| setBadge('b-net', 'ok'); | |
| const hw = await scanHW(); | |
| ws.send(JSON.stringify({ type: 'hw', score: hwScore, cores: hw.cores, ram: hw.ram, gpu: hw.gpuName })); | |
| addLog('sys', `WebSocket connected | Session: ${SESSION_ID.substring(0, 12)}...`); | |
| fetchArch(); | |
| }; | |
| ws.onmessage = e => { try { applyStats(JSON.parse(e.data)); } catch(_) {} }; | |
| ws.onclose = () => { wsOk = false; setEl('b-net', 'WS: Reconnectingβ¦'); setBadge('b-net', 'warn'); setTimeout(connectWS, 3000); }; | |
| ws.onerror = () => ws.close(); | |
| } | |
| // ============================================================================= | |
| // STATS | |
| // ============================================================================= | |
| const fmt = n => Number(n).toLocaleString(); | |
| function applyStats(s) { | |
| setEl('r-p', fmt(s.params)); | |
| setEl('r-iq', s.iq); | |
| setEl('r-l', s.loss); | |
| setEl('r-e', s.expansions); | |
| setEl('r-ly', s.layers); | |
| setEl('r-ts', fmt(s.train_steps)); | |
| setEl('r-tk', fmt(s.tokens)); | |
| setEl('r-sps', s.steps_sec); | |
| const ramEl = document.getElementById('r-ram'); | |
| ramEl.textContent = s.ram_pct + '%'; | |
| ramEl.className = s.ram_pct > 80 ? 'st-v warn' : 'st-v'; | |
| setEl('b-cli', s.clients + ' CLIENTS'); | |
| setEl('b-fed', 'FED: ' + s.fed_updates); | |
| const bEnv = document.getElementById('b-env'); | |
| bEnv.textContent = s.is_hf ? 'HF SPACES' : 'LOCAL'; | |
| bEnv.className = s.is_hf ? 'badge warn' : 'badge ok'; | |
| if (s.exp_paused) { | |
| addLog('ram', 'Expansion paused β RAM at ' + s.ram_pct + '%. Training continues at current architecture.'); | |
| } | |
| if (s.expansions > prevExp) { | |
| addLog('evt', 'NEUROGENESIS #' + s.expansions + ' β params now ' + fmt(s.params)); | |
| prevExp = s.expansions; | |
| fetchArch(); | |
| syncWeights(); | |
| } | |
| if (s.dataset !== lastDataset) { | |
| lastDataset = s.dataset; | |
| const short = s.dataset.split('/').pop().substring(0, 28); | |
| addLog('ds', 'Dataset switch: ' + short); | |
| prependDs(s.dataset); | |
| } | |
| if (s.params !== prevParams && prevParams !== 0) { | |
| const el = document.getElementById('r-p'); | |
| el.className = 'st-v hot'; | |
| setTimeout(() => { el.className = 'st-v'; }, 2000); | |
| } | |
| prevParams = s.params; | |
| } | |
| // ============================================================================= | |
| // ARCHITECTURE DIAGRAM | |
| // ============================================================================= | |
| async function fetchArch() { | |
| try { | |
| const r = await fetch('/api/architecture'); | |
| const d = await r.json(); | |
| layerShapes = d.layers; | |
| drawNeuro(layerShapes); | |
| } catch(e) {} | |
| } | |
| function drawNeuro(layers) { | |
| const c = document.getElementById('nc'); | |
| c.width = c.offsetWidth; | |
| c.height = c.offsetHeight; | |
| const ctx = c.getContext('2d'); | |
| const W = c.width, H = c.height; | |
| ctx.clearRect(0, 0, W, H); | |
| if (!layers || !layers.length) return; | |
| const MAX = 12; | |
| const colW = W / layers.length; | |
| layers.forEach((layer, ci) => { | |
| const x = ci * colW + colW / 2; | |
| const n = Math.min(layer.fan_in, MAX); | |
| const dy = H / (n + 1); | |
| if (ci < layers.length - 1) { | |
| const nx = (ci + 1) * colW + colW / 2; | |
| const nn = Math.min(layers[ci + 1].fan_in, MAX); | |
| const ndy = H / (nn + 1); | |
| for (let a = 0; a < n; a++) for (let b = 0; b < nn; b++) { | |
| ctx.beginPath(); | |
| ctx.moveTo(x, (a + 1) * dy); | |
| ctx.lineTo(nx, (b + 1) * ndy); | |
| ctx.strokeStyle = 'rgba(0,255,136,.07)'; | |
| ctx.lineWidth = 0.4; | |
| ctx.stroke(); | |
| } | |
| } | |
| for (let ni = 0; ni < n; ni++) { | |
| ctx.beginPath(); | |
| ctx.arc(x, (ni + 1) * dy, 2.5, 0, Math.PI * 2); | |
| ctx.fillStyle = '#00ff88'; | |
| ctx.shadowBlur = 5; | |
| ctx.shadowColor = '#00ff88'; | |
| ctx.fill(); | |
| ctx.shadowBlur = 0; | |
| } | |
| ctx.fillStyle = 'rgba(0,204,102,.6)'; | |
| ctx.font = '8px Courier New'; | |
| ctx.textAlign = 'center'; | |
| ctx.fillText(layer.fan_out, x, H - 1); | |
| }); | |
| } | |
| // ============================================================================= | |
| // TERMINAL | |
| // ============================================================================= | |
| function addLog(cls, text) { | |
| const term = document.getElementById('term'); | |
| const d = document.createElement('div'); | |
| d.className = 'ln ' + cls; | |
| d.textContent= '[' + new Date().toTimeString().slice(0, 8) + '] ' + text; | |
| term.appendChild(d); | |
| term.scrollTop = term.scrollHeight; | |
| while (term.children.length > 400) term.removeChild(term.firstChild); | |
| } | |
| function prependDs(name) { | |
| const c = document.getElementById('ds-log'); | |
| const d = document.createElement('div'); | |
| d.className = 'ds-e'; | |
| d.textContent = '[' + new Date().toTimeString().slice(0, 8) + '] ' + name; | |
| c.prepend(d); | |
| while (c.children.length > 25) c.removeChild(c.lastChild); | |
| } | |
| // ============================================================================= | |
| // CHAT | |
| // ============================================================================= | |
| async function send() { | |
| const inp = document.getElementById('msg'); | |
| const text = inp.value.trim(); | |
| if (!text) return; | |
| inp.value = ''; | |
| addLog('usr', 'YOU: ' + text); | |
| // Flush worker training on the user message immediately | |
| if (workerReady) { | |
| worker.postMessage({ type: 'flush', text }); | |
| trainingText = text; | |
| } | |
| try { | |
| const res = await fetch('/api/chat', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ message: text, session_id: SESSION_ID }), | |
| }); | |
| const data = await res.json(); | |
| if (data.expanded) { | |
| addLog('evt', 'NEUROGENESIS β now ' + fmt(data.total_params) + ' params (' + data.layer_count + ' layers)'); | |
| } | |
| addLog('bot', 'OMEGA: ' + data.reply); | |
| } catch(e) { | |
| addLog('err', 'Request failed: ' + e.message); | |
| } | |
| } | |
| // ============================================================================= | |
| // DATASET LOG POLL | |
| // ============================================================================= | |
| async function pollDsLog() { | |
| try { | |
| const r = await fetch('/api/status'); | |
| const data = await r.json(); | |
| const log = (data.dataset.recent_log || []).slice(-3); | |
| const dsEl = document.getElementById('ds-log'); | |
| log.forEach(entry => { | |
| if (!dsEl.innerHTML.includes(entry.substring(12, 30))) prependDs(entry); | |
| }); | |
| } catch(e) {} | |
| } | |
| // ============================================================================= | |
| // HELPERS | |
| // ============================================================================= | |
| function setEl(id, val) { const e = document.getElementById(id); if (e) e.textContent = val; } | |
| function setBadge(id, cls) { const e = document.getElementById(id); if (e) e.className = 'badge ' + cls; } | |
| function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } | |
| // ============================================================================= | |
| // BOOT | |
| // ============================================================================= | |
| window.onload = () => { | |
| addLog('sys', 'ScaleUp-OmegaB v4 β Federated Infinite Expansion β imsuprtwo2'); | |
| addLog('sys', 'Session: ' + SESSION_ID.substring(0, 16) + '...'); | |
| addLog('sys', 'Connecting to server...'); | |
| connectWS(); | |
| addLog('sys', 'Initialising TF.js browser worker...'); | |
| initWorker(); | |
| setInterval(pollDsLog, 6000); | |
| setInterval(fetchArch, 20000); | |
| setInterval(syncWeights, 60000); | |
| }; | |
| window.addEventListener('resize', () => drawNeuro(layerShapes)); | |
| </script> | |
| </body> | |
| </html>""" | |
| async def home(): | |
| return INDEX_HTML | |
| # ============================================================================= | |
| # [ S12 LIFECYCLE + ENTRY POINT ] | |
| # ============================================================================= | |
| async def on_startup(): | |
| log.info("=" * 72) | |
| log.info(" ScaleUp-OmegaB v4 | imsuprtwo2 | FEDERATED INFINITE EXPANSION") | |
| log.info(f" Environment : {'HuggingFace Spaces' if IS_HF_SPACES else 'Local / custom'}") | |
| log.info(f" Server HW score : {SERVER_HW.compute_score:.1f} " | |
| f"cores={SERVER_HW.cpu_cores_logic} gpu={SERVER_HW.gpu_name}") | |
| log.info(f" Brain seed : {BRAIN.param_count:,} params / {len(BRAIN.layers)} layers") | |
| log.info(f" Training workers: {COORD.hw.allocated_threads} " | |
| f"(batch={COORD.hw.allocated_batch})") | |
| log.info(f" HF persistence : " | |
| f"{'ENABLED -> ' + HF_REPO_ID if HF_TOKEN else 'DISABLED (set HF_TOKEN)'}") | |
| log.info(f" Dataset cycling : " | |
| f"{'ENABLED' if HAS_DATASETS else 'DISABLED (pip install datasets)'}") | |
| log.info(f" RAM guard : expansion pauses above {RAM_EXPAND_CEILING*100:.0f}%") | |
| log.info("=" * 72) | |
| async def on_shutdown(): | |
| COORD.stop() | |
| log.info("[SHUTDOWN] Saving final checkpoint...") | |
| try: | |
| BRAIN.hf.push(BRAIN.snapshot(), BRAIN.status) | |
| log.info("[SHUTDOWN] Checkpoint pushed.") | |
| except Exception as e: | |
| log.warning(f"[SHUTDOWN] Checkpoint failed: {e}") | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run("app:app", host="0.0.0.0", port=PORT, workers=1, log_level="info") | |