#!/usr/bin/env python3 """ FSI_ECHO - Morphing Code Swarm Novel architecture: token morph embedding + nanobot swarm + assembly blocks + self-verification. 2.6M params — fits in 1.3MB at q4, runs on any phone. """ import os, sys, json, time, math, random, re, struct from typing import List, Dict, Optional, Tuple import torch import torch.nn as nn import torch.nn.functional as F # ============================================================================= # 1. TOKENIZER # ============================================================================= class CodeTokenizer: SPECIAL = { '': 0, '': 1, '': 2, '': 3, '': 4, '': 5, '': 6, '': 7, '': 8, '': 9, '': 10, '': 11, } def __init__(self, vocab_size: int = 4096): self.vocab_size = vocab_size self.vocab = dict(self.SPECIAL) self.inverse = {v: k for k, v in self.SPECIAL.items()} self.next_id = len(self.SPECIAL) self._build() def _build(self): for i in range(32, 127): self._add(chr(i)) for t in ['def','class','return','if','else','elif','for','while','in','not', 'and','or','import','from','as','try','except','finally','raise','with', 'pass','break','continue','yield','lambda','self','None','True','False', 'async','await','global','nonlocal','assert','del','print','len','range', 'int','str','float','list','dict','set','tuple','type','is','isinstance', 'hasattr','getattr','setattr','super','open','Exception','ValueError', 'TypeError','KeyError','IndexError','AttributeError','ImportError', 'Error','Warning','property','staticmethod','classmethod']: self._add(t) for s in ['==','!=','<=','>=','->','+=','-=','*=','/=','//=','**=','%=', '<<','>>','**','//','::','=>','++','--','...']: self._add(s) for t in ['fn','func','function','const','let','var','this','typeof','void', 'null','undefined','prototype','module','exports','require','new','delete', 'throw','catch','switch','case','default','do','while','interface','enum', 'implements','private','public','protected','abstract','final','static', 'package','boolean','byte','char','double','float','int','long','short', 'printf','scanf','malloc','free','sizeof','typedef','struct','union', 'include','define','template','typename','namespace','using','virtual', 'override','friend','operator','inline','explicit','string','vector', 'map','set','auto','decltype','noexcept','constexpr','std','cout','cin', 'endl','printf','scanf','NULL','nullptr','true','false','bool']: self._add(t) while self.next_id < self.vocab_size: self._add(f'v{self.next_id}') def _add(self, t): if t not in self.vocab and self.next_id < self.vocab_size: self.vocab[t] = self.next_id self.inverse[self.next_id] = t self.next_id += 1 def encode(self, text: str, bos: bool = True, eos: bool = False) -> List[int]: ids = [] if bos: ids.append(2) for token in re.findall(r'<[^>]+>|[A-Za-z_][A-Za-z0-9_]*|\.\.\.|==|!=|<=|>=|->|\*\*|//|::|=>|\d+\.\d*|\d+|\S', text): if token in self.vocab: ids.append(self.vocab[token]) elif token.lower() in self.vocab: ids.append(self.vocab[token.lower()]) else: for ch in token: if ch in self.vocab: ids.append(self.vocab[ch]) else: ids.append(3) if eos: ids.append(1) return ids[:2048] def decode(self, ids: List[int], skip_special: bool = True) -> str: tokens = [] for i in ids: if i in self.inverse: t = self.inverse[i] if skip_special and t.startswith('<') and t.endswith('>'): continue tokens.append(t) else: tokens.append(' ') return ''.join(tokens) @property def pad_id(self): return 0 @property def eos_id(self): return 1 @property def bos_id(self): return 2 @property def vocab_size_(self): return len(self.vocab) # ============================================================================= # 2. MORPH EMBEDDING # ============================================================================= class MorphEmbedding(nn.Module): def __init__(self, vocab_size: int, d_model: int, morph_width: int = 3): super().__init__() self.d_model = d_model self.morph_width = morph_width self.base_embed = nn.Embedding(vocab_size, d_model) # Causal morph: only current + past (morph_width tokens, no future leakage) self.morph_net = nn.Sequential( nn.Linear(d_model * morph_width, d_model), nn.Tanh(), nn.Linear(d_model, d_model), ) self.gate = nn.Linear(d_model * 2, d_model) def forward(self, tokens: torch.Tensor) -> torch.Tensor: B, T = tokens.shape base = self.base_embed(tokens) # Causal sliding window: each position only sees itself and preceding tokens padded = F.pad(base, (0, 0, self.morph_width - 1, 0), mode='replicate') contexts = [] for i in range(self.morph_width): contexts.append(padded[:, i:i+T, :]) context = torch.cat(contexts, dim=-1) morph = self.morph_net(context) gate = torch.sigmoid(self.gate(torch.cat([base, morph], dim=-1))) return base + gate * morph # ============================================================================= # 3. NANOBOT SWARM # ============================================================================= class NanobotSwarm(nn.Module): def __init__(self, d_model: int, n_nanobots: int = 512, scout_dim: int = 64, combat_dim: int = 128): super().__init__() self.d_model = d_model self.n_nanobots = n_nanobots self.nano_keys = nn.Parameter(torch.randn(n_nanobots, d_model // 4)) self.nano_vals = nn.Parameter(torch.randn(n_nanobots, d_model)) self.scout_ffn = nn.Sequential( nn.Linear(d_model, scout_dim), nn.GELU(), nn.Linear(scout_dim, d_model), ) self.combat_ffn = nn.Sequential( nn.Linear(d_model, combat_dim), nn.GELU(), nn.Linear(combat_dim, d_model), ) self.mode_router = nn.Linear(d_model, 2) self.assembly = nn.Linear(d_model, d_model) self.norm = nn.LayerNorm(d_model) self.dropout = nn.Dropout(0.1) def forward(self, x: torch.Tensor) -> torch.Tensor: B, T, D = x.shape residual = x x = self.norm(x) router_query = x[..., :self.d_model // 4] nano_scores = torch.matmul(router_query, self.nano_keys.T) nano_weights = F.softmax(nano_scores / math.sqrt(self.d_model // 4), dim=-1) mode_logits = self.mode_router(x) mode_w = F.softmax(mode_logits, dim=-1) scout_out = self.scout_ffn(x) combat_out = self.combat_ffn(x) mode_out = mode_w[:, :, 0:1] * scout_out + mode_w[:, :, 1:2] * combat_out nano_out = torch.matmul(nano_weights, self.nano_vals) out = residual + self.dropout(self.assembly(mode_out + nano_out)) return out # ============================================================================= # 4. ASSEMBLY BLOCK # ============================================================================= class AssemblyBlock(nn.Module): def __init__(self, d_model: int, n_heads: int = 4, dropout: float = 0.1): super().__init__() self.d_model = d_model self.n_heads = n_heads self.head_dim = d_model // n_heads self.qkv = nn.Linear(d_model, 3 * d_model, bias=False) self.proj = nn.Linear(d_model, d_model, bias=False) self.ffn = nn.Sequential( nn.Linear(d_model, d_model * 2), nn.GELU(), nn.Linear(d_model * 2, d_model), nn.Dropout(dropout), ) self.adapt_gate = nn.Linear(d_model, 1) self.norm1 = nn.LayerNorm(d_model) self.norm2 = nn.LayerNorm(d_model) self.dropout = nn.Dropout(dropout) def forward(self, x: torch.Tensor) -> torch.Tensor: B, T, D = x.shape qkv = self.qkv(self.norm1(x)) qkv = qkv.reshape(B, T, 3, self.n_heads, self.head_dim) q, k, v = qkv[:, :, 0], qkv[:, :, 1], qkv[:, :, 2] q, k, v = q.transpose(1, 2), k.transpose(1, 2), v.transpose(1, 2) scale = math.sqrt(self.head_dim) attn = torch.matmul(q, k.transpose(-2, -1)) / scale mask = torch.triu(torch.ones(T, T, device=x.device) * float('-inf'), diagonal=1) attn = attn + mask.unsqueeze(0) attn = F.softmax(attn, dim=-1) out = torch.matmul(attn, v).transpose(1, 2).reshape(B, T, D) out = self.proj(out) x = x + self.dropout(out) gate = torch.sigmoid(self.adapt_gate(self.norm2(x))) x = x + gate * self.dropout(self.ffn(self.norm2(x))) return x # ============================================================================= # 5. FSI_ECHO MODEL # ============================================================================= class FSIEchoModel(nn.Module): def __init__(self, vocab_size: int = 4096, d_model: int = 192, n_swarm_layers: int = 3, n_assembly_layers: int = 3, n_nanobots: int = 512): super().__init__() self.vocab_size = vocab_size self.d_model = d_model self.morph_embed = MorphEmbedding(vocab_size, d_model) self.swarm_layers = nn.ModuleList([ NanobotSwarm(d_model, n_nanobots) for _ in range(n_swarm_layers) ]) self.assembly_layers = nn.ModuleList([ AssemblyBlock(d_model) for _ in range(n_assembly_layers) ]) self.norm = nn.LayerNorm(d_model) self.verify = nn.Sequential( nn.Linear(d_model, d_model // 2), nn.GELU(), nn.Linear(d_model // 2, 1), ) self.lm_head = nn.Linear(d_model, vocab_size, bias=False) self.lm_head.weight = self.morph_embed.base_embed.weight self._init_weights() def _init_weights(self): for m in self.modules(): if isinstance(m, (nn.Linear, nn.Embedding)): nn.init.normal_(m.weight, mean=0.0, std=0.02) if hasattr(m, 'bias') and m.bias is not None: nn.init.zeros_(m.bias) elif isinstance(m, nn.LayerNorm): nn.init.ones_(m.weight) nn.init.zeros_(m.bias) def forward(self, tokens: torch.Tensor, targets: Optional[torch.Tensor] = None) -> Dict: x = self.morph_embed(tokens) for layer in self.swarm_layers: x = layer(x) for layer in self.assembly_layers: x = layer(x) x = self.norm(x) logits = self.lm_head(x) confidence = torch.sigmoid(self.verify(x)).squeeze(-1) loss = None if targets is not None: loss = F.cross_entropy(logits.view(-1, self.vocab_size), targets.view(-1), ignore_index=0) return {'logits': logits, 'confidence': confidence, 'loss': loss} @torch.no_grad() def generate(self, tokenizer, prompt: str, max_tokens: int = 512, temperature: float = 0.3, top_k: int = 5, top_p: float = 0.9) -> Dict: self.eval() device = next(self.parameters()).device toks = torch.tensor([tokenizer.encode(prompt)], dtype=torch.long, device=device) generated_ids = [] confs = [] for _ in range(min(max_tokens, 2048 - toks.shape[1])): out = self.forward(toks) logits = out['logits'][0, -1, :] / max(temperature, 0.01) if top_k > 0: vals, _ = torch.topk(logits, min(top_k, logits.size(-1))) logits[logits < vals[-1]] = float('-inf') if top_p < 1.0: sorted_lg, sorted_idx = torch.sort(logits, descending=True) cum = torch.cumsum(F.softmax(sorted_lg, dim=-1), dim=-1) rm = cum > top_p rm[1:] = rm[:-1].clone() rm[0] = False logits[sorted_idx[rm]] = float('-inf') logits = torch.nan_to_num(logits, nan=-100.0, posinf=100.0, neginf=-100.0) logits[0] = float('-inf') for rid in range(300, logits.size(-1)): logits[rid] = float('-inf') if (logits > float(-1e9)).sum() == 0: logits[tokenizer.eos_id] = 0.0 nxt = logits.argmax().unsqueeze(0) confs.append(out['confidence'][0, -1].item()) if nxt.item() == tokenizer.eos_id: break generated_ids.append(nxt.item()) toks = torch.cat([toks, nxt.unsqueeze(0)], dim=1) generated = tokenizer.decode(generated_ids, skip_special=True) avg_conf = sum(confs) / max(len(confs), 1) return {'generated': generated, 'confidence': avg_conf, 'tokens': len(generated_ids)} def param_count(self) -> int: return sum(p.numel() for p in self.parameters()) # ============================================================================= # 6. TRAINER # ============================================================================= class Trainer: def __init__(self, model: FSIEchoModel, tokenizer: CodeTokenizer, lr: float = 3e-4): self.model = model self.tokenizer = tokenizer self.optimizer = torch.optim.AdamW(model.parameters(), lr=lr, betas=(0.9, 0.95), weight_decay=0.1) self.scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(self.optimizer, T_max=5000, eta_min=1e-5) def step(self, texts: List[str], batch_size: int = 2, device: str = 'cpu') -> float: self.model.train() batch = random.sample(texts, min(batch_size, len(texts))) encoded = [] max_len = 0 for t in batch: toks = self.tokenizer.encode(t) if 5 < len(toks) <= 2048: encoded.append(toks) max_len = max(max_len, len(toks)) if not encoded: return 0.0 padded = torch.zeros(len(encoded), max_len, dtype=torch.long) targets = torch.full((len(encoded), max_len), 0, dtype=torch.long) for i, toks in enumerate(encoded): padded[i, :len(toks)] = torch.tensor(toks) targets[i, :len(toks)-1] = torch.tensor(toks[1:]) targets[i, len(toks)-1] = 1 padded, targets = padded.to(device), targets.to(device) out = self.model(padded, targets) self.optimizer.zero_grad() out['loss'].backward() torch.nn.utils.clip_grad_norm_(self.model.parameters(), 1.0) self.optimizer.step() self.scheduler.step() return out['loss'].item() def save(self, path: str): os.makedirs(os.path.dirname(path), exist_ok=True) torch.save({ 'model': self.model.state_dict(), 'optimizer': self.optimizer.state_dict(), 'config': {'vocab_size': self.model.vocab_size, 'd_model': self.model.d_model, 'n_swarm': len(self.model.swarm_layers), 'n_assembly': len(self.model.assembly_layers), 'n_nanobots': self.model.swarm_layers[0].n_nanobots if self.model.swarm_layers else 512}, }, path) @classmethod def load(cls, path: str, device: str = 'cpu') -> 'Trainer': data = torch.load(path, map_location=device, weights_only=True) cfg = data.get('config', {}) model = FSIEchoModel( vocab_size=cfg.get('vocab_size', 4096), d_model=cfg.get('d_model', 192), n_swarm_layers=cfg.get('n_swarm', 3), n_assembly_layers=cfg.get('n_assembly', 3), n_nanobots=cfg.get('n_nanobots', 512), ) model.load_state_dict(data['model']) tokenizer = CodeTokenizer(vocab_size=cfg.get('vocab_size', 4096)) t = cls(model, tokenizer) if 'optimizer' in data: t.optimizer.load_state_dict(data['optimizer']) model.to(device) return t # ============================================================================= # 7. CLOSED-LOOP DEBUG # ============================================================================= class CodeVerifier: @staticmethod def check_syntax(code: str) -> Tuple[bool, str]: try: compile(code, '', 'exec') return True, "" except SyntaxError as e: return False, f"Line {e.lineno}: {e.msg}" @staticmethod def find_issues(code: str) -> List[str]: issues = [] for i, line in enumerate(code.split('\n'), 1): s = line.strip() if s == 'except:': issues.append(f"L{i}: Bare except — specify exception") return issues def verify(self, code: str) -> Dict: ok, err = self.check_syntax(code) issues = self.find_issues(code) return {'valid': ok and not issues, 'syntax_ok': ok, 'error': err, 'issues': issues, 'code': code} class ClosedLoopDebugger: def __init__(self, model: FSIEchoModel, tokenizer: CodeTokenizer, max_iters: int = 3): self.model = model self.tokenizer = tokenizer self.max_iters = max_iters self.verifier = CodeVerifier() def debug(self, code: str, requirement: str = "", max_iterations: int = None) -> Dict: iters = max_iterations or self.max_iters result = self._extract_code(code) if not result: return {'code': code, 'error': 'Could not parse code', 'iterations': 0, 'confidence': 0.0} buggy = result prompt = f"Fix this code:\n```python\n{buggy}\n```\nFixed:\n```python\n" best_code, best_v = buggy, self.verifier.verify(buggy) for i in range(iters): gen = self.model.generate(self.tokenizer, prompt, max_tokens=256, temperature=0.3, top_k=5) fixed = self._extract_code(gen['generated']) if not fixed: prompt += "\n```python\n" continue v = self.verifier.verify(fixed) if v['valid']: return {'code': fixed, 'verification': v, 'iterations': i+1, 'confidence': gen['confidence']} if len(v['issues']) < len(best_v['issues']): best_code, best_v = fixed, v if v['issues']: prompt += f"\nIssues: {'; '.join(v['issues'])}\nFixed:\n```python\n" elif not v['syntax_ok']: prompt += f"\n{v['error']}\nFixed:\n```python\n" else: break return {'code': best_code, 'verification': best_v, 'iterations': iters, 'confidence': 0.0} def _extract_code(self, text: str) -> str: m = re.search(r'```(?:python)?\n(.*?)```', text, re.DOTALL) if m: return m.group(1).strip() lines = text.split('\n') code = [] in_code = False for line in lines: if line.startswith('```'): in_code = not in_code; continue if in_code: code.append(line) return '\n'.join(code).strip() if code else '' # ============================================================================= # 8. GGUF EXPORT # ============================================================================= def export_gguf(model: FSIEchoModel, tokenizer: CodeTokenizer, path: str): sd = model.state_dict() keys = sorted(sd.keys()) meta = { 'general.name': 'FSI_ECHO', 'general.architecture': 'fsi_echo', 'general.description': 'Morphing Code Swarm', 'general.file_type': 0, 'general.vocab_size': model.vocab_size, 'general.context_length': 2048, 'general.parameter_count': model.param_count(), 'fsi_echo.block_count': len(model.swarm_layers) + len(model.assembly_layers), 'fsi_echo.embedding_length': model.d_model, 'fsi_echo.feed_forward_length': model.d_model * 2, 'fsi_echo.attention.head_count': 4, 'fsi_echo.nanobot_count': model.swarm_layers[0].n_nanobots if model.swarm_layers else 512, } with open(path, 'wb') as f: f.write(b'GGUF' + struct.pack('