Thousands of product sheets from dirty catalogs: a pipeline that doesn't publish mistakes
A design and lighting retailer, thousands of SKUs, dozens of brands with inconsistent source data. A real case of a pipeline where AI writes but doesn't decide: normalization in code, a technical glossary, automatic validation.
A lighting and design retailer sells thousands of items from dozens of brands online. Every brand delivers data its own way: different fields, different units, the same finish named three different things. Product sheets were written by hand — slow to produce, and with a risk that weighs more than slowness: the mistake that gets published, in front of customers.
The problem wasn't writing: it was trusting
Generating text is easy now. Anyone who has opened ChatGPT can get a product description in ten seconds. A real e-commerce operation has a different problem: across thousands of sheets, how many contain a wrong measurement, an invented wattage, a finish that doesn't exist? And who finds out — the customer, with a return?
Which is why the project isn't "use AI to write the sheets". It's building a chain where AI writes, but doesn't decide.
The pipeline, in three links
1. Normalization — in code, not in the model
Before the model sees a single row, every brand's data goes through a normalization written in code, deterministic: same fields, same units, same names for the same things. The dirty work — and it's the biggest part of the project — isn't done by AI: it's done by code that gives the same result today, tomorrow, and at row one hundred thousand.
2. Controlled generation — with a technical glossary
Only then does the model come in, and it writes inside rails: an industry glossary defines the correct terms — finishes, materials, measurements — and generation can use those, not invented synonyms. The text reads naturally, but the vocabulary is under control.
3. Automatic validation — the link that matters
Every generated sheet is re-checked by code against the source data: every technical value has to match. What doesn't pass doesn't get published — it goes back in the queue, with the reason. One sentence sums up the whole approach: the output is verified by code, not by the model. Trust isn't requested from the reader: it's built into the pipeline.
The numbers
The engine has worked across ten manufacturer catalogs, for a total of 30,512 product pages downloaded. Six of those catalogs were taken all the way to the import files, and they span two different worlds — technical lighting and furniture — on the same code: only a per-brand configuration module changes.
On the way out: 2,548 product sheets with 8,644 variant combinations, and 5,517 descriptions generated — every sheet exists in Italian and English, produced together because the fact-check has to be able to compare the two languages. The count is deliberately conservative: canonical import files only, without the later top-up waves.
And here is the number that actually matters. Out of 2,308 sheets that went through the generator, 48 came out with an empty description: 2.1%. That isn't an error rate — it's the opposite. Those are the sheets where the fact-check rejected the text three times running and the pipeline chose to publish nothing rather than publish a sentence it couldn't verify. Forty-eight missing descriptions are forty-eight mistakes no customer ever saw online.
That is the difference between this and “just let the AI write it”. The model doesn't get an acceptable margin of error; it gets a gate in front of it. If a measurement, a material or a colour temperature isn't in the source data, that sentence doesn't ship. On top of that run 22 automated checks over the generated files, plus a separate image check that on a single brand isolated 1,097 combinations where the associated photo needed a human look.
What makes this case repeatable
Nothing above is specific to furniture. Supplier catalogs, price lists, bills of materials, item master data: wherever there is dirty source data and an output that can't afford mistakes, the structure is the same — deterministic normalization, generation inside rails, validation that blocks instead of hoping. If your bottleneck looks like this, I'm happy to talk: automations on documents and data.
Frequently asked questions
Doesn't the model invent specs that don't exist?
That's risk number one in these projects, and it's why generation is the least important link in the chain. Every technical value in the final sheet is re-checked by code against the source data: if it doesn't match, the sheet doesn't pass and goes back in the queue with the reason. The output is verified by code, not by the model.
Our source data is a mess. Does it still work?
Dirty data isn't the obstacle to the project: it is the project. The pipeline starts exactly there — a normalization written in code, deterministic, that brings inconsistent fields and formats to one schema before the model sees a single row. If the data were clean, this page wouldn't exist.
What happens when brands change their catalogs?
The system re-runs: it picks up the sources, redoes normalization and generation only on what changed, and validation flags the differences. That's the difference between a one-off script and a system that lasts — and why these projects usually continue with recurring maintenance.
What does a system like this cost?
It depends on how many sources, what state they're in, and how rich the industry glossary needs to be. The order of magnitude gets defined in a call after seeing a sample of your data — it's half an hour, and its first job is telling you whether the game is worth it.
