Instructions to use OpenMed/Qwen3.5-0.8B-WSP-Clinical with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use OpenMed/Qwen3.5-0.8B-WSP-Clinical with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="OpenMed/Qwen3.5-0.8B-WSP-Clinical") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("OpenMed/Qwen3.5-0.8B-WSP-Clinical") model = AutoModelForMultimodalLM.from_pretrained("OpenMed/Qwen3.5-0.8B-WSP-Clinical", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use OpenMed/Qwen3.5-0.8B-WSP-Clinical with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "OpenMed/Qwen3.5-0.8B-WSP-Clinical" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "OpenMed/Qwen3.5-0.8B-WSP-Clinical", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/OpenMed/Qwen3.5-0.8B-WSP-Clinical
- SGLang
How to use OpenMed/Qwen3.5-0.8B-WSP-Clinical with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "OpenMed/Qwen3.5-0.8B-WSP-Clinical" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "OpenMed/Qwen3.5-0.8B-WSP-Clinical", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "OpenMed/Qwen3.5-0.8B-WSP-Clinical" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "OpenMed/Qwen3.5-0.8B-WSP-Clinical", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use OpenMed/Qwen3.5-0.8B-WSP-Clinical with Docker Model Runner:
docker model run hf.co/OpenMed/Qwen3.5-0.8B-WSP-Clinical
OpenMed Qwen3.5-0.8B WSP Clinical
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.
- Open models on Hugging Face for clinical NER, de-identification and more.
- The OpenMed Python SDK, Apache-2.0:
pip install openmed. - Follow OpenMed on Hugging Face and @OpenMed_AI on X.
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
- 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_editrefuses 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. - 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.
- 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, andreceipt.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
Model tree for OpenMed/Qwen3.5-0.8B-WSP-Clinical
Datasets used to train OpenMed/Qwen3.5-0.8B-WSP-Clinical
openlifescienceai/medmcqa
GBaker/MedQA-USMLE-4-options
Collection including OpenMed/Qwen3.5-0.8B-WSP-Clinical
Article mentioning OpenMed/Qwen3.5-0.8B-WSP-Clinical
Evaluation results
- Accuracy (thinking on, one sample, seed 0) on MedQA-USMLE (4 options)test set self-reported39.000