Qwen3.5-0.8B: an AI edited 0.016% of its weights, and thinking loops fell from 93% to about 32%
No training, two edited layers. Answers cut at the token limit fell from 93% to about 32%. On our 50 problems: 62% right vs 8%.
Another AI changed 64 columns of numbers in each of two places inside Qwen3.5-0.8B, a small open reasoning model, and it did so with no training at all. We ran the edited model and the original side by side on one RTX 4090 on our cloud, on the same 50 math problems with the same settings. The edited one got 62% right. The original got 8%, because 96% of its answers never ended: it kept thinking in circles until it hit the limit of 32,768 tokens (pieces of words). If you serve small reasoning models on your own GPUs, that is a cost story as much as an accuracy story. An answer that never ends holds a slot on your card until the limit cuts it off, and it usually produces no answer. The edited file loads and serves with the same command as the base model. We checked only math with thinking on.

The question on the image is simple: how many divisors does 196 have? The answer is 9. The edited model found it and stopped. The base model started listing numbers past 3,300, one by one, and was still going when the limit cut it.
| On our 50 competition math problems (MATH-500) | Edited | Base |
|---|---|---|
| Right answers | 62% | 8% |
| Answers cut at the 32,768-token limit | 20% | 96% |
| Average tokens per answer | 20,444 | 31,832 |
A model that cannot find the ending, and an edit that hands it one
The edit does one thing: it removes the habit that made the model loop. The math the model gets right was already in there.
Qwen3.5-0.8B is a member of the Qwen3.5 family with about 0.8 billion learned numbers (the weights). Before it answers, a reasoning model writes a scratchpad: it thinks out loud, then gives the result. Qwen's own model card warns that this size is "more prone to entering thinking loops" than its siblings. It is like a band that cannot find the ending of a song. Everyone is still in key, but the outro goes round and round until the sound engineer pulls the plug. On a GPU, the sound engineer is the token limit, and every token the model writes takes time on the card.
On November 2, 2026, a team at MIT CSAIL published a blog post on what they call weight-space programming. In one of their experiments, a large model they call GPT-6 Astra gets a tool to inspect and change the small model's numbers. It also gets practice problems, none from the test it is graded on. Its budget is a number of practice runs of the small model: 10, 25 or 50. Astra watches what the model does, reads its internals and edits the numbers directly. No training of any kind.
Of the base model's first 96 practice answers, 85 ran to the 32,768-token limit. With 50 runs, Astra found the pattern behind the loops in two places inside the model, and erased it from 64 columns of numbers in each. That is 131,072 weights out of the whole model: 0.016%. On MATH-500, a standard set of 500 competition math problems, the authors report a jump from 7.9% to 48.1% right. The share of answers cut at the limit fell from 93% to 33.1%. They report similar jumps on two other tests, which we did not rerun (see the appendix).
The authors published the exact change and a script that rebuilds it. The Hugging Face user akhaliq rebuilt the edited model file, reran it on all 500 problems and put up a public demo. His rerun got 51.0% right, with 31.6% of answers cut at the limit. We spotted the story in the AI Search news video of November 8.
62% right against 8% on one RTX 4090, and the loops fall from 96% to 20%
Under the authors' evaluation settings, the edited file stopped most of its loops on our hardware and got nearly eight times as many answers right.
Both models ran side by side on a single RTX 4090 with 24 GB on our cloud, each behind its own API endpoint. Both used vLLM, the open-source serving engine akhaliq's rerun used, with the thinking scratchpad on, and with the authors' randomness settings.
The questions were the first 50 MATH-500 problems in the order of akhaliq's rerun, one try each, up to 32,768 tokens per answer. All 50 ran at once for each model, both models at the same time. We graded them with the authors' own grading script.
| Edited | Base | |
|---|---|---|
| Right | 31 of 50 (62%) | 4 of 50 (8%) |
| Cut at 32,768 tokens | 10 (20%) | 48 (96%) |
| Average tokens per answer | 20,444 | 31,832 |
Our 62% is above both published figures. That is the small sample talking: on these 50 problems, akhaliq's rerun averaged 54%, and our answers matched its usual result on 42 of 50. The base model's 8% and 96% sit right on the authors' figures.
The two times the base model finished an answer, it was right. Its other 2 right answers came from loops that had written the right number before the limit cut them.
The saving: 1.02 million tokens instead of 1.59 million for the same 50 problems
On the same 50 problems, the edited model averaged 20,444 tokens per answer and the base 31,832, and 20% of edited answers were cut at the limit against 96%. Per right answer: about 5 minutes of batch time against 32 seconds (398,000 tokens against 33,000). That gap rests on just 4 right base answers, so treat it as rough.
A GPU serves a fixed number of answers at once. With the base model, almost every one of those places was stuck in a loop, for up to 12.6 minutes on the divisors question. The edited model still writes long answers, but most of them end with a result.
Why not just lower the limit, or watch the stream and stop a loop, as Qwen's card suggests? That makes a loop fail sooner and saves card time. We have not tried it, or thinking off, on the base model, so test that before you swap files.
Where it stops working: it removes loops, it does not add skill
The edit fixed one bad habit. It did not make the model smarter, and the authors say so themselves.
They tried the same approach on Gemma 3 270M, a model that rarely loops: only 8.5% of its answers hit the limit. Astra could not improve it. It stayed between 6.8% and 7.7% on MATH-500 whatever the budget. In their words: "Editing weights could remove an obstacle that hid an ability, but it could not add an ability the model lacked." So do not expect this to work on a model whose problem is not loops.
Even edited, a fifth of our answers still looped, and 3 more ended without a final answer. The answers are long, so a single answer takes about a minute on its own. And the jump only came with the largest budget: with 10 or 25 runs, Astra's edits left the model at 12.3% and 14.1%.
The AI Search video also warns against the hype, and mentions an analysis that reportedly got the unedited model to about 44% on MATH-500 just by changing settings. The video names no source, and we have not checked it.
We tested math with thinking on only. We did not check general chat, following instructions, thinking off or images on the edited file. Qwen's card says the 0.8B model runs with thinking off by default.
Which GPU: the edited model finished under an emulated 6 GB memory cap
This check shows the model starts and finishes long answers under each cap. We used five problems it had already solved in the batch, and it gave the same five right answers under 6 GB as under 8 GB, in the same time. At 5 GB it passed only after we cut the room reserved for parallel conversations from 256 to 32. At 4 GB it would not start.

Every cap below 24 GB was a limit we set on the 4090. We did not run a real 6 or 8 GB card. A real small card also has slower memory, so expect it to run slower than this. We did not try the 4 GB cap with a shorter answer limit, or a compressed version of the model.
On InferenceKey: the base and its edited twin on one 24 GB card, ready in 7 minutes
One 24 GB card held the base and its edited twin at once, each given under half the card, with 16.9 GiB used at the peak. Both were ready 418 seconds after we asked for them, from a cold machine. About three minutes went to installing vLLM, and about three more to the engine's own warm-up. Once that install sat on the machine, a new engine was ready in about one minute.
Our API cannot yet change some settings per request, such as the thinking switch, so we fixed them on the server for every caller.
One problem you will hit: a base-model answer streamed through the endpoint stopped after 152 seconds, with no error our client could see and no end marker. To a client, a cut answer looks like a finished one. We suspect the platform's two-minute silence timeout, which would send an error that our example script ignores, but the cause is not confirmed. Until then, check that each streamed answer says it finished properly before you trust it.
Should you use it? Try it if you serve Qwen3.5-0.8B with thinking on
- If you already serve Qwen3.5-0.8B with thinking on and send it math: try the swap. It is the same size and license, and runs on the same engine.
- If you want the best math from a tiny model: treat it as a fix, not an upgrade. It brings out what the model already knew, and it still writes long answers.
- If you are sizing a GPU: the 6 GB result was emulated on a 24 GB card, not a real 6 GB card; see the memory section.
- If you run another small model that loops: this is a published method with logs, not a product. The Gemma result says it only helps when loops are the problem.
To run the same comparison on your own GPU machine, use the Qwen3.5-0.8B weight edit SDK example with IK_WITH_BASELINE=1. It needs a registered NVIDIA machine (a worker) with a 24 GB card and about 15 GB of free disk. The access keys and the local SDK build are in the step by step below. It deletes both workloads when it finishes.
For engineers
Credits
- Qwen team: Qwen/Qwen3.5-0.8B, Apache-2.0, including the loop warning on the card.
- Rikiya Takehi, Jayden Teoh (equal contribution), Alex Zhang, Omar Khattab, MIT CSAIL: the method, Experiment 8, the bit-exact diff and
apply_edit.pythat rebuilds and hash-verifies the edit, and the logs. Blog post (November 2, 2026), checkpoint, logs and diffs. The editing model is "GPT-6 Astra". - akhaliq, with ML Intern on HF Jobs (2026-11-02): rebuilt the edit on CPU, hash-verified it and built the Hugging Face checkpoint and its card; the independent full MATH-500 rerun; the demo Space (first published as
akhaliq/weight-space-programming-demo, Gradio on ZeroGPU). - AI Search: where we spotted it, video 9RIK3A24ZxA, segment 12:01 to 16:59.
- Verification: the authors' logs repository holds the exact diff from the base and
apply_edit.py, which checks the sha256 of each rebuilt tensor; akhaliq used them to rebuild and verify the checkpoint. - Us: serving both on one card (we did not recompute the tensor hashes; the file was served as published) through InferenceKey, the 50-problem comparison, the endpoint takes, the memory ladder, the SDK example.
Model and the edit
| Item | Value |
|---|---|
| Edited repo | RikiyaT/Qwen3.5-0.8B-weight-space-programming, sha d1671a178705bcab7644806d23c535517f35723b, Apache-2.0, one bf16 shard of 1,746,943,032 bytes (1.75 GB, 1.63 GiB) |
| Base repo | Qwen/Qwen3.5-0.8B, sha 2fc06364715b967f1860aea9cf38778875588b17, Apache-2.0, shard 1,746,942,600 bytes |
generation_config.json | shipped by neither repo |
| Architecture | Qwen3_5ForConditionalGeneration (full multimodal release). The post evaluated a text-only export, LM tensors are hash-identical and text prompts do not use the vision tower |
| Changed tensors | model.language_model.layers.15.mlp.down_proj.weight sha256 82e2d733ea64feaeb4af93a1e065641d3df98b494a8b7576ef2f52e90fe2ee53; model.language_model.layers.19.mlp.down_proj.weight sha256 8ef3c61bc36af113ad58e89dbb0a4a14dcba5a45cb750c15ab515c82ddd12eb2 (raw bf16 bytes) |
| Shape | each [1024, 3584] bf16, 64 changed columns, 131,072 touched weights (0.016%) |
Manifest (exp8_math/runs/p50c/edit/manifest.json) | changed entries 65,260 (layer 15) and 64,928 (layer 19), 130,188 total (touched entries that round back to the same bf16 value are not counted); relative change 0.106 and 0.081 |
| Rebuild | exp8_math/code/apply_edit.py sha256-verifies every rebuilt tensor against the checkpoint evaluated in the post |
| Logs license | the card says CC BY 4.0 / MIT; GitHub reports NOASSERTION |
Experiment 8: Astra traced the loops to one direction written by the MLPs of layers 15 and 19 and subtracted it from 64 output columns of down_proj in each. Harness: a Python kernel over the weights (no GPU for Astra), practice problems (7,469 GSM8K and 7,275 MATH training problems, not test sets), a budget of 10, 25 or 50 forward passes (one pass: up to 512 problems answered or 1,024 texts read). Evaluation: thinking on, up to 32,768 tokens, temperature 0.6, top-p 0.95, top-k 20, presence penalty 1.5. MATH-500 averages 4 samples, GSM8K and IFEval 2.
Authors' numbers (not reproduced by us except MATH-500 on 50 problems)
| MATH-500 | GSM8K | IFEval | Hit token limit | |
|---|---|---|---|---|
| Base | 7.9 | 13.8 | 21.0 | 93.0% |
| Edited, 10 passes | 12.3 | 25.7 | 49.0 | 87.2% |
| Edited, 25 passes | 14.1 | 25.1 | 39.9 | 86.4% |
| Edited, 50 passes (the released checkpoint) | 48.1 | 67.1 | 62.3 | 33.1% |
Gemma 3 270M: base 6.8% MATH-500, edited 7.0 / 7.6 / 7.7 / 7.0% with 5 / 10 / 25 / 50 passes, 8.5% of base answers hit the limit.
Independent rerun (akhaliq, 2026-11-02): full MATH-500, 500 x 4 = 2,000 generations, 43,407,495 tokens, 3,059 s on one H200, vLLM 0.33.0, transformers 5.20.2, math-verify 0.9.0, seed 0: 51.0% right, 31.6% hit the limit, 14,190.9 tokens/s, mean 21,704 tokens. Base smoke test, 25 problems x 4: 5.0% right, 95% hit the limit, mean 31,690 tokens.
The model card does not state a minimum vLLM version. The rerun used 0.33.0 and so did we. No other version was tested.
Setup
- One RTX 4090 24 GB on InferenceKey Cloud (driver 595.91.07, CUDA 13.2), both models on the same card.
- Local InferenceKey manager built from
origin/maineb1ee503, built-invllmbackend,vllm_version="0.33.0". Production never touched. - Serving command, per workload:
vllm serve <model> --dtype bfloat16 --max-model-len 34816 \
--gpu-memory-utilization 0.45 \
--default-chat-template-kwargs '{"enable_thinking": true}' \
--override-generation-config '{"temperature": 0.6, "top_p": 0.95, "top_k": 20, "presence_penalty": 1.5}'
Use --gpu-memory-utilization 0.90 when the edited model runs alone. The vLLM log confirms the override: "Default vLLM sampling parameters have been overridden ... {'presence_penalty': 1.5, 'temperature': 0.6, 'top_k': 20, 'top_p': 0.95}".
Why on the server: at eb1ee503 the manager's ChatSampling (crates/shared/src/models.rs) forwards temperature, max_tokens, top_p, stop, presence_penalty, frequency_penalty and seed. top_k and chat_template_kwargs are not forwarded, and the SDK's generate_text() has no presence_penalty or top_k.
Step by step with the SDK example
Folder: examples/qwen3-5-0-8b-weight-edit-math-vllm-private-nvidia (commit 7661793, plus 07215bb).
- Build the SDK locally with maturin and install the example's
requirements.txt. - Copy
.env.exampleto.envand fill in anik_sdk_token, anik_live_API key scoped to<project>/*, the project slug andIK_WORKER_ID(a registered NVIDIA worker with about 15 GB of free disk). - Optional:
IK_WITH_BASELINE=1deploys the base model next to the edited one (0.45 of the card each),IK_MAX_TOKENS(default 32,768),IK_KEEP_ALIVE=1keeps the workloads after the run. python main.py. It callsensure()for each workload,wait_until_ready(), streams MATH-500test/number_theory/572(divisors of 196, answer 9) from each endpoint over plain HTTP, prints tokens, time and the boxed answer, and deletes the workloads unlessIK_KEEP_ALIVE=1.- For a 5 GB budget add
--max-num-seqs 32to the command (documented in the example).
Timings
| Step | Edited | Base |
|---|---|---|
ensure() to ready, cold worker | 418.1 s | 418.2 s |
pip install vllm==0.33.0 | about 3 min (shared) | |
| Weights load (pre-downloaded) | 0.29 to 0.32 s | |
| Engine init (profile, KV cache, warm-up) | 181.7 s | 186.0 s |
| of which torch.compile | 17.3 to 17.7 s | |
| CUDA graphs | 8 to 9 s | |
| Warm ladder engines, one at a time | 60 to 63 s (133 s for the 5 GB rung) |
MATH-500, 50 problems per model
First 50 problem ids in the order of akhaliq's rerun file eval/scores_edited_math500.json (on the HF checkpoint), 1 sample, seed 0, max 32,768 new tokens, all 50 in flight per model, both models at once, requests sent directly to the two vLLM servers the platform launched. Graded with the authors' mathqa.py (last \boxed{} of the whole output) and math-verify 0.9.0; recomputed from the graded files, identical.
| Edited | Base | |
|---|---|---|
| Right | 31/50 (62%) | 4/50 (8%) |
| Hit 32,768 tokens | 10 (20%) | 48 (96%) |
| Finished without a box | 3 | 0 |
| Mean / max tokens | 20,444 / 32,768 | 31,832 / 32,768 |
| Median tokens of finished answers | 17,477 (40 finished) | 9,377 (2 finished, both right; the other 2 right answers were cut at the limit after boxing the right answer) |
| Total tokens / wall time | 1,022,176 in 986.7 s | 1,591,617 in 1,194.4 s |
| Tokens per right answer | about 33,000 | about 398,000 |
| By subject | algebra 10/12, number theory 5/7, prealgebra 4/7, precalculus 4/7, geometry 3/5, intermediate algebra 3/8, counting 2/4 | prealgebra 2/7, algebra 2/12, others 0 |
| akhaliq's rerun | same 50: 54% (4-sample average); our 1-sample right/wrong agrees with its majority on 42/50 | base smoke test, 25 problems x 4: 5% (95% cut) |
Throughput: one request alone 300 to 380 tokens/s; two at once through the endpoints about 175 tokens/s each; 3,100 to 4,300 tokens/s per engine at the start with 50 running, falling as the KV cache filled. Aggregate over the run: about 1,036 tokens/s edited vs 1,333 base, not a fair comparison: the two engines started at the same moment and the edited one got half the working memory, so it started queuing earlier. Details: KV cache split base 6.48 GiB (517,266 tokens) vs edited 3.32 GiB (265,098 tokens) at the same 0.45 setting, because both engines profiled memory at the same moment, so the edited engine queued requests (99% KV, 22 running, 21 waiting at one point). The whole 100-problem run (2.61 M tokens) took 1,194 s.
Problem 572 (divisors of 196)
- Through the platform endpoints, both at once, recorded: edited
\boxed{9}in 14,518 tokens, 87 s. Base 32,768 tokens after 138 s, no answer, last lines repeating "Wait, $14 \times 14 = 196$." - Batch run: edited 17,077 tokens, stopped, right, about 287 s with 50 in flight. Base 32,768 tokens, cut, enumerating "Let's check 3309. $3309 \times 2 = 6618$. No." upwards, about 757 s. This is the key comparison image.
GPU memory and VRAM ladder
Weights 1.63 GiB per model. Card peak 17,282 MiB (16.9 GiB) with both engines at 0.45, 100% utilization, 286 W. Edited engine alone at 0.45, idle: 6,846 MiB.
Ladder: edited model alone, same command, --max-model-len 34816, 5 problems the edited model solved in the batch (572, 515, 807, 2584, 248) in flight, max 32,768. Every rung below 24 GB is a cap set with --gpu-memory-utilization on the 4090, not a real card.
| GPU or cap | Config | KV cache | Result | Real or emulated |
|---|---|---|---|---|
| RTX 4090 24 GB | both models, 0.45 each, 50 problems each | 6.48 / 3.32 GiB | 62% vs 8% right, peak 16.9 GiB | real |
| 8 GB cap | 0.333 | 4.3 GiB (343,186 tokens) | 5/5 right, 25 to 96 s per answer, longest 31,606 tokens in 95.5 s | emulated |
| 6 GB cap | 0.245 | 2.23 GiB (177,561 tokens) | 5/5 right, identical outputs and times to 8 GB (95.7 s) | emulated |
| 5 GB cap | 0.204, default max_num_seqs 256 | fails: max_num_seqs (256) exceeds available Mamba cache blocks (202) | emulated | |
| 5 GB cap | 0.204, --max-num-seqs 32 | 1.74 GiB (138,766 tokens) | 5/5 right (different texts, other batch shapes), longest 30,948 tokens in 97 s | emulated |
| 4 GB cap | 0.163 | 0.29 GiB | fails: needs 0.44 GiB of KV cache for one 34,816-token request; vLLM suggests a 22,304-token max | emulated |
| 3 GB cap | 0.122 | -0.66 GiB | fails: no available memory for the cache blocks | emulated |
Not tried: a real small card (nothing under 16 GB was available that day, the 16 GB RTX 2000 Ada was not tried), 4 GB with a shorter context, fp8, more than 50 concurrent requests, the vision path. Real 6 to 8 GB cards have less memory bandwidth: expect them slower than these times.
Remaining problems
- Silent end of a streamed base answer (open). Through the endpoint, while the base engine's KV cache was saturated, the stream closed after 152.3 s with 3,286 characters, no
finish_reason, nousage. Cause not confirmed, raw SSE not captured. Ateb1ee503the manager's GPU stream path usesSTREAM_IDLE_TIMEOUT_MS = 120_000and on timeout emits a chunk{"error":{"code":"inference_timeout",...}}followed by[DONE]. The example'sask()reads onlychoicesandusage, so such a chunk would be ignored silently by the client; the example still needs a fix to surface it. Check for anerrorkey and afinish_reasonin your own client. - Concurrent pip into one venv (open). Two workloads with the same
vllm_versionranpip install vllm==0.33.0into the same venv at the same time. It worked here. It is a race. - Uneven KV split (workaround). Two engines starting together on one card profile memory at the same time and the second sees less free memory. Start them one after the other.
- 5 GB needs
--max-num-seqs 32(documented in the example). - The model: 20% of edited answers still run to 32,768 tokens and 3 finished without a box. An early run of the example with a 16,384-token default cut the edited answer, so the default is now 32,768.
- Minor:
min_disk_gb60 in the worker create request was ignored (100 GB given). The first nats-proxy start of the local stack failed for a missingJWT_SECRET. - Grading: the authors'
mcqa.pyis not published. A stub covered an import used only in loop statistics, the grading code was untouched. - Not verified by us: GSM8K, IFEval; the AI Search video's mention of about 44% for the unedited model with other settings (no source named).
Demo video
176.6 s, narrated: the authors' blog with credit, Qwen's loop warning, the authors' numbers and ours, the two models answering the divisors question through the endpoints, and the memory caps.

Sources
- Blog: Sparks of Weight-Space Programming, Takehi, Teoh, Zhang, Khattab (MIT CSAIL), November 2, 2026.
- Edited checkpoint and card, including the rerun and hashes: RikiyaT/Qwen3.5-0.8B-weight-space-programming.
- Base model and loop warning: Qwen/Qwen3.5-0.8B.
- Logs, diffs and
apply_edit.py: RikiyaT/lm_understand-logs. - Demo Space: ML-Intern-lab/weight-space-programming-demo (formerly
akhaliq/weight-space-programming-demo). - Where we spotted it: AI Search, November 8, 2026.
- Our example: inferencekey-sdk, qwen3-5-0-8b-weight-edit-math-vllm-private-nvidia.
