Skip to content

Repository files navigation

TemporalFocus

TemporalFocus.jl

Spike-driven relevance routing for modular neural systems

Julia MIT OR Apache-2.0

Dev


TemporalFocus.jl is a small Julia library for computing per-component relevance scores from spike activity and readout change over time. The core abstraction is a routing loop that updates component weights from:

  • spike density
  • readout surprise relative to an exponential moving average
  • routing momentum
  • lateral inhibition between components

The library is intentionally narrow. It does not try to be a full SNN runtime, an LLM integration layer, or a hardware supervisor.

Project status

TemporalFocus is an extracted, early-stage library. It is useful today, but it still needs a lot of work before it reaches the broader long-term shape rmems wants for it.

What this means in practice:

  • the current API is small and focused
  • several defaults still reflect the original research/runtime context
  • documentation and boundaries are improving, but the package is not yet the final form
  • downstream integrations should treat this as an evolving library rather than a finished platform

What TemporalFocus owns

TemporalFocus owns spike-driven relevance routing logic:

  • ActivityRegion as a compact per-region summary (Float32 rate in [0,1], readout of length n_out)
  • RegionRouter as the mutable routing state (routing_weights length n_regions, sum ~1)
  • update_routing! as the per-tick routing update
  • routing_diagnostics for lightweight inspection/logging
  • adapt_leak! as a small optional helper for stress-aware leak adaptation

The frozen interop shapes (and what the package deliberately does not own — e.g. spike event lists / full trains) are documented in docs/interop.md.

What TemporalFocus does not own

TemporalFocus does not own:

  • spike event lists or full spike trains
  • full neuron or reservoir simulation
  • training loops or plasticity pipelines
  • token embeddings or transformer execution
  • hardware telemetry ingestion
  • deployment/runtime supervision
  • model-specific ANN/LLM adapters

If a workflow needs those pieces, they should live in surrounding libraries or applications that feed compact readouts into TemporalFocus.

Installation

using Pkg
Pkg.add("TemporalFocus")

Quick start

using TemporalFocus

router = RegionRouter(
    n_regions = 4,
    n_out = 8,
    region_names = ["sensor", "reservoir", "memory", "decoder"],
)

regions = [
    ActivityRegion(0.82f0, Float32[0.9, 0.7, 0.2, 0.1, 0.0, 0.1, 0.3, 0.5]),
    ActivityRegion(0.28f0, Float32[0.3, 0.2, 0.1, 0.0, 0.0, 0.0, 0.2, 0.2]),
    ActivityRegion(0.41f0, Float32[0.4, 0.6, 0.5, 0.2, 0.1, 0.1, 0.0, 0.1]),
    ActivityRegion(0.12f0, Float32[0.1, 0.1, 0.0, 0.0, 0.4, 0.6, 0.8, 0.9]),
]

update_routing!(router, regions)

routing_weights = router.routing_weights
println(routing_weights)
println(routing_diagnostics(router))

Examples

Worked examples live in examples/:

Run any example from the repository root:

julia --project=. examples/three_region.jl

Legacy API

The old NERO/lobe names still work as backward-compatible aliases:

# These are equivalent:
LobeState == ActivityRegion
NeroOrchestrator == RegionRouter
update_relevance! == update_routing!
nero_diagnostics == routing_diagnostics

Core routing rule

At each tick, TemporalFocus computes a raw score for each component:

score_i = α · density_i + β · surprise_i + γ · momentum_i

with:

  • density_i: current normalized spike activity
  • surprise_i: deviation from the component's EMA readout
  • momentum_i: change in routing weight relative to the previous tick

The raw scores are then:

  1. reduced by cross-component inhibition
  2. clamped with a floor so components do not go fully silent
  3. normalized with a softmax-like pass to produce routing weights that sum to 1

Public API

ActivityRegion(last_spike_rate::Float32, output::Vector{Float32})
ActivityRegion(n_out::Int)

RegionRouter(; n_regions=4, n_out=16, region_names=DEFAULT_REGION_NAMES)

update_routing!(router::RegionRouter, regions::Vector{ActivityRegion})
routing_diagnostics(router::RegionRouter)
adapt_leak!(leak_rate::Ref{Float32}, stress::Real; min_leak=0.01f0, max_leak=0.25f0, stress_adapter=nothing)

Legacy aliases (LobeState, NeroOrchestrator, update_relevance!, nero_diagnostics) resolve to the same types/functions; use the preferred names above for new code.

Default assumptions and current limitations

A few defaults still reflect the package's original extraction context:

  • the default lobe names are Attention, FFN, Memory, and Output
  • the default inhibition matrix is tuned for a 4-component example layout
  • adapt_leak! default stress scale is percent-like in [0, 100] (custom stress_adapter allowed)
  • the package currently exposes NERO terminology directly in type/function names

Those defaults are serviceable, but they are not the final abstraction boundary.

Documentation

  • Dev docs — updates from main (Documenter deploydocs)
  • Stable docs (/stable) appear only after the first version tag is pushed; until then use dev

Source markdown lives in docs/ (Documenter pages under docs/src/):

  • docs/src/overview.md — architecture, scope, and intended usage
  • docs/src/api.md — exported types/functions and behavior notes
  • docs/src/interop.md — frozen data-shape / interop contract (rates, readouts, routing weights)
  • docs/src/roadmap.md — gaps, next cleanup targets, and candid project status

(Root copies under docs/*.md may exist for GitHub browsing; Documenter builds from docs/src/.)

Build locally with:

julia --project=docs -e 'using Pkg; Pkg.develop(path="."); Pkg.instantiate()'
julia --project=docs docs/make.jl

Migration note

The Julia package / project identity changed from NeuroPulse (and earlier SpikenautAttention / SpikenautNero) to TemporalFocus. The GitHub repository and GitHub Pages path remain Limen-Neural/NeuroPulse.jl (https://limen-neural.github.io/NeuroPulse.jl/...).

Migration steps for downstream users:

  • replace Pkg.add("NeuroPulse") (or SpikenautAttention) with Pkg.add("TemporalFocus")
  • replace using NeuroPulse (or using SpikenautAttention) with using TemporalFocus
  • update any package metadata or examples that still reference the old package name

The NERO algorithm name remains in the current public API via NeroOrchestrator and nero_diagnostics, but the package identity is now TemporalFocus.

Development

Run tests with:

julia --project -e 'using Pkg; Pkg.instantiate(); Pkg.test()'

License

This project is licensed under either of

at your option.

Contributions intentionally submitted for inclusion in this package by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.

About

NERO: Neuromorphic Evaluation of Relevance and Orchestration — multi-lobe SNN relevance scoring with cross-lobe inhibition and softmax normalisation

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages