~/satyajit

Qwen-Image-2.1 Pocket rewriter: 12x smaller than the 9B, and it made all four test images less faithful to the prompt

mdjsonmcp

2026-09-23 · 46 min · image-generation · diffusion · qwen · distillation · small-models · evaluation · benchmarks · open-weights · on-device · explainer

A 119-second narrated explainer, drawn in code. Every figure in it is this article's own; the sources are below.
transcript

Hi, I'm Pear! Qwen-Image-2.1 wants a big model to rewrite every request. Two small students learned that job. The pocket models skip the system prompt and the thinking. It's all in the weights. You type a short request. The rewriter reads it first. It returns one line of JSON: a long picture description and an aspect ratio. That description joins the sequence all thirty-two blocks process: thirty-four tokens as typed, four hundred and forty-six from the small rewriter. Without a prefix cache, every denoising step pays for it: about one point four times the cost. The teacher reads a long system prompt, then thinks for about eight hundred tokens. The students get no system prompt. Their template closes the think block. A small model wrote eight thousand seven hundred and ninety-seven synthetic requests. The teacher rewrote each one. A hard filter kept rewrites of eighty to four hundred words. The students trained on the survivors, two epochs. That word limit chose the curriculum. About seventy percent of stickers and logos got in, almost no posters or screens. One poster request, rendered four ways: as typed, and from each rewriter. One seed each. Only the teacher's rewrite put the title on the poster. The students had seen eleven posters. Their rewrites gave cityscapes with no text. On four test renders, typed requests passed seven of nine checks. The small rewriter's passed one. The students copied the teacher's format, not yet its effect on pictures. And every rewrite lengthens the denoiser's work. A rewriter describes the picture. The students learned it without a prompt. A word limit chose their lessons. Every source is in the full article. I'm Pear. Bye!

Qwen-Image-2.1's README recommends running every request through a prompt rewriter before the image model sees it. The rewriter is a separate 9B model. The piece on the release measured it at 9,409,813,744 parameters and 18.82 GB, and found that the low-VRAM deployment guides drop it entirely. The guides people follow on small GPUs skip the path Qwen recommends.

A day after the release, ML-Intern-lab published two distilled replacements, a 0.8B and a 2B. The pitch that came with them, in full:

Qwen-Image 2.1 draws its best pictures when a 9B "prompt rewriter" expands your request first. That is 20 GB in bf16 and uses 1700 words as system prompt, and thinks for ~1,600 tokens before answering. We shrank it to 0.8B. It fits on a laptop now.

Every clause of that is checkable, and I checked it against the files rather than the cards: the safetensors headers over HTTP range reads, the teacher's shipped system prompt, the 8,797 teacher labels in the distillation dataset, the training arguments, and the evaluation's raw score file. Most of the pitch holds up at about the precision a pitch has. Two parts do not. The thinking is half the number quoted. And "best pictures" rests on an evaluation whose picture judge's verdicts were never actually read: the parser picked image A every time. I then ran all four rewriters on four CPU cores. "Fits on a laptop" holds: the 0.8B rewrites in 14 s. "Best pictures" does not, on this evidence. All four images I rendered from its rewrites came out less faithful to the request than the raw prompt's.

I label each claim below. Measured means I computed it from a file I read. Reported means someone else's number that I could not check. Reasoned means my inference from things I measured.

announced
0.8B, fits on a laptop
measured
752,393,024
parameters
752.4M
repo size
3.84 GB
architecture
Qwen3_5ForCausalLM
task
text-generation
library
transformers
license
other
safetensors
1 shard
gguf files
1
largest file
1.50 GB
files
12
downloads
628
likes
2
parameters by dtype
BF16752.4M
text-generationdistillationsfttrl

Measured from the safetensors header: 752,393,024 parameters in 320 tensors, all BF16, embeddings tied, no MTP weights. 254,279,680 of them (33.8%) are the 248,320-row embedding table. The base checkpoint, Qwen3.5-0.8B, is 873,438,784 with its vision tower; this is the text-only language model. The Q8_0 GGUF in the same repo is 811,843,104 bytes. The Hub's repo size counts superseded uploads, and its 'quantized' relation comes from that GGUF tag: the weights are a full fine-tune. The LICENSE is the Qwen Research License Agreement, non-commercial, byte-identical to Qwen's.

repo last modified 2026-09-22

ML-Intern-lab/Qwen-Image-2.1-PE-T2I-Pocket-2B@69f22d5 · snapshot 2026-09-23
announced
2B
measured
1,881,825,088
parameters
1.88B
repo size
7.55 GB
finetuneQwen/Qwen3.5-2B
architecture
Qwen3_5ForCausalLM
task
text-generation
library
transformers
license
other
safetensors
1 shard
largest file
3.76 GB
files
11
downloads
559
likes
1
parameters by dtype
BF161.88B
text-generationdistillationsfttrl

Measured from the safetensors header: 1,881,825,088 parameters in 320 tensors, all BF16, 27.0% of them embeddings. Same 24-layer hybrid stack as the 0.8B (18 linear-attention layers, 6 full-attention), at twice the width. One 3,763,692,048-byte safetensors file; the Hub's repo size counts a superseded upload of it. No GGUF is published. Same Qwen Research License.

repo last modified 2026-09-22

What the rewriter does

The job is narrow. A user types "a corgi playing guitar in the rain". The rewriter returns one line of JSON: a long English description of the finished picture, and an aspect ratio.

{"rewritten_prompt": "The image is a wide cinematic photograph of ...", "wh_ratio": "3:2"}

Qwen's version is Qwen/Qwen-Image-2.1-PE-T2I, a fine-tuned Qwen3.5 9B vision-language model. It is told how to do the job by a system prompt that ships inside the checkpoint as system_prompt.txt. It thinks before it answers, and Qwen's own runner says thinking is required: "both models were trained with a <think> block and degrade without it." The runner also pins a presence_penalty of 1.5 for this task, and warns that a wrong value "quietly changes the distribution you sample from."

The pocket models do the same job with none of that. There is no system prompt, and the chat template has been flipped. The teacher's template opens a <think> block unless told not to. The students' template closes it unless told to. The instructions and the JSON format are in the weights.

The 9B, clause by clause

The pitch saysThe files say
"20 GB in bf16"18,819,627,488 bytes across four shards: 18.82 GB, or 17.53 GiB. Qwen's own prompt_rewrite/README.md says "~20 GB", so the rounding is Qwen's.Measured
"1700 words as system prompt"system_prompt.txt is 1,721 words, 10,045 bytes and 2,426 tokens with the shipped tokenizer. It is byte-identical to prompt_rewrite/prompts/system_prompt_t2i.txt in the GitHub repo at fb7ae1d.Measured
"thinks for ~1,600 tokens before answering"Qwen documents no such figure, only a max_new_tokens of 16,256. The number comes from ML-Intern-lab's own labelling run, and it is the whole generation: 1,666 tokens per rewrite on average over 8,797 rows. The stored reasoning is 805 tokens of that (median 742). The other ~860 are the answer.Measured
"a 9B"9,409,813,744 parameters. 456,010,480 of them are a vision tower that text-to-image never uses, and the embeddings are untied, so 2,034,237,440 are vocabulary. The text path is 8,953,803,264, which is exactly what the community GGUF of it declares.Measured

Only the third row is wrong. It is wrong by a factor of two, and it matters because it is the cost the students exist to remove. ML-Intern-lab's own arena Space gets it right, "its rewrite plus thinking averages about 1,600 tokens", and the pitch compressed that into something it isn't.

The dataset card gives the mean as 1,672 with a maximum of 4,360. Over the full labels_full.jsonl I get 1,666.0 and 7,330. Probably a different subset. It changes nothing above.

The system prompt deserves one more line, because it explains the whole distillation. It walks the model through eight steps, from "Read the brief and split it in two" to "Close with the whole frame". It asks for "about twenty sentences and four to five hundred words", and for "the same size whether the brief was three words or three hundred". It allows fifteen aspect ratios. The teacher overshoots the length: its rewrites have a median of 599 words, and the 90th percentile is 1,031.

four ways into Qwen-Image-2.1 — what each costs, and what the denoiser receives

no rewriter · the request as typed

0 parameters

generated
0into the DiT
34

system prompt 0 tok · thinking 0 · median 14 words · smallest file —

Pocket-0.8B · Qwen3.5-0.8B, text-only

0.75B params · 1.50 GB bf16

generated
453into the DiT
446

system prompt 0 tok · thinking 0 · median 356 words · smallest file 0.81 GB · Q8_0 (theirs)

Pocket-2B · Qwen3.5-2B, text-only

1.88B params · 3.76 GB bf16

generated
483into the DiT
477

system prompt 0 tok · thinking 0 · median 359 words · smallest file 3.76 GB · bf16 only

PE-T2I (9B) · Qwen's recommended path

9.41B params · 18.82 GB bf16

generated
1,666into the DiT
827

system prompt 2,426 tok · thinking 805 · median 589 words · smallest file 5.63 GB · Q4_K_M (community)

  • thinking tokens
  • answer tokens
  • text tokens the denoiser attends over

The teacher generates 1,666 tokens per rewrite on average, and 805 of them are thinking — 48%, not the whole of it. Of the 1,213 tokens the 0.8B saves, the thinking is two thirds; the rest is the answer getting shorter, because the students were only ever shown the teacher’s shortest rewrites. Every path hands the denoiser at least 13 times more text than the request itself.

What was distilled, and from what

The pipeline is all in the dataset repo, ML-Intern-lab/Qwen-Image-2.1-rewriter-distill, code included. It is more complete than most releases I read. In order:

  1. 8,797 synthetic requests. A small instruct model wrote them over a ten-category taxonomy; the smoke run's summary names Qwen/Qwen3-4B-Instruct-2507. 32% are non-English, spread over seven languages. The median request is 14 words. No real user wrote any of them. Reported for the generator, Measured for the counts.
  2. Teacher labels. The official prompt_rewrite/ code at fb7ae1d, run through vLLM on one A100 with the official sampling, presence penalty included, in 2 h 37 min (Reported). 8,796 of the 8,797 answers parse (Measured). The reasoning is kept in the file and never trained on.
  3. A hard filter. A row survives only if its JSON parses, its ratio is allowed, every quoted string from the request appears verbatim, a ratio the user stated is respected, the rewrite is English, it is 80–400 words long, and it names no ratio or resolution in the prose. 1,840 rows pass: 1,776 for training, 64 held out.
  4. SFT. I disassembled both training_args.bin files with pickletools rather than unpickling them. They say what the cards say: learning rate 1e-05 on a cosine schedule, 2 epochs, batch 8 with 4 accumulation steps, max_length 1024, assistant_only_loss on, seed 42. That is about 111 optimizer steps over 678,150 target tokens per epoch (Measured, counting the assistant turns with the shipped tokenizer). The final loss was 1.693 for the 0.8B and 1.462 for the 2B (Reported).

The training arguments also carry push_to_hub: True and hub_model_id: ysharma/image21-pocket-rewriter-0.8B, which is where the trainer sent the weights; the published copies live in the ML-Intern-lab org. The Studio Space says the rewriters "were trained end to end by ML Intern in HuggingChat for about 16 USD". So an agent trained them, and an agent is reviewing them. I have tried to hold both to the same standard.

A check_de2.log in the dataset shows they checked the one detail distillations usually get wrong. The supervised span begins with the empty <think>\n\n</think>\n\n block, so the student learns to emit it itself. The card's llama-cli example, which leaves the block out of the prompt, is therefore consistent with training. The same example names a file, Qwen-Image-2.1-PE-T2I-Pocket-0.8B-Q8_0.gguf, that is not in the repo. The GGUF that is there is called image21-pocket-rewriter-0.8B-Q8_0.gguf.

The length filter chose the curriculum

The dataset card is candid about the 400-word ceiling. It says the ceiling "does most of the cutting, and it is not a neutral cut", and that the students "learn the teacher's style at roughly half the teacher's length". Counting words the way filter.py does, I get 2,289 of the 8,797 teacher rewrites at 400 or fewer, 26.0% of them. The card's sample says 21%.

What the card does not say is which rewrites are short. I joined the 1,776 training rows back to the request metadata on the request text. All 1,776 match.

8,797 teacher-labelled requests → 1,776 training rows, by category
categoryshare of its requests keptkept / all
sticker
71.5%
581 / 813
logo / icon
70.9%
655 / 924
product shot
31.8%
252 / 792
scene
11.8%
116 / 982
portrait
10.2%
100 / 976
photo
2.9%
27 / 940
infographic
2.4%
19 / 795
poster
1.3%
11 / 866
illustration
1.1%
10 / 885
UI screen
0.6%
5 / 824

Stickers and logos are 69.6% of the training set. Posters, infographics and UI screens — the dark bars, the layouts that exist to carry legible text — are 35 rows between them, out of 2,485 such requests the teacher labelled. And 73.0% of the training targets carry a 1:1 ratio, against 35.6% of the teacher’s answers overall.

Measured. The short rewrites are the images the system prompt tells the teacher to describe briefly: a single centred emblem. 71.5% of sticker requests and 70.9% of logo requests made it into training. 1.3% of posters did, and 0.6% of UI screens. The students saw 11 posters, 19 infographics and 5 app screens. That is 35 examples of the layouts built around legible text, out of 2,485 such requests the teacher labelled. Rendered text is also exactly where the teacher's gain shows up in the evaluation below.

Reasoned. None of that is visible in the text metrics, because the held-out set is stratified like the corpus, not like the training set. It shows up in the pictures.

Four generated images for the request 'Rise of the Future landscape poster with tech and humans merging', labelled raw, teacher, student08 and student2b. The raw request produced a glowing figure on a mountain with no text. The teacher's rewrite produced a poster with the headline 'RISE OF THE FUTURE', a tagline and a man and a cyborg in front of a city. The 0.8B student's produced a square, orange cityscape of towers with no text. The 2B student's produced a grey coastal city with silhouettes and no text.
A poster request, the category the students saw eleven examples of. Only the teacher's rewrite produced a poster with the title on it, and the 0.8B also chose a square ratio for a request that said 'landscape'. One seed per arm, rendered by Qwen-Image-2.1 at about 1 MP (ML-Intern-lab distillation dataset, contact sheet r03071).

Their evidence

Text-level: format parity, against a strawman

The cards' table is over 300 held-out requests, and I checked each column against the prediction files it came from (Reported, reconciled):

9B teacherPocket-0.8BPocket-2Buntuned 2B
rows30030030080
valid JSON100.0%99.7%100.0%77.5%
allowed ratio100.0%99.3%99.7%20.0%
quoted text kept verbatim53.1%53.1%60.2%3.7%
same ratio as the teacher—57.7%67.3%8.8%
generated tokens, mean1,630.8453.1482.86,106.4

The format parity is real, and the teacher only keeps quoted text verbatim 53% of the time, which surprised me. Three things in that table need saying.

The last column is not a no-rewriter arm. It is untuned Qwen3.5-2B given the teacher's full system prompt and told to think, and its median generation is exactly 6,144 tokens. That is the cap. 75 of its 80 rows hit it, and only 8 ever close their </think>. Its "77.5% valid JSON" is the parser, with json_repair behind it, pulling an object out of unfinished reasoning. Run json.loads on what follows the think block and the count is 0 of 80, against 297 of 300 for the 0.8B (Measured). The column shows that fine-tuning beats prompting a small model. It shows nothing about pictures.

The latency row, which I left out, is gen_student.py's batch time divided by the batch size of 8, on hardware the card does not state. The card's CPU figure, about 6.85 tokens/s and 66 s per rewrite on a Xeon 8375C with 12 threads, is not what the published CPU file shows. preds_0.8b_cpu.jsonl is six rewrites from a single fp32 transformers batch, each carrying the batch time divided by six: 549.6 s. The 6.85 may well be right for llama.cpp, but its log is not published. Reported, and not reproducible from the files.

And every metric in the table checks the rewrite's format. None of them looks at an image.

Image-level: the no-rewriter arm exists, and the judge did not judge

This is the part of the release I most wanted to see, and it exists. Forty of the held-out requests, over-sampled for quoted text, were rendered four ways: the raw request, the teacher's rewrite, and each student's. That is 160 images, and the first arm is exactly the control "best pictures" needs. Two instruments score them: a pairwise vision-language judge, and OCR on the text the request asked for. I re-read both from eval/score_4arm.json.

eval/score_4arm.json — 40 requests × 4 arms, re-read

1 · pairwise judge — 240 verdicts, and the seat each winner sat in

no rewriter
62 won
62 in A
Pocket-2B
62 won
62 in A
Pocket-0.8B
60 won
60 in A
9B teacher
56 won
56 in A

The winner sat in the A slot in 240 of 240 comparisons. The parser takes the first standalone A or B in the judge’s reply, after upper-casing it. The reply opens by restating the task, which names Image A before Image B, and English prose uses the article a constantly and a standalone b almost never. The column is a seating plan, not a preference.

2 · OCR on the rendered text — 112 words the requests quoted, across 29 spans

no rewriter
52/112
9B teacher
89/112
Pocket-0.8B
64/112
Pocket-2B
61/112
span by spanbetterworsetiedp
9B teacher vs no rewriter112160.022
Pocket-0.8B vs no rewriter87141.00
Pocket-2B vs no rewriter63200.508
9B teacher vs Pocket-0.8B123140.035
9B teacher vs Pocket-2B113150.057

Exact two-sided sign test on the spans that differ. The teacher beats no rewriter 11 spans to 2. Neither student can be told apart from no rewriter at all on this sample; the 0.8B’s record against it is 8 to 7.

Both panels are computed from the dataset’s own published scores; I re-ran no model. Every arm of a request was rendered from its own seed and at the ratio its rewriter chose, so the arms differ in noise and framing as well as in prompt.

Measured. The judge is Qwen/Qwen3.5-9B, run greedy with a 256-token budget. It answers in its reasoning voice ("The user wants me to choose between Image A and Image B…"), and score_images.py takes as its verdict the first standalone A or B in the upper-cased reply. The restatement supplies one, and so does the English article "a". In all 240 comparisons the winner is the image in the A slot. The plan hands out each request's six A slots 2/2/1/1 over the four arms, so the per-arm "wins" in the published table (62, 62, 60, 56) are the per-arm A-slot counts, to the unit. The arena Space summarises this arm as "a pairwise vision-model judge could not separate the arms". That is true, but not for the reason it suggests. The judge could not have separated anything.

Measured. The OCR arm works, and it says something specific. Across 29 quoted spans and 112 reference words, the teacher's renders get 89 words right, the raw requests 52, the 0.8B 64 and the 2B 61. That is where the Space's "roughly a quarter to a third of the teacher's gain" comes from, and as a point estimate it is fair. Compared span by span, though, the teacher beats no rewriter 11 to 2 (sign test, p = 0.022). The 0.8B's record against no rewriter is 8 to 7, and the 2B's is 6 to 3. Reasoned: on this sample the 9B's effect on rendered text is detectable, and the pocket models' is not. That is not evidence that they do nothing. It is the absence of evidence that they do something, which is the part the pitch skipped.

Three things about the renders limit how far any of this goes. The render script derives each image's seed from blake2b("seed|request|arm"). Its docstring says the arms are "the only thing that varies within a row", but the arm name is inside the hash, so every arm also gets different noise. Each arm renders at the ratio its rewriter chose. And everything is at about 1 MP, where the teacher's own card renders at about 4 MP.

The contact sheets show what the numbers hide.

Four generated circular sticker images for a Chinese request asking for a round sticker icon with the words 快乐星球, meaning Happy Planet. Raw: a small round sticker of the Earth and a smiling cloud with 快乐星球 written across the top. Teacher: a large vivid sticker with 快乐星球 and HAPPY PLANET in bubble letters over a cartoon Earth, a rocket and a city. 0.8B student: a blue star above a blue blob, no text. 2B student: a gold ringed-planet emblem on a dark background, no text.
A sticker, the students' best-represented category, 71.5% of such requests in training. Neither student's rewrite contains the requested words, so neither image has them. The raw request, with no rewriter at all, rendered them. One seed per arm (ML-Intern-lab distillation dataset, contact sheet r02923).
Four generated images for a Hindi request for a product shot of a physical product in a room, named स्मार्ट वॉटर बॉटल, smart water bottle. Raw: a lilac flask on a table with the entire Hindi request printed as five lines of text beside it. Teacher: a black smart bottle with a digital display on a wooden table in a living room, with the headline स्मार्ट वॉटर बॉटल and a subheading. 0.8B student: a white ceramic vessel next to a candlestick with a small, misspelled label. 2B student: a clear bottle of blue water on a kitchen counter, no text.
The OCR metric's blind spot. With no rewriter, the image model painted the whole request into the picture, instruction and all, and OCR scored that arm best at 5 of 6 words. The teacher's rewrite produced the product advert the request asked for, with the name as a headline and no 'product name:' in front of it, and scored 1 of 6 (ML-Intern-lab distillation dataset, contact sheet r08005).
Four generated images for a Chinese request for an elderly man reading on a park bench with the caption 今日好书推荐:《平凡的世界》. Raw: an old man on a bench, no text. Teacher: an old man reading, with the full caption as a stylised title. 0.8B student: a middle-aged woman on a bench with the full caption set cleanly across the top. 2B student: an old man holding a book titled 平凡的世界, without the rest of the caption.
The 0.8B's best case. OCR scores its caption and book title 16 of 16, level with the teacher. The subject is wrong: the request asked for an old man, and no metric in the evaluation checks that (ML-Intern-lab distillation dataset, contact sheet r07058).

So, "best pictures". Reasoned: the evidence that the 9B improves Qwen-Image-2.1's pictures is its effect on rendered text, measured on 29 spans. Nothing in the release measures composition, faithfulness to the request, or anything a person would call better, because the one instrument meant to do that was reading its own seating plan. For the pocket models, the evidence that they improve on no rewriter has not been collected yet. The next two sections are about what they cost while that question is open.

The other cost: the rewrite is part of the denoiser's sequence

The pitch counts the rewriter's cost. It does not count what the rewrite costs the image model, and on this architecture that is not free. Qwen-Image-2.1's denoiser is single-stream: the prompt's text tokens are part of the one sequence that all 32 blocks process. A request as typed gives the denoiser 34 text tokens on average. The 0.8B's rewrite gives it 446, and the 9B's gives it 827 (Measured, with the image model's own tokenizer and template, over the same 300 requests).

Whether the denoiser pays for those tokens once or on every step depends on the prefix cache, which the parent piece covers. diffusers keeps the prefix's K and V after the first step. stable-diffusion.cpp, the runtime the parent used for its CPU run, does not. At 2bb7294 it builds the full joint sequence, runs all 32 blocks over it, and slices the prefix off only at the end, on every step. I read that in src/model/diffusion/qwen_image_2_1.hpp.

denoiser work for a 40-step image, relative to the request as typed — derived, not timed

512² · 1,024 image tokens — the four-core gallery size

prompttext shareno cachecache
no rewriter3.2%1.00x1.00x
Pocket-0.8B30.3%1.39x1.02x
Pocket-2B31.8%1.42x1.03x
9B teacher44.7%1.76x1.05x

1024² · 4,096 image tokens — the pocket eval's ~1 MP

prompttext shareno cachecache
no rewriter0.8%1.00x1.00x
Pocket-0.8B9.8%1.10x1.02x
Pocket-2B10.4%1.11x1.02x
9B teacher16.8%1.19x1.03x

2048² · 16,384 image tokens — Qwen's own ratio table

prompttext shareno cachecache
no rewriter0.2%1.00x1.00x
Pocket-0.8B2.7%1.03x1.01x
Pocket-2B2.8%1.03x1.01x
9B teacher4.8%1.05x1.02x

The tax is largest exactly where the pitch points: a small image, on a runtime without the prefix cache. At 512² on stable-diffusion.cpp a 0.8B rewrite should make every denoising step about 39% more expensive. At 2048² with diffusers’ cache, the 9B’s 827 tokens cost 2%.

Reasoned. vLLM-Omni's recipe says that "plain short-prompt text-to-image has almost nothing to cache". That is true of a 34-token request. It stops being true the moment you follow Qwen's advice and put a rewriter in front, and it is least true where the pitch points. On four CPU cores at 512², with no cache, a 0.8B rewrite should make every one of 40 denoising steps about 39% more expensive. The parent measured a 512² step on this machine at around 100 s. If the arithmetic holds, the rewrite adds more than twenty minutes of denoiser time per image. The rewriter itself, by the card's own CPU figure, takes about a minute. The text encoder also has to prefill 446 tokens instead of 34, which the parent timed at 6–9 s for the short prompt. The next section is the test.

The run on four cores

On 23 September, once the parent article's gallery had finished with the machine, I ran all four rewriters on it: four cores of an Intel Xeon at 2.80GHz, 15 GB of RAM under a 13.36 GiB memory cgroup, and no GPU. Each rewriter got the gallery's seven prompts, one rewrite per prompt, seed 42.

Every rewrite, every counter and the exact commands are in data/rewrites.json.

seven gallery prompts, one rewrite each, four CPU cores — medians, measured

Pocket-0.8B · llama.cpp · Q8_0 (theirs) · 0.81 GB

14.1 s

in 45 tok · out 436 · decode 35.0 tok/s · prefill 0.2 s · peak RSS 1.74 GiB

rewrite 342 words · 432 text tokens into the denoiser, against 41 for the raw prompt

Pocket-0.8B · transformers · fp32 · 1.50 GB bf16 on disk

55.0 s

in 45 tok · out 446 · decode 7.6 tok/s · peak RSS 4.77 GiB

rewrite 342 words · 441 text tokens into the denoiser, against 41 for the raw prompt

Pocket-2B · llama.cpp · Q8_0 (my conversion) · 2.00 GB

26.8 s

in 45 tok · out 410 · decode 17.1 tok/s · prefill 0.5 s · peak RSS 4.11 GiB

rewrite 316 words · 406 text tokens into the denoiser, against 41 for the raw prompt

PE-T2I (9B) · llama.cpp · Q4_K_M (community) · 5.63 GB

387 s

in 2,473 tok · out 934 (623 thinking) · decode 3.0 tok/s · prefill 65.9 s · peak RSS 10.13 GiB

rewrite 348 words · 424 text tokens into the denoiser, against 41 for the raw prompt

The 9B takes 27x as long per rewrite as the 0.8B through llama.cpp: about a sixth of it reading its system prompt, and about half decoding its own reasoning before the first word of the answer. It does fit: this box ran it in 10.1 GiB. What the distillation buys on a CPU is time, not memory headroom.

Measured. Three runs overlapped a wait loop of mine that turned out to be spinning a full core. I re-ran two of them. With the same seed they produced byte-identical text, so only the clock was affected. The table excludes the third, a transformers run that decoded at 0.78 tokens/s against a median of 7.6. What the rest say:

The rewrites themselves, checked against the prompts:

0.8B · llama.cpp0.8B · transformers2B9B
strictly valid JSON7 / 77 / 77 / 77 / 7
quoted strings (g1, g2), as exact quoted units5 / 6: "Demos," gained a comma6 / 66 / 64 / 6: two split across lines, plus six strings it invented
RGBA sentence kept (g5)nononono
g5 background described as"the white background""plain off-white""warm studio-lit""checkerboard transparency preview"
three red cups, two blue bowls (g3)three pairs of red cupstwo red bowls, blue between themkeptkept
words, median342342316348
text tokens into the denoiser, median432441406424

The raw prompts give the denoiser a median of 41 text tokens. Three things in that table matter for the images:

The pairs

Each pair re-renders a gallery prompt from the rewrite with the gallery's exact command. That is Q4_K denoiser, 512², 20 Euler steps on the vendor's schedule, cfg 1.0, seed 42, and --mmap, with only the prompt text changed. Each image sits next to the raw-prompt image the parent published. The gallery renders square, so I held the square and discarded the rewriters' ratio choices. Per-step times are medians over the 20 steps.

Four prompts, chosen before any output: the transparent glass bottle, the conference poster, the bilingual noodle-shop sign, and the cups and bowls. The 0.8B rewrote all four, and the 9B rewrote the glass and the poster. That is six renders, 36 to 49 minutes each, and all six are below.

What I expected, written down before any of this ran:

  1. Neither pocket model will carry the transparency sentence through intact, and the rewritten glass bottle will lose whatever alpha channel the raw prompt's image has. Not one of the 8,797 requests asked for RGBA, and not one of the 1,776 training targets contains the word.
  2. Each denoising step will cost 1.3–1.5x the raw prompt's with a 0.8B rewrite, and more with the 9B's, as the table above derives.
  3. The 9B will think for roughly 500 to 1,200 tokens per prompt, not 1,600. Its own labels put the 10th and 90th percentiles at 500 and 1,175.

One more, added at 13:27 UTC on 23 September, after reading the rewrites and before the 9B's glass bottle rendered:

  1. The 9B's glass bottle will show a painted checkerboard in opaque pixels, with little or no real transparency. Its rewrite asks for "a gray-and-white checkerboard transparency preview background … evenly spaced square tiles in alternating very light gray and off-white". That describes the pattern an image editor displays behind a transparent layer, not a transparent layer.

How each came out is tallied at the end of this section.

The glass bottle

Two panels. Left: a green glass bottle of olive oil with a cork stopper over a grey checkerboard, but the background is solid white and the checkerboard shows only in a thin fringe around the bottle and one small blob at the lower right. Right: the alpha channel, white almost everywhere, with a thin black outline around the bottle.
Raw prompt, from the parent's gallery: the output over a checkerboard, and its alpha channel beside it, white meaning opaque. The background came back opaque white, with only a fringe around the bottle, 1.30% of the pixels, below alpha 32. Q4_K, 512², 20 steps, cfg 1.0, seed 42, on four CPU cores.
Two panels. Left: a dark olive-green glass bottle with a cork stopper standing on a pale grey-white studio backdrop with a soft shadow; no checkerboard shows anywhere. Right: the alpha channel, pure white across the whole frame.
The same command with only the prompt swapped for the 0.8B's rewrite, one sample. There is no transparency left at all: 100.00% of pixels are at alpha 250 or above. The bottle has become dark tinted glass on a studio backdrop, as the rewrite described. Q4_K, 512², 20 steps, cfg 1.0, seed 42, on four CPU cores.

Measured. The rewrite dropped both sentences that ask for transparency, and not only those. Neither 0.8B sample contains "transparent", "transparency", "alpha", "RGBA", "cutout" or "isolated" anywhere. In their place this one wrote "a soft gray drop shadow onto the white background" and "a clean white-to-light-gray surface with soft vignette shading", and the image did exactly that. The raw prompt had already failed at this size, since its background came back opaque white too. So the rewrite did not break a working alpha channel. It removed the fringe that was left, 1.30% of the frame below alpha 32, down to nothing. The first prediction holds, in the least interesting way it could. It also changed the object: the request's "clear glass bottle of green olive oil" became dark tinted glass, following the rewrite's "dark brown or charcoal glass".

The cost came almost entirely after the rewriter:

raw prompt0.8B rewrite
rewrite, 0.8B on llama.cpp—10.6 s
text tokens into the denoiser41351
text encoding (Qwen3-VL, Q4_K_M)5.53 s70.19 s
denoising step, median of 2088.57 s134.59 s
VAE decode41.15 s51.69 s
whole image1,819.53 s2,860.40 s

The rewrite took 10.6 s and the image took 1,041 s longer. Measured: the text encoder alone went from 5.5 s to 70.2 s, because it now prefills 351 tokens instead of 41. Measured: the denoising step rose 1.52x. Reasoned: that is above the 1.29x my cost model gives for this pair and just above the range I predicted. Part of that is noise. The raw gallery's per-step medians run from 88.6 s to 103.9 s across prompts of almost the same length, and this prompt's was the fastest of them, which flatters any ratio taken against it. Over all six pairs this turns out to be the model's largest miss.

Two panels. Left: a clear glass bottle with a cork stopper, full of yellow-green olive oil with sprigs of narrow dark-green leaves suspended in it, standing on a faint grey-and-white checkerboard. Right: the alpha channel, white across the whole frame.
The 9B's rewrite, one sample, same command. The checkerboard is painted: 100.00% of pixels are at alpha 250 or above, so what reads as a transparency preview is opaque grey and white squares. The glass is clear and the oil green, as asked; the leaves in the oil are the rewrite's addition. Q4_K, 512², 20 steps, cfg 1.0, seed 42, on four CPU cores.

Measured. The fourth prediction holds. The rewrite asked for a "gray-and-white checkerboard transparency preview background" and got one, painted in opaque pixels: 100.00% of the frame at alpha 250 or above, the same as the 0.8B's studio backdrop, and less transparency than the raw prompt's 1.30% fringe. The student forgot the instruction. The teacher kept the words "transparency", "alpha" and "cutout" and turned them into a picture of transparency, the thing an image editor shows in place of it. Neither reached a transparent pixel. The teacher did get the object right where the student did not: clear glass, green oil, cork. It also added something nobody asked for, "numerous olive leaves and thin stems" suspended in the oil, and the image drew them.

The 9B's rewrite ran 474 s on four cores. Its 464 text tokens made each step 1.42x the raw prompt's, against 1.40x from the cost model, and the image took 756 s longer. Rewrite and image together, the teacher added 1,231 s to this picture and the student 1,052 s.

The poster

A minimalist cream poster. At the top, bold black sans-serif text reads 'EDGE AI SUMMIT' with 'Bengaluru, 14 November 2026' in smaller type beneath it; along the bottom, three words in a row read 'Talks', 'Workshops', 'Demos'. The middle is empty.
Raw prompt, from the parent's gallery. All five text elements are exact. Q4_K, 512², 20 steps, cfg 1.0, seed 42, on four CPU cores.
A cream poster. At the top, 'EDGE', 'AI' and 'SUMMIT' in large black serif capitals spread across the width; in the middle, 'Bengaluru, 14' on one line, with a stray mark above the vowel after the l, and 'November 2026' on the next; along the bottom, 'Talks Workshops Demos,' in dark navy with a trailing comma. The rest is empty.
The 0.8B's rewrite, one sample, same command. Not text-perfect: 'Demos,' carries a trailing comma, and 'Bengaluru' has a stray mark above the vowel after the l. The date also breaks over two lines. The comma and the line break are both in the rewrite text; the stray mark is the image model's own.

Measured. The raw prompt had every string right. The 0.8B's rewrite kept the strings but wrapped them in layout the user never asked for. The words are spread "with 'EDGE' aligned on the left, 'AI' centered, and 'SUMMIT' aligned on the right". The date gets "a two-line layout". And the last word is quoted as "Demos,". The image model drew all three. It then added an error of its own, a small stray mark above the vowel after the "l" in "Bengaluru", which the rewrite does not contain. The strings themselves were not corrupted. The same letters rendered less exactly inside a prompt five times longer. The middle of the poster is as empty as before. On the one category the students saw eleven examples of, the rewrite made the text worse and the layout no better.

raw prompt0.8B rewrite
rewrite, 0.8B on llama.cpp—12.8 s
text tokens into the denoiser75371
text encoding9.07 s40.92 s
denoising step, median of 2099.83 s134.82 s
whole image2,097.40 s2,809.56 s

The step rose 1.35x, against 1.27x from the cost model. That is inside the predicted 1.3–1.5x range, and above the model. The image took 712 s longer, against a 12.8 s rewrite.

A cream poster. At the top centre, 'EDGE AI' and 'SUMMIT' on two lines in heavy black sans-serif capitals; beneath them, 'Bengaluru, 14 November 2026' in smaller type; a wide empty middle; along the bottom, 'Talks', 'Workshops' and 'Demos' evenly spaced.
The 9B's rewrite, one sample, same command. All five strings are exact, checked at three times zoom. The title breaks over two lines because the rewrite says so; the raw prompt's image kept it on one. Q4_K, 512², 20 steps, cfg 1.0, seed 42, on four CPU cores.

Measured. The teacher's rewrite gave back what the student's took away. Every string is exact, and the only change to the layout is the one its rewrite asked for, the title on two lines. That rewrite was also the shortest of the six, 299 text tokens against the 0.8B's 371, and each step cost 1.05x the raw prompt's against 1.21x from the cost model. That is the model's second-largest miss, in the other direction, and it sits inside the spread of the raw gallery's own per-step medians. On the one prompt where the raw image was already exact, the 9B matched it and did not beat it. What matching it cost was the rewrite: 362 s on four cores, for an image that took 66 s longer than the raw prompt's.

One pair proves nothing about text in general. It does line up with the release's own OCR arm, where the teacher beats no rewriter on rendered text and the 0.8B does not.

The noodle-shop sign

A small shop front at night under a glowing red sign. The sign reads 面馆 in white characters, then a garbled glyph, then 'BAR'; the word 'NOODLE' is missing. Steam drifts out of the lit doorway and the wet street in front reflects the light.
Raw prompt, from the parent's gallery. The sign is above the door, the Chinese and 'BAR' are exact, and 'NOODLE' is a garbled glyph. Steam rises from the doorway. Q4_K, 512², 20 steps, cfg 1.0, seed 42, on four CPU cores.
A shop front at night seen at an angle. The door stands open onto a lit interior; to its right, a vertical black sign on the wall carries, top to bottom, a red 面, a small illegible Latin word, a red 馆 and 'BAR'. Two red bowls sit on a ledge in front of the door, a figure stands at the right edge, and the wet street reflects the sign. There is no steam.
The 0.8B's rewrite, one sample, same command. The sign has moved from above the door to the wall beside it, and the steam is gone. 'NOODLE' is still illegible, now wedged between the two characters. The bowls on the ledge and the figure at the right come from the rewrite, not the request.

Measured. This rewrite does not expand the request. It replaces it with a description of a different photograph. The request puts the sign "above the door"; the rewrite mounts "a vertical black sign … on the exterior wall" to "the right of the counter". The request has "steam rising from the doorway"; in the rewrite, steam survives only in a list of the palette's colours, "warm yellows from the lanterns, steam, and reflections". It then adds "two slender, glossy black ramen bowls" as the foreground subject, "a small dark figure" on the far right, and "additional smaller dark Chinese characters" on the sign. The image model drew the rewrite, not the request: a sign beside the door, no steam, two bowls, a figure. The one thing a rewrite could have fixed is the word the raw image garbled, and it is still garbled.

The rewrite also reads like a caption more than a prompt. It hedges about its own scene, a figure "likely" standing near the door, a puddle "shaped like a small bowl-like basin". That is the register of someone describing an image they are looking at, and the image model takes every hedge as an instruction.

At 500 text tokens this was the longest of the six rewrites. Each step cost 1.33x the raw prompt's, against 1.42x from the cost model, and the image took 754 s longer after an 18.6 s rewrite.

The cups and bowls

On a glossy white surface, three red cups on the left fused into a single three-lobed object with shared walls, and two separate blue bowls on the right, each reflected in the surface.
Raw prompt, from the parent's gallery. Three red cups to the left of two blue bowls, seen from the front: count and placement right, though the three cups have fused into one piece. Q4_K, 512², 20 steps, cfg 1.0, seed 42, on four CPU cores.
Four separate glossy red ceramic cups with white interiors grouped at the front left of a white table, and one large blue bowl with pale rings behind them on the right, in front of blurred dark kitchen cabinets, seen from slightly above.
The 0.8B's rewrite, one sample, same command. Four red cups and one blue bowl, where the request asked for three and two, seen from above rather than from the front. The cups are separate now, which is the one improvement.

Measured. The raw image got the count right. The rewrite could not have: it opens with "three sets of small ceramic bowls", then describes "a pair of red ceramic cups", "a second pair of red cups" and "a third pair", which is six, and "an oval blue glass bowl", which is one. It also moves the camera, "viewed slightly from above", against the request's "photographed from the front". The image model followed the rewrite on the bowl and the camera, and neither the rewrite nor the request on the cups: it drew four. What did improve is that the cups are separate cups with white interiors, where the raw image had fused three into one piece. That is a rendering change, and it has nothing to do with the count. On a prompt that is nothing but a count, the rewrite broke the count.

From 28 text tokens to 432, each step cost 1.45x, against 1.39x from the cost model. The image took 669 s longer after a 14.5 s rewrite.

Six pairs, added up

Every check below is one the request itself states: a count, a string, a position, an alpha value. None of them is a judgement of taste.

the request asked forraw prompt0.8B rewrite9B rewrite
glass: a transparent backgroundno: 1.30% of pixels below alpha 32no: 0.00%no: 0.00%, a painted checkerboard
glass: clear glass, green oil, corkyesno: dark tinted glassyes, plus leaves in the oil
poster: five strings, exact5 of 53 of 55 of 5
sign: above the dooryesno: on the wall beside itnot run
sign: 面馆, NOODLE and BAR legible2 of 32 of 3not run
sign: steam from the doorwayyesnonot run
cups: three red, two blueyes, fusedfour red, one bluenot run
cups: red to the left of blueyesyesnot run
cups: photographed from the frontyesno: from abovenot run

Of the nine checks, the raw prompts pass seven and the 0.8B's rewrites pass one. On every prompt, the rewritten image is less faithful to the request than the raw one. The 9B's rewrites pass two of the three checks they were given, and fail the third along with everyone else.

The step cost, pair by pair:

pairtext tokens, raw to rewritestep, measuredstep, cost model
glass · 0.8B41 to 3511.52x1.29x
poster · 0.8B75 to 3711.35x1.27x
sign · 0.8B49 to 5001.33x1.42x
cups · 0.8B28 to 4321.45x1.39x
glass · 9B41 to 4641.42x1.40x
poster · 9B75 to 2991.05x1.21x

And the four predictions:

  1. Holds. No rewrite, from either student or from the teacher, kept the transparency sentence, and both rewritten bottles came back with no transparent pixel at all. The raw prompt had failed here first, so what the rewrites lost was a 1.30% fringe, not a working alpha channel.
  2. Half holds. The 0.8B's steps cost 1.33x to 1.52x, a mean of 1.41x: three of four inside the predicted range and one just above it. "More with the 9B's" is wrong, and the table above already said so before anything rendered. What sets the step is the rewrite's length, not which model wrote it, and this run's 9B wrote no longer than the 0.8B did, a median of 424 text tokens against 432. The cost model itself held: measured over modelled runs from 0.87 to 1.18 across the six, a mean of 1.02.
  3. Holds. The 9B thought for 477 to 851 tokens, six of seven prompts inside the range and one just under it.
  4. Holds. The checkerboard is in the pixels, and every pixel is opaque.

These are one draw of each rewriter on four prompts, and I do not generalise the counts. What six pairs can show is how a rewrite fails, and all four of the 0.8B's fail the same way. The rewrite replaces the request with a description of a picture, and the image model draws the description. On a CPU that costs 33% to 57% more time per image, 669 s to 1,041 s here, of which the rewriter itself is 11 s to 19 s.

The licence

The pocket models are for research and evaluation, and nothing else.

ComponentLicence
Base weights: Qwen/Qwen3.5-0.8B, Qwen/Qwen3.5-2BApache-2.0
Teacher: Qwen/Qwen-Image-2.1-PE-T2IQwen Research License, non-commercial
The image model they exist to feed: Qwen/Qwen-Image-2.1Qwen Research License, non-commercial
Distillation dataset (teacher outputs)Qwen Research License, by the distributor
The pocket modelsQwen Research License, by the distributor

Measured: six LICENSE files in that chain are byte-identical, SHA-256 8dc973f0…. They are Qwen-Image-2.1's, PE-T2I's, the GitHub repo's, the dataset's and both pocket models'. The agreement grants use "FOR NON-COMMERCIAL PURPOSES ONLY" and defines non-commercial as "for research or evaluation purposes only".

Reasoned, and I am not a lawyer. Three separate things put the students under those terms. The distributor licenses them that way, in the README, the NOTICE and the LICENSE. The teacher outputs they were trained on could only be generated by using a research-licensed model, which is itself only permitted for research or evaluation. And the one thing a pocket rewriter is for is feeding Qwen-Image-2.1, which carries the same restriction. Pairing one with an Apache-2.0 image model such as Qwen-Image-2512 does not change the terms you received the rewriter under.

Their compliance is better than most repackaging I have read. There is a copy of the agreement (§3(a)), a NOTICE with the exact attribution text (§3(c)), a modification statement (§3(b)), and "Built with Qwen" at the top of every card (§4(b)). Three gaps remain:

The take

The distillation is competent, and its paper trail is unusually good. The teacher labels, the filter flags, the training arguments, the prediction files, the evaluation code and its raw scores are all published. That is the only reason I could find the problems. The pocket models do what the text metrics say: they emit the teacher's JSON at the teacher's format reliability, with no system prompt and no thinking, in 453 tokens instead of 1,666. As a replacement for the 9B's output format, they work.

As a replacement for the 9B's effect on pictures, nothing shows it yet, and my own run points the other way. The one image metric in the release that measures anything detects the teacher's gain on rendered text and cannot tell either student from no rewriter at all. The one that was meant to measure everything else picked image A 240 times. On four CPU renders, the 0.8B's rewrites made every picture less faithful to its request: a broken count, two new text errors, a sign moved off the door, and the last of the transparency gone. Each time, the rewrite replaced the request with a description of a picture, and the image model drew the description. The training set offers a reason to expect exactly that: a length cut turned into a curriculum of stickers and logos, with 35 examples of the text-heavy layouts where a rewriter earns its keep.

The teacher is no clean win on a CPU either. It matched the raw prompt's poster, string for string, six minutes of rewriting later, and it answered the transparent bottle with a painted checkerboard. On these four prompts, one draw each, the request as the user typed it was the most faithful prompt and the fastest one.

Two fixes are cheap, and I would make them before the next release. First, give the judge enough tokens to finish, parse its verdict from after its reasoning, and re-score the 240 pairs. That needs no new renders. Second, raise the word ceiling, or truncate long rewrites instead of discarding them, so posters and screens survive into the training set. That costs one more fine-tune, at about 16 USD by their own account.

What would change my mind

6 claims above, and what would falsify each

  1. The published pairwise-judge result measures slot position, not image preference.

    Measured, from eval/score_4arm.json: in 240 of 240 judge.units the winner is arm_a, and the per-arm win counts equal the per-arm A-slot counts exactly. What would narrow this is a re-score of the same 240 pairs with the verdict parsed from the end of the reply, or with the judge's thinking turned off. If that still gives every arm about 50%, then "the judge could not separate the arms" becomes a real finding. My point would shrink to "it had not been measured", and the pocket models would have a second null result rather than a missing one.

  2. On the release's own OCR data, the 9B's rendered-text gain over no rewriter is detectable and neither student's is.

    Measured from ocr.by_request, with an exact two-sided sign test per span: the teacher beats no rewriter 11–2 (p = 0.022), the 0.8B goes 8–7 (p = 1.00) and the 2B goes 6–3 (p = 0.51). This is 29 spans with one seed per arm, and the seeds differ between arms. A re-render of the same 40 requests at several shared seeds, where either student beats no rewriter at p below 0.05, falsifies the second half. The teacher coming out level with no rewriter over more seeds falsifies the first.

  3. The 400-word ceiling made the training set 70% stickers and logos, and that, more than model size, is why the students lose the teacher's text gain.

    The composition is Measured: 1,236 of 1,776 rows, joined on request text. The causal half is Reasoned. A student trained on a category-balanced set, with long rewrites truncated rather than dropped, would test it. If that student shows the same OCR gap on posters and screens, the gap is capacity rather than curriculum and I have the explanation wrong. The 2B does not settle it: 2.5x the parameters, the same curriculum, and 61 words against the 0.8B's 64.

  4. The teacher thinks for about 800 tokens per rewrite, not 1,600; the 1,600 is thinking plus answer.

    Measured: I tokenized the stored thinking text of all 8,797 rows with the shipped tokenizer and got a mean of 805 against a mean gen_tokens of 1,666. The two halves sum to within 0.6% of the total. If the stored thinking field is a trimmed or post-processed copy of what the model generated, my count is low. The 9B arm of the CPU run measured it directly, on the gallery's seven prompts at Q4_K_M: 477 to 851 thinking tokens, median 623. That is one quantisation and one sample per prompt, so it corroborates the count rather than replacing it.

  5. On a runtime without the prefix cache, at 512², a 0.8B rewrite makes each denoising step about 39% more expensive.

    Reasoned, from a cost model with no timing in it: 13d² multiply-accumulates per token per layer, plus block-causal attention pairs, at 1,024 image tokens and 34 against 446 text tokens. The four-core run timed it, Measured: 1.33x to 1.52x across the 0.8B's four pairs, a mean of 1.41x, and measured over modelled from 0.87 to 1.18 across all six pairs. The one ratio below 1.2x, the 9B's poster at 1.05x, came from a 299-token rewrite the model itself put at 1.21x. The same pairs landing below 1.2x or above 1.6x on other hardware, or at other image sizes, would mean the model is missing something that dominates there, and the claim that the denoiser, not the rewriter, is where a rewritten prompt costs time on a CPU should go with it.

  6. The pocket models can be used for research and evaluation only.

    Reasoned from three licences, none of which I am qualified to interpret authoritatively. A statement from Qwen that models trained on PE-T2I's outputs are not bound by the Research License, or a relicensing by ML-Intern-lab that Qwen accepts, would change the first two legs. It would not change the third: every image these rewriters are for is made by a model under that licence.


Sources, all read directly. The two model repos, ML-Intern-lab/Qwen-Image-2.1-PE-T2I-Pocket-0.8B and -2B: README, LICENSE, NOTICE, config.json, chat_template.jinja, training_args.bin (disassembled, never unpickled), and both safetensors headers by range read. The dataset ML-Intern-lab/Qwen-Image-2.1-rewriter-distill at 48e631c: its card, the scripts in code/ that label, filter, train, render and score, labels_full.jsonl, requests_full.jsonl, sft_train.jsonl, the five prediction files, eval/metrics.md, eval/score_4arm.json and four of its contact sheets. The Spaces Qwen-Image-2.1-rewriter-arena and Qwen-Image-2.1-pocket-studio. Qwen's Qwen/Qwen-Image-2.1-PE-T2I: README, system_prompt.txt, chat_template.jinja, config.json, the safetensors index and all four shard headers. The GitHub repo QwenLM/Qwen-Image-2.1 at fb7ae1d, for prompt_rewrite/. The base models Qwen/Qwen3.5-0.8B and Qwen/Qwen3.5-2B, for licence and size. The community GGUF prithivMLmods/Qwen-Image-2.1-PE-T2I-GGUF, for file sizes and its declared parameter count. The diffusers pipeline_qwenimage21.py and stable-diffusion.cpp at 2bb7294, for how each builds the denoiser's text sequence. Word counts split on whitespace; token counts use each model's shipped tokenizer.json. The four figures are the dataset's own contact sheets, served locally with a NOTICE and the licence beside them.

Cite this article

For attribution, please use the following reference or BibTeX:

Satyajit Ghana, "Qwen-Image-2.1 Pocket rewriter: 12x smaller than the 9B, and it made all four test images less faithful to the prompt", ai.thesatyajit.com, September 2026.

bibtex
@misc{ghana2026qwenimage21pocketrewriter,
  author = {Satyajit Ghana},
  title  = {Qwen-Image-2.1 Pocket rewriter: 12x smaller than the 9B, and it made all four test images less faithful to the prompt},
  url    = {https://ai.thesatyajit.com/articles/qwen-image-2-1-pocket-rewriter},
  year   = {2026}
}
share