GLM-4.6V-Flash, think symbolic image
GLM-4.6V-Flash, think symbolic image is a LoRA adapter of zai-org/GLM-4.6V-Flash, Zhipu AI's 10-billion-parameter vision model (a GLM-4V vision encoder of 24 layers and the GLM-4-9B language model of 40 layers), 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. It is one of five model families trained beside the Lucia line (Qwen3.5) and the Ulisse line (Gemma 4) under Lucia v1's recipe and read on the same held-out sets; it is not named yet. Every looker is taught the same rows under the same recipe; the base models differ in what they can hold, and the reads below say what this one holds. The first family beside Lucia to name the medium at her level (415 of 500); it writes the row's form whole and backs its thoughts at its base model's level.
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 (rank 32, 95.2 M trainable parameters, saved in fp32); there is no full fine-tune. Needs transformers 5 (the reads ran on 5.21.0) and peft 0.18 or newer.
Run it as it was trained: thinking off through the template's own switch (enable_thinking=False, which ends the user turn with /nothink and opens the answer with an empty <think></think> block), greedy decoding, no system prompt. The template writes nothing after an answer, so the rows were trained to end with <|endoftext|>, one of the four ids its generation config stops on.
The base model, the adapter merged into it, the processor from this repository (the base processor's files are kept here):
import torch
from peft import PeftModel
from transformers import AutoModelForMultimodalLM, AutoProcessor
processor = AutoProcessor.from_pretrained("AbstractPhil/glm-4.6v-flash-think-symbolic-image")
model = AutoModelForMultimodalLM.from_pretrained("zai-org/GLM-4.6V-Flash", dtype=torch.bfloat16, device_map="cuda")
model = PeftModel.from_pretrained(model, "AbstractPhil/glm-4.6v-flash-think-symbolic-image").merge_and_unload().eval()
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; then write a caption and a "
"prompt or tags, and the questions a careful looker would still ask, each as `question: what -> "
"answer [record, chain or unknown]`.")
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 prompts it was trained on
The adapter was trained on these exact asks (the trained forms of the package's prompts.full and prompts.short); a reworded
ask is a different input. The reads below use the whole row at each picture's depth.
| depth | the whole row (the form these reads use) | the short form |
|---|---|---|
| a quick look | Look at this picture and think it through in writing, a quick look; then write a caption, and the questions a careful looker would still ask, each as question: what -> answer [record, chain or unknown]. |
Look at this picture and think it through in writing, a quick look, ending with a caption. |
| a closer look | Look at this picture and think it through in writing, a closer look; then write a caption and a prompt or tags, and the questions a careful looker would still ask, each as question: what -> answer [record, chain or unknown]. |
Look at this picture and think it through in writing, a closer look, ending with a caption. |
| a long look | Look at this picture and think it through in writing, a long look; then write a caption, a prompt, tags and a critique, and the questions a careful looker would still ask, each as question: what -> answer [record, chain or unknown]. |
Look at this picture and think it through in writing, a long look, ending with a caption. |
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 and Ulisse lines, by the same reader, beside Lucia v1 (the model the recipe was made for) and Ulisse 12B. First a screen: 60 pictures and 40 specifications no training row came from, scored against the dataset's own rows. Row shape is the share of rows written in the row's form; at its depth, the share whose chain holds the number of thoughts its depth asks for; said is the share of a picture's own captions' content words that the thoughts and the caption say, and backed the share of the model's content words those captions back; a definition is a thought that defines a word instead of looking. Then the medium term on two sets no training row came from, from the picture list AbstractPhil/qwen-thinking-images: 500 National Gallery of Art pictures (100 drawings, prints, paintings, photographs and objects each), the prompt line's first term read against the catalogue's kind, and 200 pictures of the Art Institute of Chicago, the National Gallery, the Cleveland Museum of Art and the Met.
| read | GLM-4.6V-Flash | Lucia v1 (Qwen3.5-9B) | Ulisse 12B (Gemma 4 12B) |
|---|---|---|---|
| row shape, pictures / specifications | 1.00 / 1.00 | 1.00 / 1.00 | 1.00 / 1.00 |
| at its depth: pictures, whole row / short form; specifications | 1.00 / 1.00; 0.97 | 1.00 / 1.00; 0.95 | 1.00 / 1.00; 0.93 |
| said / backed, whole rows (short form) | 0.18 / 0.26 (0.25 / 0.29) | 0.19 / 0.30 (0.23 / 0.30) | 0.18 / 0.27 (0.21 / 0.27) |
| rows with a definition: pictures / specifications | 1 of 60 / 10 of 40 | 1 of 60 / 3 of 40 | 1 of 60 / 5 of 40 |
| 500 held-out pictures: painting / print / drawing / photograph / object named rightly of 100 (sum) | 82 / 77 / 84 / 81 / 91 (415) | 83 / 76 / 86 / 80 / 90 (415) | 83 / 74 / 80 / 81 / 91 (409) |
| 200 museum pictures: painting / print / drawing / photograph / object | 15 of 27 / 37 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 | 13 of 27 / 36 of 39 / 12 of 13 / 11 of 13 / 66 of 66 |
| time a picture on one RTX PRO 6000 (batch 64, 800 new tokens a row) | 0.55 s | 0.27 s | 0.36 s |
What this says: This is the first family beside Lucia to name the medium at her level: 415 of the 500 held-out pictures, her own sum, every kind within 2 of hers (drawings 84 against her 86), and the museum pictures within 2 a kind; read one picture at a time the same adapter names 414, so the batched read holds. The form is whole (at its depth on every picture row, against its base's 0.63). The grounding stays at its base's level: it backs 0.26 of what it says on the full row (its base 0.26; Lucia v1 0.30) and 0.29 on the short form, and says 0.18 of a picture's own captions (hers 0.19). On the specification rows it puts a defining phrase in 10 rows of 40 (Lucia 3). Its pictures take about 1,369 tokens at 1,024 pixels, so it reads at 0.55 to 0.58 seconds a picture at batch 64 and took 7 hours to train.
Before training the base model wrote the row's form from the plain ask (1.00) at a short length (2.9 thoughts), 0.63 of rows at their depth, and backed 0.26 of what it said: the best-grounded base after Phi-4. The training taught it the row's shape at each depth, the backing and the house vocabulary.
Limits, shared with the family: quick looks are the fragile depth, where one thought can name a wrong thing; the museum painting
row understates every model, because watercolours and gouaches on paper are named drawings, as the National Gallery's own catalogue
does; English only; the row's conventions (the steps, the depths, the question form) are the dataset's. The specification-row
definitions are counted on 40 rows, the noisiest line of the table. The reads are made with qwen_symbolic_thinking.tools
(probe_read, museum_read, museum_mismatch, screen_conflicts), so any adapter can be read the same way.
How it was trained
| base | zai-org/GLM-4.6V-Flash, bf16; pictures at the processor's default: about 1,369 picture tokens for a square 1,024-pixel picture (14-pixel patches merged 2 x 2); its vision encoder frozen, outside the adapter |
| adapter | LoRA rank 32, alpha 64, dropout 0.05 on the language model's q, k, v and o projections, the fused gate-up projection and the down projection of all 40 layers; 95.2 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 (18,336 whole rows, 2,951 short forms, 500 specification rows); the 500 held-out probe pictures never trained |
| optimiser | plain Adam 2e-4, cosine schedule, 3% warmup, batch 8 x 2, two epochs (2,724 steps, 9.31 s a step, 423 minutes on one RTX PRO 6000), the loss on the answer only, seed 20261030; final training loss 0.399 (each family's own tokens, so not comparable across families) |
| length | max_len 2,560; no example of the 43,574 collated was cut (the longest 1,673 tokens) |
| thinking and turn end | on by default in the base model; off in training and at inference through the template's switch (enable_thinking=False); the rows end with `< |
| record | qwen-symbolic-thinking v0.1.31 on transformers 5.21.0, run_queue("lane3") from notebooks/lane3.ipynb; the run's full log is train_summary.json beside the weights |
Where it was trained
- The code: qwen-symbolic-thinking on GitHub: the trainer, the screens, the reads and what each model family
needs (
qwen_symbolic_thinking/family.py). This adapter was trained by v0.1.31 (tagv0.1.31); the batching and loading notes on this card hold for v0.1.38. - The run's record: the model repository AbstractPhil/qwen-symbolic-thinking-image-training (a model repository, not a
dataset): this adapter with its step checkpoints under
lora/GLM-4.6V-Flash/r32/20261102_041223_G_med4_2ep_glm46v/, the training sets it read (sft/pictures_v2.json,sft/drawn_deep_v2.json,synth/S_synth.json,sft/medium_v4.json) and the screens underscreens/. - The rows: the dataset thought-symbolic-image-captions (the row's form and the picture rows) and the picture list AbstractPhil/qwen-thinking-images (the museum pictures and the held-out probe).
Versions
| version | where | tag |
|---|---|---|
| GLM-4.6V-Flash, think symbolic image v1 | the root of this repository | v1 |
The lookers
The Lucia line is Qwen3.5 and starts at AbstractPhil/qwen3.5-9b-think-symbolic-image; the Ulisse line is Gemma 4. The five families below them (North-Micro-Vision, GLM-4.6V-Flash, Molmo2-O-7B, Ministral 3 14B and Phi-4-reasoning-vision-15B) are trained under Lucia v1's recipe at her learning rate (each has its own vision encoder, frozen under the adapter) and read on the same sets.
License
MIT, the base model's licence. The rows it was taught come from the datasets above under their own terms.