--- license: apache-2.0 tags: - text-encoder - comfyui - moss-image - qwen3.5 - projection - distillation - image-generation base_model: - Qwen/Qwen3.5-0.8B - Qwen/Qwen3.5-2B - Qwen/Qwen3.5-4B language: - zh - en --- # MOSS-Image 小文本编码器适配器 用 **Qwen3.5-0.8B / 2B / 4B** 替代 MOSS-Image 的 **Qwen3.5-9B** 文本编码器。 学生模型完全冻结,只学一个逐 token 的线性投影,把隐状态映射到 DiT 期望的 4096 维。 配套代码与节点:[moss-image-mini-encoder](https://github.com/1cyberlangke1/moss-image-mini-encoder)。 完整的 8 档 × 10 条测试矩阵(含全部出图、余弦矩阵、耗时)见 [docs/benchmark.md](https://github.com/1cyberlangke1/moss-image-mini-encoder/blob/main/docs/benchmark.md)。 ## 学生权重(已量化,在 `weights/`) 这些 w4a8 / int8 文件是用 ComfyUI 的 `comfy_kitchen` 量化器从官方 Qwen3.5 权重转出来的, 格式与 ComfyUI 的 `asym_w4a8_int8` / `int8_tensorwise` 一致,直接放进 `ComfyUI/models/text_encoders/` 就能用,**不需要自己再量化**。 | 文件 | 基座 | 格式 | 体积 | 配套适配器 | |---|---|---|---:|---| | `weights/qwen3.5-0.8b-int8.safetensors` | Qwen3.5-0.8B | int8 | 1.17 GB | `qwen3.5-0.8b_int8_linear.safetensors` | | `weights/qwen3.5-0.8b-w4a8.safetensors` | Qwen3.5-0.8B | w4a8 | 0.96 GB | `qwen3.5-0.8b_w4a8_linear.safetensors` | | `weights/qwen3.5-2b-int8.safetensors` | Qwen3.5-2B | int8 | 2.97 GB | `qwen3.5-2b_int8_linear.safetensors` | | `weights/qwen3.5-2b-w4a8.safetensors` | Qwen3.5-2B | w4a8 | 2.38 GB | `qwen3.5-2b_w4a8_linear.safetensors` | | `weights/qwen3.5-4b-w4a8.safetensors` | Qwen3.5-4B | w4a8 | 3.84 GB | `qwen3.5-4b_w4a8_linear.safetensors` | bf16 档直接用官方 `Qwen/Qwen3.5-0.8B` / `Qwen/Qwen3.5-2B` 原版权重,不需要转换。 量化文件由本项目的 `src/scripts/quantize_encoder.py` 生成,基座权重遵循其原始许可。 ## 文件 | 文件 | 学生 | 量化 | 训练集 cos | relL2 | |---|---|---|---|---:| | `qwen3.5-0.8b_linear.safetensors` | 0.8B | bf16 | 0.85192 | 0.5237 | | `qwen3.5-0.8b_int8_linear.safetensors` | 0.8B | int8 | 0.85169 | 0.5241 | | `qwen3.5-0.8b_w4a8_linear.safetensors` | 0.8B | w4a8 | 0.84997 | 0.5268 | | `qwen3.5-2b_linear.safetensors` | 2B | bf16 | 0.87478 | 0.4846 | | `qwen3.5-2b_int8_linear.safetensors` | 2B | int8 | 0.87474 | 0.4846 | | `qwen3.5-2b_w4a8_linear.safetensors` | 2B | w4a8 | 0.87326 | 0.4873 | | `qwen3.5-4b_w4a8_linear.safetensors` | 4B | w4a8 | 0.89692 | 0.4422 | 训练集 cos 是在 6,374,951 token 的验证集上逐 token 评估的均值。 **适配器必须与学生尺寸和量化格式同时匹配**。同一学生的 bf16 与 w4a8 权重会产出不同特征, 用错适配器时条件向量只能对上 0.9927,出图肉眼可见掉细节,不要交叉使用。 ## 用法 1. 下载对应的 Qwen3.5 学生权重,放到 `ComfyUI/models/text_encoders/` 2. 本仓库的 `.safetensors`(一个文件即完整适配器)放到 `ComfyUI/models/moss_encoder_adapters/` 3. 节点: ``` MossCLIPLoader(学生权重, moss_image, adapter) → CLIPTextEncode → KSampler ``` `adapter` 选 `none` 时不投影,等价于官方 `CLIPLoader`——9B 走这条。 ## 实测:同一组提示,四档出图 固定 seed 42、4 步 LoRA、cfg 1、1024×1024。左到右:9B / 4B w4a8 / 2B w4a8 / 0.8B bf16。 **只给角色名「蔚蓝档案的鬼方カヨコ蹲在巷子里喂流浪猫」** ![](images/prompt-02.jpg) - 9B:白发黑挑染、红瞳、双角、光环、黑外套——角色对 - 4B:有角和光环,但蓝瞳、无挑染——落进「蔚蓝档案」这个域,认错人 - 2B:白发蓝瞳的普通少女,没有角也没有光环,与 0.8B 的区别只是换了发色 - 0.8B:金发蓝眼、白衬衫蓝裙——完全没识别,落回通用萌系 **只给品牌名「蜜雪冰城的雪王站在店门口」** ![](images/prompt-04.jpg) - 9B:招牌「蜜雪冰城」、白胖雪人、金冠、红披风、冰淇淋火炬,身上还有竖排「蜜雪冰城」,全对 - 4B:以上要素齐全,只少了身上的竖排字 - 2B:招牌与金冠正确,但雪人变成了真的雪堆、披风变成红围巾、没有火炬 - 0.8B:招牌写成「𠳨雪冰城」,雪王被画成穿龙袍的白胡子老者 ## 实测:条件向量与耗时 对 9B 条件逐 token 计算,10 条中英混合提示(含一条 627 token 的长 JSON): | 档位 | cos 均值 | cos 最小 | relL2 | 纯编码 30/326 tok | 端到端热态 | |---|---:|---:|---:|---:|---:| | 9B w4a8 | 1.0000 | 1.0000 | 0.0000 | 87.0 / 130.7 ms | 33.1 s | | 4B w4a8 | 0.8638 | 0.8099 | 0.537 | 87.9 / 86.9 ms | 23.6 s | | 2B bf16 | 0.8406 | 0.7924 | 0.697 | 43.1 / 44.8 ms | 21.7 s | | 2B w4a8 | 0.8372 | 0.7862 | 0.720 | 72.9 / 71.1 ms | 20.4 s | | 0.8B bf16 | 0.8149 | 0.7640 | 0.830 | 47.3 / 43.4 ms | 20.3 s | | 0.8B w4a8 | 0.8136 | 0.7633 | 0.780 | 91.3 / 76.8 ms | 20.9 s | - **纯编码**远小于端到端:编码只占 20~33 秒里的 0.2~0.5%,其余是 4 步采样与每张图的模型装卸 - **w4a8 比 bf16 慢**(要反量化),它省的是显存:0.8B 958 MB / 2B 2.4 GB / 4B 3.8 GB - 量化对余弦几乎没有影响:同尺寸下 int8 与 bf16 差 0.0001~0.0003,w4a8 差 0.0013~0.0034 ## 是什么、不是什么 - **是**:把 6 个中间层的隐状态沿特征轴拼起来(0.8B 得 6144 维、2B 12288、4B 15360), 做 `((h-mean)/std) @ W * std_y + mean_y`,逐 token 独立映射 - **不是**:不是微调。学生权重一个字节都没改,只有这一份 48~120 MB 的矩阵 - 训练数据 38,496 条提示词,含中英 caption、tag、MOSS layout JSON、负面提示词 - 抽头固定为第 2 / 4 / 8 / 12 / 16 层与最后一层,已写进适配器 metadata ## 已知限制 - **专名绑定随尺寸退化**:9B 画得对;4B 只学到「属于哪个作品」;0.8B 认不出。 - **0.8B 在长结构化提示里会单字错**:627 token 的 layout JSON 里,`捐` 被系统性画成 `抬`, 同图出现 5 次。短提示不受影响。4B 无此问题。 - 训练集 P99 长度 937 token、最长 3235;再长的提示属于分布外。 - 只适用于 MOSS-Image,输出固定 4096 维。 ## 致谢 - [ComfyUI-ClipProj](https://github.com/nicolab28/ComfyUI-ClipProj) — 投影层训练方法 - [moss-image-smaller-encoder](https://github.com/bakapotatolord/moss-image-smaller-encoder) — 适配器格式 - [MOSS-Image](https://github.com/OpenMOSS/MOSS-Image) — 提示词模板与 layout 格式 - [Qwen3.5](https://huggingface.co/Qwen) — 基座模型:[0.8B](https://huggingface.co/Qwen/Qwen3.5-0.8B) / [2B](https://huggingface.co/Qwen/Qwen3.5-2B) / [4B](https://huggingface.co/Qwen/Qwen3.5-4B) / [9B](https://huggingface.co/Qwen/Qwen3.5-9B)