--- license: mit language: - en tags: - comfyui - custom-nodes - stanno - nodes --- # STANNO — Neural Networks That Train Neural Networks A modern, open-source Python library implementing the **Artificial Neurogenesis Network** concept from US Patent 5,852,815 (Thaler, 1998). One network (the trainer) decides how another network (the trainee) should update its weights — no backpropagation needed. Multiple STANNOs can be chained into cascade pipelines, and any trained STANNO can be turned into a data scanner that finds matching rows in large datasets. > **Attribution**: This is a faithful, open-source implementation of Thaler's patented design with modern extensions (cascading, data scanning, ComfyUI integration). The original patent has expired. All core concepts are credited to the original patent. ## ⚠️ What STANNO Is (and Isn't) **STANNO is specialized**, not a drop-in replacement for PyTorch. **Good for:** - Anomaly detection (reconstruction-based scoring) - Online/continual learning (one-sample-at-a-time updates) - Interpretable weight modification (see exactly what changes) - Multi-stage cascade pipelines (encoder → bottleneck → decoder, end-to-end) - Semantic data scanning (find rows in a large dataset that match learned distribution) - ComfyUI creative workflows (style transfer via dream mode) **NOT for:** - General regression (accuracy ~0.4, use PyTorch instead) - Image generation alone (need Stable Diffusion + nodes) - High-throughput training (slow NumPy) For details, see [STANNO_IS_NOT.md](./STANNO_IS_NOT.md). **What you can do with this:** **Train networks on your data:** ```python from stanno import STANNO from stanno.config.schema import STANNOConfig import numpy as np config = STANNOConfig(layers=[784, 256, 10]) stanno = STANNO(config) stanno.fit(x_train, y_train, epochs=100) predictions = stanno.predict(x_test) ``` **Chain into cascade pipelines:** ```python from stanno import STANNO, STANNOConfig, CascadeSTANNO # Encoder-decoder autoencoder enc = STANNO(STANNOConfig(layers=[768, 256, 64], learning_rate=0.05)) dec = STANNO(STANNOConfig(layers=[64, 256, 768], learning_rate=0.05)) ae = CascadeSTANNO([enc, dec]) ae.fit(embeddings, embeddings, epochs=200) # end-to-end gradient cascade # Extract compressed representations codes = ae.intermediate_output(embeddings, stage=0) # (N, 64) # Freeze the encoder, continue adapting the decoder ae.freeze(0) ae.fit(new_domain_embeddings, new_domain_embeddings, epochs=100) ``` **Scan large datasets for matching rows (DSANNO):** ```python from stanno import STANNO, STANNOConfig, DSANNO # Train on known-good data detector = STANNO(STANNOConfig(layers=[64, 128, 64], learning_rate=0.05)) detector.fit(normal_data, normal_data, epochs=200) scanner = DSANNO(detector, mode="reconstruction") # Auto-calibrate threshold from training distribution threshold = scanner.calibrate_threshold(normal_data, percentile=95) # Find matching rows in a large corpus result = scanner.scan(large_corpus, threshold=threshold) matching = large_corpus[result.matched_indices()] # Or retrieve the top-k best matches indices, scores, _ = scanner.top_k(large_corpus, k=20) # Stream huge files without loading all at once for batch_result in scanner.scan_stream(file_batches, threshold=threshold): process(batch_result.matched_indices()) ``` **Detect when inputs are unusual (anomaly filter):** ```python from stanno.integration.filter import STANNOFilter # Train on normal data stanno.fit(normal_data, normal_data, epochs=50) # Score new input score, metadata = stanno_filter.score(new_input) # score ranges [0, 1]: low = normal, high = anomaly ``` **Generate variations via "dream mode":** ```python # Start with a seed input, add noise, generate a sequence dream_sequence = stanno.dream( num_steps=64, input_seed=seed_vector, noise_sigma=0.1 # controls creativity ) ``` **Use in ComfyUI workflows (9 nodes):** - Load/create STANNO models - Train on image batches - Score/filter images - Inject dream creativity into CLIP conditioning - Apply dream output as LoRA-style patches - Route images by style match - Scan image batches for best matches with auto-calibrated thresholds - Build multi-stage cascade autoencoders ## Why use STANNO? - **Interpretable**: You can see exactly what the trainer does to weights. No black-box backprop. - **Flexible**: Three trainer types (Fixed, LocalRule, Evolutionary) fit different problems. - **Learnable**: The trainer itself can adapt (meta-learning). - **Cascadable**: Chain STANNOs into multi-stage pipelines with end-to-end gradient flow across stages. - **Scannable**: Turn any trained STANNO into a semantic scanner over large datasets. - **No autodiff**: Works with NumPy. No GPU required (but supports PyTorch if you have it). - **ComfyUI ready**: Nine custom nodes for image generation workflows. ## Install ```bash pip install git+https://github.com/nitroxido/stanno.git ``` ## Quick examples ### Regression on sin(x) ```bash python -m stanno train --config examples/sin_regression.json python -m stanno predict --config examples/sin_regression.json --input 0.5 python -m stanno dream --config examples/sin_regression.json ``` ### Autoencoder on images ```python from stanno import STANNO from stanno.config.schema import STANNOConfig import numpy as np # Reshape images to flat vectors (B, H*W*C) x = images.reshape(images.shape[0], -1).astype('float32') # Autoencoder: input and output have same size config = STANNOConfig(layers=[x.shape[1], 256, x.shape[1]]) stanno = STANNO(config) stanno.fit(x, x, epochs=100, batch_size=32) # Get reconstruction x_reconstructed = stanno.predict(x[:10]) ``` ### Online learning (continual) ```python from stanno.integration.continual import ContinualSTANNO cont = ContinualSTANNO(stanno) for sample, label in data_stream: loss = cont.observe(sample, label) if cont.steps % 100 == 0: test_loss = cont.test_loss(x_test, y_test) print(f"Step {cont.steps}: train_loss={loss:.4f}, test_loss={test_loss:.4f}") ``` ### Anomaly scoring ```python from stanno.config.schema import FilterConfig from stanno.integration.filter import STANNOFilter # Train on normal embeddings stanno.fit(normal_embeddings, normal_embeddings, epochs=50) # Create filter filt = STANNOFilter(stanno, FilterConfig(anomaly_threshold=0.7)) # Score new embedding score, info = filt.score(new_embedding) print(f"Anomaly score: {score:.3f} (0=normal, 1=anomaly)") if info["blocked"]: print("Blocked: input is too unusual") ``` ## How it works **The core idea:** - **TraineeNet**: A neural network with weights you want to train. - **TrainerNet**: Another network that looks at the TraineeNet's internal state (activations, errors, weights) and computes how to update those weights. - **No backprop**: The update formula is explicit, not learned via autodiff. - **Cascades**: Multiple TraineeNet+TrainerNet pairs can be chained so that gradient signals flow backward across stage boundaries, enabling end-to-end training of multi-stage pipelines. - **Scanning**: Any trained STANNO can be used as a similarity function to scan and rank rows in large datasets by how closely they match the learned distribution. **The three trainer types:** | Type | Mechanism | Best for | |------|-----------|----------| | **Fixed** | 4-module design (patent 5852815A), cascade-aware | Baseline, reproducibility, understanding the concept | | **LocalRule** | Shared MLP per synapse | Adaptive training, interpretability | | **Evolutionary** | Evolve per-layer scales (ES) | Unconventional problems, when autodiff fails | ## Technical details - **Backend agnostic**: Uses NumPy by default, but can swap in PyTorch. - **Variable architecture**: Networks can be any depth (list of layer sizes). - **Configurable feedback**: Dream mode can "repeat" outputs, use a learned "linear" projection, or "zero" them. - **Pickle-serializable**: Save/load trained models easily. ## Benchmark On sin(x) regression (512 samples, 100 epochs): ``` Fixed MSE=0.047 LocalRule MSE=0.021 (learnable rules = better fit) Evolutionary MSE=0.053 ``` ## For ComfyUI users The [comfyui-stanno](https://github.com/[your-username]/comfyui-stanno) custom node package provides nine nodes in the **STANNO** category: | Node | What it does | |------|--------------| | **STANNOLoad** | Create or load a model (JSON config or .pkl file) | | **STANNOTrainImages** | Train on image batches | | **STANNOScoreImages** | Filter images by reconstruction error | | **STANNODreamCond** | Modify CLIP embeddings with dream mode | | **STANNODynamicLoRA** | Apply learned style as LoRA patches | | **STANNOCompositeCheck** | Route images to whichever of two STANNOs matches best | | **STANNOScan** | DSANNO scanner: auto-calibrated threshold + top-k image retrieval | | **STANNOCascadeLoad** | Create or load a multi-stage CascadeSTANNO | | **STANNOCascadeTrainImages** | Train a cascade end-to-end on an image batch | Install via ComfyUI-Manager or manually. ## Patent & Attribution **STANNO is an open-source implementation of US Patent 5,852,815** (*Artificial Neurogenesis Network*), filed by Stephen L. Thaler. The patent has expired (US utility patents: 20 years from filing). We fully acknowledge and credit all core architectural concepts to the original patent. **This implementation adds:** - Modern Python/NumPy/PyTorch backend - CascadeSTANNO (multi-stage gradient cascade) - DSANNO (data scanning and semantic search) - Three trainer types (Fixed, LocalRule, Evolutionary) - ComfyUI integration (9 custom nodes) - CLI tools for common tasks See **Citation** below for how to cite the original patent and this implementation. ## Citation If you use STANNO in research, cite the original patent: ```bibtex @patent{thaler1998artificial, title={Artificial neurogenesis network}, author={Thaler, Stephen L}, year={1998}, number={5852815}, institution={United States Patent} } ``` And mention this implementation: ```bibtex @software{stanno2026, title={STANNO: Self-Training Artificial Neural Network Object}, author={Raides J. Rodríguez}, year={2026}, url={https://github.com/nitroxido/stanno} } ``` ## Questions? - **Bug report**: Open an issue on GitHub - **Question**: Start a discussion - **Feature request**: Describe what you want to build ## License MIT ## Core Package This integration requires the [stanno](https://huggingface.co/oldman-dev/stanno) core package. Install with: ```bash pip install git+https://github.com/nitroxido/stanno.git ``` {data-source-line="259"}