Inspiration

Descriptive geometry — sistemas de representación, the Monge tradition — is a first-year subject in architecture, engineering and animation degrees. It has a property most drawing subjects do not: correctness is objective. An isometric axis is at 30° or it is not. A point's plan lies on the reference line dropped from its elevation or it does not. Nothing depends on an examiner's taste.

So I read eighteen published syllabi and rubrics — Spanish public engineering and architecture schools, Carnegie Mellon's 48-175, Sheridan College, open courseware. The finding is documented in docs/PEDAGOGY.md:

Not one of them states a numerical tolerance.

The discipline defines correctness precisely and then hands the checking to a person with a set square at the end of a stack of plates. Meanwhile a general-purpose multimodal model asked to critique a drawing will happily invent the number — "your angle is off by about 15 degrees" — with no spatial ground truth behind it.

Atelier sits in that gap, and the scope is narrow on purpose: it automates the objective verification the discipline already defines. It does not invent a new criterion.

What it does

A student photographs a construction. Before anything is measured, Gemini 3.5 Flash looks at the page and answers two questions: is this an exercise at all, and which system is it. A shopping list is declined in the model's own words, and nothing is measured.

Then the matching engine runs. Atelier measures three of the four systems of representation, and what separates them is not difficulty but where the reference comes from — which sets a ceiling on how far each result can be trusted:

System Reference Trust
Conic perspective Inferred — RANSAC estimates the vanishing point from the student's own lines Weakest. A consistently wrong drawing yields a vanishing point that agrees with it, and the reported error shrinks
Orthographic (diédrico) Read off the page — the ground line is a line the student drew Middle. Nothing is guessed, but a crooked ground line skews everything, so its tilt is reported separately
Axonometric Given — the axes are constants of the projection system Strongest. Nothing is estimated at all

That ranking is stated in the documentation rather than hidden, and it is measurable: in the golden case an error injected at exactly 6° comes back at 6.00°, asserted to within 0.05°. The perspective suite cannot hold a bound that tight, and says so.

The critique is then split into two planes that may not mix. Plane A carries only figures OpenCV produced. Plane B carries what a teacher would say and is forbidden a number at all. An anti-hallucination validator asks the analysis what it measured and rejects any figure the model did not get from that set — then regenerates with corrective feedback.

The collaborative loop is four verbs: ASK before measuring, GUIDE to the next exercise from a ladder documented in published curricula, CAPTURE explicit feedback as an immutable Firestore event, and ADAPT the profile from that event stream. The profile is a difficulty level, not a person.

How I built it

  • atelier-agent — Python 3.12 + FastAPI on Cloud Run. Three OpenCV engines (geometry.py, axonometry.py, dihedral.py), a two-stage pre-router, the validator, and the append-only memory model.
  • Atelier.Web — Blazor Server on .NET 10, also on Cloud Run. Three-step flow, one viewer per projection system, bilingual EN/ES with the language travelling with the request so the critique is written in the student's language rather than translated afterwards.
  • Gemini 3.5 Flash on Vertex AI (europe-west3) for the vision gate and the critique, called through the Google GenAI SDK.
  • Gemma 4 (gemma-4-26b-a4b-it) through the Gemini API, routing intent from the student's own words.
  • Firestore as the append-only store — every exercise and every feedback event, never updated in place. Plus Cloud Storage + Eventarc for asynchronous ingestion and Cloud Scheduler for the weekly digest, so the agent works with nobody at the keyboard.

Challenges I ran into

The mean of an empty set is not zero. Twice — in the orthographic engine and again in the progress profile — an average computed over nothing was reported as 0.00, which reads as perfect. A plate whose two views did not correspond at all reported a correspondence error of zero: a worse drawing produced a better number. Both aggregates are nullable now and render as a dash.

Silent fallbacks make a broken system look healthy. The critique path once caught every exception and returned a hand-written template stamped validated=true with the real model's name on it. Deleting Vertex AI from the project would have changed nothing observable. Provenance is now stamped by the server, never by the model, and the green badge is gated on it.

A schema that cannot express the answer produces no answer. The intent router still offered only the conic taxonomy after the axonometric and orthographic engines shipped. Asking it to classify "an isometric cube" into a set with no axonometric member did not return something wrong — it returned nothing at all, for 300 seconds, and what eventually unblocked the interface was the HTTP client's 100-second default. Three of the eleven calibration samples are parallel projections, so any user describing what they opened would have hit it. Fixed by extending the taxonomy to the three systems and putting a deadline on the call.

Vertex AI region. gemini-3.5-flash is not published in the Cloud Run region, and pointing Vertex at the service's own region made every critique fail into a silent fallback for days. The two are configured separately now, and the video says so out loud.

Accomplishments I'm proud of

The golden case: an error injected at exactly six degrees comes back at exactly six, and the critique separates a systematic deviation from a per-line one — which lets it say something no published rubric can: your hand is steady, the set square was placed wrong, and the fix happens once before drawing rather than edge by edge.

And the refusal. Measuring the wrong thing carefully is worse than declining to measure it.

What I learned

For technical disciplines — drawing, engineering, surgery — use computer vision for ground truth and a language model for teaching, and make the boundary between them something the code enforces rather than something the prompt requests.

And that the useful failures are all about honesty rather than about models: a figure that looks like success when nothing was measured is not a formatting detail, it is the failure mode.

What's next

Planos acotados — the fourth system — needs the numeric annotations read off the page, which is OCR rather than line geometry. Cylinders and ellipses, cast shadows, and true magnitudes (abatimientos, giros, cambios de plano) are each documented as measurable in principle and unimplemented in fact, in the README's gaps table. The agent does not prescribe a rung the engine cannot yet assess.

Built With

Share this project:

Updates

Submission history