Built with mlx-optiq, the MLX-native toolkit to quantize, fine-tune, and serve LLMs locally on Apple Silicon, no PyTorch and no cloud. Try the Lab · All OptiQ quants · Docs
A 4-bit mixed-precision MLX quant of ccore/Qwen3.5-4B-3D-Coder, a Qwen3.5 4B fine-tune that writes 3D scenes and assets as single-file Three.js HTML. It runs at about 26 tokens/s on a 24 GB M4, with peak memory between 4 and 6 GB.
Every asset below was written by this quant on an M4, then opened in a browser. The code is unedited, and the HTML is in examples/ so you can open each one and orbit it yourself.
These are hand-picked from 18 attempts, not a typical sample. See What to expect for how the rest went.
They aren't flawless. The potions have no visible corks, the goblin's ears are flat from the side, and the tower's battlements are oversized.
Prompts and settings
System prompt, from the model's author:
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.
Settings: temperature 0.6, top_p 0.95, top_k 20, no repetition penalty, max_tokens 64000, thinking on, seeded.
Golem: Please create one self-contained HTML file with Three.js from cdnjs showing a stone golem boss with glowing green crystals growing from its shoulders. Make it a single game-ready asset: centred on a plain ground plane, a clear readable silhouette, built from separate named meshes, slowly turning on a turntable, with mouse orbit controls.
Cannon: Please create one self-contained HTML file with Three.js from cdnjs showing a pirate deck cannon on a wooden carriage with a stack of cannonballs. Make it a single game-ready asset: centred on a plain ground plane, a clear readable silhouette, built from separate named meshes, slowly turning on a turntable, with mouse orbit controls.
Potions: Please create one self-contained HTML file with Three.js from cdnjs showing a set of three potion bottles, red, blue and green, with corks, on a small wooden tray. Make it a single game-ready asset: centred on a plain ground plane, a clear readable silhouette, built from separate named meshes, slowly turning on a turntable, with mouse orbit controls.
Voxel goblin: Please create one self-contained HTML file with Three.js from cdnjs showing a swamp goblin enemy with big ears, a leather vest and a spiked wooden club. Render it as a deliberate 3D voxel model built from visible cubic blocks, with clear depth, readable silhouettes, and solid spatial relationships. Make it a single game-ready asset centred on a plain ground plane, slowly turning on a turntable, with mouse orbit controls.
Tower: Please create one self-contained HTML file with Three.js from cdnjs showing a medieval castle guard tower module with battlements, a wooden door and a flag waving at the top. Make it a single game-ready asset: centred on a plain ground plane, a clear readable silhouette, built from separate named meshes, slowly turning on a turntable, with mouse orbit controls.
Out of 18 attempts across 10 asset prompts and 8 voxel prompts:
Outcome
Count
Rendered in the browser
11
Crashed on load
3
Reasoning looped until the 64k token cap, no HTML
4
An asset takes minutes. The ones that finished ran 10,000 to 22,000 tokens, or 7 to 14 minutes, most of it reasoning. Set max_tokens high. A 20k cap cut off one run that wasn't stuck.
Set a cap anyway. All four loops came from voxel prompts, and each ran about 53 minutes before hitting the cap.
Rendering doesn't mean it looks right. Some that rendered had floating parts or broken animation, and those were left out of the picks above.
The crashes were small code errors. One was a duplicate variable name, which the author lists as a known issue.
No attempts were run on the parent model, so this card makes no claim about how these rates compare with it.
The per-layer allocation was not measured on this model. It was transferred from mlx-community/Qwen3.5-4B-OptiQ-4bit, whose allocation came from a KL-divergence sensitivity pass over a six-domain calibration mix.
The two models share an architecture, so each layer in that recipe has a counterpart with the same role and shape. All 249 tensors matched, with none unmatched.
Sensitivity measures how much a layer's role in the architecture suffers from precision loss. It can't tell whether this fine-tune's training moved that sensitivity. To measure the allocation against the model itself, run optiq convert.
18 generation runs, with each result opened in headless Chromium and checked for script errors and a drawn canvas.
Text and image input, both loaded directly and through optiq serve.
OptiQ's release contract.
Not run for this model: the six-metric Capability Score. The published scores for the Qwen3.5-4B quant describe that model, not this one, and are not claimed here.
from mlx_lm import generate, load
from mlx_lm.sample_utils import make_sampler
SYSTEM = """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."""
model, tokenizer = load("mlx-community/Qwen3.5-4B-3D-Coder-OptiQ-4bit")
prompt = tokenizer.apply_chat_template(
[{"role": "system", "content": SYSTEM},
{"role": "user", "content": "Please create one self-contained HTML file with Three.js from cdnjs showing a stone golem boss with glowing green crystals growing from its shoulders."}],
add_generation_prompt=True, tokenize=False)
print(generate(model, tokenizer, prompt=prompt, max_tokens=64000,
sampler=make_sampler(temp=0.6, top_p=0.95, top_k=20)))
The author recommends temperature 0.6 to 0.8, top_p 0.90 to 0.95, top_k 20 to 40, and repeat penalty 1.0.
The per-layer bit map is in optiq/metadata.json and in the quantization block of config.json.
Files
24 files · 3.96 GBWeights 3.94 GB (safetensors). Sizes and sha256 from the signed manifest.
import os
os.environ["HF_ENDPOINT"] = "https://freeweights.allternit.com"
from transformers import AutoModelForCausalLM, AutoTokenizer
tok = AutoTokenizer.from_pretrained("mlx-community/Qwen3.5-4B-3D-Coder-OptiQ-4bit", revision="4d50ce8223fe0f866c1e2ecf2f1ee56e3d4598ca")
model = AutoModelForCausalLM.from_pretrained("mlx-community/Qwen3.5-4B-3D-Coder-OptiQ-4bit", revision="4d50ce8223fe0f866c1e2ecf2f1ee56e3d4598ca", device_map="auto")