← All work
Case studyMultimodal AI · Auction cataloging

AI Cataloging System for Fine-Jewelry Auctions

Suppliers describe their jewelry in spreadsheets of raw specifications. This system turns every row into a publishable auction lot — photos mirrored to the house’s own storage, images examined by an AI gemologist, copy written by an AI specialist under the house’s rules, and everything mapped to the auction platform’s taxonomy for bulk upload.

The hard part is not getting a model to write — it is deciding what the model is allowed to say. Here, the camera decides what a piece looks like, the supplier decides what it weighs, and the house decides how it sounds.

Client
Serenity Gallerie
Role
Design, engineering & coding
Domain
Fine-jewelry auctions · cataloging · AI
Shape
FastAPI + Celery · serverless images · Vue admin
Status
Shipped in 2025
The problem
Suppliers describe their jewelry in spreadsheets of raw specifications; every row has to become a publishable auction lot with photos, copy and taxonomy.
What was built
Morsalin designed and built a FastAPI and Celery system with two Gemini stages on Vertex AI — a vision “gemologist” and a copywriter — bound to a 335-term vocabulary.
The result
Shipped in 2025. Staff upload a file and review finished lots, and the model is never allowed to invent stone counts, carats or metal purity.
2AI stages
335vocabulary terms
15controlled taxonomies
14API endpoints
~1.9klines of Python backend
~570lines of Vue & TypeScript
~450lines of scripts & services
~650lines of prompts
01The problem

A spreadsheet row is not an auction lot.

01

Supplier data describes a product, not a lot.

A row carries metal, weights, stone counts, dimensions, cost and image links — but no title, no description a buyer would read, and none of the platform’s category, style or material IDs.

02

Supplier photos live on supplier servers.

A catalog that links to them breaks the day the supplier moves or removes an image.

03

The spreadsheet does not say what the piece looks like.

Style, setting, cut and hallmarks are visible in the photos, not in the columns.

04

An AI can see a stone but not weigh it.

A model that estimates carats or reads “18K” off a photo will state things the house cannot stand behind.

And a delivery is hundreds of pieces. Writing and classifying each one by hand is the bottleneck.
02What it does

One upload, finished lots.

Import

Staff upload a supplier spreadsheet; the request returns at once and the import runs in the background with per-piece progress.

Photos

A serverless service mirrors every supplier image into the house’s own storage, ten pieces in parallel.

Vision

An AI gemologist examines the photos alongside the spreadsheet row and returns a structured profile.

Copy

An AI specialist writes the lot title and HTML description from the merged record, within fixed templates.

Taxonomy

Every lot is mapped to the auction platform’s category, style and material IDs.

Export & admin

Lots export as a bulk-upload file per delivery, from a sign-in-protected admin interface.

03Architecture

Long work never blocks a request.

fig.02 — import pipelineone upload · three phases
Supplier spreadsheetuploaded by staffAPIreturns at once with a job idBackground jobprogress saved after every piece1Parse & normalize› skip pieces already listed› clean karat, units, numbers› replace trade terms2Mirror photos› serverless image service› 10 pieces in parallel› into cloud storage3AI, piece by piece› gemologist: vision profile› specialist: title + copy› platform taxonomy IDsCloud Storagethe catalog's photo hostGeministructured outputPostgreSQLlots + profilesBulk-upload export

A job, not a request

Every piece needs its photos fetched and two AI calls. The upload only stores the file and creates a job; a worker does the rest, saving progress after every piece.

Three phases, in order

Filtering comes first, so pieces already cataloged are never downloaded again. Photos then mirror in parallel; the AI runs piece by piece, so each lot is saved as soon as it is done.

A service for supplier images

The least predictable work lives in its own serverless service: token-authenticated, guarded against path tricks, with pooled connections, timeouts and concurrent downloads.

04Two AI roles

One looks. One writes.

Stage 1 · the gemologist

Looks at the piece

Photos and the spreadsheet row go to a vision model framed as a certified gemologist. It returns category, subcategories, style, setting, main and accent stones with type, shape and cut, hallmarks and gender — every field chosen from the house’s vocabulary.

Where photos and data disagree, the rule is set: the camera wins on condition and hallmarks, the supplier on anything the camera cannot see.

Stage 2 · the specialist

Writes the lot

  • ›A title template — Under 80 characters, with a defined order of what to remove first when it runs long.
  • ›Approved opening lines — Ten romance hooks and six metal-and-setting hooks are fixed text; the supplier data picks which one each piece uses.
  • ›A specification list — With inclusion rules, so an empty weight never appears as “0”.
  • ›House style — Title case, lowercase units and no repeated facts — with worked examples.
  • ›The platform’s taxonomy — Embedded in the prompt, with a rule that a style is always chosen — the nearest match rather than none.
From the vision prompt

NO COUNTS, WEIGHTS, or DIMENSIONS: Do not attempt to quantify stones, carats, or measurements.

NO METAL PURITY: Do not include karatage or fineness (e.g., STRICTLY EXCLUDE '14K', '18K', '925'). Only report the metal type and color.

05Keeping AI honest

Constrained by schema, isolated on failure.

Structured output

Both calls return JSON validated against a schema, so a category or stone type outside the vocabulary cannot come back.

Low temperature

0.1 for analysis, where consistency matters; 0.3 for copy, where a little variety helps.

Retries with backoff

Up to five attempts, waiting 4 to 60 seconds, for transient model errors.

Failure isolation

A piece the AI cannot complete is skipped; the rest of the delivery carries on.

06Supplier data

Cleaned before the AI ever sees it.

Karat spellings“10kt” or “10 Karat” become “10K”, matched on word boundaries so words that merely contain the letters are left alone.
Numbers in textValues are extracted from text-laden cells, with a safe default when there is none.
UnitsDimension and weight units are detected and carried with the value.
FinishInferred from description keywords into a fixed list.
Total carat weightComputed from diamond and gem weights.
Trade termsOne supplier’s trademarked name for a setting style is replaced with the generic term before it can reach a listing.
07Key decisions

Every non-obvious choice, with its reason.

Two AI passes, not one

Seeing and writing are different jobs; each prompt stays narrow and checkable.

Numbers only from supplier data

A model estimating carats or reading purity from a photo states facts the house cannot back.

Vocabulary-constrained output

A category the platform does not know is a rejected upload.

Opening lines chosen by data

Tone and variety stay a business decision, not a model’s.

Import as a background job

Photo fetching and AI calls take far longer than a request should.

Filter before downloading

Pieces already cataloged cost nothing on a re-import.

Mirror photos to own storage

Exported lots must not depend on a supplier’s links.

Downloads in a separate service

The least predictable work is isolated, parallel and independently scalable.

Skip a failed piece, keep the batch

One difficult piece should not cost a whole delivery.

08Outcome

From drafting every lot to reviewing them.

Import

A supplier spreadsheet becomes catalog entries in one upload, processed in the background.

Media

Every piece’s photos mirrored to the house’s own storage, organized by delivery.

Content

Titles, descriptions and platform taxonomy IDs written for every piece under house rules.

Export

Upload-ready files for the auction platform, per delivery.

  • ✓Cataloging moved from writing to reviewing — staff upload a file and review finished lots instead of drafting each one.
  • ✓Facts stay facts — weights, counts and metal purity come from the supplier; the AI describes only what it can see.
  • ✓One voice across hundreds of lots — approved lines and fixed templates keep the catalog sounding like one house.
  • ✓Stable catalog links — every photo is served from the house’s own storage, not a supplier’s server.

My role

I designed, built and coded the system: the data model for a jewelry piece and its AI-derived profile, the import pipeline and its background processing, the serverless image service, both AI stages and their prompts, the export in the platform’s format, and the admin interface. I did the coding myself, working with AI-assisted tooling.

Stack

Backend
Python · FastAPI · SQLModel · PostgreSQL
Jobs
Celery · Redis · parallel downloads
AI
Gemini on Vertex AI · vision · structured output · Jinja2
Cloud
Cloud Run image service · Cloud Storage
Admin
Vue 3 · Vuetify · Pinia · TypeScript · Vite
Auth
JWT in httpOnly cookie · bcrypt
PythonFastAPIPostgreSQLCeleryVue 3TypeScriptMultimodal AIPrompt engineeringStructured outputGoogle CloudServerlessImage pipelinesData normalization

Built at Serenity Gallerie, an online auction house for luxury jewelry and watches, where I have been Tech Lead since Q4 2025. Supplier and platform identifiers are deliberately omitted.

Next

Want AI that knows what it may say?

Get in touch →
© 2026 MD Morsalinbuilt with care · OSS-first · sustainable by design
lat: 23.81°Nlon: 90.41°Etz: UTC+6status: 200 OK