同一个 4B 基座正被推向 3D 场景、自动驾驶和通用助手
2026 年 3 月,Qwen3.5-4B 作为「多模态轻量智能体底座」开源,32 层、2560 隐藏维、26 万 token 上下文。半年多之后,同一份权重在三个完全不同的方向上长出了三种产物:一个把提示词直接编译成可运行的 Three.js 页面,一个挂上感知头和规划专家去开车,还有一个保持原样作为通用助手和 Agent 底座被反复私有化部署。
本文不讨论「哪个方向更性感」,而是把这三条路线的产出物、微调套路和基座代价放在一起拆。所有关于 3D-Coder 的判断都基于本仓库的config.json、chat_template.jinja、generation_config.json和权重索引model.safetensors.index.json,可以直接对照复现。
三条分叉路线:产出物形态决定了微调方式
先把三个产物摆在一张表里,差异一目了然:
| 维度 | Qwen3.5-4B-3D-Coder | Qwen-Drive-1.0-4B | Qwen3.5-4B 通用助手 |
|---|---|---|---|
| 直接产出 | 单个自包含 HTML 文件(Three.js 0.160.0) | 结构化问答 + 50 路点轨迹 | 对话、工具调用、视觉问答 |
| 是否新增结构 | 无,纯监督微调 | BEV 感知头 + 约 1.1B 规划专家 | 无 |
| 新增参数 | 0 | 感知头 + 两个规划专家 | 0 |
| 训练数据规模 | 4146 个场景样例(3933 训练 / 213 验证) | 公开驾驶数据清洗至 3.09M,规划样本约 2.83M | 预训练语料 |
| 许可 | Apache-2.0(数据集 MIT) | Apache-2.0 | Apache-2.0 |
最值得注意的是:三条路线的分叉点都不在主干结构上。3D-Coder 一个 token 的结构都没改,权重索引里 723 个键,model.language_model.*426 个、model.visual.*297 个,和基座的多模态形态完全对应——它甚至没有裁掉视觉塔。Qwen-Drive 则是「按住主干、把 3D 和轨迹接到外面」,用外挂头把语言 token 换成几何张量。
换句话说,4B 这个体量已经小到不适合再拆:任何结构改动都会直接吃掉本就紧张的表征预算。可行的窄化手段只剩两个——约束输出契约,或者外挂专用解码头。
套路一:把「输出契约」写进提示词,而不是写进权重
3D-Coder 最反直觉的地方是,它对输出格式的强约束没有落在训练目标里,而是落在系统提示词里。README.md 给出的系统提示词只有四行:
Use only the Three.js core ES module from https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.module.min.js. Do not import addons or legacy examples/js paths; implement any camera controls directly inside the HTML.这四行同时干掉三类失败:锁死版本,避免 CDN 上three的 breaking change 让生成结果在半年后失效;禁用 addons,避免模型写出OrbitControls这类需要额外模块解析的 import;要求相机控制内联,把交互闭环塞回单文件。
模型侧对应的训练目标也很明确——数据集里的每条样本都是「提示词 + 完整 thinking trace + 完整 HTML/JS 响应 + 复杂度分级」,产出物永远是一个能双击打开就跑的文件。这种约束让 4B 的容量被集中投放在「空间布局 + 几何拼装 + 材质光照」上,而不是分散到工程脚手架。
从生成结果看,这套约定确实被内化了。仓库画廊里的十张截图跨越了风格化建筑、日式庭园、体素环境、家具、机械件五类题材,其中 LGA 3647 插座这种带触点阵列和扣具结构的工业件,是整个集合里对「部件层级」要求最高的一类:
套路二:分阶段冻结,把「通用能力」当预算来管
Qwen-Drive-1.0 的四阶段训练是这条线上最值得抄的工程细节:第一段只训新初始化的感知头,主干冻结;第二段解冻视觉编码器和语言模型,让感知损失回传到预训练 ViT,nuScenes 检测 mAP 和地图 mIoU 分别涨了 10.46 和 9.84;第三段重新冻结主干,只训规划专家得到 SFT 版;第四段仍只动规划专家,用组内相对优势做强化学习。
代价被控制得非常干净:知识推理识别十项均分 66.41,底座是 67.40,差不到 1 分;空间理解五项均分 53.96,反而略高于底座的 52.99。这个交换比之所以成立,核心是**「主干只在需要挤出几何结构的那一段解冻」**——如果从头到尾全量微调,通用能力大概率保不住。
同一条原则在 3D-Coder 上表现为另一种形式:它保留了完整的多模态主干(包括 297 个视觉塔权重键),却只用一个领域数据集做监督微调。这是「不追求能力替换,只追求输出分布偏移」的做法。
顺带说一个只有读配置才能发现的细节。config.json 的text_config里写着"mtp_num_hidden_layers": 1,也就是基座自带一层多 token 预测头;但model.safetensors.index.json的weight_map里不存在任何mtp.*键。这与社区反复报告的现象对得上:LM Studio 默认开启 MTP(多 token 预测)时,模型会出现输出乱码、截断或无响应,而关掉就正常。README 里那条加粗警告——「disable multi-token prediction (MTP)」——本质上不是玄学调参,而是配置声明与权重实际内容不一致时,推理端的投机解码路径走空了。这也解释了为什么 Q4_K_M 和 Q8_0 表现一致:问题与量化格式无关。
一个 4B 基座的真实体质
把 config.json 摊开看,这个基座的取舍非常清晰:
- 32 层,隐藏维 2560,FFN 9216,注意力头 16 个、KV 头 4 个,head_dim 256;
- 线性注意力与全注意力按 3:1 交替:
layer_types里每 4 层出现一次full_attention(第 3、7、11…31 层),其余 24 层是linear_attention,卷积核linear_conv_kernel_dim: 4; - mRoPE:
mrope_interleaved: true,mrope_section: [11, 11, 10],partial_rotary_factor: 0.25,rope_theta: 1e7; - 上下文 262144,词表 248320,
tie_word_embeddings: true(所以索引里没有独立lm_head); - 多模态塔 24 层、hidden 1024、patch 16、spatial_merge 2,图像与视频走同一套 token(
image_token_id: 248056/video_token_id: 248057)。
权重索引给出的总量是4,539,265,536 参数、9,078,531,072 字节(约 9.08 GB),切成 4 个 shard。这就是 FP16 版本要占的显存下限,再叠 KV Cache 和视觉塔的激活。
对 3D 生成这个任务来说,几个参数是直接相关的:3:1 的线性注意力让 26 万上下文的分块预填充成本可控,而单文件 Three.js 场景动辄几千行 HTML,长上下文的实际收益是「不必在生成到一半时遗忘前面的变量声明」;tie_word_embeddings: true把 4.8 亿参数的词表矩阵复用了一份,这在 4B 体量下是一个不小的节省。
两个 GGUF 的体积也对得上:Q4_K_M 是 2,708,804,096 字节(约 2.52 GiB),Q8_0 是 4,482,402,816 字节(约 4.17 GiB)。前者能在 8 GB 内存机器上带上下文跑起来,后者把精度损失压到接近 FP16,代价是翻倍的驻留内存。
生成参数:默认值与推荐值几乎重合
generation_config.json 里的默认值是temperature 0.6 / top_k 20 / top_p 0.95 / repetition_penalty 1.0,do_sample为真,eos_token_id同时接受248046(<|im_end|>)和248044(<|endoftext|>)。
README 推荐区间是temperature 0.6–0.8 / top_p 0.90–0.95 / top_k 20–40 / repeat penalty 1.0——也就是说默认值正好落在推荐区间的下沿。对代码生成任务来说这个取值是合理的:温度再高,几何布局的数值参数(坐标、缩放、旋转)会先崩,而不是风格先变。
模板侧还有一个能省 token 的开关。chat_template.jinja 在add_generation_prompt分支里判断enable_thinking:
{%- if enable_thinking is defined and enable_thinking is false %} {{- '<think>\n\n</think>\n\n' }} {%- else %} {{- '<think>\n' }} {%- endif %}关掉思考模式时,模板仍会写入一对空的think标签,而不是完全跳过——这保证了 prompt 结构与训练分布一致。数据集里保留了完整 thinking trace,说明思考链是这个模型的训练目标之一;但在 3D 场景这种「结构明确、路径依赖少」的任务上,直接关掉思考往往更快,代价是复杂场景的一次成型率下降。
选基座时真正该权衡的三件事
看完三条路线,选基座的判断标准其实被重新定义了。
第一,许可链路是否干净。3D-Coder 的模型权重是 Apache-2.0,训练数据集ccore/ThreeJS-3D-Scenes是 MIT。这意味着它可以直接进商业产品,也可以做二次微调后再分发。相比之下,很多领域微调模型的权重许可与底层数据许可互相打架,商用前要逐层追溯。这一条在小模型上尤其关键,因为小模型的典型买家正是「想私有化部署但法务预算有限」的团队。
第二,部署形态与算子支持度。FP16 要 9 GB 显存;GGUF 是 2.5 GB / 4.2 GB;走 vLLM 这类服务端框架则需要框架侧对新架构(线性注意力、mRoPE、MTP)有原生实现。社区记录显示 vLLM v0.17.0 已对 Qwen3.5 全系做了 RoPE 重算与 3D Attention Mask 的原生支持,但这类支持通常滞后于基座发布。选基座时,推理栈怎么跑比跑分多少更能决定项目能不能上线。
第三,通用能力预算够不够花。Qwen-Drive 的经验是:只要分阶段冻结,4B 可以在吃掉大量领域数据后仍保住 99% 的通用知识分。但这有个前提——它保留的是基座原有的通用能力,而不是新增。如果你的场景需要模型同时做代码生成和驾驶推理,指望一个 4B 同时扛住两条窄域是不现实的;反过来,如果你的场景只需要一条窄域 + 一点兜底对话,4B 的余量是够的。
下一批可能出现的方向
从仓库和情报里能推出来的方向,大致有三个,都有明确的证据支撑而非猜测。
一是从「页面」走向「资产」。当前 3D-Coder 的产出契约是「自包含 HTML」。数据集里同时提供可选的previews渲染图,说明作者已经在做「生成结果 → 参考图」的闭环。一旦把这个闭环反过来用(图 → 结构化场景描述 → 代码),输出的就不只是给人看的页面,而是可以进引擎的场景图。这条路的门槛不在模型,而在场景表示的统一。
二是 4B 从「生成者」退到「校验者」。数据集带复杂度分级,且已知问题集中在「变量名重复」这类局部一致性瑕疵——这恰好是另一个更小的模型或规则引擎能捕获的。用 4B 生成、用更轻的判别器或确定性检查器兜底,比强行把 4B 的一次成型率推到 100% 更经济。
三是仿真与回放侧的复用。Qwen-Drive 已把「公开数据 + 分阶段冻结 + 外挂头」这条路走通,且明确说明规划样本仅使用公开来源构建。这套方法论可以平移:任何需要「语言模型 + 几何输出」的场景——机器人操作序列、CAD 参数、场景布局——都能复用同样的四阶段骨架,而不必重新发明训练流程。
十条截图里最能说明「同一基座、不同窄化」的,其实是这张 Kōrin 庭园:它要求模型同时处理水体的反射材质、植被的重复结构、石组的非规则排布和庭园的轴对齐布局。这些都不是「知识」,而是空间约束的遵守能力——一条 4B 模型通过 4146 个场景样例就能学到的东西。
复现清单
拉取完整权重(仓库使用 Git LFS,images/*.png、*.gguf、*.safetensors均为 LFS 对象):
git lfs install git clone <仓库地址>用 Transformers 加载 FP16(索引model.safetensors.index.json声明的架构类为Qwen3_5ForConditionalGeneration,transformers_version为5.20.2):
import torch from transformers import AutoProcessor, Qwen3_5ForConditionalGeneration model = Qwen3_5ForConditionalGeneration.from_pretrained( ".", dtype=torch.float16, device_map="auto" ) processor = AutoProcessor.from_pretrained(".")本地 GGUF 部署三件事:关掉 MTP、用temperature 0.6–0.8 / top_p 0.90–0.95 / top_k 20–40 / repeat penalty 1.0、把 README 里那段四行系统提示词原样贴上。剩下的交给提示词结构:主题 + 空间布局 + 渲染风格,三段写清,一次成型的概率明显高于长段散文化描述。
对想复用这套方法的人,最值得抄的不是提示词,而是两件事:用系统提示词锁死依赖版本与禁用路径,让输出可复现;用分阶段冻结控制通用能力的损耗,让窄化不变成偏科。这两条与参数规模无关,4B 能这么干,更小的模型也能。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考