oaustegard/experiments · latent-calculator

Latent Calculator

A calculator wired into a frozen 135M model between two layers, with no tokens in either direction

A frozen language model, a calculator, and no tokens between them. SmolLM2-135M never sees the tool: a small trained head reads the operands out of its layer-16 activations, a Python calculator does the arithmetic, and a small trained encoder writes the result back into the residual stream after layer 16, once per answer step. Every model weight is frozen. Nothing is appended to the prompt. The model then answers as if it knew.

Below: the same twelve prompts through the frozen model alone, through the usual text route (the result pasted into the prompt as tokens), and through the latent port. Then the numbers over 2,000 prompts.

Twelve prompts, three routes
Frozen model
0 / 12
no tool · 28 tokens · 762 ms per answer
Tool result as text
0 / 12
pasted into the prompt · 42 tokens · 834 ms per answer
Latent port
10 / 12
injected after layer 16 · 21 tokens · 384 ms per answer
Side by side

Random rows from the in-distribution test split (operand lengths 1-4 and 6 digits). "Query" is what the trained head read out of the activations; the calculator ran on exactly that.

PromptAnswerFrozen modelTool as textLatent portQuery read from layer 16
52 - 604109 =-604057100000000000000 wrongThe last two numbers are the same, so… wrong-604057 rightsub 52 604109 → -604057
Which is larger, 3436 or 9549?lessThe answer is 9549. wrong## How to convert 100000000 wrongless rightcmp 3436 9549 → less
Is 40 greater or less than 240434?lessThe answer is 40 less than 24043 wrong## How to calculate 40 percent of 2404 wrongless rightcmp 40 240434 → less
Is 428583 greater or less than 53?greaterThe answer is 428583 is 42 wrong## How to calculate 428583 percent of wronggreater rightcmp 428583 53 → greater
Compare 8891 and 65:greaterThe 8891 is a 16-bit number wrong8891 and 65: [less] 88 wronggreater rightcmp 8891 65 → greater
What is 539451 plus 927818?1467269539451 + 927818 is wrongIs 539451 a prime number? wrong1467269 rightadd 539451 927818 → 1467269
915061 * 966343 =884262791923100000000000000 wrongThe first 10000000000 wrong884267296266 wrongmul 915061 966343 → 884262791923
Compute 689851 times 471707.325407545657### Division wrong### Division wrong325407545045 wrongmul 689851 471707 → 325407545657
Compare 1212 and 975558:lessThe 1212 is a composite number. It ca… wrong## What is 1212 in words? wrongless rightcmp 1212 975558 → less
What is 105 multiplied by 36?3780The 105 multiplied by 36 is equal to wrong105 x 36 = 3780 wrong3780 rightmul 105 36 → 3780
Add 614793 and 284983:899776``` wrongThe 284983 is a safe number. wrong899776 rightadd 614793 284983 → 899776
Add 52 and 122:174The 52 and 122 are the same as the wrong122 + 52 = 176. wrong174 rightadd 52 122 → 174
Over 2,000 prompts

Exact match of the generated answer. In distribution means unseen operand values at training lengths; held-out length means at least one 5-digit operand, a length never trained on.

RouteIn distributionHeld-out lengthTool tokensms / answer
Frozen model0%0%0.0489
Tool result as text (answer anywhere in output)19%18%6.1554
Single vector, oracle operands (phase 1)60%34%0.0235
Latent port, oracle operands91%85%0.0357
Latent port, learned query90%41%0.0449
Learned query, by operatorIn distributionHeld-out length
add99%34%
sub98%26%
mul66%18%
cmp100%86%
By longest operand1 digits2 digits3 digits4 digits6 digits
in distribution100%100%100%95%79%
How the port works
Where it fails

SmolLM2-135M, frozen, fp32, 4 CPU cores. Trained parts: query head 232k, result encoder about 1M. Port at layer 16 of 30, chosen by a linear-probe sweep. 20,000 synthetic training prompts over twelve templates. Code, predictions and results: oaustegard/experiments/latent-calculator.