Adoption: drop-in recurrent trunk¶
Short path from install to a working stack. Cell APIs:
docs/cells.md, docs/xlstm.md.
Replace an Attention block¶
ParaSLSTMBlock is a pre-norm residual trunk:
RMSNorm → ParaRNN(ParaSLSTM) → residual → RMSNorm → SwiGLU → residual
import torch
from pararnn import NewtonConfig, ParaSLSTMBlock
d_model = 256
block = ParaSLSTMBlock(
d_model,
mlp_ratio=4.0,
config=NewtonConfig(max_iters=3),
)
x = torch.randn(2, 128, d_model)
y = block(x) # (2, 128, 256)
# Stack like transformer layers (no GQA inside this package):
layers = torch.nn.ModuleList([ParaSLSTMBlock(d_model) for _ in range(8)])
In torchtitan / Megatron / Llama-Factory style code, swap the attention module
for this block (or alternate Attention every k layers outside ParaRNN). The
library owns the recurrent Newton solve; attention kernels stay in your stack.
Full CausalLM¶
from pararnn import ParaSLSTMConfig, ParaSLSTMForCausalLM
cfg = ParaSLSTMConfig(
vocab_size=32000,
hidden_size=512,
num_hidden_layers=8,
mlp_ratio=4.0,
)
model = ParaSLSTMForCausalLM(cfg)
logits, loss = model(input_ids, labels=input_ids) # train
tokens = model.generate(prompt_ids, max_new_tokens=32) # eval decode
model.save_pretrained("./ckpt") # config.json + model.safetensors
model = ParaSLSTMForCausalLM.from_pretrained("./ckpt")
Smoke: examples/causal_lm_smoke.py.
Packed continuous batch: examples/continuous_batch.py.
Serve: inference.md (carry / decode_step) ·
vllm.md (plugin).
Dreamer / RSSM recurrent slot¶
World-model imagination is usually h_t = GRU(h_{t-1}, concat(z, a)). Use
ParaGRU(mix='head') inside ParaRNN for that slot; keep encoder / prior /
actor in your RL code.
from pararnn import NewtonConfig, ParaGRU, ParaRNN
# Cho gates; Dreamer LayerNorm stays outside the cell.
rssm_h = ParaRNN(
ParaGRU(d_in=z_dim + a_dim, d_h=512, mix="head", n_heads=8),
config=NewtonConfig(max_iters=3),
)
# .train() → parallel Newton over the imagination horizon
# .eval() → sequential step (T=1 CUDA: decode_step)
Smoke: examples/rssm_recurrent.py.
Griffin / RecurrentGemma recurrent slot¶
For a nonlinear replacement of linear RG-LRU (input-only gate, diagonal mix,
tanh inside the step), use ParaNLRU:
from pararnn import ParaNLRU, ParaRNN
core = ParaRNN(ParaNLRU(d_model, d_model))
This shares the diag-Jacobian class with fused ParaGRU. Griffin's
$a^{c r_t}$ parameterization needs its own weight map; treat ParaNLRU as
a nonlinear slot with the same Newton path, with separate checkpoints.
Liquid / irregular-Δt slot¶
For a Liquid-style closed-form step with irregular sampling intervals,
use ParaCfC (fidelity research-variant vs Hasani / ncps — see
architecture/para_cfc.md). Features live in
x[..., :-1]; Δt is x[..., -1] (d_in >= 2):
from pararnn import ParaCfC, ParaRNN
# d_in = feature_dim + 1
core = ParaRNN(ParaCfC(d_model + 1, d_model))
feat = ... # (B, T, d_model)
dt = ... # (B, T, 1), positive
y = core(torch.cat((feat, dt), dim=-1))
Gate $a=\exp(-\mathrm{softplus}(f)\,\Delta t)$ and diagonal mix \(u\) keep
the Newton Jacobian channelwise diagonal (fused Alg. 1 on CUDA).
Modern Hopfield / attractor slot¶
For a recurrent one-step Modern-Hopfield update with input-conditioned
pattern matrices, use ParaHopfield. Softmax couples channels, so Newton
uses a dense Jacobian and scan_dense (keep d_h ≤ 32; tests use 8):
from pararnn import NewtonConfig, ParaHopfield, ParaRNN
core = ParaRNN(
ParaHopfield(d_model, 8),
config=NewtonConfig(max_iters=None, jac_structure="dense"),
)
y = core(x) # (B, T, d_model) → (B, T, 8)
Default $\beta=1/\sqrt{d_h}$. max_iters=None selects the measured
K*(T) envelope (hopfield_auto_newton_iters); pin an int or pass
newton_iters_by_t={64: 2, 1024: 3, …} to override. Fused cell+scan and
packed VJP are parked; eq. 2.6 uses Autograd on step.
RWKV-7 Goose / matrix-state delta slot¶
For the linear RWKV-7 Goose transition (Peng et al. arXiv:2503.14456), use
ParaRWKV7. State is per-head $S\in\mathbb{R}^{d_{\mathrm{head}}\times d_{\mathrm{head}}}$;
gates are input-only, so the map is an affine monoid in \(S\):
from pararnn import ParaRWKV7, newton_apply, sequential_apply
cell = ParaRWKV7(d_in=d_model, n_heads=4, d_head=16)
s = sequential_apply(cell, x) # (B, T, H, D, D)
y = cell.scan_apply(x) # (B, T, n_heads*d_head) = flatten(S @ r)
# newton_apply runs the linear (G,U) scan (iters=0).
s2 = newton_apply(cell, x)
This is a factorized matrix-state delta brick (same class as the M²RNN linear warm-start). Full RWKV-7 token-mix and Wind CUDA live in the RWKV stack.
Titans / shallow neural memory slot¶
For a vector memory with one surprise-GD associative step plus a diagonal
nonlinear polish (Behrouz et al. arXiv:2501.00663 flavor), use
ParaTitans. Deep multi-layer MLP memory is parked:
from pararnn import ParaTitans, ParaRNN
core = ParaRNN(ParaTitans(d_model, d_model))
The Newton Jacobian is channelwise diagonal (fused Alg. 1 on CUDA).
Scope¶
Local save_pretrained / from_pretrained (config.json + model.safetensors).
Hugging Face AutoModel registration is a separate integration workstream.
Compose Attention / GQA in your trainer next to ParaSLSTMBlock for a hybrid
stack. RSSM / Dreamer keep encoder, prior, and actor in the RL codebase; this
library supplies the recurrent h_t slot.