cad0
cad0 is a fine-tuned language model for text-to-CAD generation. Given a natural language description of a mechanical part, it generates Compact IR — a token-efficient domain-specific language for parametric 3D geometry.
Demo
Try it: cad0-demo on HuggingFace Spaces
For browser/offline use: cad0-mini (0.5B, ONNX quantized)
What It Does
Input: "50x30mm mounting plate with 4 corner holes"
Output: C 50 30 5
Y 2.5 10
T 1 5 5 0
D 0 2
...
The Compact IR output can be parsed and evaluated by the vcad kernel to produce editable parametric geometry.
Supported Part Types
| Family | Examples |
|---|---|
| Bracket | L-brackets, Z-brackets, mounting plates |
| Standoff | Cylindrical spacers, threaded standoffs |
| Enclosure | Boxes, vented enclosures, rounded shells |
| Gear | Spur gears, hubs |
| Flange | Bolt circles, blind flanges |
| Clip | Snap clips, spring clips |
Usage
With Transformers + PEFT
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-Coder-7B-Instruct",
torch_dtype="auto",
device_map="auto"
)
model = PeftModel.from_pretrained(base_model, "campedersen/cad0")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-Coder-7B-Instruct")
prompt = "50x30mm mounting plate with 4 corner holes"
messages = [{"role": "user", "content": prompt}]
text = tokenizer.apply_chat_template(messages, tokenize=False,
add_generation_prompt=True)
inputs = tokenizer(text, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=256, temperature=0.1,
do_sample=True)
ir = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:],
skip_special_tokens=True)
print(ir)
API Endpoint
curl -X POST https://ecto--cad0-training-inference-infer.modal.run \
-H "Content-Type: application/json" \
-d '{"prompt": "L-bracket with mounting holes", "temperature": 0.1}'
Compact IR Reference
┌──────────────┬──────────────┬──────────────────────────────────┐
│ Op │ Syntax │ Description │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Cube │ C x y z │ Box with dimensions x, y, z (mm) │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Cylinder │ Y r h │ Cylinder with radius r, height h │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Sphere │ S r │ Sphere with radius r │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Cone │ K r1 r2 h │ Cone/frustum │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Translate │ T n x y z │ Move node n by offset │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Rotate │ R n rx ry rz │ Rotate node n (degrees) │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Scale │ X n sx sy sz │ Scale node n │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Union │ U a b │ Boolean union │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Difference │ D a b │ Boolean subtraction │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Intersection │ I a b │ Boolean intersection │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Shell │ SH n t │ Hollow out with wall thickness t │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Fillet │ F n r │ Round edges with radius r │
├──────────────┼──────────────┼──────────────────────────────────┤
│ Chamfer │ CH n d │ Bevel edges with distance d │
└──────────────┴──────────────┴──────────────────────────────────┘
Nodes are 0-indexed; each line creates a new node.
Training
┌───────────────────┬───────────────────────────┐
│ Parameter │ Value │
├───────────────────┼───────────────────────────┤
│ Base model │ Qwen2.5-Coder-7B-Instruct │
├───────────────────┼───────────────────────────┤
│ Method │ QLoRA (4-bit NF4) │
├───────────────────┼───────────────────────────┤
│ LoRA rank │ 64 │
├───────────────────┼───────────────────────────┤
│ LoRA alpha │ 128 │
├───────────────────┼───────────────────────────┤
│ Training examples │ 530,531 │
├───────────────────┼───────────────────────────┤
│ Epochs │ 1 │
├───────────────────┼───────────────────────────┤
│ Batch size │ 64 (effective) │
├───────────────────┼───────────────────────────┤
│ Learning rate │ 2e-4 (cosine) │
├───────────────────┼───────────────────────────┤
│ Hardware │ 1x NVIDIA H100 80GB │
├───────────────────┼───────────────────────────┤
│ Training time │ 9h 15m │
└───────────────────┴───────────────────────────┘
Evaluation
┌──────────────────────────┬───────────────────────────┐
│ Metric │ Value │
├──────────────────────────┼───────────────────────────┤
│ Final eval loss │ 0.324 │
├──────────────────────────┼───────────────────────────┤
│ In-distribution accuracy │ 75% │
├──────────────────────────┼───────────────────────────┤
│ Out-of-distribution │ Limited (see Limitations) │
└──────────────────────────┴───────────────────────────┘
Limitations
- Training bias: May add features (holes, fillets) to simple primitives — training data weighted toward complex manufactured parts
- Dimension ambiguity: Occasionally confuses radius vs diameter for cylinders
- Limited primitives: No native hexagon support; hex shapes require boolean workarounds
- OOD generalization: Struggles with part types not in training distribution
Related
- https://github.com/ecto/vcad — Open-source parametric CAD with custom BRep kernel
- https://vcad.io — Web app with cad0 integration
- https://huggingface.co/campedersen/cad0-mini — 0.5B distilled model for browser inference
Citation
@misc{cad0, author = {Cam Pedersen}, title = {cad0: Text-to-CAD Language Model}, year = {2026}, publisher = {HuggingFace}, url = {https://huggingface.co/campedersen/cad0} }
License
MIT
- Downloads last month
- 124