Ulisse 12B: gemma-4-12B-it, think symbolic image
Ulisse 12B is the 12-billion-parameter member of the Ulisse line, the thinking lookers' second family beside Lucia, on Gemma 4: a LoRA adapter of google/gemma-4-12B-it that looks at a picture and writes the row of thought-symbolic-image-captions: a short chain of plain-language thoughts, one named step per line, then the wordings (a caption, a prompt, tags, a critique, by depth), then the questions a careful looker would still ask, each with its answer and what settles it. Every size is taught the same rows under the same recipe; the sizes differ in what they can hold, and the reads below say what this one holds. He writes the row's form whole and backs his thoughts at the family's level, defines little on the long specification rows, and keeps his sight at a quarter of the recipe's learning rate.
see: A single figure, seated, holding a book, in three-quarter view.
place: The figure sits at the centre, the book held low against the lap.
form: The sitter fills the frame from the knees up, the background a plain dark wash.
colour: Brown ink over graphite, the paper a warm cream.
mood: The lowered eyes and the still hands suggest absorption, a reader lost in the page.
caption: A seated figure reads a book held in the lap, drawn in brown ink over graphite.
prompt: drawing, seated figure reading, three-quarter view, brown ink over graphite, cream paper, plain dark wash
question: thing name -> book [record]
question: medium -> ink and graphite [record]
question: mood tone -> absorbed [chain]
question: sitter identity -> unknown [unknown]
The steps a chain may use, in the order a careful looker takes them: see, name, place, count, relate, form, light, colour, mood,
mean, intend, story, compare, change, check, say. A quick look holds 1 to 2 thoughts, a closer look 3 to 5, a long look 6 to 10.
Questions end in [record] (the answer is a fact of the picture), [chain] (the chain worked it out) or [unknown]. The prompt
line's first term names the kind of picture (painting, print, drawing, photograph).
Loading
This repository holds the LoRA adapter; the Gemma 4 line ships adapters, no full fine-tune. Every Ulisse 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-12b-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 torch
from peft import PeftModel
from transformers import AutoModelForMultimodalLM, AutoProcessor
processor = AutoProcessor.from_pretrained("AbstractPhil/gemma-4-12b-think-symbolic-image")
model = AutoModelForMultimodalLM.from_pretrained("google/gemma-4-12B-it", dtype=torch.bfloat16, device_map="cuda")
model = PeftModel.from_pretrained(model, "AbstractPhil/gemma-4-12b-think-symbolic-image").merge_and_unload().eval()
The full fine-tune: none for the Ulisse 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. Ulisse E4B (the line's other size) and Lucia v1 (the Qwen3.5 9B, the model of the same class) stand beside.
| read | Ulisse 12B | Ulisse E4B | Lucia v1 (9B) |
|---|---|---|---|
| row shape, pictures / specifications | 1.00 / 1.00 | 1.00 / 1.00 | 1.00 / 1.00 |
| said / backed, whole rows | 0.18 / 0.27 | 0.17 / 0.28 | 0.19 / 0.30 |
| definitions, pictures / specifications | 0.02 / 0.12 | 0.00 / 0.28 | 0.02 / 0.08 |
| 500 held-out pictures: painting / print / drawing / photograph / object named rightly of 100 | 83 / 74 / 80 / 81 / 91 | 83 / 71 / 80 / 82 / 90 | 83 / 76 / 86 / 80 / 90 |
| 200 museum pictures: painting / print / drawing / photograph / object | 13 of 27 / 36 of 39 / 12 of 13 / 11 of 13 / 66 of 66 | 13 of 27 / 36 of 39 / 12 of 13 / 12 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.36 s a row | 0.22 s a row | 0.27 s a row |
What this says: the Ulisse 12B holds the row's form whole and backs what it says at the family's level (0.27 against the E4B's
0.28 and Lucia v1's 0.30 on the 60-row screen; that read moves by 0.03 to 0.05 between seeds of one recipe), saying as much of a
picture's caption as the others (0.18). On the medium term it names paintings, photographs and objects as the Qwen sizes do, a
little more of the prints than the E4B (74 of 100 against 71; the Qwen sizes 76 to 78) and fewer of the drawings than Lucia (80
against 86); the museum pictures sit at the family's level. On the long specification rows, written from a text description alone,
it defines far less than the E4B (a defining phrase in 12% of rows against 28%; the Qwen sizes 8 to 12%); its stock mood words come
as often as the E4B's (48% of the 500 held-out rows against the Qwen sizes' 44%). Its picture pathway is different from the E4B's:
Ulisse 12B has no separate vision encoder, the picture's patches enter the language model directly, so the layers the adapter
trains are also the layers that read the picture. A first adapter trained at the Lucia recipe's learning rate lost that pathway
early in training (after a loss spike it wrote one caption for every picture) and was not released; at a quarter of the rate the
dependence on the picture grows through training, checked at the step checkpoints, and the training loss has no spike. Before
training, the base model already wrote the row's shape from the plain ask (format 1.00, 73% of rows at their depth, 4 thoughts);
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, picture_probe), so any arm can be read
the same way.
How he was trained
| base | google/gemma-4-12B-it, bf16, 280 image tokens a picture (the model's default budget); the model has no separate vision encoder: the picture's patches are projected and enter the language model directly, so the early language-model layers read the picture |
| 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 48 layers (the value projection exists on 40 of them; 131 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 5e-5, cosine schedule, 3% warmup, batch 8 x 2, two epochs (2,724 steps, 4.49 s a step, 204 minutes on one RTX PRO 6000), the loss on the answer only, seed 20261030 |
| the learning rate | a quarter of the Lucia recipe's 2e-4, the one change. At 2e-4 a first adapter of this model lost its dependence on the picture between steps 300 and 400 (the training loss spiked from 0.5 to 2.1 around step 440 and settled above its old level) and wrote one caption for every picture; it was not released. The layers that read the picture sit under the adapter here, where the E4B's vision tower is a separate frozen module, so a divergent step costs this model its sight. At 5e-5 the loss has no spike (0.47 at step 300, 0.45 at 600, 0.36 over the last 300 steps; the E4B 0.31) and the answer's dependence on the picture, measured at the step checkpoints as the loss gap between the true picture and a blank one, grows through training as the E4B's does |
| 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 every long specification row, so the line is taught and run without it |
| record | qwen-symbolic-thinking v0.1.26, run_queue("lucia_4b") from notebooks/lucia_4b.ipynb (the lane that was free); the run's full log is train_summary.json beside the weights; the checkpoint traces are tools/picture_probe.py in mode trace |
Versions
| version | where | tag |
|---|---|---|
| Ulisse 12B v1 | the root of this repository | ulisse-v1 (the tag v1 marks the same release before the line was named) |
The family
| size | base | the LoRA adapter | the full fine-tune |
|---|---|---|---|
| E4B | google/gemma-4-E4B-it | gemma-4-e4b-think-symbolic-image | not trained (the line ships adapters) |
| 12B | google/gemma-4-12B-it | gemma-4-12b-think-symbolic-image | not trained (the line ships adapters) |
The Ulisse line is Gemma 4; its name is Dante's voyager who sails out to see (Inferno XXVI), as Lucia is the lady of light and sight. 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 he was taught come from the datasets above under their own terms.