#!/usr/bin/env python3 """ Flask Web GUI for the Self-Evolving Neural Network. Provides real-time monitoring of evolutionary training with: - Live fitness charts (Chart.js) - Start/Stop/Reset controls - Genome architecture visualization - Evolution history browser """ import os import sys import json import threading import time from pathlib import Path import numpy as np from flask import Flask, render_template_string, jsonify, request # Import the evolution engine from our main module from self_evolving_model import ( EvolutionEngine, DataHandler, Genome, CHECKPOINT_DIR, log ) # ═════════════════════════════════════════════════════════════════════ # Global Application State # ═════════════════════════════════════════════════════════════════════ app = Flask(__name__) state = { "running": False, "generation": 0, "total_generations": 0, "history": [], "best_genome": None, "population_summary": [], "best_fitness": 0.0, "improvement": 0.0, "status_message": "Idle. Click Start to begin evolution.", "dataset_loaded": False, "dataset_info": None, } engine: EvolutionEngine = None engine_thread: threading.Thread = None X_global: np.ndarray = None Y_global: np.ndarray = None # ═════════════════════════════════════════════════════════════════════ # Engine Callback # ═════════════════════════════════════════════════════════════════════ def on_generation_complete(stats, best_genome): """Called by EvolutionEngine after each generation.""" state["generation"] = stats["generation"] + 1 state["history"].append(stats) state["best_fitness"] = stats["best_fitness"] if best_genome: state["best_genome"] = best_genome.to_dict() state["population_summary"] = [ g.to_dict() for g in (engine.population if engine else []) ] if len(state["history"]) > 1 and state["history"][0]["best_fitness"] > 0: state["improvement"] = ( (state["history"][-1]["best_fitness"] - state["history"][0]["best_fitness"]) / state["history"][0]["best_fitness"] * 100 ) def run_evolution_with_data(pop_size, generations, mutation_rate, train_epochs, n_samples): """Background thread: loads dataset (if needed) then runs evolution.""" global engine, X_global, Y_global try: state["running"] = True state["total_generations"] = generations # Load dataset in background if not pre-loaded if X_global is None: state["status_message"] = "Loading FABLE.5 dataset..." try: X_global, Y_global = DataHandler.load_fable_dataset(n_samples=n_samples) state["dataset_loaded"] = True state["dataset_info"] = f"{X_global.shape[0]} samples, {X_global.shape[1]} features" except Exception as e: state["status_message"] = f"Dataset load failed: {e}. Using synthetic data." log(f"Dataset load failed: {e}. Falling back to synthetic.", "warn") X_global, Y_global = None, None state["status_message"] = f"Evolution in progress: 0/{generations} generations" engine = EvolutionEngine( pop_size=pop_size, generations=generations, mutation_rate=mutation_rate, train_epochs=train_epochs, ) engine.on_generation_complete = on_generation_complete engine.run(X=X_global, Y=Y_global, reset=True) state["status_message"] = ( f"Evolution complete! Best fitness: {state['best_fitness']:.2f} " f"(+{state['improvement']:.1f}%)" ) except Exception as e: state["status_message"] = f"Error: {str(e)}" log(f"Evolution error: {e}", "error") finally: state["running"] = False # ═════════════════════════════════════════════════════════════════════ # HTML Template (Single-page app with embedded CSS/JS) # ═════════════════════════════════════════════════════════════════════ HTML_TEMPLATE = r"""
Architecture evolves through mutation, crossover & natural selection — trained on FABLE.5 traces