meshscale-worker-template / GUI_API_AUDIT.md
tostido's picture
Build MeshScale CPU worker template
96ef23c verified
|
Raw
History Blame Contribute Delete
35.8 kB
# KEY System GUI API Audit
> **Generated**: January 3, 2026
> **Purpose**: Specification for GUI redesign - All public APIs, data structures, actions, and observable state
---
## Table of Contents
1. [Public APIs](#1-public-apis)
2. [Data Structures](#2-data-structures)
3. [User Actions](#3-user-actions)
4. [Observable State](#4-observable-state)
5. [Event System](#5-event-system)
6. [Configuration Schema](#6-configuration-schema)
---
## 1. Public APIs
### 1.1 Brain Module (`brain.py`)
#### `Brain` (Abstract Base Class)
```python
class Brain(ABC):
# Properties
@property id: str # Unique brain identifier (12 char hex)
@property generation: int # Generation number
@property fitness: Optional[float] # Fitness score (settable)
@property param_count: int # Total trainable parameters
@property brain_type: str # Architecture type ('mlp', 'lora', 'random')
# Core Methods (abstract)
def forward(inputs: Dict[str, Any]) -> Dict[str, Any]
def get_params() -> np.ndarray # Flatten all params to 1D
def set_params(params: np.ndarray) # Load params from 1D array
# State Management (for stateful brains)
def get_state() -> Dict[str, Any]
def set_state(state: Dict[str, Any])
def reset_state()
# Evolution Interface
def mutate(rate: float = None, scale: float = None) -> Brain
def crossover(other: Brain, method: str = 'uniform') -> Brain
def copy() -> Brain
# Serialization
def save(path: Path)
@classmethod load(path: Path) -> Brain
def to_dict() -> Dict[str, Any]
```
#### `MLPBrain` (Concrete)
```python
class MLPBrain(Brain):
# Properties
input_size: int
hidden_size: int
output_size: int
activation: Callable # 'tanh', 'relu', 'sigmoid', 'linear'
# Weights (internal)
w1: np.ndarray # (input_size, hidden_size)
b1: np.ndarray # (hidden_size,)
w2: np.ndarray # (hidden_size, output_size)
b2: np.ndarray # (output_size,)
```
#### `LoRABrain` (VLM Adapter Evolution)
```python
class LoRABrain(Brain):
# Configuration
lora_rank: int = 8
lora_alpha: int = 16
target_modules: List[str] = ['q_proj', 'v_proj']
hidden_dim: int = 2048
test_mode: bool = False
# Class-level (shared singleton)
_base_model: Model # Frozen VLM (shared)
_processor: Processor # Tokenizer/processor (shared)
# Instance-level
_adapter_weights: Dict[str, np.ndarray] # Per-module LoRA A/B matrices
_peft_model: PeftModel # PEFT model instance
# Methods
def forward(inputs: Dict) -> Dict[str, Any]
# inputs: {'text': str, 'image': optional, 'video': optional, 'max_new_tokens': int}
# returns: {'response': str, 'confidence': float}
async def aforward(prompt: str, images=None, max_new_tokens: int = 512) -> str
def get_adapter_weights() -> Dict[str, np.ndarray]
def apply_to_model() # Apply evolved weights to PEFT model
def save_adapter(path: Path)
@classmethod load_adapter(path: Path) -> LoRABrain
# Quine (Self-Replication)
def to_source(path: Path = None) -> str # Generate Python source file
@classmethod from_source(path: Path) -> LoRABrain
def replicate(mutation_rate: float = 0.1, mutation_scale: float = 0.1,
output_dir: Path = None) -> Path # Write mutated child as .py file
async def live(pulse=None, vp=None, perceive_fn=None, max_ticks: int = None)
```
#### Factory Functions
```python
def create_Brain(brain_type: str, **kwargs) -> Brain
def create_population(n: int, brain_type: str = 'mlp', **kwargs) -> List[Brain]
```
---
### 1.2 Mobile Population (`mobile.py`)
```python
class MobilePopulation:
"""Async population where each brain runs its own lifecycle loop"""
# Constructor
def __init__(
pulse: Pulse = None,
vp: ViolationPressure = None,
children_dir: Path = None,
max_population: int = 100,
enable_logging: bool = False,
)
# Properties (Observable State)
members: Dict[str, BrainState] # Active brains
total_spawned: int
total_despawned: int
generation: int
pulse: Pulse
vp: ViolationPressure
# Core Methods
async def spawn(brain: LoRABrain) -> str # Add brain, returns ID
async def despawn(brain_id: str) # Remove brain
async def run_forever(tick_interval: float = 0.01)
async def run_for(duration: float = None, ticks: int = None)
async def shutdown()
# Status
def status() -> Dict[str, Any]
# Returns: {
# 'population_size': int,
# 'max_population': int,
# 'total_spawned': int,
# 'total_despawned': int,
# 'generation': int,
# 'running': bool,
# 'brains': Dict[id, BrainState]
# }
@dataclass
class BrainState:
brain: LoRABrain
task: asyncio.Task
spawned_at: float
tick_count: int
last_fitness: float
children_spawned: int
status: str # 'running', 'stopping', 'cancelled', 'error: ...'
# Convenience Function
async def run_mobile_evolution(
initial_population: int = 5,
duration: float = None,
ticks: int = 100,
layers: List[int] = None,
) -> MobilePopulation
```
---
### 1.3 Population Manager (`population.py`)
```python
class PopulationManager:
"""NEAT-inspired population management with speciation"""
# Constructor
def __init__(
trait_keys: List[str],
population_size: int,
fitness_fn: Callable[[Node], float],
config: SpeciesConfig = None,
brain_factory: Optional[Callable] = None,
)
# Properties (Observable State)
population: List[Node]
species_list: List[Species]
generation: int
best_node: Node
best_fitness: float
history: List[Dict]
trait_keys: List[str]
config: SpeciesConfig
# Core Methods
def evaluate(verbose: bool = False) -> List[float]
def speciate(verbose: bool = False)
def reproduce() -> Dict # Returns: {'mutations': int, 'crossovers': int, 'elites': int, 'eliminated': int}
def step(verbose: bool = False) -> Dict # evaluate + speciate + reproduce
# Query Methods
def get_snapshot() -> Dict[str, Any] # Comprehensive population state
def get_best() -> Tuple[Node, float]
def get_species_info() -> List[Dict]
# Serialization
def to_checkpoint_dict() -> Dict
@staticmethod from_checkpoint_dict(data: Dict, fitness_fn: Callable, brain_factory=None) -> PopulationManager
@dataclass
class SpeciesConfig:
genetic_distance_threshold: float = 0.35
max_stagnation: int = 50
elitism: int = 0
survival_threshold: float = 0.2
crossover_rate: float = 0.7
min_species_size: int = 3
tournament_size: int = 3
class Species:
id: int
representative: Node
members: List[Node]
generation_created: int
last_improvement: int
best_fitness: float
avg_fitness: float
def get_avg_fitness() -> float
def get_best_fitness() -> float
def is_stagnant(current_gen: int, max_stagnation: int) -> bool
def contains_node(node, threshold: float) -> bool
def update_representative()
def genetic_distance(node1, node2) -> float # Returns 0-1+
```
---
### 1.4 VLM Base (`vlm_base.py`)
```python
# Configuration
@dataclass
class VLMConfig:
model_name: str = "Qwen/Qwen2.5-VL-3B-Instruct"
quantization: Literal['none', '8bit', '4bit'] = '4bit'
device: str = 'auto'
torch_dtype: str = 'float16'
trust_remote_code: bool = True
use_flash_attention: bool = False
max_memory: Optional[Dict[str, str]] = None
offload_folder: Optional[str] = None
min_pixels: int = 256 * 28 * 28
max_pixels: int = 1280 * 28 * 28
# Singleton API
def configure(
model_name: str = None,
quantization: Literal['none', '8bit', '4bit'] = None,
device: str = None,
torch_dtype: str = None,
use_flash_attention: bool = None,
max_memory: Dict[str, str] = None,
offload_folder: str = None,
min_pixels: int = None,
max_pixels: int = None,
) -> VLMConfig
def get_config() -> VLMConfig
def get_base_model() -> Model # Singleton, loads on first call
def get_processor() -> Processor # Singleton
def reload() # Force reload with current config
```
---
### 1.5 Configuration (`config.py`)
```python
def load_config(path: Path = None) -> Dict[str, Any]
def get(section: str, key: str = None, default: Any = None) -> Any
def reload() -> Dict[str, Any]
def get_defaults() -> Dict[str, Any]
```
---
### 1.6 Causation Explorer (`explorer.py`)
```python
@dataclass
class Event:
timestamp: float
component: str
event_type: str # 'state_change', 'threshold_crossed', 'transition'
data: Dict[str, Any]
event_id: str
def to_dict() -> Dict[str, Any]
@dataclass
class CausationLink:
from_event: str
to_event: str
causation_type: str # 'temporal', 'correlation', 'threshold', 'direct'
strength: float # 0.0-1.0
explanation: str
metrics: List[str]
class CausationExplorer:
# Properties
graph: nx.DiGraph # Causation graph (NetworkX)
events: Dict[str, Event]
events_by_component: Dict[str, List[str]]
events_by_type: Dict[str, List[str]]
metric_history: Dict[str, deque]
thresholds: Dict[str, Dict] # Configurable thresholds
# Event Management
def add_event(event: Event) -> List[CausationLink]
# Exploration
def explore_backwards(event_id: str, max_depth: int = 10) -> List[Dict]
def explore_forwards(event_id: str, max_depth: int = 10) -> List[Dict]
def find_path(from_id: str, to_id: str) -> Optional[List[Dict]]
def get_event_summary(event_id: str) -> Dict[str, Any]
# Search
def search(query: str) -> List[Dict]
def search_by_metric(metric: str, min_val: float = None, max_val: float = None) -> List[Dict]
# Statistics
def stats() -> Dict[str, Any]
# Data Loading
def load_from_json(filepath: Path) -> int
def load_from_jsonl(filepath: Path) -> int
def load_all_jsonl(log_dir: Path = None) -> int
def load_from_shared_state(filepath: Path = None) -> int
def load_from_logs(log_dir: Path = None) -> int
def load_all(data_dir: Path = None) -> Dict[str, int]
# Export
def save_to_json(filepath: Path)
def to_numpy() -> Tuple[np.ndarray, np.ndarray, List[str]] # features, adjacency, event_ids
def to_dataframe() -> pd.DataFrame
```
---
### 1.7 Fitness Functions (`fitness.py`, `fitness_code.py`)
#### Base Classes
```python
class Fitness(ABC):
@abstractmethod def evaluate(node: Any, context: Dict = None) -> float
def evaluate_batch(nodes: List, context: Dict = None) -> np.ndarray
@property name: str
@property is_minimization: bool
class FunctionFitness(Fitness): # Wrap lambda as Fitness
class CompositeFitness(Fitness): # Weighted combination
```
#### Benchmark Functions
```python
class SphereFitness(Fitness) # f(x) = -sum(x_i^2)
class RastriginFitness(Fitness) # Multimodal, many local optima
class RosenbrockFitness(Fitness) # Narrow curved valley
```
#### VLM Fitness
```python
@dataclass
class VLMTask:
prompt: str
image: Optional[Union[str, Path, np.ndarray]] = None
video: Optional[Union[str, Path]] = None
expected: Optional[str] = None
keywords: List[str] = []
forbidden: List[str] = []
bbox_expected: Optional[List[float]] = None
max_tokens: int = 128
weight: float = 1.0
class VLMFitness(Fitness):
def __init__(tasks: List[VLMTask], time_penalty: float = 0.0, ...)
def evaluate(node, context=None) -> float
```
#### Code Understanding Fitness
```python
@dataclass
class CodeTask:
file_path: str
code_snippet: str
question: str
expected_keywords: List[str]
task_type: str # 'comprehension', 'pattern', 'reasoning'
difficulty: float = 1.0
class CodeFitness:
def __init__(config: CodeFitnessConfig = None)
def evaluate(adapter_id: str) -> float
def evaluate_single(adapter, prompt: str, code_snippet: str, expected_keywords: List[str]) -> float
```
---
### 1.8 Pulse & Pressure (`pulse.py`, `pressure.py`)
#### Pulse (System Clock)
```python
class Pulse:
# Properties
rate: float # Breaths per second
phase: float # 0 to 2π
depth: float # 0 to 1
cycle: int # Completed cycles
intensity: float # Multiplier
# Methods
def tick() -> Dict[str, float] # Advance pulse, return state
def state() -> Dict[str, float] # {'depth', 'phase', 'cycle', 'intensity', 'timestamp'}
def value() -> float # depth * intensity
def is_inhale() -> bool # phase < π
def is_exhale() -> bool # phase >= π
def set_rate(rate: float)
def set_intensity(intensity: float)
```
#### Violation Pressure (Loss Function)
```python
class ViolationClass(Enum):
VP0 = "VP0" # 0.00-0.25: Stable
VP1 = "VP1" # 0.25-0.50: Drifting
VP2 = "VP2" # 0.50-0.75: Unstable
VP3 = "VP3" # 0.75-0.99: Critical
VP4 = "VP4" # >= 1.00: Collapse
@dataclass
class StabilityEnvelope:
center: float = 0.5
radius: float = 0.25
compression: float = 1.0
class ViolationPressure:
envelopes: Dict[str, StabilityEnvelope]
def set_envelope(trait: str, center: float, radius: float, compression: float)
def get_envelope(trait: str) -> StabilityEnvelope
def compute(traits: Dict[str, float]) -> Tuple[float, Dict[str, float]] # (total_vp, breakdown)
def classify(total_vp: float) -> ViolationClass
def error(traits: Dict[str, float]) -> float # Simple loss value
# ML Integration
def as_loss_fn() -> Callable
def torch_loss(values, centers, radii) -> Tensor
```
---
### 1.9 Tracking (`tracking.py`)
#### WandB Tracker
```python
class WandbTracker:
def __init__(project: str = "evolutionary-nlp", entity: str = None, enabled: bool = True)
def start_run(name: str = None, config: Dict = None, tags: List[str] = None)
def log_generation(generation: int, fitness: np.ndarray, species_info: List[Dict] = None, extra_metrics: Dict = None)
def log_evaluation(generation: int, train_metrics: Dict, eval_metrics: Dict)
def log_population_viz(generation: int, embedding: np.ndarray, labels: np.ndarray, fitness: np.ndarray)
def log_vlm_inference(adapter_id, file, task_type, question, response, prompt_tokens, output_tokens, inference_ms, ...)
def log_vlm_fitness(adapter_id, fitness, scores, task_types, step=None)
def log_causation_event(event_type, component, data, links=None, step=None)
def log_adapter_population(generation, adapter_fitness, adapter_similarity=None, anomaly_ratio=None, diversity_score=None)
def save_inference_table()
def finish()
```
#### TensorBoard Tracker
```python
class TensorBoardTracker:
def __init__(log_dir: str = "runs", experiment_name: str = None, enabled: bool = True)
def log_generation(generation: int, fitness: np.ndarray, species_info: List[Dict] = None, extra_metrics: Dict = None)
def log_evaluation(generation: int, train_metrics: Dict, eval_metrics: Dict)
def close()
```
#### Unified Tracker
```python
class EvolutionTracker:
def __init__(backend: str = "auto", project: str = "evolutionary-nlp", log_dir: str = "runs")
# backend: "wandb", "tensorboard", "auto", "none"
def start_run(name: str = None, config: Dict = None)
def log_generation(generation: int, fitness: np.ndarray, species_info: List[Dict] = None, extra_metrics: Dict = None)
def log_evaluation(generation: int, train_metrics: Dict, eval_metrics: Dict)
def finish()
```
---
### 1.10 Checkpointing (`checkpoints.py`)
```python
@dataclass
class CheckpointMetadata:
name: str
version: str
timestamp: str
generation: int
best_fitness: float
avg_fitness: float
num_species: int
population_size: int
config_hash: str
notes: str = ""
@dataclass
class Checkpoint:
metadata: CheckpointMetadata
config: Dict
population_traits: List[Dict]
history: List[Dict]
species_data: Optional[Dict]
nlp_weights: Optional[bytes]
event_log: Optional[List[Dict]]
def save(path: Path = None) -> Path
@classmethod load(path: Path) -> Checkpoint
# Functions
def create_checkpoint(name, generation, config, population, history, ...) -> Checkpoint
def list_checkpoints(name_filter: str = None) -> List[CheckpointMetadata]
def get_latest_checkpoint(name: str = None) -> Optional[Path]
def compare_checkpoints(ckpt1, ckpt2) -> Dict
class AutoCheckpointer:
def __init__(name, config, checkpoint_every=50, keep_best=5, keep_recent=3)
def maybe_checkpoint(generation, population, history, ..., force=False) -> Optional[Path]
```
---
### 1.11 Node (`node.py`)
```python
@dataclass
class Node:
traits: Dict[str, float]
generation: int = 0
parent_ids: List[str] = []
brain: Optional[Brain] = None
fitness: Optional[float] = None
@property id: str
# Methods
def score(vp: ViolationPressure) -> float
def mutate(rate: float = 0.1, mutate_brain: bool = True) -> Node
def crossover(other: Node, cross_brain: bool = True) -> Node
def think(inputs: Dict) -> Dict
def has_brain() -> bool
def attach_brain(brain: Brain)
def detach_brain() -> Optional[Brain]
def to_vector(keys: List[str] = None) -> np.ndarray
@classmethod from_vector(vector: np.ndarray, keys: List[str]) -> Node
def to_dict() -> Dict
@classmethod from_dict(data: Dict, brain_class=None) -> Node
# Helper Functions
def random_node(keys: List[str], brain_factory=None) -> Node
def create_nodes(n: int, keys: List[str], brain_factory=None) -> List[Node]
def create_population(n: int, keys: List[str], brain_factory=None) -> List[Node]
```
---
## 2. Data Structures
### 2.1 Brain State
```python
{
'id': str, # 12-char hex identifier
'brain_type': str, # 'mlp', 'lora', 'random'
'generation': int, # Generation number
'param_count': int, # Total parameters
'fitness': Optional[float], # Current fitness
'parent_ids': List[str], # Parent brain IDs
# LoRA-specific
'lora_rank': int,
'lora_alpha': int,
'target_modules': List[str],
'hidden_dim': int,
'adapter_weights': Dict[str, np.ndarray],
}
```
### 2.2 Population Snapshot
```python
{
# Core
'generation': int,
'population_size': int,
# Fitness
'best_fitness': float,
'avg_fitness': float,
'min_fitness': float,
'max_fitness': float,
'fitness_std': float,
'fitness_range': float,
'selection_pressure': float,
# Species
'num_species': int,
'species_sizes': List[int],
'species_avg_fitnesses': List[float],
'species_best_fitnesses': List[float],
'largest_species_size': int,
'smallest_species_size': int,
'avg_species_age': float,
'max_stagnation': int,
# Sklearn Clustering Quality
'silhouette_score': float, # [-1, 1]
'davies_bouldin_score': float, # [0, inf)
'calinski_harabasz_score': float, # [0, inf)
# Diversity
'overall_diversity': float,
'trait_means': Dict[str, float],
'trait_stds': Dict[str, float],
# Brain/Neural metrics
'num_brains': int,
'brain_ratio': float,
'avg_brain_params': float,
'avg_brain_weight_mean': float,
'avg_brain_weight_std': float,
'avg_brain_weight_norm': float,
'brain_weight_norm_std': float,
# LoRA Adapter metrics
'num_lora_brains': int,
'avg_lora_params': float,
'avg_lora_rank': float,
'lora_weight_diversity': float,
'avg_adapter_similarity': float,
'min_adapter_similarity': float,
'max_adapter_similarity': float,
'num_anomalous_adapters': int,
'anomaly_ratio': float,
# Reproduction stats (from step())
'mutations': int,
'crossovers': int,
'elites': int,
'eliminated': int,
'step_time_ms': float,
}
```
### 2.3 Species Info
```python
{
'id': int,
'size': int,
'avg_fitness': float,
'best_fitness': float,
'age': int, # Generations since created
'stagnant_gens': int, # Generations without improvement
}
```
### 2.4 Pulse State
```python
{
'depth': float, # 0-1, sine wave position
'phase': float, # 0 to 2π
'cycle': int, # Completed breath cycles
'intensity': float, # Multiplier
'timestamp': float, # Last tick time
}
```
### 2.5 Violation Pressure State
```python
{
'total_vp': float, # 0-1+ overall pressure
'vp_class': ViolationClass, # VP0-VP4
'breakdown': Dict[str, float], # Per-trait VP values
}
```
### 2.6 Mobile Population Status
```python
{
'population_size': int,
'max_population': int,
'total_spawned': int,
'total_despawned': int,
'generation': int,
'running': bool,
'brains': {
brain_id: {
'id': str,
'generation': int,
'ticks': int,
'fitness': float,
'children': int,
'status': str, # 'running', 'stopping', 'cancelled', 'error: ...'
}
}
}
```
### 2.7 Causation Event
```python
{
'event_id': str,
'timestamp': float,
'component': str,
'event_type': str,
'data': Dict[str, Any],
}
```
### 2.8 Checkpoint
```python
{
'metadata': {
'name': str,
'version': str,
'timestamp': str,
'generation': int,
'best_fitness': float,
'avg_fitness': float,
'num_species': int,
'population_size': int,
'config_hash': str,
'notes': str,
},
'config': Dict,
'population': List[NodeDict],
'species': List[SpeciesDict],
'history': List[SnapshotDict],
}
```
---
## 3. User Actions
### 3.1 Initialization
| Action | API Call | Parameters |
|--------|----------|------------|
| Create Population Manager | `PopulationManager(...)` | trait_keys, population_size, fitness_fn, config, brain_factory |
| Create Mobile Population | `MobilePopulation(...)` | pulse, vp, children_dir, max_population |
| Configure VLM | `vlm_base.configure(...)` | model_name, quantization, device, ... |
| Load Config | `config.load_config(path)` | path |
### 3.2 Evolution Control
| Action | API Call | Parameters |
|--------|----------|------------|
| Step (sync) | `pm.step(verbose)` | verbose |
| Evaluate Only | `pm.evaluate(verbose)` | verbose |
| Speciate Only | `pm.speciate(verbose)` | verbose |
| Reproduce | `pm.reproduce()` | - |
| Run Mobile (forever) | `await pop.run_forever(tick_interval)` | tick_interval |
| Run Mobile (limited) | `await pop.run_for(duration, ticks)` | duration, ticks |
| Shutdown | `await pop.shutdown()` | - |
### 3.3 Brain Management
| Action | API Call | Parameters |
|--------|----------|------------|
| Spawn Brain | `await pop.spawn(brain)` | brain |
| Despawn Brain | `await pop.despawn(brain_id)` | brain_id |
| Mutate Brain | `brain.mutate(rate, scale)` | rate, scale |
| Crossover Brains | `brain.crossover(other, method)` | other, method |
| Copy Brain | `brain.copy()` | - |
| Replicate (Quine) | `brain.replicate(mutation_rate, output_dir)` | mutation_rate, output_dir |
### 3.4 Checkpointing
| Action | API Call | Parameters |
|--------|----------|------------|
| Save Checkpoint | `checkpoint.save(path)` | path |
| Load Checkpoint | `Checkpoint.load(path)` | path |
| Create Checkpoint | `create_checkpoint(...)` | name, generation, config, population, history, ... |
| List Checkpoints | `list_checkpoints(name_filter)` | name_filter |
| Get Latest | `get_latest_checkpoint(name)` | name |
| Auto-checkpoint | `checkpointer.maybe_checkpoint(...)` | generation, population, ... |
| Compare | `compare_checkpoints(ckpt1, ckpt2)` | ckpt1, ckpt2 |
### 3.5 Saving/Loading
| Action | API Call | Parameters |
|--------|----------|------------|
| Save Brain | `brain.save(path)` | path |
| Load Brain | `Brain.load(path)` | path |
| Save Adapter | `lora_brain.save_adapter(path)` | path |
| Load Adapter | `LoRABrain.load_adapter(path)` | path |
| Export to Source | `brain.to_source(path)` | path |
| Load from Source | `LoRABrain.from_source(path)` | path |
| Save PM State | `pm.to_checkpoint_dict()` | - |
| Load PM State | `PopulationManager.from_checkpoint_dict(...)` | data, fitness_fn |
### 3.6 Tracking
| Action | API Call | Parameters |
|--------|----------|------------|
| Start Run | `tracker.start_run(name, config, tags)` | name, config, tags |
| Log Generation | `tracker.log_generation(gen, fitness, species_info, extra)` | gen, fitness, ... |
| Log Evaluation | `tracker.log_evaluation(gen, train_metrics, eval_metrics)` | gen, metrics, ... |
| Log VLM Inference | `wandb_tracker.log_vlm_inference(...)` | adapter_id, file, task_type, ... |
| Log Causation | `wandb_tracker.log_causation_event(...)` | event_type, component, data, links |
| Finish | `tracker.finish()` | - |
### 3.7 Causation Exploration
| Action | API Call | Parameters |
|--------|----------|------------|
| Add Event | `explorer.add_event(event)` | event |
| Explore Why | `explorer.explore_backwards(event_id, max_depth)` | event_id, max_depth |
| Explore Effects | `explorer.explore_forwards(event_id, max_depth)` | event_id, max_depth |
| Find Path | `explorer.find_path(from_id, to_id)` | from_id, to_id |
| Search Events | `explorer.search(query)` | query |
| Get Stats | `explorer.stats()` | - |
| Load Data | `explorer.load_all(data_dir)` | data_dir |
### 3.8 Configuration
| Action | API Call | Parameters |
|--------|----------|------------|
| Get Config Value | `config.get(section, key, default)` | section, key, default |
| Reload Config | `config.reload()` | - |
| Set VP Envelope | `vp.set_envelope(trait, center, radius, compression)` | trait, center, radius, compression |
| Set Pulse Rate | `pulse.set_rate(rate)` | rate |
| Set Pulse Intensity | `pulse.set_intensity(intensity)` | intensity |
---
## 4. Observable State
### 4.1 Real-time Metrics (per step/tick)
| Metric | Source | Update Frequency |
|--------|--------|------------------|
| Current Generation | `pm.generation`, `pop.generation` | Per step/tick |
| Population Size | `len(pm.population)`, `len(pop.members)` | Per step |
| Best Fitness | `pm.best_fitness` | Per step |
| Avg Fitness | `snapshot['avg_fitness']` | Per step |
| Fitness Distribution | `snapshot` fitness stats | Per step |
| Species Count | `len(pm.species_list)` | Per step |
| Pulse State | `pulse.state()` | Per tick |
| VP Level | `vp.compute(traits)` | Per tick |
### 4.2 Curves (time series)
| Metric | Source | Chart Type |
|--------|--------|------------|
| Fitness over generations | `pm.history` | Line chart |
| Species count over time | `pm.history` | Line chart |
| Diversity over time | `snapshot['overall_diversity']` | Line chart |
| VP levels over time | Per-brain VP values | Multi-line |
| Population size over time | `pm.history` | Area chart |
| Selection pressure | `snapshot['selection_pressure']` | Line chart |
### 4.3 Population Composition
| Metric | Source | Visualization |
|--------|--------|---------------|
| Species distribution | `pm.get_species_info()` | Pie/treemap |
| Fitness per species | Species info | Box plot |
| Trait distributions | `snapshot['trait_means/stds']` | Histogram |
| Brain type breakdown | Population analysis | Bar chart |
| LoRA adapter similarity | `snapshot['avg_adapter_similarity']` | Heatmap |
### 4.4 Individual Brain State
| Metric | Source | Update |
|--------|--------|--------|
| Brain ID | `brain.id` | Static |
| Generation | `brain.generation` | Static |
| Param Count | `brain.param_count` | Static |
| Fitness | `brain.fitness` | Per eval |
| Parent IDs | `brain._parent_ids` | Static |
| Adapter Weights | `lora_brain.get_adapter_weights()` | On demand |
### 4.5 Causation Graph
| Metric | Source | Visualization |
|--------|--------|---------------|
| Event count | `explorer.stats()['total_events']` | Counter |
| Link count | `explorer.stats()['total_links']` | Counter |
| Graph density | `explorer.stats()['graph_density']` | Gauge |
| Components | `explorer.events_by_component` | Legend |
| Strongest links | `explorer.stats()['strongest_links']` | Table |
---
## 5. Event System
### 5.1 Events to Log/Display
| Event | Trigger | Data |
|-------|---------|------|
| Fitness Improvement | New best fitness | old_best, new_best, node_id, traits |
| Species Created | New species | species_id, founding_node_id, founding_traits |
| Species Extinct | Species dies | species_id, age, peak_fitness, cause |
| Mutation | Node mutated | parent_id, child_id, parent_traits, child_traits |
| Crossover | Crossover occurs | parent1_id, parent2_id, child_id, traits |
| Selection | Generation complete | selected_ids, eliminated_ids, elite_ids |
| Brain Spawn | Mobile spawn | brain_id, generation, parent_id |
| Brain Despawn | Mobile despawn | brain_id, reason, tick_count |
| VP Threshold | VP level change | vp_class, total_vp, traits |
| Checkpoint Saved | Checkpoint written | filepath, generation, best_fitness |
| Checkpoint Loaded | Checkpoint loaded | filepath, generation |
### 5.2 Event Types (CausationExplorer)
- `state_change` - General metric update
- `threshold_crossed` - VP/metric threshold crossed
- `transition` - State machine transition
### 5.3 Causation Types
- `temporal` - Time-based correlation
- `correlation` - Metrics changed together
- `threshold` - Threshold crossing caused event
- `direct` - Known direct causation (pulse→network, etc.)
---
## 6. Configuration Schema
### 6.1 Full `config.json` Schema
```json
{
"pressure": {
"default_center": 0.5,
"default_radius": 0.25,
"default_compression": 1.0,
"envelopes": {
"<trait_name>": {"center": float, "radius": float, "compression": float}
}
},
"vp_thresholds": {
"VP0": 0.25, "VP1": 0.5, "VP2": 0.75, "VP3": 0.99,
"modularity_collapse": 0.3, "organism_collapse": 500
},
"convergence": {"mutation_rate": 0.1, "noise_std": 0.05},
"attractor": {"max_iterations": 1000, "tolerance": 1e-6, "learning_rate": 0.01},
"pulse": {"rate": 1.0, "intensity": 1.0, "decay": 0.99},
"population": {
"size": 6, "dimensions": 10,
"trait_keys": ["x0", "x1", ...],
"use_brains": true
},
"evolution": {
"generations": 100, "mutation_rate": 0.3, "mutation_strength": 0.2,
"crossover_rate": 0.7, "fitness_function": "code",
"target_species": 5, "log_interval": 10, "mode": "hybrid"
},
"speciation": {
"genetic_distance_threshold": 0.25, "max_stagnation": 15,
"elitism": 2, "survival_threshold": 0.2,
"crossover_rate": 0.7, "min_species_size": 3
},
"dbscan": {"eps": null, "min_samples": 3, "eps_percentile": 0.7, "scale_features": true},
"fitness": {
"function": "code", "bounds_low": -5.12, "bounds_high": 5.12,
"normalize": true, "invert": true
},
"communication": {
"enabled": false, "max_turns": 10, "task_type": "collaboration",
"role_pair": ["Developer", "Architect"],
"scoring_weights": {"turn_engagement": 0.3, "task_completion": 0.3, "coherence": 0.4}
},
"node": {"mutation_rate": 0.3, "mutation_strength": 0.2},
"brain": {
"enabled": false, "hidden_sizes": [16, 16],
"activation": "tanh", "mutation_rate": 0.1, "mutation_strength": 0.3
},
"lora_brain": {
"enabled": true, "base_model": "D:/models/Qwen2.5-VL-3B-Instruct",
"quantization": "4bit", "lora_rank": 8, "lora_alpha": 16,
"lora_dropout": 0.0, "target_modules": ["q_proj", "v_proj"],
"hidden_dim": 2048, "use_flash_attention": false
},
"vlm": {
"min_pixels": 200704, "max_pixels": 1003520,
"max_new_tokens": 150, "code_dir": "F:/folder/key", "tasks_per_eval": 3
},
"weight_evolution": {
"algorithm": "CMA_ES", "sigma_init": 0.1, "weight_decay": 0.0, "fitness_shaping": true
},
"nlp_training": {
"enabled": true, "vocab_size": 1500, "embed_dim": 64,
"hidden_dim": 128, "max_seq_len": 32, "num_lstm_layers": 1,
"num_classes": 2, "population_size": 16, "sigma_init": 0.3,
"train_samples": 64, "eval_samples": 32
},
"explorer": {
"log_dir": "data/logs", "shared_state_path": "data/.shared_simulation_state.json",
"max_events": 10000,
"causation_thresholds": {"temporal_window": 1.0, "correlation_min": 0.7, "direct_max_delay": 0.1}
},
"checkpointing": {
"enabled": true, "checkpoint_every": 10, "keep_best": 5,
"keep_recent": 3, "checkpoint_dir": "checkpoints"
},
"logging": {
"wandb_project": "key-evolution", "wandb_entity": null,
"tensorboard_enabled": true, "tensorboard_logdir": "runs/key",
"log_interval": 1, "log_level": "INFO"
},
"performance": {
"batch_size": 5, "tick_delay_ms": 20, "parallel_fitness": true, "num_workers": 4
},
"hf_sync": {
"enabled": true, "dataset_name": null, "sync_checkpoints": true,
"sync_logs": true, "retry_attempts": 3, "timeout_seconds": 30
},
"visualization": {
"umap_enabled": true, "umap_n_neighbors": 15, "umap_min_dist": 0.1,
"umap_n_jobs": 1, "plot_every": 10, "max_history_points": 500
},
"selection": {"method": "tournament", "tournament_size": 3, "truncation_threshold": 0.5},
"experiment": {"name": "default", "tags": ["evolution", "bbob"], "seed": 42, "deterministic": true}
}
```
---
## GUI Design Recommendations
### Panels/Views
1. **Dashboard** - Overview: generation, best fitness, population size, VP status
2. **Population View** - Species tree, fitness distribution, individual brains
3. **Evolution Control** - Start/stop/step, parameter adjustments
4. **Brain Inspector** - Selected brain details, weights visualization, lineage
5. **Causation Explorer** - Event graph, search, exploration tools
6. **Metrics Charts** - Fitness curves, diversity, species count over time
7. **Checkpoints** - List, load, compare, export
8. **Configuration** - Edit config.json sections, VP envelopes
9. **Logs** - Real-time event stream, wandb/tensorboard links
### Real-time Updates
- WebSocket or polling for `get_snapshot()`, `pulse.state()`, `pop.status()`
- Event stream from logger for mutations, crossovers, spawns
### Key Interactions
- Click brain → show details, lineage, weights
- Click species → filter to species members
- Click event → explore causation backwards/forwards
- Drag VP envelope centers/radii in visualization
- Play/pause/step evolution controls