6/5/2026

From DeepCAD to CadQuery: Building the Transpiler

Turning 179,000 parametric construction sequences into training data meant building a transpiler first — and testing it before trusting it.

You can't fine-tune a code-generation model on CadQuery programs if no CadQuery programs exist for the shapes you want it to learn. The datasets that do exist — DeepCAD's 179,000 parametric construction sequences sourced from real Onshape models, and Text2CAD's roughly 158,000 text-annotated pairs built on top of DeepCAD's geometry — are stored as a proprietary JSON schema of sketch-and-extrude operations, not as CadQuery. Before any training could start, we needed a transpiler: something that reads DeepCAD's operation format and writes out equivalent, runnable CadQuery Python.

Why go through an intermediate representation

The transpiler isn't a single function that maps JSON strings to Python strings. It's a three-stage pipeline: DeepCAD JSON is parsed into a typed intermediate representation (IR), and the IR is then emitted as canonicalized CadQuery Python. The IR stage — implemented as a small set of typed objects for sketches, curves, extrudes, boolean operations, and fillets — exists specifically to decouple the two halves of the problem.

Without it, the parser and the emitter would be one large, tangled piece of code where a bug could hide on either side of the DeepCAD-to-CadQuery boundary. With the IR in between, each half has a narrow, testable contract: the parser's job is only to turn DeepCAD's JSON into correct IR objects (tested against JSON fixtures), and the emitter's job is only to turn IR objects into correct CadQuery code (tested by constructing IR by hand and checking the resulting program's volume or topology). Neither side needs to know the other exists. That separation is what makes it possible to unit-test each op type — sketch, extrude, boolean join/cut, fillet — independently rather than only being able to test the pipeline end to end.

The round-trip filter

Parsing and emitting correctly doesn't guarantee the output is right — a transpiler can produce code that runs without error and still describes the wrong shape. So the pipeline includes a round-trip filter as a gate before any pair is allowed into the training set: transpile the DeepCAD sequence to CadQuery, execute it to get a fresh B-Rep solid, export that to STEP, and compare it against DeepCAD's own reference reconstruction of the same sequence.

The comparison uses two complementary, deliberately cheap and robust metrics rather than a single exact-match check. First, topology counts — the number of solids, faces, edges, and vertices — which catch structural disagreements (a missing cut, an extra body) immediately. Second, Chamfer distance computed over points uniformly sampled from both surfaces, which catches subtler geometric drift that topology counts alone would miss, such as a fillet radius or extrude depth that's slightly off. Pairs where the two disagree beyond tolerance are dropped rather than repaired or guessed at. The design's working estimate is that this discards roughly 10% of the corpus — an acceptable cost for the guarantee that everything left in the training set is geometrically verified against ground truth, not just syntactically valid.

Why canonicalization matters

The emitter doesn't just produce any CadQuery program that reproduces the geometry — it produces a canonical one. Variable names are fixed (op_0, op_1, ...), operation order is fixed where the underlying operations are commutative, and numeric values are rounded to a fixed precision. The output is run through a Python formatter so that whitespace and line breaks are also deterministic.

This matters because the model doesn't learn geometry in the abstract — it learns to predict tokens, and every token of incidental, arbitrary formatting is a token it has to spend capacity distinguishing from tokens that actually encode geometric meaning. If the same shape could transpile to a dozen superficially different but equivalent programs, the model would waste effort learning which formatting variant is "correct" instead of learning the underlying construction logic. Canonicalizing removes that noise at the source, so what the model actually trains on is the geometry, not one transpiler run's arbitrary choices.

Building the transpiler this way — IR in the middle, round-trip verification as a hard gate, canonical output — is more upfront work than a quick JSON-to-Python string substitution would have been. But the transpiled corpus is the entire foundation the fine-tuning stage rests on, and errors baked in at this stage are expensive to discover only after a full training run.