Downloads · 30 days
401
100% of all-time downloads
LinaTea/Qwen3.5-4B-Fix
Qwen3.5-4B-Fix is a image-text-to-text model from LinaTea. Use it for the image-text-to-text task on the model card, and read the license before you ship it in a product. It is set up for transformers. The card lists the license as apache-2.0.
An unofficial, experimental derivative of Qwen/Qwen3.5-4B-Base, published as Qwen3.5-4B-Fix. The vision tower, tokenizer, chat template and image processor are carried over from the base unchanged; the language model'…
Downloads · 30 days
401
100% of all-time downloads
All-time downloads
401
Public
Parameters
6.9B
16.3 GB on disk
Likes
1
Public
Click a slice to open those files.
.safetensors13.9 GB · 100%
From the Hugging Face model README
An unofficial, experimental derivative of
Qwen/Qwen3.5-4B-Base, published as
Qwen3.5-4B-Fix. The vision tower, tokenizer, chat template and image processor
are carried over from the base unchanged; the language model's dense MLP
blocks are replaced by a 2-expert mixture-of-experts, and LoRA SFT plus GRPO RL
are then applied on the text side only.
Not affiliated with, or endorsed by, the Qwen team.
What the name refers to: the upcycle from the base had dropped the vision tower entirely (a text-only checkpoint whose template still emitted image placeholders), and this build grafts the tower back so the model is genuinely multimodal again. It does not contain the QKV row clipping used elsewhere in this line to cure the family's repetition loops — see Limitations.
| Component | Source | Note |
|---|---|---|
Vision tower (model.visual.*, 297 tensors) | Qwen3.5-4B-Base, verbatim | never trained, never modified |
| Language layers | Qwen3.5-4B-Base, upcycled | dense MLP → 2 experts, top-1 routing, 512-wide shared expert |
| Tokenizer / chat template / image processor | Qwen3.5-4B-Base, verbatim | token ids and rendered prompts verified identical to the base |
| SFT | LoRA r=16, α=32, all-linear, merged | ~17k decontaminated samples, 500 steps |
| RL | GRPO, correctness-only reward, 1497 steps, merged | movement on held-out benchmarks stayed inside noise (±1 pp stderr) |
| MTP head | dropped | the base's mtp.* tensors are not part of this checkpoint |
Scale: 32 layers, hidden 2560, vocab 248320, 2 experts with top-1 routing,
shared_expert_intermediate_size 512, tied embeddings, max_position_embeddings
262144. 6.93B parameters, bfloat16, 13.9 GB in three shards.
Needs transformers >= 5.16 (the version this was built and tested with) and a
torch with the model's custom kernels available.
import torch
from PIL import Image
from transformers import AutoModelForImageTextToText, AutoProcessor
repo = "REPO_ID"
processor = AutoProcessor.from_pretrained(repo)
model = AutoModelForImageTextToText.from_pretrained(repo, dtype=torch.bfloat16,
device_map="auto")
image = Image.open("photo.jpg").convert("RGB")
messages = [{"role": "user", "content": [
{"type": "image", "image": image},
{"type": "text", "text": "Describe this image in one sentence."},
]}]
text = processor.apply_chat_template(messages, tokenize=False,
add_generation_prompt=True,
enable_thinking=False)
inputs = processor(text=[text], images=[image], return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=256, do_sample=False)
print(processor.decode(out[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True))
Several images in one message work the same way: add more {"type": "image", ...}
parts and pass the matching list of PIL images to processor(images=[...]).
Text only, either of these works:
messages = [{"role": "user", "content": "1+1=?"}]
# a) through the processor
inputs = processor.apply_chat_template(messages, tokenize=True, add_generation_prompt=True,
return_dict=True, return_tensors="pt").to(model.device)
# b) through the tokenizer, then the processor
text = processor.tokenizer.apply_chat_template(messages, tokenize=False,
add_generation_prompt=True)
inputs = processor(text=[text], return_tensors="pt").to(model.device)
The chat template pre-opens the thought block, so with the default
enable_thinking=True the generated text starts inside <think> and carries the
closing </think> followed by the answer:
We need answer simple. 2+3=5. Need final concise.
</think>
5
With enable_thinking=False the template emits an empty, already-closed thought
block and the model answers directly. The model is bilingual; prompts in English
or Chinese both work.
The Qwen3.5 chat template carries no default system prompt. With no system
message the rendered prompt contains no system block at all, and the template
raises System message must be at the beginning. if a system message appears
anywhere else. This checkpoint was also fine-tuned without any system message,
so it has no baked-in identity: it will repeat whatever identity it is handed.
That shows up in practice. Served behind a chat app that injects its own prompt, the model answers "who are you?" with the app's wording, e.g. "I am MoE-SFT-Think, an enhanced mixture-of-experts model provided by Chatbox…" — that text came from the client, not from the weights.
If you serve this model yourself, send a system prompt. One that matches what this checkpoint actually is:
你是 Qwen3.5-4B 的开源社区微调模型:语言部分是 2 专家、top-1 路由的 MoE,视觉塔取自基座, 基于 Qwen/Qwen3.5-4B-Base 改造并做过 SFT 与 RL,属于非官方构建,与阿里云官方发布无关。 支持中英文和图片输入。回答要准确、简洁;不确定就直接说明,不要编造身份或能力。
English equivalent:
You are an unofficial community fine-tune of Qwen/Qwen3.5-4B-Base: a 2-expert top-1 MoE language model with the base model's vision tower, further SFT'd and RL'd on text. You are not an official Qwen release. Be concise and accurate, and say when you do not know.
With that prompt in place the model answers "who are you?" with the description above instead of inventing an identity.
For reference, the last official Qwen default system prompt was in Qwen2.5: its template injected
You are Qwen, created by Alibaba Cloud. You are a helpful assistant.
whenever no system message was given. Qwen3 and Qwen3.5 dropped it — the Qwen3.5-4B
instruct template is byte-identical to the base template used here (same 7756-byte
file, sha256 a4aee8af…) and contains no system block and no identity sentence at
all. Qwen3.5's own identity therefore lives in the instruction-tuned weights, not in
any prompt file; this checkpoint, being a fine-tune of the base, has none of it.
llama.cpp builds live in the sibling repository
LinaTea/Qwen3.5-4B-Fix-GGUF:
F16, Q8_0, Q4_0 and MXFP4_MOE of the language model, plus F16 and Q8_0 versions of the
vision encoder. That repository has the exact llama-mtmd-cli / llama-cli command
lines.
This repository holds the original weights only. They are packed in 18 safetensors
shards of at most ~800 MB each (model-00001-of-00018.safetensors … ), which keeps
every file small enough to upload and re-download individually. The tensor set, dtypes
and layout are otherwise unchanged, and AutoModelForImageTextToText.from_pretrained
loads them transparently.
FP8 and NVFP4 are not provided in either repository. llama.cpp has no FP8 or
NVFP4 weight-quantization type: its quantizer rejects FP8, FP8_E4M3, NVFP4 and
MXFP4 outright and only accepts MXFP4_MOE. FP8/NVFP4 checkpoints (for example
Unsloth's Dynamic NVFP4, which runs in vLLM/SGLang on Blackwell) are produced by a
different toolchain — NVIDIA ModelOpt / llm-compressor into compressed-tensors
safetensors — not by GGUF tooling.
generate() builds the whole prompt's attention in one
pass, so practical context length there is set by available VRAM rather than by
this model's 262144 limit.video_grid_thw, but nothing here was validated on
video. The audio tokens have no audio tower in this checkpoint.Apache-2.0, following
Qwen/Qwen3.5-4B-Base; the full
LICENSE is included in this repository. The weights derive from that base
checkpoint: the vision tower and tokenizer are unmodified copies, the language
model was structurally modified (dense → 2-expert MoE) and then fine-tuned as
described above. This is an unofficial community build.