A coprocessor-augmented language model that embeds a frozen WASM bytecode interpreter transformer inside a 4.9B-parameter language model (NanochatGPT d34), connected via trained cross-attention bridges. The LM and coprocessor execute in parallel within a single forward pass; from LM layer 10 onward, cross-attention lets the LM read the coprocessor's completed state. The LM generates text and WASM instructions; the coprocessor executes them deterministically; results flow back into the LM — enabling the model to think in computation.
WASM instruction tokens → the LM emits them, and the frozen coprocessor immediately executes them
Feedback tokens → coprocessor results (REPL_RESULT, BRANCH_TAKEN, BRANCH_NOT_TAKEN) are fed back via cross-attention
Lockstep execution — each WASM instruction is immediately followed by a feedback token, creating instruction-feedback pairs that the LM sees simultaneously
The coprocessor is a hand-compiled transformer that executes WASM bytecode via real matrix multiplications. It was not trained — every weight was set by a compiler. It supports arithmetic, comparisons, memory, local variables, filesystem I/O, and loops with conditional branching.
Cross-Attention Bridge
Layer 10: Primary injection point — cross-attention reads coprocessor hidden states
Layers 11-33: Additional cross-attention heads (gate-initialized near zero) refine the compute signal
WasmTokenEmbedding: Learned 260×2176 embedding mapping WASM tokens to LM representation space
wasm_logit_bias: Learned bias controlling WASM token generation probability
Training
Parameter
Value
GPU
NVIDIA B200 (192GB HBM3e)
Optimizer
MuonAdamW (Muon for matrix params, AdamW for scalars)
Precision
FP8 (Blackwell native) with bf16 master weights
Phase
Supervised Fine-Tuning (SFT)
Data
WASM programs + text conversations (SmolTalk + MMLU)
All checkpoints are loadable via AutoModelForCausalLM.from_pretrained with trust_remote_code=True.
Note: This is an early preview. WASM coprocessor triggering reliability
varies across checkpoints and prompts. Conversational (non-math) prompts
work reliably. Math/WASM execution may not trigger consistently depending
on the checkpoint and prompt phrasing.
How to Use
Important: This model was trained with integers in the prompt encoded as
4-byte WASM tokens (not as regular text). You must byte-encode numbers in
your input and decode WASM output values back to integers for display.
Quick Start
python
1import re
2import torch
3from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer
45REPO ="eastlondoner/nanochat-wasm-fused-preview-01"6WASM_OFFSET =655367BYTE_OFFSET =26489# ── 1. Load model + tokenizer ───────────────────────────────────10config = AutoConfig.from_pretrained(REPO, trust_remote_code=True)11model = AutoModelForCausalLM.from_pretrained(12 REPO, config=config, trust_remote_code=True,13 torch_dtype=torch.bfloat16,14 subfolder="epoch_4_batch_6100",15)16model = model.to("cuda").eval()1718tok = AutoTokenizer.from_pretrained(REPO, trust_remote_code=True, use_fast=False)1920# ── 2. Encode prompt (byte-encode integers) ─────────────────────21# encode_chat() automatically byte-encodes integers with i32.const prefix22prompt_ids = tok.encode_chat("What is 15 + 27?")2324# ── 3. Generate ─────────────────────────────────────────────────25eos_id = tok._special_token_ids["<|assistant_end|>"]26generated, wasm_outputs, trace = model.generate_chat(27 prompt_ids,28 max_new_tokens=1024,29 temperature=0,30 return_outputs=True,31 eos_token_id=eos_id,32)3334# ── 4. Decode response ──────────────────────────────────────────35# Filter text-only tokens for human-readable text36text_tokens =[t for t in generated[len(prompt_ids):]if0< t < WASM_OFFSET]37response = tok.decode(text_tokens)38print(f"Text: {response}")3940# The coprocessor's computed results are in wasm_outputs (list of ints)41if wasm_outputs:42print(f"Answer: {wasm_outputs[-1]}")# → 42
Input/Output Encoding
Inputs: All integers in the user prompt must be byte-encoded before
tokenization. The tokenizer's encode_chat() method handles this
automatically — it finds integer literals via regex and replaces each with
an i32.const opcode token (65536) followed by 4 big-endian byte tokens
in the WASM token range (65800–66055).
where i32.const is token 65536 and each byte b maps to token 65536 + 264 + b.
Outputs: The model generates a mix of text tokens (< 65536) and WASM
tokens (≥ 65536). The WASM coprocessor executes the WASM trace and returns
integer results via wasm_outputs. These are plain Python integers ready
for display. The text portion of the response (e.g., "The answer is") can be
decoded normally; the actual numeric answer comes from wasm_outputs.
Conversational (Non-Math) Prompts
For prompts without numbers (e.g., "Hello, how are you?"), standard
tokenization works fine — no byte encoding needed:
python
1prompt_ids = tok.encode_chat("What is the capital of France?")2generated, _, _ = model.generate_chat(3 prompt_ids, max_new_tokens=1024, temperature=0.8,4 eos_token_id=eos_id,5)6text_tokens =[t for t in generated[len(prompt_ids):]if0< t < WASM_OFFSET]7print(tok.decode(text_tokens))
Token Contract
The model uses an extended vocabulary where tokens ≥ 65536 are WASM tokens: