QLLM is an attention-free, complex-valued language model. Tokens live in complex phase space, and sequence memory is Phase-Associative Memory (PAM) — a complex matrix-state associative layer that retrieves by complex-conjugate phase matching, not by softmax attention and not by a standard real-valued SSM.
It is not a transformer and not Mamba. Inference is O(1) per token with a fixed-size state — there is no KV cache that grows with context length.
We use AI assistants (e.g. Cursor) to help build this. Every claim below is backed by code, reproducible probes, and dated training logs in this repo — not vibes.
Paper: Phase-Associative Memory: Sequence Modeling in Complex Hilbert Space (arXiv:2604.05030) — Vishwakarma & Agostino.
Model weights (Hugging Face): gowravvishwakarma/qllm-pam-v11-e3k3-chat
Latest shipped (2026-07-09): revision
round-6b-gate, also promoted tomain— the v2 gate line at ~6B pretrain + smoltalk2 SFT (content-aware phase gate, vocab 50261, blended pretrain). What we learned: the pretrain base carries real knowledge, but the SFT step was hurting short factual answers — it collapsed into<think>/ "explain-the-question" prose and occasionally switched language.round-8bis now in pretrain with thinking removed (see the recipe update below). Pin a tag:huggingface-cli download … --revision round-6b-gate. Details: hf_release/README.md · v11/MODEL_RELEASES.md.
Architecture still under development. The PAM stack (gates, tokenizer, data recipe) is actively changing. We restarted training from scratch on the v2 line (phase-aware gate, vocab 50261). After every +2B pretrain tokens we ship a new checkpoint to Hugging Face under a round revision tag (e.g.
round-2b-gate,round-4b-gate). Older weights onmainare milestones for comparison, not the current training line — pin a revision tag for reproducibility.
Two dominant families each pay a tax:
s ∈ ℝ^{S×d} has limited associative capacity: cramming many facts into one vector
causes catastrophic interference. (An earlier QLLM experiment, Holographic State Binding,
failed for exactly this reason — and motivated PAM.)QLLM's bet: give each head a matrix state and code keys by phase. You keep O(1)-per-token inference and get high associative capacity (O(d²) associations per head via outer-product storage). The architecture can hold the associations; training only has to learn when to write and when to protect.
Each token is a complex vector: magnitude encodes how salient, phase encodes
what kind of meaning. A context shift ("bank" → finance vs. river) is a phase rotation —
rotations compose and are invertible. A single complex multiply
(a+bi)(c+di) = (ac−bd) + (ad+bc)i carries four cross-terms (rotation + scaling), so the
algebra is richer per parameter than two independent real vectors.
Phase must be preserved end-to-end. Passing complex activations through real nonlinearities
(GELU, plain sigmoid gates) destroys phase and collapses the design. QLLM uses phase-preserving
primitives throughout the main path: modReLU, ComplexGatedUnit (CGU), and ComplexNorm.
v11_e3_k3)flowchart TD
tok["Tokens"] --> emb["ComplexEmbed"]
emb --> norm0["ComplexNorm"]
norm0 --> block
subgraph block ["Repeated x N layers"]
direction TB
cgu["ComplexGatedUnit (CGU)"] --> r1["+ residual"]
r1 --> pam["Phase-Associative Memory (PAM)"]
pam --> r2["+ residual"]
end
block --> lin["ComplexLinear"]
lin --> norm1["ComplexNorm"]
norm1 --> head["TiedComplexLMHead"]
ComplexGatedUnit (CGU) gives dual control that only exists in complex space — a standard
GLU gate scales intensity only; the CGU gate sets both magnitude (how much) and
phase (what rotation):
# Standard GLU: gate controls intensity only
output = sigmoid(W_g @ x) * (W_v @ x)
# CGU: magnitude AND phase
output = modReLU(|W_g @ z|) * rotate(z, arg(W_g @ z)) * (W_v @ z)
The PAM layer keeps a complex matrix state S ∈ ℂ^{H×d×d} per head and updates it with an
outer product of value and conjugated key:
State: S_t = γ_t · S_{t-1} + V_t ⊗ K_t* # outer product; K* is the complex conjugate
Retrieve: Y_t = S_t @ Q_t # complex-conjugate match, no softmax
Train: chunked dual form O(T·C) # GPU-friendly dense matmuls
Infer: recurrent O(1)/token # fixed state, no KV cache
Why conjugate matching works. K* · Q is a complex inner product: when the query phase
aligns with a stored key phase the contribution adds constructively; when it is
misaligned it cancels destructively. Retrieval is interference, not a length-normalized
softmax over positions. There is no softmax in the core path.
Why the capacity is real. Each V ⊗ K* writes a full d×d (rank-1) association. A matrix
state therefore stores O(d²) associations per head, where a single vector state stores ~O(d)
and interferes badly past a handful. This is an architectural property — it holds before any
training (see the binding-capacity probe below).
E3 multistate (the V11 win). Instead of one matrix state, each head keeps K matrix
states with distinct decay biases; at retrieval they are combined by data-dependent phase
interference (a learned phase_proj). It is essentially param-matched (only phase_proj
plus K decay biases are added) and inference stays O(K·d²)/token — still constant in
sequence length. K=3 is the current best.
| Aspect | Transformer | Vector SSM (Mamba) | QLLM PAM |
|---|---|---|---|
| State | KV cache (grows with T) | vector s ∈ ℝ^{S×d} | matrix S ∈ ℂ^{H×d×d} |
| Matching | QKᵀ + softmax | gated recurrence | complex conjugate K*·Q |
| Capacity | O(n) per seq | ~O(S·d) | O(H·d²) per layer |
| Inference | O(T) per token + growing cache | O(1) per token | O(1) per token, fixed state |
memory_probes/ is a standalone, reproducible (seed=42) battery that tests the PAM math
with no trained LM. Run it yourself: ./scripts/run_memory_probes.sh. Full tables and JSON in
memory_probes/README.md and logs/memory_probes/.
| Probe | Result |
|---|---|
| Binding capacity | 100% retrieval @ 64 associations (d=64) vs ~13% for vector HRR |
| Correctness (selftest / layer-bridge) | Chunked/dual train form ≡ O(1) recurrent form, `max |
| Long context | With GSP protection a needle survives to 65K+ tokens; bare decay loses it (mechanism ceiling) |
| Language filler | Real WikiText interference: language relative retrieval ≈ 9.3 mean, beats random on all 50 projection seeds (min 14×) |
In one line: matrix outer-product storage gives near-perfect multi-association retrieval where vector memory fails, with O(d²) capacity per head and O(1) recurrent inference at any length.
Validation perplexity progression as the architecture improved:
medium-pam-v3 (interleaved CGU+PAM) — 29.957d (flat stack, chunked dual form, B=18) — 26.88Honest baseline (inline, not hidden): a same-pipeline GPT-2-style transformer (B=18) reaches val PPL 22.69 — so PAM is +3.08 PPL behind on this benchmark. We report this on purpose. The trade is deliberate: PAM gives a different memory mechanism and O(1)-per-token inference with no KV cache, and the PAM path has no Flash-class custom CUDA/Triton kernels yet, while the baseline rides PyTorch SDPA/Flash. The gap has shrunk every generation (+7.26 → +4.19 → +3.08).
GPU-poor mercy clause: this line of work is essentially one person, months to years, on a single RTX 4090 and some access to one RTX PRO 6000. We're compute-budget-limited, not malice-limited — be kind.
The Phase C pipeline — DCLM-Edu pretrain → chat SFT on the fixed ~100M v11_e3_k3
architecture — produces coherent, instruction-following chat. The pretrain demonstrably worked:
| Checkpoint | WikiText val PPL | DCLM-Edu holdout PPL |
|---|---|---|
| WikiText-only base | 25.77 | 1222.11 |
| + 2B DCLM-Edu pretrain | 66.26 | 33.86 |
The DCLM holdout collapse (1222 → 33.86) confirms the base learned the new domain; the WikiText rise is expected domain shift (WikiText is only an anchor). To our knowledge this is a working conversational model built on phase-associative memory — not a transformer, not an SSM, with O(1)-per-token recurrent inference.
round-6b-gate (~6B)Full batch eval (72 generations, two profiles × two temperatures): hf_release/SAMPLES_round-6b-gate.md.
Curated highlights (recommended profile, T=0.0):
User: what is the capital of France? Assistant: The capital of France, France, is Paris. (correct — but note the "France, France" degeneration)
User: Answer in one word: yes or no — is water wet? Assistant: Yes, water is wet.
User: hello Assistant: Hello! How can I help you today?
User: What is 2+2? Assistant: The given statement "2+2" is a bit ambiguous… (rambles — the SFT step talks itself out of the answer; this regression is the one fixed for
round-8b)
Download, chat flags, and reproduction: hf_release/README.md (Hugging Face model card).
Honest caveats: at ~100M params with ~6B tokens on the v2 line, facts are still hit-or-miss
and responses can ramble. This round's SFT also over-verbosifies short factual answers and may
emit <think> blocks (pass --no-think) — diagnosed and fixed in the round-8b recipe
(thinking removed from pretrain + SFT, English-only splits, per-turn length cap). These are a
pretraining-scale + SFT-recipe ceiling, not an architecture failure — each round adds +2B fresh tokens.
Latest: round-6b-gate (shipped 2026-07-09, also promoted to main) — ~6B pretrain + SFT
on the v2 architecture (content-aware gate, vocab 50261, blended data). Rounds add +2B fresh
tokens each (round-2b-gate → round-4b-gate → round-6b-gate → …). round-8b is in pretrain
now with the thinking-removed recipe below.
The architecture and training recipe are still evolving; we treat each shipped round as a
snapshot, not a frozen product. We retrain from scratch on the v2 line, then add +2B
fresh pretrain tokens per round (no token reuse), run chat SFT, and publish the weights to
gowravvishwakarma/qllm-pam-v11-e3k3-chat
under a revision tag (round-2b-gate, round-4b-gate, …). Full provenance per round:
v11/MODEL_RELEASES.md.
What every round trains on (knowledge + chat):
| Ingredient | Dataset | Role |
|---|---|---|
| Knowledge / grammar | DCLM-Edu + FineWeb-Edu (edu≥3) | web pretrain, unique per round (skip_docs) |
| Chat context | smoltalk2 Mid, ChatML-rendered (<think> stripped) | blended into pretrain after a grammar warmup |
| Chat behavior | smoltalk2 SFT — English, direct-answer, multi-turn | per-round supervised fine-tune |
Preset v11_e3_k3_chat: phase-aware GSP gate, vocab 50261 (ChatML <|im_start|>/<|im_end|>
<think>/</think>). Freshness is guaranteed by per-source cursors saved in each
checkpoint; the blend adds a small ChatML sprinkle so those tokens are trained from step 0.Recipe update (from
round-8b, 2026-07-09). A pretrain-vs-SFT diagnosis found the SFT chat model regressing on factual QA: it collapsed into<think>/ "explain-the-question" prose and occasionally switched language (a multilingual data leak). Fixes applied going forward: (1)<think>reasoning is stripped from the smoltalk2 Mid pretrain blend (final answers kept) so the base never learns to emit it; (2) SFT runs withTHINK_FRACTION=0on an English-only split allowlist (multilingual / tool / long-context splits dropped); (3) a per-turn length cap (≤300 words per answer) keeps replies short and direct while preserving multi-turn chats (up to ~8 exchanges). Earlier rounds (round-2b…round-6b) used the prior think-capped, multilingual mix. Full diagnosis and before/after target profiling: v11/EXPERIMENTS_V11.md.
Run a round (GCP training, then publish from the RTX4090):
# Round 1 from scratch (2B blended pretrain -> SFT -> smoke -> export)
ROUND=1 ROUND_TAG=round-2b-gate SCRATCH=1 TOKEN_BUDGET=2000000000 \
tmux new-session -d -s v11_round './scripts/run_v11_round.sh pretrain'
./scripts/run_v11_round.sh probes && ./scripts/run_v11_round.sh sft
./scripts/run_v11_round.sh smoke
ROUND=1 ROUND_TAG=round-2b-gate TOKEN_BUDGET=2000000000 ./scripts/run_v11_round.sh export
# On RTX4090 (has HF token): incremental pull -> verify -> push revision tag
ROUND_TAG=round-2b-gate ./scripts/run_v11_round.sh ship
Pull a specific shipped round from the HF repo:
huggingface-cli download gowravvishwakarma/qllm-pam-v11-e3k3-chat --revision round-6b-gate --local-dir .
# Browse all tags: https://huggingface.co/gowravvishwakarma/qllm-pam-v11-e3k3-chat
What to ask / current limits (full chat guide, flags, and sample Q&A):
hf_release/README.md · hf_release/SAMPLES_round-6b-gate.md —
use --no-think and --max_new_tokens 64 for short factual Q&A. Tulu-3 is not
used routinely — only as an optional instruct-upgrade branch after saturation gates pass.
For round-2b-gate and later revision tags, do not use scripts/chat_v11.py — that
script targets training checkpoints inside this repo. After download:
huggingface-cli download gowravvishwakarma/qllm-pam-v11-e3k3-chat \
--revision round-6b-gate --local-dir hf_release
cd hf_release && uv run python run_chat.py --checkpoint qllm_v11_e3k3_chat.pt --no-think
Full usage (--system, --temperature, thinking blocks, sample Q&A):
hf_release/README.md · hf_release/SAMPLES_round-6b-gate.md.
modReLU, CGU, ComplexNorm). A 28.7M model beat much
larger V4 runs.medium-pam-v3: 29.95.Dead ends (do not revisit without new evidence): V9 readout gates, V10 custom Triton, V11 E1 per-channel decay (a tie that doesn't stack with E3), V11 E2 delta-rule write (impractical compile cost), and V7 hierarchy / multi-scale loss / reverse-assoc / learned positions. Details: v11/EXPERIMENTS_V11.md, EXPERIMENTS_V_6_7_8_9.md.
V11 is still the hero. The paper architecture, Hugging Face weights, chat model, and
Quick Start all stay on v11_e3_k3. Later folders are research tracks — they did not
replace it.
--freeze_shared);
whether the fact band binds generally is still open. It did not beat V11 as a shipped
model. v12/README.md · v12/EXPERIMENTS_V12.md.V11/V13 model.py spent more brain on where an axis sat (unsqueeze(-1).unsqueeze(-1),
view(B, T, 3, H, d, 2).transpose(1, 2), permute(3, 0, 2, 1)) than on the algebra. We
need to focus on the maths, not a mental map of integer indices.
So we built sempyt (semantic PyTorch,
pronounced sem-pi-T) — a separate package, a thin named-dimension frontend over PyTorch.
Axes are Dim objects you define once. Rearranges, broadcasts, and contractions are
written over those objects and lower to ordinary permute / view / matmul. A no-op
.to() whose layout already matches returns the same object.
from sempyt import Dim, dims, named, contract
B, T, H, d = dims("B T H d")
q = named(q_raw, (B, T, H, d))
k = named(k_raw, (B, T, H, d))
Tq, Tk = Dim("Tq"), Dim("Tk")
scores = contract(q.alias(T, Tq), k.alias(T, Tk), over=d) # (B, Tq, H, Tk)
memory = memory * gamma # named broadcast — no unsqueeze ladder
Not on PyPI yet (beta; API still settling). Install from the Git URL:
pip install git+https://github.com/gowrav-vishwakarma/sempyt.git
The first QLLM model written on it is v13_sempty/ — the lean PAM
recurrence, named end to end, so new mechanisms can be added without reverse-engineering
axis indices.
# Install
uv sync
uv sync --extra cuda # CUDA extras
# Train the headline V11 config on WikiText-103 (~100.5M params, val PPL 25.77)
./scripts/run_v11_exp.sh v11_e3_k3
# Knowledge pretrain from scratch: ~100M `v11_e3_k3_chat` (chat vocab baked in),
# DCLM-Edu + FineWeb-Edu mix, ~10B-token budget, cosine LR, resumable.
# >>> Text pretrain ~10B on RTX PRO 6000 (server, tmux v11_pretrain) — 2026-06-24 <<<
tmux new-session -d -s v11_pretrain './scripts/run_v11_pretrain_scratch.sh'
# custom budget (e.g. 20B): ./scripts/run_v11_pretrain_scratch.sh 20000000000
# resume after a stop: RESUME=checkpoints_v11_e3_k3_chat_pretrain/latest.pt \
# ./scripts/run_v11_pretrain_scratch.sh
# Reproduce the PAM mechanism probes (no checkpoint needed)
./scripts/run_memory_probes.sh
# Duplex audio POC (4090, parallel — turn-taking, NOT speech-to-speech):
./scripts/run_v11_duplex_stage1.sh # train Stage 1 (Kathbath hi/gu default)
./scripts/run_v11_duplex_gradio.sh # mic → listen / speak / backchannel
# Chat — shipped HF weights (recommended for round-2b-gate+)
cd hf_release && uv run python run_chat.py --checkpoint qllm_v11_e3k3_chat.pt --no-think
# Chat — in-repo training checkpoint (dev / reproduction)
python scripts/chat_v11.py --checkpoint checkpoints_v11_e3_k3_chat_pretrain/best_model.pt
| Track | GPU | What |
|---|---|---|
| Text pretrain ~10B | RTX PRO 6000 | v11_e3_k3_chat, DCLM-Edu + FineWeb-Edu, resumable latest.pt every 5000 steps |
| Duplex audio POC | RTX 4090 | ~5M V11 PAM E3 K=3 + frozen Whisper encoder; predicts <listen> / <speak> / <backchannel> — not an S2S model (no speech output yet) |
Duplex is additive only (v11/duplex/); it does not modify pretrain scripts or shared v11/model.py.
Stage 1 Hindi+Gujarati: 100% val thinking accuracy, 232 s —
checkpoints_v11_duplex_5m_stage1_hi_gu/best_model.pt.
Math, scope, and results: v11/duplex/EXPERIMENTS_DUPLEX.md.
Other presets, Phase C pretrain/SFT runners, and older version paths live in the docs below.
round-6b-gate, on main); architecture still evolving.run_chat.py (--no-think, --max_new_tokens), current chat limits.--freeze_shared).QLLM_CORE_IDEA.pdf, v5/paper/, QLLM_V2.pdf.Contributions are subject to the project's Contributor License Agreement; see CONTRIBUTING.md. Licensed under the MIT License — see LICENSE.
Python
75.2%
Shell
8.8%
TeX
6.0%
HTML
4.2%
TypeScript
2.5%
JavaScript
2.3%
QLLM is an attention-free, complex-valued language model. Tokens live in complex phase space, and sequence memory is Phase-Associative Memory (PAM) — a complex matrix-state associative layer that retrieves by complex-conjugate phase matching, not by softmax attention and not by a standard real-valued SSM.
It is not a transformer and not Mamba. Inference is O(1) per token with a fixed-size state — there is no KV cache that grows with context length.
We use AI assistants (e.g. Cursor) to help build this. Every claim below is backed by code, reproducible probes, and dated training logs in this repo — not vibes.
Paper: Phase-Associative Memory: Sequence Modeling in Complex Hilbert Space (arXiv:2604.05030) — Vishwakarma & Agostino.
Model weights (Hugging Face): gowravvishwakarma/qllm-pam-v11-e3k3-chat
Latest shipped (2026-07-09): revision
round-6b-gate, also promoted tomain— the v2 gate line at ~6B pretrain + smoltalk2 SFT (content-aware phase gate, vocab 50261, blended pretrain). What we learned: the pretrain base carries real knowledge, but the SFT step was hurting short factual answers — it collapsed into<think>/ "explain-the-question" prose and occasionally switched language.round-8bis now in pretrain with thinking removed (see the recipe update below). Pin a tag:huggingface-cli download … --revision round-6b-gate. Details: hf_release/README.md · v11/MODEL_RELEASES.md.
Architecture still under development. The PAM stack (gates, tokenizer, data recipe) is actively changing. We restarted training from scratch on the v2 line (phase-aware gate, vocab 50261). After every +2B pretrain tokens we ship a new checkpoint to Hugging Face under a round revision tag (e.g.
round-2b-gate,round-4b-gate). Older weights onmainare milestones for comparison, not the current training line — pin a revision tag for reproducibility.
Two dominant families each pay a tax:
s ∈ ℝ^{S×d} has limited associative capacity: cramming many facts into one vector
causes catastrophic interference. (An earlier QLLM experiment, Holographic State Binding,
failed for exactly this reason — and motivated PAM.)QLLM's bet: give each head a matrix state and code keys by phase. You keep O(1)-per-token inference and get high associative capacity (O(d²) associations per head via outer-product storage). The architecture can hold the associations; training only has to learn when to write and when to protect.
Each token is a complex vector: magnitude encodes how salient, phase encodes
what kind of meaning. A context shift ("bank" → finance vs. river) is a phase rotation —
rotations compose and are invertible. A single complex multiply
(a+bi)(c+di) = (ac−bd) + (ad+bc)i carries four cross-terms (rotation + scaling), so the
algebra is richer per parameter than two independent real vectors.
Phase must be preserved end-to-end. Passing complex activations through real nonlinearities
(GELU, plain sigmoid gates) destroys phase and collapses the design. QLLM uses phase-preserving
primitives throughout the main path: modReLU, ComplexGatedUnit (CGU), and ComplexNorm.
v11_e3_k3)flowchart TD
tok["Tokens"] --> emb["ComplexEmbed"]
emb --> norm0["ComplexNorm"]
norm0 --> block
subgraph block ["Repeated x N layers"]
direction TB
cgu["ComplexGatedUnit (CGU)"] --> r1["+ residual"]
r1 --> pam["Phase-Associative Memory (PAM)"]
pam --> r2["+ residual"]
end
block --> lin["ComplexLinear"]
lin --> norm1["ComplexNorm"]
norm1 --> head["TiedComplexLMHead"]
ComplexGatedUnit (CGU) gives dual control that only exists in complex space — a standard
GLU gate scales intensity only; the CGU gate sets both magnitude (how much) and
phase (what rotation):
# Standard GLU: gate controls intensity only
output = sigmoid(W_g @ x) * (W_v @ x)
# CGU: magnitude AND phase
output = modReLU(|W_g @ z|) * rotate(z, arg(W_g @ z)) * (W_v @ z)
The PAM layer keeps a complex matrix state S ∈ ℂ^{H×d×d} per head and updates it with an
outer product of value and conjugated key:
State: S_t = γ_t · S_{t-1} + V_t ⊗ K_t* # outer product; K* is the complex conjugate
Retrieve: Y_t = S_t @ Q_t # complex-conjugate match, no softmax
Train: chunked dual form O(T·C) # GPU-friendly dense matmuls
Infer: recurrent O(1)/token # fixed state, no KV cache
Why conjugate matching works. K* · Q is a complex inner product: when the query phase
aligns with a stored key phase the contribution adds constructively; when it is
misaligned it cancels destructively. Retrieval is interference, not a length-normalized
softmax over positions. There is no softmax in the core path.
Why the capacity is real. Each V ⊗ K* writes a full d×d (rank-1) association. A matrix
state therefore stores O(d²) associations per head, where a single vector state stores ~O(d)
and interferes badly past a handful. This is an architectural property — it holds before any
training (see the binding-capacity probe below).
E3 multistate (the V11 win). Instead of one matrix state, each head keeps K matrix
states with distinct decay biases; at retrieval they are combined by data-dependent phase
interference (a learned phase_proj). It is essentially param-matched (only phase_proj
plus K decay biases are added) and inference stays O(K·d²)/token — still constant in
sequence length. K=3 is the current best.
| Aspect | Transformer | Vector SSM (Mamba) | QLLM PAM |
|---|---|---|---|
| State | KV cache (grows with T) | vector s ∈ ℝ^{S×d} | matrix S ∈ ℂ^{H×d×d} |
| Matching | QKᵀ + softmax | gated recurrence | complex conjugate K*·Q |
| Capacity | O(n) per seq | ~O(S·d) | O(H·d²) per layer |
| Inference | O(T) per token + growing cache | O(1) per token | O(1) per token, fixed state |
memory_probes/ is a standalone, reproducible (seed=42) battery that tests the PAM math
with no trained LM. Run it yourself: ./scripts/run_memory_probes.sh. Full tables and JSON in
memory_probes/README.md and logs/memory_probes/.
| Probe | Result |
|---|---|
| Binding capacity | 100% retrieval @ 64 associations (d=64) vs ~13% for vector HRR |
| Correctness (selftest / layer-bridge) | Chunked/dual train form ≡ O(1) recurrent form, `max |
| Long context | With GSP protection a needle survives to 65K+ tokens; bare decay loses it (mechanism ceiling) |
| Language filler | Real WikiText interference: language relative retrieval ≈ 9.3 mean, beats random on all 50 projection seeds (min 14×) |
In one line: matrix outer-product storage gives near-perfect multi-association retrieval where vector memory fails, with O(d²) capacity per head and O(1) recurrent inference at any length.
Validation perplexity progression as the architecture improved:
medium-pam-v3 (interleaved CGU+PAM) — 29.957d (flat stack, chunked dual form, B=18) — 26.88Honest baseline (inline, not hidden): a same-pipeline GPT-2-style transformer (B=18) reaches val PPL 22.69 — so PAM is +3.08 PPL behind on this benchmark. We report this on purpose. The trade is deliberate: PAM gives a different memory mechanism and O(1)-per-token inference with no KV cache, and the PAM path has no Flash-class custom CUDA/Triton kernels yet, while the baseline rides PyTorch SDPA/Flash. The gap has shrunk every generation (+7.26 → +4.19 → +3.08).
GPU-poor mercy clause: this line of work is essentially one person, months to years, on a single RTX 4090 and some access to one RTX PRO 6000. We're compute-budget-limited, not malice-limited — be kind.
The Phase C pipeline — DCLM-Edu pretrain → chat SFT on the fixed ~100M v11_e3_k3
architecture — produces coherent, instruction-following chat. The pretrain demonstrably worked:
| Checkpoint | WikiText val PPL | DCLM-Edu holdout PPL |
|---|---|---|
| WikiText-only base | 25.77 | 1222.11 |
| + 2B DCLM-Edu pretrain | 66.26 | 33.86 |
The DCLM holdout collapse (1222 → 33.86) confirms the base learned the new domain; the WikiText rise is expected domain shift (WikiText is only an anchor). To our knowledge this is a working conversational model built on phase-associative memory — not a transformer, not an SSM, with O(1)-per-token recurrent inference.
round-6b-gate (~6B)Full batch eval (72 generations, two profiles × two temperatures): hf_release/SAMPLES_round-6b-gate.md.
Curated highlights (recommended profile, T=0.0):
User: what is the capital of France? Assistant: The capital of France, France, is Paris. (correct — but note the "France, France" degeneration)
User: Answer in one word: yes or no — is water wet? Assistant: Yes, water is wet.
User: hello Assistant: Hello! How can I help you today?
User: What is 2+2? Assistant: The given statement "2+2" is a bit ambiguous… (rambles — the SFT step talks itself out of the answer; this regression is the one fixed for
round-8b)
Download, chat flags, and reproduction: hf_release/README.md (Hugging Face model card).
Honest caveats: at ~100M params with ~6B tokens on the v2 line, facts are still hit-or-miss
and responses can ramble. This round's SFT also over-verbosifies short factual answers and may
emit <think> blocks (pass --no-think) — diagnosed and fixed in the round-8b recipe
(thinking removed from pretrain + SFT, English-only splits, per-turn length cap). These are a
pretraining-scale + SFT-recipe ceiling, not an architecture failure — each round adds +2B fresh tokens.
Latest: round-6b-gate (shipped 2026-07-09, also promoted to main) — ~6B pretrain + SFT
on the v2 architecture (content-aware gate, vocab 50261, blended data). Rounds add +2B fresh
tokens each (round-2b-gate → round-4b-gate → round-6b-gate → …). round-8b is in pretrain
now with the thinking-removed recipe below.
The architecture and training recipe are still evolving; we treat each shipped round as a
snapshot, not a frozen product. We retrain from scratch on the v2 line, then add +2B
fresh pretrain tokens per round (no token reuse), run chat SFT, and publish the weights to
gowravvishwakarma/qllm-pam-v11-e3k3-chat
under a revision tag (round-2b-gate, round-4b-gate, …). Full provenance per round:
v11/MODEL_RELEASES.md.
What every round trains on (knowledge + chat):
| Ingredient | Dataset | Role |
|---|---|---|
| Knowledge / grammar | DCLM-Edu + FineWeb-Edu (edu≥3) | web pretrain, unique per round (skip_docs) |
| Chat context | smoltalk2 Mid, ChatML-rendered (<think> stripped) | blended into pretrain after a grammar warmup |
| Chat behavior | smoltalk2 SFT — English, direct-answer, multi-turn | per-round supervised fine-tune |
Preset v11_e3_k3_chat: phase-aware GSP gate, vocab 50261 (ChatML <|im_start|>/<|im_end|>
<think>/</think>). Freshness is guaranteed by per-source cursors saved in each
checkpoint; the blend adds a small ChatML sprinkle so those tokens are trained from step 0.Recipe update (from
round-8b, 2026-07-09). A pretrain-vs-SFT diagnosis found the SFT chat model regressing on factual QA: it collapsed into<think>/ "explain-the-question" prose and occasionally switched language (a multilingual data leak). Fixes applied going forward: (1)<think>reasoning is stripped from the smoltalk2 Mid pretrain blend (final answers kept) so the base never learns to emit it; (2) SFT runs withTHINK_FRACTION=0on an English-only split allowlist (multilingual / tool / long-context splits dropped); (3) a per-turn length cap (≤300 words per answer) keeps replies short and direct while preserving multi-turn chats (up to ~8 exchanges). Earlier rounds (round-2b…round-6b) used the prior think-capped, multilingual mix. Full diagnosis and before/after target profiling: v11/EXPERIMENTS_V11.md.
Run a round (GCP training, then publish from the RTX4090):
# Round 1 from scratch (2B blended pretrain -> SFT -> smoke -> export)
ROUND=1 ROUND_TAG=round-2b-gate SCRATCH=1 TOKEN_BUDGET=2000000000 \
tmux new-session -d -s v11_round './scripts/run_v11_round.sh pretrain'
./scripts/run_v11_round.sh probes && ./scripts/run_v11_round.sh sft
./scripts/run_v11_round.sh smoke
ROUND=1 ROUND_TAG=round-2b-gate TOKEN_BUDGET=2000000000 ./scripts/run_v11_round.sh export
# On RTX4090 (has HF token): incremental pull -> verify -> push revision tag
ROUND_TAG=round-2b-gate ./scripts/run_v11_round.sh ship
Pull a specific shipped round from the HF repo:
huggingface-cli download gowravvishwakarma/qllm-pam-v11-e3k3-chat --revision round-6b-gate --local-dir .
# Browse all tags: https://huggingface.co/gowravvishwakarma/qllm-pam-v11-e3k3-chat
What to ask / current limits (full chat guide, flags, and sample Q&A):
hf_release/README.md · hf_release/SAMPLES_round-6b-gate.md —
use --no-think and --max_new_tokens 64 for short factual Q&A. Tulu-3 is not
used routinely — only as an optional instruct-upgrade branch after saturation gates pass.
For round-2b-gate and later revision tags, do not use scripts/chat_v11.py — that
script targets training checkpoints inside this repo. After download:
huggingface-cli download gowravvishwakarma/qllm-pam-v11-e3k3-chat \
--revision round-6b-gate --local-dir hf_release
cd hf_release && uv run python run_chat.py --checkpoint qllm_v11_e3k3_chat.pt --no-think
Full usage (--system, --temperature, thinking blocks, sample Q&A):
hf_release/README.md · hf_release/SAMPLES_round-6b-gate.md.
modReLU, CGU, ComplexNorm). A 28.7M model beat much
larger V4 runs.medium-pam-v3: 29.95.Dead ends (do not revisit without new evidence): V9 readout gates, V10 custom Triton, V11 E1 per-channel decay (a tie that doesn't stack with E3), V11 E2 delta-rule write (impractical compile cost), and V7 hierarchy / multi-scale loss / reverse-assoc / learned positions. Details: v11/EXPERIMENTS_V11.md, EXPERIMENTS_V_6_7_8_9.md.
V11 is still the hero. The paper architecture, Hugging Face weights, chat model, and
Quick Start all stay on v11_e3_k3. Later folders are research tracks — they did not
replace it.
--freeze_shared);
whether the fact band binds generally is still open. It did not beat V11 as a shipped
model. v12/README.md · v12/EXPERIMENTS_V12.md.V11/V13 model.py spent more brain on where an axis sat (unsqueeze(-1).unsqueeze(-1),
view(B, T, 3, H, d, 2).transpose(1, 2), permute(3, 0, 2, 1)) than on the algebra. We
need to focus on the maths, not a mental map of integer indices.
So we built sempyt (semantic PyTorch,
pronounced sem-pi-T) — a separate package, a thin named-dimension frontend over PyTorch.
Axes are Dim objects you define once. Rearranges, broadcasts, and contractions are
written over those objects and lower to ordinary permute / view / matmul. A no-op
.to() whose layout already matches returns the same object.
from sempyt import Dim, dims, named, contract
B, T, H, d = dims("B T H d")
q = named(q_raw, (B, T, H, d))
k = named(k_raw, (B, T, H, d))
Tq, Tk = Dim("Tq"), Dim("Tk")
scores = contract(q.alias(T, Tq), k.alias(T, Tk), over=d) # (B, Tq, H, Tk)
memory = memory * gamma # named broadcast — no unsqueeze ladder
Not on PyPI yet (beta; API still settling). Install from the Git URL:
pip install git+https://github.com/gowrav-vishwakarma/sempyt.git
The first QLLM model written on it is v13_sempty/ — the lean PAM
recurrence, named end to end, so new mechanisms can be added without reverse-engineering
axis indices.
# Install
uv sync
uv sync --extra cuda # CUDA extras
# Train the headline V11 config on WikiText-103 (~100.5M params, val PPL 25.77)
./scripts/run_v11_exp.sh v11_e3_k3
# Knowledge pretrain from scratch: ~100M `v11_e3_k3_chat` (chat vocab baked in),
# DCLM-Edu + FineWeb-Edu mix, ~10B-token budget, cosine LR, resumable.
# >>> Text pretrain ~10B on RTX PRO 6000 (server, tmux v11_pretrain) — 2026-06-24 <<<
tmux new-session -d -s v11_pretrain './scripts/run_v11_pretrain_scratch.sh'
# custom budget (e.g. 20B): ./scripts/run_v11_pretrain_scratch.sh 20000000000
# resume after a stop: RESUME=checkpoints_v11_e3_k3_chat_pretrain/latest.pt \
# ./scripts/run_v11_pretrain_scratch.sh
# Reproduce the PAM mechanism probes (no checkpoint needed)
./scripts/run_memory_probes.sh
# Duplex audio POC (4090, parallel — turn-taking, NOT speech-to-speech):
./scripts/run_v11_duplex_stage1.sh # train Stage 1 (Kathbath hi/gu default)
./scripts/run_v11_duplex_gradio.sh # mic → listen / speak / backchannel
# Chat — shipped HF weights (recommended for round-2b-gate+)
cd hf_release && uv run python run_chat.py --checkpoint qllm_v11_e3k3_chat.pt --no-think
# Chat — in-repo training checkpoint (dev / reproduction)
python scripts/chat_v11.py --checkpoint checkpoints_v11_e3_k3_chat_pretrain/best_model.pt
| Track | GPU | What |
|---|---|---|
| Text pretrain ~10B | RTX PRO 6000 | v11_e3_k3_chat, DCLM-Edu + FineWeb-Edu, resumable latest.pt every 5000 steps |
| Duplex audio POC | RTX 4090 | ~5M V11 PAM E3 K=3 + frozen Whisper encoder; predicts <listen> / <speak> / <backchannel> — not an S2S model (no speech output yet) |
Duplex is additive only (v11/duplex/); it does not modify pretrain scripts or shared v11/model.py.
Stage 1 Hindi+Gujarati: 100% val thinking accuracy, 232 s —
checkpoints_v11_duplex_5m_stage1_hi_gu/best_model.pt.
Math, scope, and results: v11/duplex/EXPERIMENTS_DUPLEX.md.
Other presets, Phase C pretrain/SFT runners, and older version paths live in the docs below.
round-6b-gate, on main); architecture still evolving.run_chat.py (--no-think, --max_new_tokens), current chat limits.--freeze_shared).QLLM_CORE_IDEA.pdf, v5/paper/, QLLM_V2.pdf.Contributions are subject to the project's Contributor License Agreement; see CONTRIBUTING.md. Licensed under the MIT License — see LICENSE.
Python
75.2%
Shell
8.8%
TeX
6.0%
HTML
4.2%
TypeScript
2.5%
JavaScript
2.3%