OpenMed

OpenMed Qwen3.5-0.8B WSP Clinical

OpenMed on Hugging Face OpenMed SDK on GitHub License Apache-2.0 No training

OpenMed's clinical weight edit of Qwen3.5-0.8B: no training, one direction removed from one attention layer, and the model answers medical exam questions in the format they ask for. On the 1,273 MedQA-USMLE test questions it scores 39.0%, against 24.4% for Qwen3.5-0.8B as released (paired difference +14.6 points, 95% CI +11.6 to +17.5, McNemar p = 2.6e-21). No gradient descent, no fine-tuning, no training data: a frontier model read the weights in a Python kernel and changed them directly, following "Sparks of Weight-Space Programming" (MIT CSAIL).

Developed by OpenMed
Base model Qwen/Qwen3.5-0.8B @ 2fc06364715b967f1860aea9cf38778875588b17
What changed The attention output projection (o_proj) of layer 23, the last layer: one direction removed
Method Weight-space programming (Takehi, Teoh, Zhang and Khattab, MIT CSAIL, 2026): a frontier LLM reads the weights in a Python kernel and edits them directly
Editor of the clinical edit a frontier LLM, 12 forward passes, 39 Python runs, 52 turns
Practice data the editor could use training splits only: MedQA-USMLE train (10,178) and 10,000 MedMCQA train questions
License Apache-2.0 (see Credits for the inputs and their licenses)
Intended use research on model editing and evaluation; not for clinical use

About OpenMed

OpenMed builds open models and open-source tools for clinical and biomedical text that run on your own hardware.

Results

Same model architecture, tokenizer, chat template and sampling for every row; only weight values differ. One sample per question with seed 0 (MedQA also with seeds 1 and 2). Thinking on, temperature 0.6, top_p 0.95, top_k 20, presence penalty 1.5, at most 32,768 new tokens (the paper's evaluation protocol). The prompt is OpenMed's fixed MedQA exam prompt (below), and an answer is graded from the text after </think>: its last Answer: X line, X in A to D. Answers cut at the token limit and answers with no gradable line count as wrong, as in the paper.

Checkpoint MedQA (seed 0) MedQA, median of 3 seeds (range) MedMCQA MMLU medical MedQA answers cut at 32,768 tokens MedQA answers with no gradable line
OpenMed WSP Clinical 0.8B (this model) 39.0% 38.6% (37.0% to 39.0%) 39.9% 55.4% 19.6% 0.0%
Random patch, same size, random direction (seed 1) 25.7% n/a 28.3% 45.4% 19.2% 31.7%
Random patch, same size, random direction (seed 2) 23.8% n/a 30.5% 45.7% 18.2% 33.7%
Qwen3.5-0.8B as released 24.4% 23.1% (22.1% to 24.4%) 30.6% 43.4% 18.3% 32.9%

Paired tests on the same questions (seed 0; exact McNemar on the questions only one checkpoint got right; bootstrap 95% CI over questions, 10,000 resamples):

Comparison Benchmark n Before After Difference (95% CI) Only before right / only after right McNemar p
Qwen3.5-0.8B -> WSP Clinical 0.8B MedQA-USMLE (4 options) 1,273 24.4% 39.0% +14.6 pts (+11.6 to +17.5) 105 / 291 2.6e-21
Qwen3.5-0.8B -> WSP Clinical 0.8B MedMCQA 1,000 30.6% 39.9% +9.3 pts (+6.2 to +12.4) 87 / 180 1.3e-08
Qwen3.5-0.8B -> WSP Clinical 0.8B MMLU 1,089 43.4% 55.4% +11.9 pts (+8.9 to +15.0) 88 / 218 6.9e-14
random patch 1 -> WSP Clinical 0.8B MedQA-USMLE (4 options) 1,273 25.7% 39.0% +13.3 pts (+10.5 to +16.3) 106 / 276 1.4e-18
random patch 1 -> WSP Clinical 0.8B MedMCQA 1,000 28.3% 39.9% +11.6 pts (+8.5 to +14.7) 75 / 191 7.7e-13
random patch 1 -> WSP Clinical 0.8B MMLU 1,089 45.4% 55.4% +10.0 pts (+7.0 to +13.1) 100 / 209 5.4e-10
random patch 2 -> WSP Clinical 0.8B MedQA-USMLE (4 options) 1,273 23.8% 39.0% +15.2 pts (+12.3 to +18.1) 88 / 282 8.3e-25
random patch 2 -> WSP Clinical 0.8B MedMCQA 1,000 30.5% 39.9% +9.4 pts (+6.0 to +12.8) 106 / 200 8.4e-08
random patch 2 -> WSP Clinical 0.8B MMLU 1,089 45.7% 55.4% +9.6 pts (+6.5 to +12.7) 96 / 201 1.1e-09

Format-agnostic score (secondary)

Also accepting Answer: <B>, Answer: (b), Answer: <letter>B and \boxed{B} after </think>. The gap between this and the main score shows how much of a checkpoint's score is lost to the format of its final line rather than to the choice itself.

Checkpoint MedQA MedMCQA MMLU medical
OpenMed WSP Clinical 0.8B (this model) 39.0% 39.9% 55.4%
Random patch, same size, random direction (seed 1) 33.8% 32.7% 51.9%
Random patch, same size, random direction (seed 2) 31.6% 34.5% 52.2%
Qwen3.5-0.8B as released 32.5% 34.8% 50.0%

Nothing else broke (general benchmarks, one sample, seed 0)

Checkpoint MATH-500 MATH-500 cut at 32,768 tokens IFEval (strict, prompt level)
OpenMed WSP Clinical 0.8B (this model) 7.0% 93.8% 23.1%
Qwen3.5-0.8B as released 7.4% 93.6% 20.2%

What the edit does

OpenMed's fixed exam prompt ends with "finish with one last line exactly like: Answer: ". Under the evaluation's sampling, Qwen3.5-0.8B often copies the placeholder instead of filling it in and ends with Answer: <B> or Answer: <letter>, which no grader reads as a letter. The editor traced the copy to the attention output projection of the last layer (layer 23, all eight heads): at the final Answer: they attend to the prompt's < and write the direction that raises the logit of <. The presence penalty makes it worse, because the four letters have usually appeared in the thinking already while < has not.

The edit removes that one direction from the layer's attention output: W <- W - u u^T W, with u the output direction of the token ' <' made orthogonal to the letters A to D. We checked it independently: the main output direction of every edited tensor's change lines up with the output direction of < (eval/direction_check.json).

Tensor Shape bfloat16 entries changed Relative change sha256 (edited, bfloat16 bytes)
model.language_model.layers.23.self_attn.o_proj.weight 1024 x 2048 1,735,071 0.0436 a9de31b14f982be3b075fc0228dca940e7e2b8b7b3963a1ee67534dab9c7de15

1,735,071 bfloat16 entries differ from the starting checkpoint (Qwen/Qwen3.5-0.8B @ 2fc06364). edit/manifest.json and edit/edit.npz hold the edit as an exact diff (indices and bfloat16 bits), with the sha256 of every tensor before and after; rebuilding the tensors from the diff reproduces these hashes.

Quick start

from vllm import LLM, SamplingParams
from transformers import AutoTokenizer


def main():
    repo = "OpenMed/Qwen3.5-0.8B-WSP-Clinical"
    tok = AutoTokenizer.from_pretrained(repo)
    llm = LLM(model=repo, dtype="bfloat16", max_model_len=34816, language_model_only=True, generation_config="vllm")

    # a MedQA-USMLE practice question (train split, id medqa_train_4541; the key is B)
    question = ("A 23-year-old male with a homozygous CCR5 mutation is found to be immune to HIV infection. "
                "The patient's CCR5 mutation interferes with the function of which viral protein?")
    options = {"A": "Reverse transcriptase", "B": "gp120", "C": "gp41", "D": "pp17"}
    user = ("Which option is the best answer to this clinical question?\n\n" + question + "\n\n"
            + "\n".join(f"{k}. {v}" for k, v in options.items())
            + "\n\nReason as much as you need, then finish with one last line exactly like: Answer: <letter>")
    prompt = tok.apply_chat_template([{"role": "user", "content": user}], tokenize=False,
                                     add_generation_prompt=True, enable_thinking=True)
    sp = SamplingParams(temperature=0.6, top_p=0.95, top_k=20, presence_penalty=1.5, max_tokens=32768, seed=0)
    text = llm.generate([prompt], sp)[0].outputs[0].text
    print(text.split("</think>")[-1].strip())


if __name__ == "__main__":  # vLLM starts worker processes
    main()

How it was made

  1. The harness. We rebuilt the paper's setup, whose prompts and rules are published but whose code is not: a persistent CPU Python kernel over the weights (no GPU, no internet, no gradients; save_edit refuses the final norm, the embeddings and whole-tensor rescaling) and a forward-pass tool (generations with the evaluation's sampling, paired original vs edited with fixed seeds, and teacher-forced reads of hidden states, MLP activations and attention). The task text is the paper's, with the target changed from math to clinical questions.
  2. The editor. A frontier LLM had a budget of 12 forward passes and 40 Python runs. It could use only training-split practice questions; the MedQA, MedMCQA and MMLU test sets in the tables were never shown to it. It diagnosed the failures, localized them, tested strengths and confirmed its edit on fresh practice questions before submitting.
  3. Evaluation and control. Every checkpoint ran with the same vLLM 0.33.0 server and settings on one GPU. The random-patch control changes the same rows and columns of the same tensors by the same amount (the same singular values) in random directions; two seeds.

Files

  • The weights, config, tokenizer and chat template: Qwen3.5-0.8B's release files with the edited tensors (every other tensor is unchanged).
  • edit/: the clinical edit as an exact, hash-checked diff from the starting checkpoint.
  • eval/: per-question results of every checkpoint on every benchmark (id, finish reason, tokens, extracted answer, grade) with no question text, the scores, the first 20 generated texts per benchmark for this model, and receipt.json (forward passes, Python runs, turns and wall time of the edit run).

Limitations

  • Small model, one sample per question (MedQA with three seeds). The gains are relative to the same model and sampling and say nothing about clinical safety.
  • Most of the gain is the model now writing a letter where it used to copy the prompt's <letter> placeholder; the format-agnostic table shows how much is format and how much is the choice itself.
  • The fixed prompt literally says Answer: <letter>; with a prompt that shows no placeholder the edit has less to fix.
  • The edit lowers the probability of < everywhere layer 23 writes, not only in the answer line.
  • It does not fix the thinking loops: about a fifth of MedQA answers still hit the 32,768-token limit (OpenMed/Qwen3.5-0.8B-WSP-Math-Clinical also carries the paper's anti-loop edit).
  • Research only. Not for clinical use, diagnosis or treatment.

Credits

  • Method: "Sparks of Weight-Space Programming: LLMs can natively read & write neural network weights" by Rikiya Takehi, Jayden Teoh, Alex Zhang and Omar Khattab (MIT CSAIL, 2 Nov 2026), https://rikiyat.github.io/blog/weight-space-programming/; logs and diffs at https://github.com/RikiyaT/lm_understand-logs. OpenMed rebuilt their harness from the published prompts and rules and pointed it at clinical questions.
  • Base model: Qwen/Qwen3.5-0.8B by the Qwen team, Apache-2.0.
  • Data: MedQA-USMLE (GBaker/MedQA-USMLE-4-options, CC-BY-4.0), MedMCQA (openlifescienceai/medmcqa, Apache-2.0), MMLU (cais/mmlu, MIT), MATH-500 (HuggingFaceH4/MATH-500), IFEval (google/IFEval, Apache-2.0).
  • Hugging Face's ML Intern reproduction of the paper's math edit showed the method reproduces; ML Intern did not take part in this model.

Citation

@misc{takehi2026weightspace,
  title  = {Sparks of Weight-Space Programming: LLMs can natively read \& write neural network weights},
  author = {Rikiya Takehi and Jayden Teoh and Alex Zhang and Omar Khattab},
  year   = {2026},
  month  = {nov},
  url    = {https://rikiyat.github.io/blog/weight-space-programming/}
}
Downloads last month
75
Safetensors
Model size
0.9B params
Tensor type
F32
·
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for OpenMed/Qwen3.5-0.8B-WSP-Clinical

Finetuned
(750)
this model

Datasets used to train OpenMed/Qwen3.5-0.8B-WSP-Clinical

Collection including OpenMed/Qwen3.5-0.8B-WSP-Clinical

Article mentioning OpenMed/Qwen3.5-0.8B-WSP-Clinical

Evaluation results