体素、机械、建筑:同一模型三类题材的生成质量差异与成因
Qwen3.5-4B-3D-Coder 是一个基于 Qwen3.5-4B 的独立微调模型,不输出网格、点云或 glTF,而是直接吐出一个自包含的 HTML 文件:内联 CSS、内联着色器参数、只从 cdnjs 引入 Three.js 0.160.0 核心 ES 模块,打开浏览器就能拖动视角。它的官方画廊一共十张图,覆盖体素环境、幻想建筑、东方园林、家具手作与硬件机械。把这些图逐张放在一起看,会得到一个相当反直觉的结论:同一个 4B 模型、同一套提示词范式,在"体素"题材上几乎不犯错,在"机械"题材上却明显降级为剪影级表达。
这篇文章不谈跑分,只做三件事:把十张官方作品按题材重新归档做横向对照,从几何与语义两个维度解释这种"偏科"的技术成因,最后给出按题材选提示词与选部署参数的可操作建议。
一、三类题材的完成度横向对照
先把画廊的十张图按"几何表达方式"而不是按"题材名字"重新分类。这一步很关键,因为 README 里的四分类(建筑园林 / 体素 / 家具 / 机械)是按内容分的,而模型的偏科是按几何可压缩性分的。
| 作品 | 实际几何表达 | 构件组织 | 完成度观察 |
|---|---|---|---|
| Voxel launch site | 纯体素,全部方盒 | 网格对齐、模块复用 | 极高:围栏、斜撑、警示锥、地台砖缝全部到位 |
| Dragonrider Aerie | 纯体素,分层堆叠 | 崖壁分层 + 折返楼梯 | 极高:甚至自带四个机位切换按钮 |
| Sunset Village | 体素建筑 + 平滑地形 | 十余栋半木结构房屋环绕广场 | 高:鸟瞰布局有序,点光照亮窗格 |
| Pelican Bike No.07 | 体素化机械 | 车轮由方块拼圆 | 中高:造型可读,但传动部件被省略 |
| Sakura Temple Garden | 低多边形建筑 + 球簇植被 | 主殿、鸟居、石灯笼、木桥、池塘 | 中高:构图最佳,局部交接有漂移 |
| Kōrin Garden | 低多边形建筑 | 多层塔 + 围栏 + 汀步 | 中:右侧栏杆立柱与木桥接地关系明显失真 |
| Bow-Front Secretary Desk | 基础几何体拼装 | 桌体 + 抽屉 + 椅 | 中:柜体尺度成立,把手与桌面小物退化为剪影 |
| The Bookbinding Bench | 基础几何体拼装 | 室内盒 + 长桌 + 道具 | 中:氛围光到位,道具靠圆柱与方盒近似 |
| LGA 3647 Socket | 基础几何体 + 装饰曲线 | PCB、承载框、凸轮压杆 | 低:针脚阵列完全缺失,只剩一块暗色平面 |
| Sakura Bonsai | 球簇 + 曲枝近似 | 单株植物 | 中:花瓣粒子加分,枝干分叉靠随机偏移 |
最能说明问题的对照是两张图。下面这张体素发射场里,火箭由阶梯状方块逐层收窄,四根交叉斜撑把塔架和地面锚住,围栏是"柱 + 横杆"的循环实例,地面砖缝与混凝土地台严格对齐网格:
而下面这张被社区文章描述为"针脚阵列与固定结构被还原得相当工整"的 LGA 3647 插槽,真实情况要冷静得多:绿色 PCB 上的走线是一条条手工摆出的样条曲线,承载框、红色凸轮压杆、"CAM LEVER RETENTION"标注都在,但承载框中间本该由上千根针脚构成的那个区域,被一块没有任何几何细节的暗色平面替代了。模型学会了产品棚拍的全部形式语言——深色背景、三点布光、角标标签、Reset view 按钮——却跳过了这件物品之所以是这件物品的那一层几何:
这不是渲染问题,是语义下沉问题。同样是"密集重复的微小构件",体素场景里的围栏柱、砖缝、块状树木都被老老实实循环生成了出来;到了 CPU 插槽这一层,模型选择了"用一个大平面概括"这种成本最低的表达。差异出在哪里,是下一节要拆的核心。
二、两种难度:几何规则性 vs 语义复杂度
把"生成一个 3D 场景"拆成代码层面的动作,本质是三个量在博弈:图元的种类数、实例的数量、每个实例之间的约束强度。
第一层难度是几何规则性,它决定模型能否用少量代码覆盖大量构件。体素题材的极致优势在于:整个场景只有一个图元BoxGeometry,材质只有一套MeshLambertMaterial或MeshStandardMaterial的调色板,空间关系可以直接映射到整数网格坐标,于是代码结构天然收敛为"定义调色板 → 写一个addBlock(x,y,z,color)辅助函数 → 用循环和数组铺数据"。这类代码的 token 重复度高、分支熵低,4B 模型完全扛得住。
第二层难度是语义复杂度,它决定模型是否理解"部件为什么必须长成那样"。机械题材是这一层的地狱模式:
- 自行车链条必须首尾闭合、绕过牙盘与飞轮,辐条必须同时连接轮毂与轮圈,这些是功能性约束,不是外观约束;
- LGA 插槽的针脚阵列不是装饰,它的存在本身定义了"插槽"这个类别;
- 家具的抽屉必须能被理解为一个可以沿 Z 轴平移的单元,抽屉面板、导轨、拉手之间存在父子关系。
体素场景可以"看起来乱但语义全对",机械场景则是"看起来还行但语义全错"。模型在第二类任务上缺失的不是渲染能力,而是部件级的功能先验。
还有一种更隐蔽的难度:交接面。建筑题材恰好卡在两者之间——单体构件的语义很弱(一堵墙只要是个长方体就行),但构件之间的交接很强(屋顶要压在墙上、桥面要搭在岸上、灯笼要立在地上)。回看 Kōrin Garden,右侧那排围栏立柱孤零零立在草地边缘、既没有横杆也没有接地,木桥的一端悬在斜坡上,石灯笼的位置像是均匀随机撒出来的——这些都是单个构件全部正确、构件之间的关系崩了的典型症状:
对比之下,Sakura Temple Garden 是建筑类里完成度最高的一张:主殿、鸟居、石灯笼、木桥、池塘的层次关系读得出来,飘落花瓣用实例化粒子做出了氛围。但放大看,池边石灯笼直接立在水中、汀步散乱无序,说明"关系"这一层依然是概率性的:
如果给三类题材排一个难度阶梯,它并不等于"构件数量"的排序,而更接近下面这个乘积:
实际失败概率 ≈ 图元种类数 × 语义约束强度 × 交接面数量 / 可复用代码的比例体素题材右端的分母极大——一个addBlock就能覆盖成百上千个构件,所以即使构件总数很高(Sunset Village 有十几栋房子、几十扇窗、多盏路灯),失败概率依然很低。机械题材的分母极小——每个零件几乎都是一次性的new THREE.Group()加若干次位移旋转,代码无法复用,错误只能靠模型对结构的功能直觉去兜底。
三、偏科背后的三个成因推测
以下三条并非官方结论,而是从仓库里可核查的配置、数据集描述与官方画廊现象反推出来的工程解释。
成因一:训练分布的形状。数据集 ccore/ThreeJS-3D-Scenes 共 4,146 个样本(3,933 训练 / 213 验证),每个样本包含提示词、完整思考轨迹、完整 HTML/JS 响应与"复杂度等级"标签,MIT 协议公开。这个规模对一个专精微调来说是"够用但不宽裕",而 213 条验证集意味着每一类题材能分到的验证信号只有几十条。更重要的是,体素题材在这个分布里天然是"高样本效率"的:一段三四十行的调色板 + 循环代码就能产出一个看起来内容极其丰富的体素世界,同一份训练预算能覆盖更多视觉变体。机械类则相反,每条样本都要把大量 token 花在一次性零件的坐标计算上,模型能从中学到的"可迁移模式"很少,于是它学到的其实是机械产品的镜头语言(暗背景、棚拍光、角标),而不是机械结构本身。
成因二:工具链与题材的同构性。README 规定的系统提示词把模型的输出空间压得很窄——只允许核心 ES 模块,禁止 addons 与旧版examples/js路径,相机控制必须手写:
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.这条约束的隐含后果是:模型失去了所有高级几何能力——没有OrbitControls、没有GLTFLoader、没有后处理、没有LatheGeometry之外的建模辅助(更别说 CSG)。它手里只剩Box、Sphere、Cylinder、Cone、Torus、Plane这一小组图元和InstancedMesh。而这套受限工具箱恰好与"体素美学"完全同构:体素风格的定义就是"用可见立方块搭出一切",工具的短板在体素语境里反而变成了风格承诺。同样的短板放到机械语境里就暴露无遗——没有布尔运算就做不出针脚孔阵列,没有样条扫掠就做不出链条,模型只能退回到"一个大平面"。
成因三:4B 参数下的"注意力预算"分配。生成这种自包含 HTML 时,模型需要同时维持三层状态:全局调色板与光照约定、空间坐标系、以及当前正在写的构件的父子变换。层数越深、构件越一次性,状态越容易在长文件后半段漂移。README 里点明的已知 bug——"观察到的错误大多是重复变量名,而不是结构性错误"——正是这种漂移的代码层显影:一个机械场景要声明几十个Group,在 4B 模型的短时记忆里,const frame被写第二遍的概率远高于体素场景里那几个共享的blocks数组。此外config.json显示这是qwen3_5混合注意力架构,32 层里每 4 层才有一层 full attention(full_attention_interval: 4,实际为 24 层 linear attention + 8 层 full attention),256K 上下文与 8 层全局注意力足以容纳长文件,但容量够不等于分配得好。
顺带一个容易被忽略的观察:Sunset Village 的标题卡是葡萄牙语,按钮写着"Pausar movimento"和"Resetar vista";Sakura Bonsai 的副标题也是葡萄牙语。这说明在提示词未显式约束语言时,模型会从训练分布里自由抽取界面文案的语种。对工程化落地来说这是一个必须显式约束的变量,而不是彩蛋。
四、按题材选提示词与参数
基于上面的分析,三类题材应该走三套不同的写法,而不是套同一个模板。
体素题材:直接吃满模型的强项。README 里两个官方提示词(大象康复栖息地、海蚀柱龙骑士巢穴)都遵循同一个结构:主题 → 空间关系清单 → 渲染风格锚点,最后一句固定为"由可见立方块构成的刻意体素模型,层次清晰、轮廓可读、空间关系扎实"。这句话就是体素分支的"开关",它同时锁定了图元(方块)、配色(有限调色板)和相机语义(等距/鸟瞰)。保留了这句锚点,模型几乎必然给出一个可运行、可拖拽的完整场景,Dragonrider Aerie 甚至自动附带了 Isometric / Aerial / Shore / Hatchery 四个机位按钮:
建筑题材:把"关系"写进提示词,而不是指望模型自己推。建筑类的失败几乎全部发生在交接面,所以提示词里要显式给出约束句,例如"桥的两端必须落在岸边的石阶上""所有立灯与围栏立柱必须与地面网格对齐、不得悬空"。这类硬约束在体素语境里是冗余的(网格自身就保证了),在建筑语境里是必需的。
机械题材:拆成两阶段,先清单后代码。一次性让模型写完一台机械,等于让它一边规划拓扑一边算坐标。更稳的做法是先让它输出部件树(每个部件的名称、父节点、图元、大致尺寸),确认拓扑无误后再要求"按此清单生成代码",并在提示词中明确"链条件数 ≥ 40、每根辐条独立实例化、针脚区域用InstancedMesh铺满而不是贴一个平面"。后者是把本文第二节的诊断直接转成工程补丁。
参数与部署侧的三条硬性事实,都可在仓库文件中核对:
- 采样参数以 generation_config.json 的默认值为基线:
temperature 0.6、top_p 0.95、top_k 20、repetition_penalty 1.0;README.md 给出的可调区间是温度 0.6–0.8、Top P 0.90–0.95、Top K 20–40。机械类的拓扑敏感度更高,建议压在下界(温度 0.6),体素类可以用上界换取更多布局变化。命令行部署时对应--temp 0.6 --top-k 20 --top-p 0.95 --repeat-penalty 1.0,注意repetition_penalty保持 1.0 不要上调,这类代码里大量重复的坐标数字一旦被惩罚,几何会直接塌掉。 - LM Studio 必须关闭 MTP。这是社区反馈最集中的坑:
config.json里mtp_num_hidden_layers: 1表明基座带有一个单层多 token 预测头,而 LM Studio 默认开启该选项,导致输出乱码、截断或无响应。这与量化格式无关,Q4_K_M 与 Q8_0 都受影响。 - 量化选择上,Q4_K_M 约 2.5 GiB、Q8_0 约 4.2 GiB;FP16 全量权重合计约 9.08 GB、总参数 4,539,265,536(见 model.safetensors.index.json)。题材难度与量化损失是叠加的:体素类在 Q4_K_M 下几乎无损,机械类建议直接上 Q8_0 或 FP16,因为丢的那点精度往往正落在长距离的坐标引用上。
最后值得强调的一个背景:这个项目的十张画廊图取自 10 月 27 日更新的检查点,作者明确说明该版本的 one-shot 成功率与整体场景质量都有明显提升,且仍有部分场景需要重试。README 里给出的三省对比图恰好展示了这种收敛过程——同一个罗马场景在 25、26、27 三个预览版中的逐日演变:
所以"体素强、机械弱"不是这个模型的固定属性,而是一条当前检查点在难度轴上的截面。判断一个 4B 级 3D 代码模型是否真的可用,比看单张惊艳截图更有效的方法是:在同一套系统提示词下,分别提交一条体素、一条建筑、一条机械提示词,然后只看机械那条里的"必需部件"少了不少几个——那才是模型能力边界的真实刻度。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考