Cascade Correlation Neural Network implementation for the Juniper project
Project description
Juniper: Dynamic Neural Network Research Platform
Juniper is an AI/ML research platform for investigating dynamic neural network architectures and novel learning paradigms. The project emphasizes ground-up implementations from primary literature, enabling a more transparent exploration of fundamental algorithms.
Juniper Cascor
juniper-cascor is the Cascade-Correlation training service of the Juniper platform. It implements the Fahlman & Lebiere (1990) algorithm from first principles and exposes that implementation as a long-running FastAPI service with a REST interface and two WebSocket channels — a training stream (/ws/v1/training) over which clients receive live training events, and a worker stream (/ws/v1/workers) over which juniper-cascor-worker instances connect to take part in distributed candidate-pool training. The service is dataset-aware: it consumes the named-version dataset registry of juniper-data and emits structured training events that juniper-canopy renders in real time. juniper-cascor is the place where the platform's training algorithms actually run; the other components surround it as data, monitoring, and parallelism layers.
Distribution
juniper-cascor is published on PyPI as juniper-cascor.
The package is also surfaced through the platform meta-distribution
juniper-ml, which installs
the full client stack via pip install juniper-ml[all].
pip install juniper-cascor
Ecosystem Compatibility
This service is part of the Juniper ecosystem. Verified compatible versions:
| juniper-data | juniper-cascor | juniper-canopy | data-client | cascor-client | cascor-worker |
|---|---|---|---|---|---|
| 0.6.x | 0.4.x | 0.4.x | >=0.4.1 | >=0.4.0 | >=0.3.0 |
For full-stack Docker deployment and integration tests, see juniper-deploy.
Architecture
juniper-cascor is the training service of the Juniper ecosystem. It depends on juniper-data for datasets, is monitored in real time by juniper-canopy, and is parallelised across hosts by juniper-cascor-worker.
┌─────────────────────┐ REST+WS ┌──────────────────────┐
│ juniper-canopy │ ◄──────────────► │ juniper-cascor │
│ Dashboard │ │ Training Svc │
│ Port 8050 │ │ Port 8200 ◄── here │
└──────────┬──────────┘ └──────┬──────┬────────┘
│ REST │ REST │ WS
▼ ▼ │
┌──────────────────────────────────────────────────┐ │
│ juniper-data │ │
│ Dataset Service · Port 8100 │ │
└──────────────────────────────────────────────────┘ │
▼
┌─────────────────────────┐
│ juniper-cascor-worker │
│ Distributed candidate │
│ training over │
│ /ws/v1/workers │
└─────────────────────────┘
API surface: REST (/v1/...) plus two WebSocket channels — /ws/v1/training for live training events and /ws/v1/workers for remote worker connections. All REST responses use the {status, data, meta} envelope.
Related Services
| Service | Relationship | Notes |
|---|---|---|
| juniper-data | juniper-cascor fetches datasets from here |
Set JUNIPER_DATA_URL |
| juniper-canopy | Monitors CasCor training in real time | Connects to /ws/v1/training |
| juniper-cascor-client | REST + WebSocket client library | pip install juniper-cascor-client |
| juniper-cascor-worker | Distributed candidate-training worker | Connects to /ws/v1/workers |
Service Configuration
Configuration is sourced from src/api/settings.py (Pydantic BaseSettings, env_prefix="JUNIPER_CASCOR_"). The variables most relevant to typical deployment are listed below; the full set (rate-limiting, worker rate-limiting, anomaly detection, WebSocket-control cooldown, and observability) is documented in docs/install/REFERENCE.md.
| Variable | Required | Default | Description |
|---|---|---|---|
JUNIPER_DATA_URL |
Yes | http://localhost:8100 |
juniper-data service URL |
JUNIPER_CASCOR_HOST |
No | 127.0.0.1 |
Bind address (override to 0.0.0.0 for Docker) |
JUNIPER_CASCOR_PORT |
No | 8200 |
Service port (container side) |
JUNIPER_CASCOR_LOG_LEVEL |
No | INFO |
Log verbosity (DEBUG, INFO, WARNING, ERROR) |
JUNIPER_CASCOR_LOG_FORMAT |
No | text |
text or json (structured logging) |
JUNIPER_CASCOR_CORS_ORIGINS |
No | [] |
Allowed CORS origins |
JUNIPER_CASCOR_API_KEYS |
No | None |
Comma-separated API keys; authentication disabled when unset |
JUNIPER_CASCOR_API_KEYS_FILE |
No | — | Docker-secrets path for the API-keys list |
JUNIPER_DATA_API_KEY |
No | — | API key for outbound calls to juniper-data |
JUNIPER_CASCOR_METRICS_ENABLED |
No | false |
Expose /metrics for Prometheus scraping |
JUNIPER_CASCOR_SENTRY_DSN |
No | None |
Sentry DSN for error tracking |
CASCOR_LOG_LEVEL |
No | — | Legacy fallback for JUNIPER_CASCOR_LOG_LEVEL |
Docker Deployment
# Full stack (recommended) — see juniper-deploy:
git clone https://github.com/pcalnon/juniper-deploy.git # (private repository)
cd juniper-deploy && docker compose up --build
# Standalone:
docker build -t juniper-cascor:latest .
docker run --rm -p 8200:8200 \
-e JUNIPER_CASCOR_HOST=0.0.0.0 \
-e JUNIPER_DATA_URL=http://host.docker.internal:8100 \
juniper-cascor:latest
The Dockerfile is multi-stage (Python 3.14-slim builder + runtime); the runtime image installs PyTorch from the CPU-only index (https://download.pytorch.org/whl/cpu) outside the lockfile to avoid the multi-gigabyte CUDA wheels. Container health is probed against /v1/health/ready.
Dependency Lockfile
The requirements.lock file pins exact dependency versions for reproducible Docker builds. The pyproject.toml retains flexible >= ranges for local development. A parallel uv.lock covers uv-native resolution.
Regenerate after changing dependencies in pyproject.toml:
uv pip compile pyproject.toml \
--extra ml --extra api --extra observability --extra juniper-data \
--extra-index-url https://download.pytorch.org/whl/cpu \
--index-strategy unsafe-best-match \
--no-emit-package torch \
-o requirements.lock
PyTorch is excluded from the lockfile and installed separately in the Dockerfile from the CPU-only index. The ecosystem-wide lockfile-freshness gate enforces this regeneration on every PR that touches pyproject.toml; if a regenerated lockfile triggers the self-pin trap of uv pip compile -o requirements.lock reading the existing file, compile to /tmp/requirements.lock and mv into place.
Active Research Components
juniper-cascor houses four research components of the Juniper platform: the Cascade-Correlation reference implementation itself (Fahlman & Lebiere, 1990), kept inspectable at the level of candidate units, correlation objectives, and weight-freezing semantics; the candidate-pool training protocol that parallelises candidate-unit selection across processes and (via juniper-cascor-worker) across hosts; the multi-network orchestration machinery being developed for population-level comparative experiments (design notes: juniper-ml/notes/PHASE_6E_DESIGN.md, PHASE_6E_MULTI_NETWORK_DESIGN.md); and the WebSocket training-event protocol consumed by juniper-canopy for live introspection of network growth. The METRICS-MON R3.7 macOS CI integration soak (completed 2026-05-15) supports cross-platform reproducibility claims for these components.
Quick Start Guide
Prerequisites
- Python ≥ 3.12 (Docker image uses 3.14)
- Conda environment
JuniperCascor - A running
juniper-datainstance reachable atJUNIPER_DATA_URL(typicallyhttp://localhost:8100)
Installation
git clone https://github.com/pcalnon/juniper-cascor.git
cd juniper-cascor
conda env create -f conf/conda_environment.yaml
conda activate JuniperCascor
pip install -e ".[ml,api,observability,test]"
The PyPI release is installable via pip install juniper-cascor; the editable-clone form above is the standard for active development.
Verification
Start the service:
python src/server.py
Confirm the service is responding:
curl http://localhost:8200/v1/health
curl http://localhost:8200/v1/health/ready
The library is also usable directly from Python, bypassing the service:
from cascade_correlation.cascade_correlation import CascadeCorrelationNetwork
from cascade_correlation.cascade_correlation_config.cascade_correlation_config import CascadeCorrelationConfig
config = CascadeCorrelationConfig(input_size=2, output_size=2, random_seed=42)
network = CascadeCorrelationNetwork(config=config)
history = network.fit(x_train, y_train, epochs=100)
print(f"Test accuracy: {network.get_accuracy(x_test, y_test):.2%}")
Run the test suite:
cd src/tests && bash scripts/run_tests.bash
# or
pytest -m "not slow" -v
Next Steps
docs/install/QUICK_START.md— complete installation guidedocs/install/USER_MANUAL.md— comprehensive usage guidedocs/api/API_REFERENCE.md— complete REST and WebSocket API documentationjuniper-deploy— Docker Compose orchestration for the full-stack platformjuniper-ml— platform meta-package on PyPI
Research Philosophy
The Juniper platform exists to study learning algorithms whose network architecture is not fixed in advance. Its initial anchor is the Cascade-Correlation algorithm of Fahlman and Lebiere (1990), implemented from the primary literature without recourse to higher-level abstractions that elide the algorithm's operational detail. The organising commitment is that algorithm implementations remain inspectable at the level at which they were originally specified: candidate units, correlation objectives, weight-freezing semantics, and the structural events that grow the network are first-class artifacts of the codebase rather than internal details of a library wrapper. This permits comparative work — across algorithms, datasets, and hyperparameter regimes — to be conducted on a known and reproducible substrate.
The current platform comprises a Cascade-Correlation training service exposing a REST and WebSocket interface, a dataset-generation service with a named-version registry that includes the ARC-AGI families, a real-time monitoring dashboard for inspecting training dynamics as they occur, and a distributed worker that parallelises candidate-unit training across hosts. Near-term work extends the architectural-growth catalogue beyond Cascade-Correlation, introduces multi-network orchestration for comparative experiments at the level of network populations rather than individual runs, and tightens the dataset–training–monitoring loop into a reproducible research workbench. The longer-term direction is the systematic empirical study of constructive and architecture-growing learning algorithms, with first-class infrastructure for the ablation, comparison, and replication that such a study requires.
Documentation
| Document | Purpose |
|---|---|
docs/DOCUMENTATION_OVERVIEW.md |
Navigation index for all juniper-cascor documentation |
docs/INDEX.md |
Quick documentation index |
docs/install/QUICK_START.md |
Complete installation guide |
docs/install/USER_MANUAL.md |
Comprehensive usage guide |
docs/api/API_REFERENCE.md |
Complete REST and WebSocket API reference |
docs/testing/QUICK_START.md |
Testing instructions |
docs/ci_cd/QUICK_START.md |
Continuous integration guide |
docs/source/QUICK_START.md |
Contributor documentation |
docs/overview/CONSTANTS_GUIDE.md |
Configuration constants reference |
CHANGELOG.md |
Version history |
License
MIT License — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file juniper_cascor-0.5.0.tar.gz.
File metadata
- Download URL: juniper_cascor-0.5.0.tar.gz
- Upload date:
- Size: 881.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96a9360628aa55d68f9c9e688dc7f28e8d2d8ab9d25f1a473f25f2b1e2bb015a
|
|
| MD5 |
33ed4092308ea4a29e276dbcfc9722ce
|
|
| BLAKE2b-256 |
afffda5ca24bb29c65a7769d0279fc0a70df1023e0e761fe919ae6e6054562a7
|
Provenance
The following attestation bundles were made for juniper_cascor-0.5.0.tar.gz:
Publisher:
publish.yml on pcalnon/juniper-cascor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
juniper_cascor-0.5.0.tar.gz -
Subject digest:
96a9360628aa55d68f9c9e688dc7f28e8d2d8ab9d25f1a473f25f2b1e2bb015a - Sigstore transparency entry: 1611064419
- Sigstore integration time:
-
Permalink:
pcalnon/juniper-cascor@8321694735a79d9711ef8fa66a46aca9478b80c4 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/pcalnon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8321694735a79d9711ef8fa66a46aca9478b80c4 -
Trigger Event:
release
-
Statement type:
File details
Details for the file juniper_cascor-0.5.0-py3-none-any.whl.
File metadata
- Download URL: juniper_cascor-0.5.0-py3-none-any.whl
- Upload date:
- Size: 1.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c06a9e47290d994fe2930250db8ab97f427c9dd3ff91bda36aba8af22047d01
|
|
| MD5 |
0fc0032f2431b3d7bfaeb56212212e6a
|
|
| BLAKE2b-256 |
2736aa97d61dc9ec8bd77d21697082574b5c7c4e138250dbfeaaa02d2c211c11
|
Provenance
The following attestation bundles were made for juniper_cascor-0.5.0-py3-none-any.whl:
Publisher:
publish.yml on pcalnon/juniper-cascor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
juniper_cascor-0.5.0-py3-none-any.whl -
Subject digest:
0c06a9e47290d994fe2930250db8ab97f427c9dd3ff91bda36aba8af22047d01 - Sigstore transparency entry: 1611064623
- Sigstore integration time:
-
Permalink:
pcalnon/juniper-cascor@8321694735a79d9711ef8fa66a46aca9478b80c4 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/pcalnon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8321694735a79d9711ef8fa66a46aca9478b80c4 -
Trigger Event:
release
-
Statement type: