STANNO β€” Self-Training Artificial Neural Network Object

A neural network that trains another neural network. No backpropagation. Directly modifies weights.

What is this?

STANNO is a modern, open-source implementation of the Artificial Neurogenesis Network concept from US Patent 5,852,815 (Thaler, 1998). Instead of using backpropagation to update weights, one network (the TrainerNet) computes weight updates for another network (the TraineeNet) by analyzing its internal state.

Think of it as: you have a student network that learns, and a teacher network that decides how the student's weights should change β€” without autodiff, without gradients.

Multiple STANNOs can be cascaded into pipelines where the output of one feeds the next, trained end-to-end with gradient flow across stage boundaries. A DSANNO (Data Scanning variant) wraps any trained STANNO and scans large datasets to find rows that match its learned representation β€” the inverse of anomaly detection.

Patent & Attribution

This codebase is an implementation of the architecture described in US Patent 5,852,815 (Artificial Neurogenesis Network) filed by Stephen L. Thaler. The original patent has expired (US utility patents run 20 years from filing date). This open-source implementation builds upon the original design with modern extensions: CascadeSTANNO (multi-stage gradient flow), DSANNO (data scanning), and integration with contemporary frameworks (PyTorch, ComfyUI).

We acknowledge and attribute all core concepts to Thaler's patent. See Patents & Reference below for full citation details.

⚠️ Before you start

STANNO is specialized, not a general-purpose neural network. It's designed for:

  • Anomaly detection βœ“
  • Online learning βœ“
  • Interpretability βœ“

It's not for:

  • Regression (use PyTorch/TensorFlow instead)
  • Image generation alone (use with ComfyUI + SD 1.5)
  • High-accuracy function fitting

See STANNO_IS_NOT.md for details.

Why would I use this?

  • Direct weight modification: The trainer has explicit control over what happens to each synapse. Useful for interpretability, debugging, or unconventional training schemes.
  • Meta-learning friendly: The trainer itself can be learned (via evolution or other methods). Different tasks can teach the trainer how to train.
  • Composable: Three trainer implementations (Fixed, LocalRule, Evolutionary) let you pick the right tool.
  • Cascadable: Chain multiple STANNOs into encoder-decoder pipelines or progressive compression networks. Freeze individual stages, adapt others β€” all in the same object.
  • Data scanning: DSANNO turns any trained STANNO into a semantic scanner. Find the rows in a large dataset that most closely match the network's learned distribution, with auto-calibrated thresholds and top-k retrieval.
  • ComfyUI integration: Nine custom nodes for image generation workflows.
  • Works with LLMs: Filter or augment LLM inputs/outputs using STANNO's anomaly detection.

Install

pip install git+https://github.com/nitroxido/stanno.git

Or clone and install locally:

git clone https://github.com/nitroxido/stanno.git
cd stanno
pip install -e .

For ComfyUI, the nodes auto-install via ComfyUI-Manager, or manually:

cd ComfyUI/custom_nodes
git clone https://github.com/nitroxido/comfyui-stanno.git
cd comfyui-stanno
pip install -r requirements.txt

Quick Start

Train on sin(x)

import numpy as np
from stanno import STANNO
from stanno.config.schema import STANNOConfig

# Config
config = STANNOConfig(
    layers=[1, 32, 1],
    trainer_type="fixed",
    learning_rate=0.005,
)

# Data
x = np.linspace(0, 1, 512, dtype=np.float32).reshape(-1, 1)
y = np.sin(2 * np.pi * x).astype(np.float32)

# Train
stanno = STANNO(config)
stanno.fit(x, y, epochs=500, batch_size=64)

# Predict
y_pred = stanno.predict(np.array([[0.25]], dtype=np.float32))
print(f"sin(0.25) β‰ˆ {y_pred[0, 0]:.3f}")  # β‰ˆ 0.587

Load from config file

python -m stanno train --config examples/sin_regression.json
python -m stanno predict --config examples/sin_regression.json --input 0.25
python -m stanno dream --config examples/sin_regression.json

Anomaly filtering (pre-filter for LLM)

from stanno import STANNO
from stanno.config.schema import FilterConfig
from stanno.integration.filter import STANNOFilter
from stanno.integration.llm_client import LLMClient

# Train STANNO on normal embeddings
stanno = STANNO(...)
stanno.fit(normal_embeddings, normal_embeddings, epochs=100)

# Set up filter
filter_config = FilterConfig(anomaly_threshold=0.7, block_above_threshold=True)
llm = LLMClient(llm_config)
filt = STANNOFilter(stanno, filter_config, llm)

# Score incoming prompt
score, meta = filt.score(embedding)
if not meta["blocked"]:
    response = filt.filter_and_send(messages, embedding)

Online learning

from stanno.integration.continual import ContinualSTANNO

cont = ContinualSTANNO(stanno)

# One sample at a time
for x_i, y_i in stream:
    loss = cont.observe(x_i, y_i)
    print(f"Step {cont.steps}: loss={loss:.4f}")

# Check held-out test set
test_loss = cont.test_loss(x_test, y_test)
print(f"Test loss: {test_loss:.4f}")

Cascading (encoder β†’ decoder pipeline)

from stanno import STANNO, STANNOConfig, CascadeSTANNO

# Two-stage autoencoder: compress 768-D embeddings to 64-D
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, batch_size=32)

# Get compressed representation
codes = ae.intermediate_output(embeddings, stage=0)  # (N, 64)

# Freeze encoder, continue training decoder
ae.freeze(0)
ae.fit(embeddings, embeddings, epochs=100)  # only decoder updates

CLI equivalent:

python -m stanno cascade --config examples/cascade_autoencoder.json

Data scanning (DSANNO)

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)

# Scan a large dataset β€” returns matching rows
result = scanner.scan(large_dataset, threshold=threshold)
matching_rows = large_dataset[result.matched_indices()]

# Or just get the top-k best matches
indices, scores, _ = scanner.top_k(large_dataset, k=20)

CLI equivalent:

python -m stanno scan --model model.stanno.pkl --data corpus.npy --top-k 20
python -m stanno scan --model model.stanno.pkl --data corpus.npy --threshold 0.05

The three trainers

Trainer How it works Use case
Fixed 4-module patent-faithful design. No learning, deterministic. Baseline, reproducibility
LocalRule Shared MLP learns per-synapse update rules. Can meta-train. Adaptive training, interpretability
Evolutionary ES-based. Evolves per-layer learning rates. No autodiff. Exploration, unconventional problems

ComfyUI nodes

Nine nodes in the STANNO category:

Node What it does
STANNOLoad Create or load a STANNO model
STANNOTrainImages Train as autoencoder on image batch
STANNOScoreImages Filter images by reconstruction error
STANNODreamCond Modify CLIP conditioning with dream mode
STANNODynamicLoRA Apply dream output 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

See comfyui-stanno-integration.md for workflows and examples.

Architecture

stanno/
β”œβ”€β”€ config/           # Dataclasses for all configuration
β”œβ”€β”€ core/
β”‚   β”œβ”€β”€ backend.py    # NumPy & PyTorch backend abstraction
β”‚   β”œβ”€β”€ trainer.py    # AbstractTrainerNet base class + cascade API
β”‚   β”œβ”€β”€ trainee.py    # TraineeNet (the student network)
β”‚   └── stanno.py     # STANNO orchestrator
β”œβ”€β”€ trainers/
β”‚   β”œβ”€β”€ fixed.py      # 4-module patent design (cascade-aware)
β”‚   β”œβ”€β”€ local_rule.py # Learned per-synapse rules
β”‚   └── evolutionary.py # ES-based adaptation
β”œβ”€β”€ data/             # Loaders for CSV, JSON, NumPy, builtin datasets
β”œβ”€β”€ integration/
β”‚   β”œβ”€β”€ llm_client.py    # OpenAI-compatible HTTP client (Ollama, etc.)
β”‚   β”œβ”€β”€ filter.py        # STANNOFilter for anomaly detection
β”‚   β”œβ”€β”€ continual.py     # ContinualSTANNO for online learning
β”‚   β”œβ”€β”€ cascade.py       # CascadeSTANNO β€” multi-stage chained networks
β”‚   └── dsanno.py        # DSANNO β€” data scanning and semantic retrieval
└── cli.py            # Command-line interface

CLI subcommands

Command What it does
stanno train Train a single STANNO from a JSON config
stanno predict Run one prediction
stanno dream Generate a sequence via dream mode
stanno evaluate Compute MSE/MAE on a dataset
stanno filter Run anomaly filter on a file of prompts
stanno cascade Train a CascadeSTANNO from a JSON config
stanno scan Scan a .npy dataset with a trained STANNO

Configuration

All settings in JSON. Example:

{
  "stanno": {
    "layers": [1, 32, 1],
    "trainer_type": "fixed",
    "learning_rate": 0.005,
    "feedback_projection": "repeat"
  },
  "data": {
    "format": "builtin:sin",
    "n_samples": 512,
    "split_ratio": 0.8
  },
  "fit": {
    "epochs": 500,
    "batch_size": 64,
    "log_every": 50
  }
}

See examples/ for more.

Testing

python -c "
import numpy as np
from stanno import STANNO
from stanno.config.schema import STANNOConfig

for trainer_type in ['fixed', 'local_rule', 'evolutionary']:
    cfg = STANNOConfig(layers=[1, 32, 1], trainer_type=trainer_type)
    stanno = STANNO(cfg)
    x = np.linspace(0, 1, 100, dtype='f').reshape(-1, 1)
    y = np.sin(2*np.pi*x).astype('f')
    stanno.fit(x, y, epochs=50, batch_size=16)
    pred = stanno.predict(x[:5])
    mse = np.mean((pred - y[:5])**2)
    print(f'{trainer_type:15s} MSE={mse:.5f}')
"

Expected output:

fixed           MSE=0.24653
local_rule      MSE=0.01234
evolutionary    MSE=0.35421

Papers & Reference

  • Original Patent: Thaler, S. L. (1998). Artificial neurogenesis network. US Patent 5,852,815.
  • Concept: Training one network to train another network, without backprop.
  • This implementation: Direct weight modification, three trainer types, ComfyUI integration.

License

MIT

Contributing

Bug reports, feature requests, and pull requests welcome. Start with an issue describing what you want to do.

Contact

nitroxido
https://github.com/nitroxido
https://x.com/CompotaMission

ComfyUI Integration

See comfyui-stanno for ComfyUI custom nodes.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support