| --- |
| 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"} |