4B 到底够不够窄域微调的能力账本与被牺牲的部分【免费下载链接】Qwen3.5-4B-3D-Coder项目地址: https://ai.gitcode.com/hf_mirrors/ccore/Qwen3.5-4B-3D-Coder一个 4.5B 的模型被专门喂进 4146 条 Three.js 场景代码后能不能替代通用大模型写前端 3D这个问题在社区里通常被两种叙事夹击一边是小模型智能密度惊人的乐观另一边是微调即降智的怀疑。而 Qwen3.5-4B-3D-Coder 这个仓库恰好提供了一个罕见的样本——它把底座架构、训练数据规模、量化矩阵、已知缺陷全部摊开在明面上让能力账本第一次可以被逐项核对而不是靠感觉投票。本文不讲玄学只做三件事把可验证的能力边界画出来把没有证据却被默认为没退化的部分标红再给出一套可落地的分工与回退设计。一、先把账本口径定清楚这个 4B 究竟是什么很多讨论一开始就跑偏是因为把4B当成了一个孤立数字。实际上这个仓库里的 4B 是一个混合注意力 视觉塔的复合结构读 config.json 可以得到精确的骨骼语言侧 32 层、hidden_size2560、intermediate_size9216layer_types呈严格的 3:1 交替——每 4 层里有 3 层linear_attention、1 层full_attention注意力头 16 个KV 头只有 4 个GQAhead_dim256partial_rotary_factor0.25rope_theta1e7max_position_embeddings262144词表 248320tie_word_embeddings: truearchitectures是Qwen3_5ForConditionalGeneration而不是纯文本的ForCausalLM——它保留了 24 层、hidden_size1024 的视觉编码器和 patch/merger 通路。再看 model.safetensors.index.json 的元数据total_parameters为4,539,265,536total_size为 9,078,531,072 字节约 8.46 GiB FP16。723 个张量里297 个属于model.visual.*424 个属于model.language_model.layers.*另有两个是embed_tokens与最终norm。这三个数字放在一起会得出一个不太被提及的结论这个4B里有一大块参数并不在你关心的任务上工作。词嵌入一层就是 248320 × 2560 ≈ 6.36 亿参数且与输出头共享视觉塔按 24 层 ×1024 hidden 估在 3.5 亿量级。真正承载Three.js 代码语法与几何直觉的是剩下的二十多亿语言层参数。反过来看量化版本就更有意思了。社区实测给出的体积是 Q4_K_M 约 2.52 GiB、Q8_0 约 4.17 GiB见仓库提供的 Q4_K_M 与 Q8_0 文件。Q4 版本能在消费级显卡甚至纯 CPU 上跑代价是几何细节与长代码结构一致性最先崩——这一点后文会展开。还有一个容易被忽略的架构细节mtp_num_hidden_layers为 1。这就是 LM Studio 里必须**关闭 MTP多令牌预测**才能正常出词的根因——它不是一个可选优化项而是该检查点与你所用推理器的兼容性问题。README 在 Generation settings 一节用加粗写了这条警告但很多跑不起来的反馈依然来自这里。二、窄域专才的能力上界在哪里判断一个专才模型的上界不能看它最好的那张图要看它在何种约束下才稳定。这个仓库的 README 把约束写得很老实恰好构成了三条可验证的边界。第一条能力被系统提示框死在一个确切的运行时上。官方推荐的 system prompt 只有三句话核心是只从 cdnjs 加载 three.js 0.160.0 的 core ES module不要导入 addons 或 legacyexamples/js路径相机控制自己在 HTML 里实现。这不是风格建议而是把巨大的搜索空间砍成一个封闭集合没有OrbitControls、没有EffectComposer、没有GLTFLoader一切交互必须手写。模型之所以稳很大程度上是因为它只在这条窄轨上被训练过一旦你换成 npm 引入或加上后处理管线它就从专才退回会写 JS 的 4B。第二条体素化与硬表面几何是它的甜区。README 的示例提示词反复出现同一句收尾Render it as a deliberate 3D voxel model built from visible cubic blocks, with clear depth, readable silhouettes, and solid spatial relationships. 而 10 张画廊作品基本落在自然园林、幻想/科幻、家具手作、机械硬件四类Kōrin Garden、Sakura bonsai、Sunset Village、Dragonrider Aerie、Voxel launch site、Bow-Front Secretary Desk、Pelican Bike No. 07、LGA 3647 Socket 等。这种偏好的技术解释很直接用立方块拼装等于把建模降解为摆盒子。每个物体只需BoxGeometry 位置/缩放/旋转三元组模型不必推理曲面法线、UV 展开或蒙皮权重——而那恰恰是小模型最容易翻车的地方。同理机械类题材如 LGA 3647 插座受益于强对称与重复结构可以用一个循环批量生成针脚把长代码一致性的压力转嫁给了for循环。第三条一次性成功率是迭代出来的不是天生具备的。README 的 10 月 27 日检查点更新里写得很清楚新检查点让 one-shot success has improved substantially但紧接着承认 Some scenes can still require another attempt or a correction。仓库里的对比图直接展示了 10/25、10/26、10/27 三个 preview 下同一个 Rome 场景的演进这张图的信息量比任何榜单都大短短三天的权重变化就能让同一提示词下的构图从能看走到能交付。它说明上界不是固定的也说明**4B 够不够这个问题必须绑定检查点版本回答**——用旧权重的失败案例去论证小模型不行和用最新权重的成功案例去论证小模型可以都是取样偏差。三、被牺牲的通用能力面清单这里是全网讨论最含糊的地方。常见论调是它写 3D 这么强通用代码应该也没问题。但这个仓库里没有任何一项通用代码基准的分数。README 只有一句主观描述Initial hands-on results have been promising for coding in general. 而promising不是未退化。把可核对的证据摊开缺口如下能力面仓库中的证据可下的结论Three.js 单文件场景4146 条样本3933 训练 / 213 验证10 张画廊作品强且可复现通用代码 / 多语言无基准、无对照表、无消融未测量不能视为未牺牲多文件工程 / 框架生态训练目标全部是 self-contained HTML大概率退化视觉输入图生场景视觉塔 297 个张量保留但数据集无图像监督描述状态不明不应假设可用工具调用 / Agentchat template 支持tool_call但无训练说明未验证长上下文max_position_embeddings262144架构支持 ≠ 微调后仍保持先看最硬的一条数据分布。数据集 ccore/ThreeJS-3D-Scenes 的 4146 条样本全部是prompt → 完整 HTML/JavaScript 响应并且附带 full thinking traces 与复杂度分级采用 MIT 许可。这是一个极其纯净、也极其狭窄的分布。SFT 的本质是把输出分布拉向目标分布当目标分布里只有一种输出形态自包含 HTML 文件时模型会学到一条强先验任何输入都该以我来给你写个 HTML回应。对窄域这是特性对通用助手这是缺陷——你让它解释一段报错它可能开始给你搭场景。第二条被拉长的输出预算。数据集带思考轨迹chat_template.jinja 在生成时默认注入think\n除非显式传enable_thinkingfalse此时写入空思考块。这意味着每次生成都要先跑一段推理再落代码。对 Three.js 场景这段思考是有收益的——它承担了布局规划的职责但对一句简单的补全请求它就是纯粹的 token 税。generation_config.json里temperature 0.6 / top_k 20 / top_p 0.95这套偏保守的参数也是为稳定出结构化长代码调的不是为发散创意调的。第三条多模态通路的悬置。preprocessor_config.json与video_preprocessor_config.json都还在Qwen3VLProcessor也还挂着说明底座的多模态能力在结构上完整。但训练数据是纯文本 prompt 代码没有任何图像-代码配对。也就是说视觉塔在微调中没有获得与 3D 场景生成对齐的梯度信号——它要么被冻结要么在被无关信号扰动。能传图和能看图建模是两件事在这个仓库里只有前者有证据。此外 GGUF 路径通常不带视觉塔量化用户的看图能力实际上是零。第四条也是最值得玩味的一条已知问题的清单本身就是能力边界的自白。README 的 Known issues 只有一句The bugs observed so far have generally involved duplicate variable names, rather than major structural problems. 重名变量——这是一个 4B 模型在生成数百行 JS 时最典型的工作记忆瓶颈它记得住整体结构记不住三个函数里已经出现过const group。这个失败模式非常小模型结构感强于符号管理。它不构造成本失控的架构错误但会在细节处反复摩擦靠重试收敛。再补一刀关于量化Q4_K_M 的 2.52 GiB 版本让部署门槛降到极低但 4-bit 最先损失的就是长程符号一致性——也就是上面那个重名变量问题会变多。想要一次过Q8_0 的 4.17 GiB 是更诚实的下限想验证能力上限就用 FP16 的 8.46 GiB。四、什么信号出现就该换回通用模型与其争论4B 够不够不如把判断变成一组可执行的触发器。以下信号里命中任意一条就该把请求路由给通用大模型而不是继续在这个专才上重试输出不再是单文件。需要拆模块、需要package.json、需要构建步骤——训练分布里没有这些东西它生成的多文件往往是同一个文件的机械切分。依赖超出 cdnjs 上的 three.js core。一旦涉及three/addons/*、后处理、物理引擎、加载外部模型等于走出了它唯一被训练过的运行时。任务本质不是空间构造。状态管理、类型体操、SQL、后端并发、正则调试——这些在 4146 条样本里一次都没出现过。需要拒绝或澄清。窄域 SFT 模型的默认动作是产出而不是追问。当你需要它说这个需求有歧义时它更可能直接开始写代码。连续两次重试仍卡在同一类错误。尤其是重复变量名、未定义引用这类符号级错误——这说明不是采样运气问题而是模型容量到顶。需要图像作为输入。在视觉通路未验证、且 GGUF 不带视觉塔的前提下这属于未支持能力。上下文开始接近上限。262144 是底座架构值微调后的有效长度没有任何评测支撑把整个代码库塞进去做重构是在赌一个没有证据的假设。反过来什么信号说明4B 足够、不必上大模型提示词能落到一个自包含 HTML 体素/硬表面风格 明确的布局描述并且你接受一到两次重试。这时 4B 的性价比是碾压性的2.54.2 GiB 显存、本地零延迟、无 token 账单。五、两套模型混合调用的分工设计真正务实的架构不是二选一而是让通用模型做它擅长的语义与工程判断让 4B 专才做它擅长的空间落地。分工的关键在于把一句话需求变成结构化场景规格这一步交给通用模型因为这一步需要澄清、需要拒绝、需要常识把规格 → 可运行 HTML这一步交给 4B因为这一步需要的是对 three.js 0.160.0 的肌肉记忆。下面是一段可直接改造使用的调度骨架校验规则全部来自本仓库 README 的约束core-only ES module、禁用 addons、单文件自包含import json, re from openai import OpenAI # 两个端点LM Studio / vLLM 均可OpenAI 兼容 GENERAL OpenAI(base_urlhttp://127.0.0.1:8000/v1, api_keyEMPTY) # 通用大模型 SPECIAL OpenAI(base_urlhttp://127.0.0.1:8001/v1, api_keyEMPTY) # Qwen3.5-4B-3D-Coder SYSTEM_3D ( Use only the Three.js core ES module from https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.module.min.js.\n Do not import addons or legacy examples/js paths;\n implement any camera controls directly inside the HTML. ) SPEC_SCHEMA 输出 JSON{ theme: str, layout: [{name: str, pos: [x,y,z], size: [w,h,d]}], style: voxel | hard-surface, animated: bool, complexity: 1-3 } def build_spec(user_brief: str) - dict: r GENERAL.chat.completions.create( modelgeneral-large, messages[ {role: system, content: 你是 3D 场景需求分析器。 SPEC_SCHEMA}, {role: user, content: user_brief}, ], temperature0.3, response_format{type: json_object}, ) return json.loads(r.choices[0].message.content) def render_scene(spec: dict, temperature: float 0.6) - str: r SPECIAL.chat.completions.create( modelqwen3.5-4b-3d-coder, messages[ {role: system, content: SYSTEM_3D}, {role: user, content: ( Please create one self-contained HTML file with Three.js from cdnjs fshowing: {json.dumps(spec, ensure_asciiFalse)} )}, ], temperaturetemperature, top_p0.95, top_k20, # 与 generation_config.json 对齐 ) return r.choices[0].message.content生成之后必须过一道静态闸门把重名变量这类高频缺陷挡在交付前。这道闸门的检查项完全对应 README 的系统提示约束FORBIDDEN [ (rfrom\s[\].*addons, 引用了 addons超出训练运行时), (rexamples/js, 引用了 legacy examples/js 路径), (rthree(\.min)?\.js(?!0\.160\.0), 版本锁定被破坏), (rscript[^]src[^]*three, 非 ES module 方式加载 three), ] def static_gate(html: str) - list[str]: errs [msg for pat, msg in FORBIDDEN if re.search(pat, html)] if typemodule not in html: errs.append(缺少 script typemodule无法使用 core ES module) # 顶层 const/let 重名README 记录的最典型失败模式 decls re.findall(r^\s*(?:const|let)\s([A-Za-z_$][\w$]*), html, re.M) dup {n for n in decls if decls.count(n) 1} if dup: errs.append(重复声明: , .join(sorted(dup))) return errs最后是回退策略。这里要区分两种失败局部缺陷重名变量、少一个scene.add把static_gate的输出 原 HTML 交回 4B用更低的 temperature 做一次定向修补。这类问题它是能自愈的README 所说的 another attempt or a correction 指的就是这个。结构性失败找不到几何主体、违反规格、依赖越界不要再用 4B 重试。把 spec 与原 HTML 交给通用大模型重写或大改或者干脆由通用模型直接产出。判据很简单——如果static_gate报的是超出运行时说明请求本身已经出了窄域重试只会重复同一种错误。这套分工的成本结构也很清楚通用模型只处理几百 token 的规格 JSON 和失败样本4B 承担动辄数千 token 的 HTML 主体生成。真正昂贵的部分长输出被压在了本地小模型上而真正需要智力的部分理解、澄清、兜底留给了大模型。六、结论账本该这么记Qwen3.5-4B-3D-Coder 不是4B 也能写代码的证明它是4B 在把搜索空间砍到足够窄之后可以写代码的证明。它的能力上界由三件事共同定义只允许 core ES module 的运行时约束、体素/硬表面这类可降解为盒子的题材、以及一个还在持续迭代的检查点。被牺牲的部分同样清楚通用代码能力没有被测量这是最需要警惕的一点缺口不等于无损、多文件工程与包生态基本出局、视觉通路处于未验证状态、思考轨迹带来的 token 税无法关闭式规避、4-bit 量化会放大符号级缺陷。所以够不够的正确问法不是它能不能替代大模型而是你的任务里有多大比例可以表达成一段自包含 HTML。比例越高这个 2.5 GiB 的文件越香一旦跨过那道闸门就该让通用模型接管——并且要在代码里把这道闸门写成断言而不是靠人的直觉。【免费下载链接】Qwen3.5-4B-3D-Coder项目地址: https://ai.gitcode.com/hf_mirrors/ccore/Qwen3.5-4B-3D-Coder创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考