Loading
This repository holds the LoRA adapter; the Gemma 4 line ships adapters, no full fine-tune. Every model of the line loads the same way and is run the same way: thinking off through the template's own switch, greedy
decoding, no system prompt (the row's form is learned). Needs transformers 5.10 or newer (Gemma 4) and peft 0.18 or newer.
The LoRA adapter (AbstractPhil/gemma-4-e4b-think-symbolic-image): the base model, the adapter merged into it, the
processor from the adapter repository (the base processor's files are kept there).
import torchfrom peft import PeftModelfrom transformers import AutoModelForMultimodalLM, AutoProcessor processor = AutoProcessor.from_pretrained("AbstractPhil/gemma-4-e4b-think-symbolic-image")model = AutoModelForMultimodalLM.from_pretrained("google/gemma-4-E4B-it", dtype=torch.bfloat16, device_map="cuda")model = PeftModel.from_pretrained(model, "AbstractPhil/gemma-4-e4b-think-symbolic-image").merge_and_unload().eval()
The full fine-tune: none for the Gemma 4 line; the adapter is the release here.
Then:
from PIL import Image image = Image.open("picture.jpg").convert("RGB")prompt = ("Look at this picture and think it through in writing, a closer look, ending with a caption; then write a caption " "and a prompt or tags, and the questions a careful looker would still ask.")messages = [{"role": "user", "content": [{"type": "image", "image": image}, {"type": "text", "text": prompt}]}]text = processor.apply_chat_template(messages, add_generation_prompt=True, tokenize=False, enable_thinking=False)inputs = processor(text=[text], images=[image], return_tensors="pt").to(model.device)out = model.generate(**inputs, max_new_tokens=800, do_sample=False)print(processor.batch_decode(out[:, inputs["input_ids"].shape[1]:], skip_special_tokens=True)[0])
The depth words: "a quick look" (1 to 2 thoughts), "a closer look" (3 to 5), "a long look" (6 to 10). The parser, the scorer and
the trainer are in qwen-symbolic-thinking
(qwen_symbolic_thinking.chain.parse, chain.score); the same package extracted every number below.
The reads
Read the same way as the Lucia family: 60 pictures and 40 specifications no training saw, against the dataset's own rows (row
shape, said / backed, definitions); then the medium term on two sets no training row came from: 500 National Gallery of Art
pictures (100 drawings, prints, paintings, photographs and objects each) and 200 pictures of AIC, NGA, Cleveland and the Met.
Lucia 4B (the Qwen3.5 member of the same class) and Lucia v1 (the 9B) stand beside.
Table with columns: read, Gemma 4 E4B, Lucia 4B, Lucia v1 (9B)| read | Gemma 4 E4B | Lucia 4B | Lucia v1 (9B) |
|---|
| row shape, pictures / specifications | 1.00 / 1.00 | 1.00 / 1.00 | 1.00 / 1.00 |
| said / backed, whole rows | 0.17 / 0.28 | 0.19 / 0.26 | 0.19 / 0.30 |
| definitions, pictures / specifications | 0.00 / 0.28 | 0.02 / 0.12 | 0.02 / 0.08 |
| 500 held-out pictures: painting / print / drawing / photograph / object named rightly of 100 | 83 / 71 / 80 / 82 / 90 | 83 / 78 / 83 / 81 / 91 | 83 / 76 / 86 / 80 / 90 |
| 200 museum pictures: painting / print / drawing / photograph / object | 13 of 27 / 36 of 39 / 12 of 13 / 12 of 13 / 66 of 66 | 14 of 27 / 36 of 39 / 12 of 13 / 11 of 13 / 66 of 66 | 13 of 27 / 38 of 39 / 12 of 13 / 11 of 13 / 66 of 66 |
| the 200 museum pictures on one RTX PRO 6000, batch 64, 800 new tokens a row | 0.22 s a row | 0.26 s a row | 0.27 s a row |
What this says: the Gemma 4 E4B holds the row's form whole and backs what it says at the Lucia 4B's level (0.28 against 0.26 on
the 60-row screen; that read moves by 0.03 to 0.05 between seeds of one recipe), while saying a little less of a picture's
caption (0.17 against 0.19). On the medium term it names paintings, photographs and objects as the Qwen sizes do and falls short
on prints (71 of 100 against 76 to 78) and a little on drawings (80 against 83 to 86); the museum pictures sit at the family's
level. Where it differs most is the long specification rows, written from a text description alone: its thoughts there carry a
defining phrase in 28% of rows against the Qwen sizes' 8 to 12%, and its stock mood words come a little more often (48% of the
500 held-out rows against 44%). It is the fastest looker of the group at 280 image tokens a picture. Before training, the base
model already wrote the row's shape from the plain ask (format 1.00, 65% of rows at their depth, 4.5 thoughts), which no Qwen base
did; the training taught it the backing and the house vocabulary. The museum painting row understates every model: watercolours
and gouaches on paper are named drawings, as the National Gallery's own catalogue does. The reads are made with
qwen_symbolic_thinking.tools (probe_read, museum_read, museum_mismatch, screen_conflicts), so any arm can be read the same
way.
How it was trained
Table | |
|---|
| base | google/gemma-4-E4B-it, bf16, the vision encoder frozen, 280 image tokens a picture (the model's default budget) |
| adapter | LoRA rank 32, alpha 64, dropout 0.05 on the language model's q, k, v, o, gate, up and down projections of all 42 layers (the key and value projections exist on 24 of them; 69.8 M trainable parameters, saved in fp32) |
| data | Lucia v1's rows exactly: 951 picture rows taught twice, 500 long-look drawn rows, 2,000 synthetic closer looks and 17,385 museum rows whose catalogue gives the medium, the prompt line's first term set to it (6,606 drawings, 3,523 paintings, 3,000 prints, 2,016 photographs, 2,240 objects); 20,836 items, 21,787 examples; the 500 probe pictures held out |
| optimiser | plain Adam 2e-4, cosine schedule, 3% warmup, batch 8 x 2, two epochs (2,724 steps, 2.67 s a step, 121 minutes on one RTX PRO 6000), the loss on the answer only, seed 20261030 |
| thinking | off in training and at inference through the template's own switch (enable_thinking=False); with its thinking on, the base model spends about 2,400 characters of thought before a 150-character row and runs out of budget on a fifth of them, so the line is taught and run without it |
| record | qwen-symbolic-thinking v0.1.22, run_queue("gemma") from notebooks/gemma.ipynb; the run's full log is train_summary.json beside the weights |
Versions
Table with columns: version, where, tag| version | where | tag |
|---|
| Gemma 4 E4B v1 | the root of this repository | v1 |
The family
Both sizes are trained under Lucia v1's recipe (the 12B at a quarter of its learning rate, 5e-5, the one change its encoder-free picture pathway needs) and read on the same held-out sets as the Lucia family (Qwen3.5: 9B, 4B, 2B, 0.8B), whose cards start at AbstractPhil/qwen3.5-9b-think-symbolic-image.
License
Apache-2.0, the base model's licence. The rows it was taught come from the datasets above under their own terms.