Skip to content

srose69/ViperLLM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

101 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Viper-LLM

Volumetric language model with Triangle Cross-Scan State Modelling

One forward pass over a 3D token volume — no autoregressive loop, no KV-cache.

by srose69 (SimpleRose)

Python 3.10+ PyTorch 2.1+ CUDA 11.8+ O(L) complexity No attention Optimizer ATOM Memory XMem Internal Language Thought--DSL Normalization LeaRNorm State Modelling TXSSM Architecture Volumetric Code License: AGPL--3.0--only Docs License: CC--BY--4.0 Status

Some badges are clickable

English · Русский


Note: Docstrings and documentation may occasionally lag behind the code due to active development.

Примечание: Докстринги и документация могут местами отставать от кода ввиду активной разработки.

Tests and another piece of papers are coming soon

Visualizations will appear here periodically

Contents


What is Viper?

Viper is an experimental language model architecture that processes the entire input sequence in a single forward pass. There is no autoregressive token-by-token generation loop, no KV-cache, and no quadratic self-attention. Instead, tokens are embedded into a three-dimensional volume, and information propagates through the full context via linear-time associative scans.

The architecture is designed to answer a specific question: can a language model work without attention at all — replacing every pairwise token interaction with structured recurrence — and still remain trainable at scale?

How it works

Volumetric representation

A token sequence of length L is packed into a three-dimensional grid G×H×W, where L = G·H·W, using a Faced Continuous Snake Layout. Each depth slice is an H×W face traversed by a 2-D snake; odd faces reuse the same path in reverse so sequence continuity is preserved across face boundaries as well as inside each face. Spatial relationships — which tokens are adjacent horizontally, vertically, or in depth — are encoded implicitly by grid coordinates, eliminating the need for learned positional encodings. A causal 3×3×3 convolution provides local connectivity over this layout.

Small example on a 2×3×3 grid:

face g=0              face g=1
 0   1   2            11  10   9
 5   4   3            12  13  14
 6   7   8            17  16  15

The volume is the model's working memory. It starts as token embeddings shaped into 3D and accumulates information layer by layer. There are no residual skip connections around computational blocks — only additive, bounded deltas. This is documented in detail in CML — Context Modelling Layer.

TXSSM — Triangle Cross-Scan State Modelling

Where a Transformer would compute an L×L attention matrix, Viper runs parallel associative scans. The recurrence m_t = a_t · m_{t-1} + b_t · z_t is resolved by an associative scan kernel: the current CUDA path uses a fused CUB BlockScan implementation for moderate sequence lengths and falls back to a generic ping-pong scan otherwise. Full details are in scan_ops.

Each computational unit — a slab — runs three parallel scans over a shared q/k/z basis, collectively called TXSSM (Triangle Cross-Scan State Modelling):

  • Fast horizontal scan with half-life τ ≈ 32 tokens. Captures short-range structure: syntax, phrase boundaries, adjacent token relationships. High temporal resolution, rapid state update.
  • Slow horizontal scan with half-life τ ≈ 65536 tokens. Maintains an ultra-long retention reservoir for very distant past; stability comes from leaky-integrator injection normalization and fp32 retention gates rather than from a short horizon.
  • Column scan along the layout's depth-aligned axis. It connects positions that share the same face coordinates but live on different faces, providing direct cross-face information flow that the horizontal scans would otherwise reach only through long sequence distance.

All three scan outputs are combined through separate readout projections and summed into a single context vector. The horizontal and column EMA states are read through a variance-preserving gain before projection, so ultra-long-retention branches remain numerically visible without changing the carried state itself. The timescale separation (fast vs slow) is an architectural prior — the model is given two pre-set temporal resolutions plus a spatial channel, and it learns what information to route through each. Full details in CML.

RMU — Ray Matrix Unfolding

Before scanning, the volume is projected into a lower-dimensional ray space. RMU (Ray Matrix Unfolding) enriches the volume with local 3×3×3 and cross-channel 1×1×1 convolutions, applies LeaRNorm spectral normalization, and projects each position to a D-dimensional ray vector. This ray is what the slab «sees» at each position — a compressed, normalized view of the volume at that coordinate. The TXSSM scans then operate over these rays.

VAttn — directional gated context

In parallel with TXSSM, an optional VAttn module (Vectorized Attention) runs its own gated causal scan over the volume. Unlike TXSSM's fixed timescales, VAttn learns per-position retention factors — the model can implement a 5-token memory at one position and a 500-token memory at another, within the same head. VAttn accumulates directional context across the full sequence, and its output is summed with the ray projection before the read phase. VAttn provides non-quadratic context accumulation without any L×L matrix.

XMem — long-term volumetric retrieval

The TXSSM scans and VAttn handle context within a chunk, but everything they accumulate must fit into bounded scan states. To recover precise information from many chunks ago, the model carries one shared XMem bank of shape [B, D_mem, A^N] through the chunk carry. Every slab has its own read/query/write projections into that same bank, so later slabs can retrieve content that earlier slabs wrote.

XMem participates in both phases of the slab pipeline. In phase 1 it is read-only and enriches the volume before VAttn and RMU: the slab projects the raw volume into a continuous coordinate in (-1, 1)^N, gathers from the shared bank via N-linear interpolation, and adds the result back to the volume. Both causal scans then propagate the retrieved long-range content through their dynamics — making XMem impossible to passively ignore. In phase 2 it becomes read-write: after blueprint/context mixing and RayMix, the write-side representation performs a second memory read and then writes back into the bank.

Read and write addresses are intentionally separate. The read coordinate says "where is the old thing I want?"; the write coordinate says "where should the refined thing live?". The write path has its own orthogonal rotation plus a learned bounded shift conditioned on the current write hidden and the read context, so the model is not forced to overwrite exactly what it just retrieved.

The memory is six-axis by default — twice VAttn's three spatial axes. This is the classical geometric lift trick: store content in a higher-dimensional address volume, read it with the same O(L) asymptotic class as VAttn, and recover more independently placed information per trajectory than a 3D storage geometry can provide. The fixed Hadamard slice gives exact orthogonality at initialization; learned skew-symmetric rotations make the address basis trainably rotatable without breaking orthogonality.

XMem is sparse-by-construction: each read or write touches 2^N corner cells (64 at N=6), so the gradient is naturally local. No straight-through estimator, no Gumbel-softmax, and no dense A^N update are required. Because the state tensor is shared rather than replicated per slab, the activation-tape cost scales with xmem_size · batch_size · seq_len_mul, not multiplied by num_slabs.

Read phase — the decision point

The read phase receives two signals: the ray projection (what the slab sees now, plus VAttn context and the phase-1 XMem retrieval) and the TXSSM scan readout (what the slab remembers from history). From these, it computes:

  • value — what to say, derived from the current position
  • context — what history says, derived from accumulated scan state
  • blueprint — a per-dimension gate in (0, 1) that interpolates between value and context for each of the D dimensions independently
  • write gate — a direct bypass that lets the hidden state pass through with minimal transformation

The blueprint mechanism is not attention over positions — it is a per-dimension choice: use fresh information or accumulated history, independently for each feature dimension. Different semantic aspects can use different sources simultaneously.

GLE — Ghost Lift Expansion

After the read phase produces a hidden state, an optional GLE module (Ghost Lift Expansion) enriches it. GLE is an implicit lifted operator that expands the D-dimensional hidden state into a larger virtual space E > D without materializing the full E×E matrix. It uses frozen Hadamard projectors to map between base and ghost spaces, applies a learned nonlinearity in the ghost space, and projects back to D.

The purpose: a simple D→D linear projection has rank at most D. GLE gives the hidden state — the information that crosses the slab boundary — more expressive capacity than a linear bottleneck. It is applied at three points: ghost extraction from hidden after read, lifting the write signal before RayMix, and lifting the hidden state in the CML bridge to the next slab.

Write phase — delta update

The blended signal (blueprint-interpolated value and context, plus write gate bypass, lifted through GLE) passes through RayMix — a causal 1D depthwise-then-pointwise convolution with kernel size 5. This provides a 5-token local window where adjacent read-phase outputs interact, complementing the elementwise nature of the scan.

The result is projected back to the full channel dimension C, bounded to (-4, 4) per element, and added to the volume as a delta. Each slab decides independently how much to modify the volume — no slab can dominate because every delta is bounded.

CML — the context bridge between slabs

After the write phase, the slab's hidden state — enriched by GLE — is reshaped into a 5D volume and passed to the next slab. This is the CML (Context Modelling Layer): the mechanism that determines what information crosses the slab boundary and in what form. CML is not the slab itself — it is the bridge between slabs.

LeaRNorm — spectral normalization

LeaRNorm replaces standard LayerNorm throughout the model, but it is not a generic spectral normalizer. The formula is y = (x - mean(x)) / sqrt(1 + |siloid(a · rho)|), where a is the mean absolute deviation of the centered signal and rho is its weighted spectral centroid — the center of mass of the power spectrum, computed via rFFT. The product a · rho is passed through siloid (the same saturating activation used everywhere in Viper), and the denominator is always ≥ 1 — it can only shrink the signal, never amplify it.

The effect: a signal dominated by low frequencies (smooth trends) has a low spectral centroid, producing a small denominator and preserving amplitude. A signal with high-frequency content (sharp changes, noise) has a high centroid, producing a larger denominator and stronger suppression. The normalization strength adapts to what the signal contains, not just how large it is. This is fundamentally different from RMSNorm, which treats all frequency content identically.

The backward pass is a hand-written analytical autograd.Function — the rFFT intermediate is recomputed in backward rather than saved, keeping memory overhead under 1% compared to the forward activations. A range regularization loss penalizes RMS outside [0.65, 1.35] and per-element absolute values exceeding 4.0, applied as an auxiliary loss during training.

ATOM optimizer

Training uses ATOM, a custom optimizer that wraps AdamW mechanics with per-block adaptive trust scaling plus per-block predictive accept/reject — and the entire step is a single fused CUDA C++ kernel.

Parameters are partitioned into blocks of ~256 elements (configurable via ATOM_META_SCALE). Each block maintains three persistent scalars: trust (range 0.90–1.90), pnode (init 0.65, range 0.01–0.99), and gprev (EMA of mean gradient). trust is recomputed from each block's own pnode, so blocks with cleaner local acceptance history take larger steps while noisy blocks become conservative. The AdamW base step is scaled by (1 + trust), so trust=1.25 means 2.25× the standard AdamW step.

Before applying the update, each element is independently tested: a local quadratic model predicts the loss reduction using a momentum-extrapolated gradient (gpred = g + 0.35·(g - gprev)). If pred ≤ 0, the step for that element is zeroed. Additionally, the block's pnode acts as a gating probability — steps are only committed if pnode ≥ 0.5. After each step, pnode is updated via EMA based on the actual commit fraction: blocks that consistently pass the predictive test increase pnode, blocks that fail decrease it.

The first 20·meta_scale steps use a bootstrap gain of 2.4× — higher initial trust while momentum and variance estimates are still settling.

The key design: this is not a global trust region. It is hundreds of tiny independent optimizers, each tracking whether its local parameter subspace is predictable enough to take larger steps. Blocks with well-conditioned gradients accumulate higher pnode, which raises their trust; noisy blocks automatically become conservative. The fused CUDA kernel means all of this — AdamW update, trust scaling, prediction, accept/reject, pnode update — happens in one GPU kernel launch with zero Python-side per-element overhead.

Numerical precision — FFMA

For bf16 models running on Pascal GPUs (sm_61), FFMA provides a critical performance fix. Pascal has no native bf16 tensor cores. Under PyTorch's autocast(bf16), matrix multiplications dispatch to a kernel that does a serialized bf16→fp32 conversion pass before the fp32 multiply-add — this is ~25% slower than calling cuBLAS sgemm directly in fp32.

FFMA intercepts specific x @ W operations through a custom autograd.Function and forces them through fp32 sgemm. The autograd tape only saves the original bf16 tensors — the fp32 casts are transient working buffers, freed before forward returns. Backward re-casts saved bf16 tensors to fp32 just for the two backward GEMMs. Memory profile is identical to a plain bf16 addmm.

This module exists because the model was developed and tested on Pascal hardware. On Ampere or newer GPUs with native bf16 support, it is unnecessary — but harmless, as it degrades to a no-op when bf16 compute is natively available.

Container — dynamic compute routing

A lightweight Container controller maintains a fixed-size reservoir state vector (default K=512 dimensions) across chunks and decides, for each text fragment, which slabs and which neurons within them should be active.

The state update mechanism is a frozen reservoir computer: C_{k+1} = (1-g) · C_k + g · tanh(C~_k), where C~_k and gate g are produced by a fixed random projection of the previous hidden state and reservoir state. The projection weights are frozen at initialization and never trained — this is an echo state network-style design. Only the routing readout heads learn. This prevents the router from overfitting to routing patterns; the reservoir provides a stable, nonlinear dynamical memory that the readout heads can interrogate but cannot shape.

From the reservoir state, the container predicts per-slab signals for the next chunk: a write amplitude scalar alpha_s that scales the slab's output delta, additive biases for all three TXSSM scan gates (fast, slow, column), and optional hard binary gates for slab and neuron activation. Hard gates use a straight-through estimator: the forward pass sees exact binary decisions, while the backward pass follows the corresponding sigmoid probabilities. Safety invariants guarantee that when slab skipping is enabled, the first and last slab stay active and no more than the configured fraction of neurons is skipped per slab.

Chunk boundaries are stopgrad — the reservoir state does not backpropagate across chunks. This means the container learns to route computation based on local chunk characteristics, not through long-range credit assignment through the reservoir dynamics.

Thought DSL — internal tensor program

Thought DSL is an optional internal tensor program executed inside each slab (use_dsl: true). It is chunk-level, not token-level: program tensors are shaped [steps, batch, lanes], so command count does not scale with seq_len.

A lane is a typed internal query slot. At each step, it picks receiver operations (scan, diff, read, and mean only where allowed), plus execute/carry/expose controls. Receivers are already-computed causal streams (RMU, TXSSM, VAttn, XMem, bank streams, CML streams), published in append-only execution order, so the DSL never reads future slabs.

Source routing is sparse Hard-Concrete gating, not a single softmax winner. One lane can open multiple sources or none; closed sources contribute exact zero and are skipped in execution. With large receiver vocabularies, dsl_max_per_exec applies a per-(batch,lane) top-K cap before gate sampling to bound peak VRAM/compute.

The DSL returns bounded edits to hidden, context, blueprint logits, and write-gate logits. Training adds three small usage pressures: execute, carry, and source-open sparsity (dsl_exec_lambda, dsl_carry_lambda, dsl_source_lambda). Logs expose this directly as use=exec/carry/src and per-step src_n (mean active sources per DSL word).

Documentation

Architecture and runtime docs:

Design tradeoffs

Viper pays a concrete price for O(L) complexity: there is no exact pairwise interaction between arbitrary tokens. All long-range information passes through a compressed scan state — a vector of fixed size D that must summarize everything seen so far. This fundamentally limits the model's ability to perform tasks requiring precise copying, matching, or retrieval over long distances — capabilities that attention provides trivially through direct token-to-token comparison.

However, the architecture mitigates this via XMem — a shared N-dimensional content-addressable memory bank. XMem allows the model to retrieve precise information from thousands of tokens ago by addressing content in a geometric address space, bypassing the "forgetting" bottleneck of pure recurrence. Profiling shows that XMem's compute footprint is exceptionally lean, often several dozen times lower than dense matrix operations like BMM. (P.S: use xmem size ~ L% cache)

The current scan implementation is still generic compared to Mamba's SRAM-resident kernels. CUDA uses a fused CUB BlockScan path for moderate lengths and a ping-pong fallback otherwise, but it is still measurably slower than Mamba's specialized scan on equivalent sequence lengths. This is an engineering gap, not an architectural one.

The 3D causal convolution creates a potential information bleed in packed sequences at depth boundaries. While previously considered an issue, empirical training on NAT and blind-tail curricula shows that the model effectively treats this "bleed" as noise or a "garbage signal." This serves as a secondary training task for the VAttn module, which learns to filter out such noise to maintain causal consistency. In training prefix-only use cases, the model demonstrates no significant performance degradation from this effect.

Status

Engineering prototype. Published for research purposes and architectural documentation. There is no paper and most likely there won't be one, as well as typical Goodheart benchmarks.

Working: full training loop with sample packing and NAT/FIM curricula, gradient checkpointing, DDP, pipeline parallelism across GPUs, optimizer and gradient offloading, bf16/fp16 mixed-precision, chunked inference with state carry across arbitrary context lengths.

Known limitations: current generic scan kernels remain slower than Mamba's specialized implementation, embryonic fp8 support.

Quick Start

Tested on Linux x86_64 with a CUDA-capable NVIDIA GPU. Root access is not required — works on bare servers, rootless containers, and DinD environments.

Automated setup (bare server)

setup.sh handles everything — CUDA toolkit download, Python virtualenv, all dependencies. No git required:

wget -qO- https://raw.githubusercontent.com/srose69/ViperLLM/refs/heads/main/setup.sh | bash

Or with curl:

curl -fsSL https://raw.githubusercontent.com/srose69/ViperLLM/refs/heads/main/setup.sh | bash

If you prefer to inspect the script before running:

wget -O setup.sh https://raw.githubusercontent.com/srose69/ViperLLM/refs/heads/main/setup.sh
bash setup.sh 

What it does:

  • Downloads and installs the CUDA 12.1.1 toolkit locally to ~/viper/cuda (~4.5 GB download; drivers are not touched)
  • Creates a Python virtualenv at ~/viper/venv using system Python 3
  • Installs PyTorch 2.5.1 + CUDA 12.1 wheels and all packages from requirements.txt
  • Patches the venv activate script to export CUDA_HOME and LD_LIBRARY_PATH automatically on each activation

After setup:

source ~/viper/venv/bin/activate

Manual setup

If you already have CUDA 12.x and Python 3.10+ with pip:

pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cu121
pip install ninja
pip install -r requirements.txt

ninja is required to JIT-compile the CUDA extensions at first import.

Verify

Run the synthetic sensitivity probe — no data or checkpoint needed, compiles CUDA extensions on first run:

python3 sensitivity.py --synthetic \
    --seq_len 1024 --num_slabs 2 \
    --decoder_dim 512 --core_dim 512 \
    --factor_dim 256

First run takes ~1–2 min to compile kernels; subsequent runs are fast.

System prerequisites

Requirement Notes
Linux x86_64 Only platform tested
NVIDIA GPU sm_61+ Pascal or newer
Python 3.10+ System Python is fine
gcc / g++ Needed to build CUDA extensions; usually pre-installed
curl Used by setup.sh to download the CUDA toolkit
~8 GB free disk CUDA toolkit + venv + PyTorch wheels

Requirements

Python 3.10+, PyTorch 2.1+ with CUDA 11.8+, transformers, datasets. Tested on NVIDIA Pascal (sm_61) and newer GPUs.

License and Attribution

Source code in this repository is licensed under the GNU Affero General Public License v3.0 only (AGPL-3.0-only), unless stated otherwise. See LICENSE.

Documentation, architecture descriptions, diagrams, terminology definitions, docstrings, and explanatory materials in this repository are licensed under Creative Commons Attribution 4.0 International (CC BY 4.0), unless stated otherwise. See LICENSE-DOCS.

If you reuse or adapt documentation, diagrams, docstrings, or other CC BY materials from this repository, you must provide appropriate credit to Ivan K (srose69, SimpleRose), include a link to the CC BY 4.0 license, and indicate whether changes were made. Additional repository notices are in NOTICE.

This repository also documents original architectural principles, mechanisms, names, and terminology in substantial detail. If you use this repository in research, derivative implementations, benchmarks, comparisons, or architectural discussion, citation is requested even where the underlying idea itself may not be copyrightable.

Patent rights are not granted except as required by AGPL-3.0-only for covered contributions. See PATENTS.md.

Project naming, subsystem names, and origin/branding policy are described in TRADEMARKS.md.

Citation

Preferred citation:

@software{viper_llm,
  author = {Ivan K},
  title  = {Viper-LLM: Volumetric Language Model with Triangle Cross-Scan State Modelling},
  year   = {2026},
  url    = {https://github.com/srose69/ViperLLM}
}

GitHub citation metadata is provided in CITATION.cff.


(c) 2026 Ivan K (srose69, SimpleRose). Viper-LLM and method names TXSSM, XMem, Thought DSL, LeaRNorm, ATOM, VAttn are project-specific branding and identifiers. See TRADEMARKS.md for usage policy.

(c) 2026 Ivan K (srose69, SimpleRose). Viper-LLM и названия методов TXSSM, XMem, Thought DSL, LeaRNorm, ATOM, VAttn являются брендингом и идентификаторами проекта. См. TRADEMARKS.md для правил использования.


Содержание


Что такое Viper?

Viper — экспериментальная архитектура языковой модели, обрабатывающая всю входную последовательность за один forward pass. Никакого авторегрессионного цикла генерации токен за токеном, никакого KV-кэша, никакого квадратичного self-attention. Вместо этого токены укладываются в трёхмерный объём, а информация распространяется по всему контексту через линейные по времени ассоциативные сканы.

Архитектура отвечает на конкретный вопрос: может ли языковая модель работать вообще без attention — заменив каждое попарное взаимодействие токенов структурированной рекуррентностью — и оставаться обучаемой на масштабе?

Как это работает

Объёмное представление

Последовательность токенов длины L укладывается в трёхмерную сетку G×H×W, где L = G·H·W, через Faced Continuous Snake Layout. Каждая глубинная плоскость — это face размера H×W, внутри которого маршрут идёт 2D-змейкой; на нечётных face тот же маршрут разворачивается в обратную сторону, чтобы последовательность оставалась локально непрерывной и при переходе между соседними face. Пространственные отношения — какие токены соседствуют по горизонтали, вертикали или в глубину — закодированы неявно координатами в сетке, устраняя необходимость в обучаемых позиционных эмбеддингах. Причинная 3×3×3 свёртка обеспечивает локальную связность на этой укладке.

Маленький пример для сетки 2×3×3:

face g=0              face g=1
 0   1   2            11  10   9
 5   4   3            12  13  14
 6   7   8            17  16  15

Объём — это рабочая память модели. Он начинается как токенные эмбеддинги, уложенные в 3D, и накапливает информацию слой за слоем. Вокруг вычислительных блоков нет residual skip-соединений — только аддитивные ограниченные дельты. Детально это описано в CML — Context Modelling Layer.

TXSSM — Triangle Cross-Scan State Modelling

Там, где Transformer вычислил бы матрицу внимания L×L, Viper запускает параллельные ассоциативные сканы. Рекуррентность m_t = a_t · m_{t-1} + b_t · z_t разрешается через ассоциативное scan-ядро: текущий CUDA-путь использует fused CUB BlockScan для умеренных длин последовательности и generic ping-pong fallback в остальных случаях. Подробности в scan_ops.

Каждый вычислительный блок — слэб — запускает три параллельных скана над общим q/k/z базисом, что вместе называется TXSSM (Triangle Cross-Scan State Modelling):

  • Быстрый горизонтальный скан с полураспадом τ ≈ 32 токена. Захватывает короткие зависимости: синтаксис, границы фраз, отношения смежных токенов. Высокое временное разрешение, быстрое обновление состояния.
  • Медленный горизонтальный скан с полураспадом τ ≈ 65536 токенов. Это сверхдлинный retention-reservoir для очень далёкого прошлого; устойчивость обеспечивается leaky-integrator нормализацией инъекции и fp32 retention-гейтами, а не коротким горизонтом.
  • Column-скан вдоль оси глубины сетки (G). В плоской последовательности позиции с одинаковыми (h, w), но разной глубиной, находятся на расстоянии H·W токенов — сигнал горизонтального скана значительно затухает на такой дистанции. Column-скан соединяет их напрямую за G шагов, обеспечивая поток информации по оси глубины, который горизонтальные сканы не могут дёшево обеспечить.

Все три выхода сканов комбинируются через раздельные readout-проекции и суммируются в единый контекстный вектор. Перед проекцией к горизонтальным и column EMA-состояниям применяется variance-preserving gain, чтобы сверхдлинные ветки не становились численно тихими, не меняя сам carry. Разделение временных масштабов (fast vs slow) — архитектурный prior: модели даны два предустановленных временных разрешения плюс пространственный канал, и она учится, какую информацию направлять через каждый. Подробности в CML.

RMU — Ray Matrix Unfolding

Перед сканированием объём проецируется в пространство лучей меньшей размерности. RMU (Ray Matrix Unfolding) обогащает объём локальными 3×3×3 и кросс-канальными 1×1×1 свёртками, применяет спектральную нормализацию LeaRNorm и проецирует каждую позицию в D-мерный лучевой вектор. Этот луч — то, что слэб «видит» в каждой позиции: сжатое, нормализованное представление объёма в данной координате. TXSSM-сканы затем работают над этими лучами.

VAttn — направленный гейтированный контекст

Параллельно с TXSSM, опциональный модуль VAttn (Vectorized Attention) запускает собственный гейтированный причинный скан над объёмом. В отличие от фиксированных временных масштабов TXSSM, VAttn обучает per-position факторы сохранения — модель может реализовать 5-token память в одной позиции и 500-token память в другой, в пределах одной головы. VAttn накапливает направленный контекст по всей последовательности, и его выход суммируется с лучевой проекцией перед read phase. VAttn даёт неквадратичное накопление контекста без всякой матрицы L×L.

XMem — долговременный объёмный retrieval

TXSSM-сканы и VAttn обрабатывают контекст внутри чанка, но всё, что они накапливают, должно умещаться в ограниченные scan-состояния. Чтобы восстанавливать точную информацию из чанков, находящихся далеко в прошлом, модель переносит один shared XMem bank формы [B, D_mem, A^N] через chunk carry. У каждого слэба свои собственные read/query/write-проекции в этот же банк, так что поздние слэбы могут извлекать содержимое, которое ранее записали ранние.

XMem участвует в обеих фазах slab-пайплайна. В phase 1 он работает только на чтение и обогащает объём до VAttn и RMU: слэб проецирует сырой объём в непрерывную координату в (-1, 1)^N, выполняет N-линейное чтение из shared bank и добавляет результат обратно в объём. Оба каузальных скана затем пропагируют извлечённый long-range контент через свою динамику — модель не может пассивно игнорировать XMem. В phase 2 XMem становится read-write: после blueprint/context mixing и RayMix write-side представление выполняет второе чтение из памяти и затем пишет обратно в банк.

Read- и write-адреса намеренно разделены. Read-координата отвечает на вопрос «где лежит старое, что мне нужно?», а write-координата — «где должно жить уточнённое?». У write-пути своя ортогональная ротация плюс обучаемый bounded shift, зависящий от текущего write hidden и read context, так что модель не принуждается затирать ровно то, что только что извлекла.

Память по умолчанию шестиосевая — вдвое больше пространственных осей VAttn. Это классический geometric lift: хранить контент в более высокоразмерном адресном объёме, читать его в том же O(L) классе сложности, что и VAttn, и получать больше независимо расположенной информации на одну траекторию, чем может дать 3D-геометрия хранения. Фиксированная адамаровская срезка даёт точную ортогональность на старте; обучаемые skew-symmetric ротации делают адресный базис обучаемо поворачиваемым без потери ортогональности.

XMem разрежён по построению: каждый read или write касается 2^N угловых ячеек (64 при N=6), так что градиент локален естественно. Никакого straight-through estimator, никакого Gumbel-softmax и никаких плотных обновлений по всему A^N. Поскольку state tensor shared, а не replicated per slab, стоимость activation tape масштабируется как xmem_size · batch_size · seq_len_mul, а не умножается на num_slabs.

Read phase — точка принятия решения

Read phase получает два сигнала: лучевую проекцию (что слэб видит сейчас, плюс VAttn-контекст и phase-1 XMem-retrieval) и readout TXSSM-скана (что слэб помнит из истории). Из них вычисляются:

  • value — что сказать, из текущей позиции
  • context — что говорит история, из накопленного scan-состояния
  • blueprint — per-dimension гейт в (0, 1), интерполирующий между value и context для каждого из D измерений независимо
  • write gate — прямой обход, позволяющий hidden state пройти с минимальной трансформацией

Механизм blueprint — не attention по позициям. Это per-dimension выбор: использовать свежую информацию или накопленную историю, независимо для каждого измерения признаков. Разные семантические аспекты могут использовать разные источники одновременно.

GLE — Ghost Lift Expansion

После того как read phase производит hidden state, опциональный модуль GLE (Ghost Lift Expansion) обогащает его. GLE — неявный lifted-оператор, расширяющий D-мерный hidden state в большее виртуальное пространство E > D без материализации полной E×E матрицы. Используются замороженные адамаровские прожекторы для отображения между базовым и ghost-пространствами, применяется обучаемая нелинейность в ghost-пространстве, затем проекция обратно в D.

Смысл: простая D→D линейная проекция имеет ранг не более D. GLE даёт hidden state — информации, пересекающей границу слэба — большую выразительную способность, чем линейное узкое место. GLE применяется в трёх точках: извлечение ghost из hidden после read, поднятие сигнала записи перед RayMix, и поднятие hidden state в CML-мосту к следующему слэбу.

Write phase — дельта-обновление

Смешанный сигнал (blueprint-интерполированные value и context, плюс обход write gate, поднятые через GLE) проходит через RayMix — причинную 1D depthwise-затем-pointwise свёртку с ядром 5. Это даёт 5-token локальное окно, где смежные выходы read phase взаимодействуют, дополняя поэлементную природу скана.

Результат проецируется обратно в полную канальную размерность C, ограничивается (-4, 4) на элемент и добавляется к объёму как дельта. Каждый слэб независимо решает, насколько модифицировать объём — ни один слэб не может доминировать, потому что каждая дельта ограничена.

CML — контекстный мост между слэбами

После write phase hidden state слэба — обогащённый GLE — перестраивается в 5D-объём и передаётся следующему слэбу. Это CML (Context Modelling Layer): механизм, определяющий, какая информация пересекает границу слэба и в какой форме. CML — не сам слэб, а мост между слэбами.

LeaRNorm — спектральная нормализация

LeaRNorm заменяет стандартный LayerNorm во всей модели, это не совсем спектральный нормализатор. Формула: y = (x - mean(x)) / sqrt(1 + |siloid(a · rho)|), где a — среднее абсолютное отклонение центрированного сигнала, а rho — его взвешенный спектральный центроид: центр масс спектра мощности, вычисленный через rFFT. Произведение a · rho пропускается через siloid (ту же насыщающую активацию, что используется везде в Viper), и знаменатель всегда ≥ 1 — он может только сжимать сигнал, но не усиливать.

Эффект: сигнал с преобладанием низких частот (плавные тренды) имеет низкий спектральный центроид — маленький знаменатель, амплитуда сохраняется. Сигнал с высокочастотным содержимым (резкие изменения, шум) имеет высокий центроид — большой знаменатель, сильное подавление. Сила нормализации адаптируется к содержанию сигнала, а не только к его величине. Это принципиально отличается от RMSNorm, который одинаково обрабатывает все частоты.

Обратный проход — рукописный аналитический autograd.Function: rFFT-промежуточный результат перевычисляется в backward вместо сохранения, что держит memory overhead под 1% от forward-активаций. Range regularization loss штрафует RMS вне [0.65, 1.35] и поэлементные абсолютные значения выше 4.0, применяется как вспомогательный loss при обучении.

Оптимизатор ATOM

Обучение использует ATOM — кастомный оптимизатор поверх механики AdamW с поблочным адаптивным trust scaling и поблочным предиктивным accept/reject, и весь шаг выполняется одним fused CUDA C++ ядром.

Параметры разбиваются на блоки ~256 элементов (настраивается через ATOM_META_SCALE). Каждый блок хранит три персистентных скаляра: trust (диапазон 0.90–1.90), pnode (init 0.65, диапазон 0.01–0.99) и gprev (EMA среднего градиента). trust пересчитывается из собственного pnode каждого блока, так что блоки с более чистой локальной историей принятия делают большие шаги, а шумные блоки становятся консервативнее. Базовый шаг AdamW масштабируется на (1 + trust), так что trust=1.25 означает 2.25× от стандартного шага AdamW.

Перед применением обновления каждый элемент тестируется независимо: локальная квадратичная модель предсказывает снижение loss, используя градиент с momentum-экстраполяцией (gpred = g + 0.35·(g - gprev)). Если pred ≤ 0, шаг для этого элемента обнуляется. Дополнительно, pnode блока действует как гейтующая вероятность — шаги применяются только при pnode ≥ 0.5. После каждого шага pnode обновляется через EMA на основе реальной доли принятых шагов: блоки, стабильно проходящие предиктивный тест, повышают pnode, блоки с частыми отказами — снижают.

Первые 20·meta_scale шагов используют bootstrap gain 2.4× — повышенное доверие, пока momentum и оценки дисперсии ещё устанавливаются.

Ключевой дизайн: это не глобальный trust region. Это сотни крошечных независимых оптимизаторов, каждый из которых отслеживает, достаточно ли предсказуем его локальный ландшафт параметров для больших шагов. Блоки с хорошо обусловленными градиентами накапливают более высокий pnode, а значит получают больший trust; шумные блоки автоматически становятся консервативнее. Fused CUDA-ядро означает, что всё это — обновление AdamW, trust-скейлинг, предикция, accept/reject, обновление pnode — происходит за один запуск GPU-ядра без per-element накладных расходов на стороне Python.

Численная точность — FFMA

Для bf16-моделей на Pascal GPU (sm_61), FFMA обеспечивает критическое исправление производительности. У Pascal нет нативных bf16 tensor cores. Под autocast(bf16) PyTorch матричные умножения отправляются в ядро, делающее сериализованный bf16→fp32 конверсионный проход перед fp32 multiply-add — это на ~25% медленнее, чем прямой вызов cuBLAS sgemm в fp32.

FFMA перехватывает конкретные операции x @ W через кастомный autograd.Function и направляет их через fp32 sgemm. Autograd-лента сохраняет только исходные bf16-тензоры — fp32-касты являются временными рабочими буферами и освобождаются до возврата из forward. Backward заново приводит сохранённые bf16-тензоры к fp32 только для двух backward-GEMM. Профиль памяти идентичен обычному bf16 addmm.

Этот модуль существует потому, что модель разрабатывалась и тестировалась на оборудовании Pascal. На Ampere и новее с нативной поддержкой bf16 он не нужен, но безвреден — вырождается в no-op при нативной доступности bf16.

Container — динамическая маршрутизация вычислений

Лёгкий контроллер Container хранит reservoir-состояние фиксированного размера (по умолчанию K=512 измерений) между чанками и решает, какие слэбы и нейроны активировать для каждого фрагмента текста.

Механизм обновления состояния — замороженный reservoir computer: C_{k+1} = (1-g) · C_k + g · tanh(C~_k), где C~_k и гейт g производятся фиксированной случайной проекцией предыдущего hidden state и reservoir-состояния. Веса проекции заморожены при инициализации и никогда не обучаются — это дизайн в стиле echo state network. Обучаются только readout-головы маршрутизации. Это не даёт роутеру переобучиться под паттерны маршрутизации; reservoir предоставляет стабильную нелинейную динамическую память, которую readout-головы могут опрашивать, но не могут формировать.

Из reservoir-состояния контейнер предсказывает per-slab сигналы для следующего чанка: скаляр амплитуды записи alpha_s, масштабирующий выходную дельту слэба, аддитивные смещения для всех трёх гейтов TXSSM-скана (fast, slow, column), и опциональные жёсткие бинарные гейты активации слэбов и нейронов. Жёсткие гейты используют straight-through estimator: forward pass видит точные бинарные решения, а backward pass идёт через соответствующие sigmoid probabilities. Инварианты безопасности гарантируют, что первый и последний слэб всегда активны при включённом slab skipping, и не более заданной доли нейронов пропускается на слэб.

Границы чанков — stopgrad: reservoir-состояние не пропагейтится через чанки. Контейнер учится маршрутизировать вычисления на основе локальных характеристик чанка, а не через долгосрочное согласование через динамику reservoir.

Thought DSL — внутренняя тензорная программа

Thought DSL — опциональная внутренняя тензорная программа, исполняемая внутри каждого слэба (use_dsl: true). Она chunk-level, а не token-level: тензоры программы имеют форму [steps, batch, lanes], поэтому число команд не масштабируется с seq_len.

Lane — это типизированный слот внутреннего запроса. На каждом шаге он выбирает операцию receiver (scan, diff, read, а mean только там, где разрешено), а также execute/carry/expose-контроли. Receiver'ы — это уже вычисленные каузальные потоки (RMU, TXSSM, VAttn, XMem, bank streams, CML streams), публикуемые в append-only порядке исполнения, поэтому DSL не читает будущие слэбы.

Маршрутизация source построена на разреженных Hard-Concrete gate, а не на одном softmax-победителе. Один lane может открыть несколько source или ни одного; закрытые source дают точный ноль и физически пропускаются в исполнении. Для больших словарей receiver'ов dsl_max_per_exec задаёт per-(batch,lane) top-K cap до семплирования gate и ограничивает пик VRAM/вычислений.

DSL возвращает bounded-правки в hidden, context, blueprint logits и write-gate logits. В обучение добавлены три небольших давления на использование: execute, carry и source-open sparsity (dsl_exec_lambda, dsl_carry_lambda, dsl_source_lambda). В логах это отражается напрямую как use=exec/carry/src и per-step src_n (среднее число активных source на DSL word).

Документация

Документация по архитектуре и runtime:

Компромиссы

Цена O(L) — отсутствие точного попарного взаимодействия между произвольными токенами. Вся дальняя информация проходит через сжатое scan-состояние — вектор фиксированного размера D, который должен суммировать всё увиденное. Это фундаментально ограничивает способность модели к точному копированию, сопоставлению и извлечению информации на больших дистанциях — возможности, которые attention даёт тривиально через прямое сравнение токенов.

Однако архитектура компенсирует это наличие XMem — общей N-мерной ассоциативной памяти. XMem позволяет модели восстанавливать точную информацию из контекста в тысячи токенов, обращаясь к содержимому в геометрическом адресном пространстве в обход бутылочного горлышка чистой рекуррентности. Профайлинг показывает, что вычислительные затраты XMem на порядки ниже плотных матричных операций (BMM), что делает его крайне дешёвым способом расширения памяти. (P.S используйте xmem размер ~ как L% кеш)

Текущая реализация сканов всё ещё generic по сравнению с SRAM-resident ядрами Mamba. На CUDA используется fused CUB BlockScan для умеренных длин и ping-pong fallback в остальных случаях, но на тех же длинах это всё равно измеримо медленнее Mamba. Это инженерный пробел, не архитектурный.

3D причинная свёртка создаёт потенциальную утечку информации между сэмплами в packed-последовательностях на границах глубины. Ранее это считалось проблемой, однако опыт обучения на задачах NAT и blind-tail показывает, что модель эффективно воспринимает этот «блид» как шум или «мусорный сигнал». Это служит де-факто дополнительной тренировочной задачей для модуля VAttn, который учится фильтровать подобные помехи для сохранения каузальной консистентности. В тренировочных сценариях (prefix-only) модель не демонстрирует значимой деградации от этого эффекта.

Статус

Инженерный прототип. Опубликован в исследовательских целях и для документирования архитектуры. Пейпера нет и возможно не будет, как и типичных Гудхарт-бенчмарков.

Работает: полный training loop с sample packing и NAT/FIM curricula, gradient checkpointing, DDP, pipeline parallelism между GPU, offloading оптимизатора и градиентов, bf16/fp16 mixed-precision, chunked inference с переносом состояния на произвольных длинах.

Известные ограничения: текущие generic scan-ядра всё ещё медленнее специализированной реализации Mamba, зачаточная поддержка fp8.

Быстрый старт

Протестировано на Linux x86_64 с CUDA-capable NVIDIA GPU. Root не нужен — работает на голых серверах, rootless-контейнерах и DinD-окружениях.

Автоматическая установка (голый сервер)

setup.sh делает всё сам — скачивает CUDA toolkit, создаёт Python virtualenv, устанавливает зависимости. git не нужен:

wget -qO- https://raw.githubusercontent.com/srose69/ViperLLM/refs/heads/main/setup.sh | bash

Или через curl:

curl -fsSL https://raw.githubusercontent.com/srose69/ViperLLM/refs/heads/main/setup.sh | bash

Если хочется сначала просмотреть скрипт:

wget -O setup.sh https://raw.githubusercontent.com/srose69/ViperLLM/refs/heads/main/setup.sh
bash setup.sh

Что происходит:

  • Скачивает и устанавливает CUDA 12.1.1 toolkit локально в ~/viper/cuda (~4.5 ГБ; драйверы не затрагиваются)
  • Создаёт Python virtualenv в ~/viper/venv через системный Python 3
  • Устанавливает PyTorch 2.5.1 + CUDA 12.1 wheels и всё из requirements.txt
  • Патчит скрипт activate venv — CUDA_HOME и LD_LIBRARY_PATH выставляются автоматически при каждой активации

После установки:

source ~/viper/venv/bin/activate

Ручная установка

Если CUDA 12.x и Python 3.10+ с pip уже есть:

pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cu121
pip install ninja
pip install -r requirements.txt

ninja нужен для JIT-компиляции CUDA-расширений при первом импорте.

Проверка

Запусти синтетический sensitivity probe — данные и чекпоинт не нужны, CUDA-расширения компилируются при первом запуске:

python3 sensitivity.py --synthetic \
    --seq_len 1024 --num_slabs 2 \
    --decoder_dim 512 --core_dim 512 \
    --factor_dim 256

Первый запуск занимает ~1–2 минуты на компиляцию ядер, последующие — быстро.

Требования к системе

Требование Примечание
Linux x86_64 Только эта платформа тестировалась
NVIDIA GPU sm_61+ Pascal и новее
Python 3.10+ Системный Python подходит
gcc / g++ Нужен для сборки CUDA-расширений; обычно уже установлен
curl Используется setup.sh для скачивания CUDA toolkit
~8 ГБ свободного места CUDA toolkit + venv + PyTorch wheels

Требования

Python 3.10+, PyTorch 2.1+ с CUDA 11.8+, transformers, datasets. Протестировано на NVIDIA Pascal (sm_61) и новее.

Лицензирование и авторство

Исходный код в этом репозитории лицензирован под GNU Affero General Public License v3.0 (AGPL-3.0-only), если не указано иное. См. LICENSE.

Документация, описания архитектуры, диаграммы, определения терминологии, докстринги и пояснительные материалы в этом репозитории лицензированы под Creative Commons Attribution 4.0 International (CC BY 4.0), если не указано иное. См. LICENSE-DOCS.

При повторном использовании или адаптации документации, диаграмм, докстрингов или других материалов CC BY из этого репозитория, вы должны указать авторство: Ivan K (srose69, SimpleRose), предоставить ссылку на лицензию CC BY 4.0 и указать, были ли внесены изменения. Дополнительные уведомления репозитория находятся в NOTICE.

В этом репозитории также подробно описаны оригинальные архитектурные принципы, механизмы, названия и терминология. При использовании этого репозитория в исследованиях, производных реализациях, бенчмарках, сравнениях или архитектурных дискуссиях запрашивается цитирование, даже если сама идея не подлежит защите авторским правом.

Патентные права не предоставляются, за исключением случаев, предусмотренных AGPL-3.0-only для внесенных вкладов. См. PATENTS.md.

Политика именования проекта, названий подсистем и происхождения/брендинга описана в TRADEMARKS.md.

Citation

Preferred citation:

@software{viper_llm,
  author = {Ivan K},
  title  = {Viper-LLM: Volumetric Language Model with Triangle Cross-Scan State Modelling},
  year   = {2026},
  url    = {https://github.com/srose69/ViperLLM}
}

GitHub citation metadata is provided in CITATION.cff.


(c) 2026 Ivan K (srose69, SimpleRose). Viper-LLM and method names TXSSM, XMem, LeaRNorm, ATOM, VAttn are project-specific branding and identifiers. See TRADEMARKS.md for usage policy.

(c) 2026 Ivan K (srose69, SimpleRose). Viper-LLM и названия методов TXSSM, XMem, LeaRNorm, ATOM, VAttn являются брендингом и идентификаторами проекта. См. TRADEMARKS.md для правил использования.

About

Volumetric language model with Triangle Cross-Scan State Modelling. Without Attention. With Neural Turing Machines (NTM) и Differentiable Neural Computers (DNC) smells

Topics

Resources

License

AGPL-3.0 and 2 other licenses found

Licenses found

AGPL-3.0
LICENSE
AGPL-3.0
LICENSE.txt
CC-BY-4.0
LICENSE-DOCS

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors