← All work A-04 Case · /en/business/pipeline

Image & content pipeline

Product photos from the factory floor and clients' offices become clean catalog shots; product descriptions are generated from raw parameters. Drag the handle.

Status
In production
Role
Everything
Stack
PythonFastAPIGeminiRabbitMQPostgreSQL + pgvectorPillowSSEWagtail CMSMCP
W 1160 · 3:2
W 358 · 3:2
After: the same reception desk in a clean interior
Before: the reception desk photographed in the client's office
Pair 1 of 5 · reception desk · client's office → clean interior
Pair 1 of 5 · reception desk · client's office → clean interior. Left of the handle — the photo as it came from the client's office; right — the same product after the pipeline. Nothing about the furniture was changed, only the room around it.
01Why no studio, no reshootno reshoot

A catalog lives on photos

A B2B furniture catalog lives on photos, and most of them are taken in clients' offices: wrong light, brick columns, other people's furniture in the frame. Reshooting every product in a studio is not an option for a small manufacturer. The pipeline takes the real photo and rebuilds the environment around the same product.

02More pairs pairs 2–5 · pick a thumbnailswipe the row

Four more products

After: the same product in a clean interior
Before: product photographed on site
Pair 2 of 5

swipe the thumbnails, tap to switch

03Text, the same way raw parameters → description

Descriptions from raw parameters

Before · raw parameters
[TBD: real sample of raw parameters]
After · product description
[TBD: the generated description for it]
The assistant fills the product card from a dossier through the site's MCP server; photos get titles and alt texts from a vision model.
04The flow two lanes · one product cardtwo lanes

From a phone photo to the product card

Photo · manager or bot
Image task · in OMS
image_service
Gemini
Image library
Product card · CMS, MCP
Raw parameters
Bot Pioner · Pydantic AI agent
Description
Images Text queue: RabbitMQ (analyze · generate · tweak · ingest) · library: PostgreSQL + pgvector · progress: SSE
Photo · manager or bot
Image task · in OMS
image_service
Gemini
Image library
Raw parameters
Bot Pioner · Pydantic AI agent
Description
Product card · CMS, via MCP
Images Text RabbitMQ · PostgreSQL + pgvector · SSE
Images: an image task in the OMS goes through RabbitMQ to image_worker, which calls Gemini (Batch API from three frames); results land in the PostgreSQL + pgvector library and reach the product card through the site's MCP. Text: the content bot writes the description and publishes it through the same MCP. Progress reaches the browser as SSE on the task's version counter; images are served by signed links.
05Generation task id · wait queue · Batch API

How a frame is made

Generation takes minutes, and a batch job up to a day, so the queue message carries only the task id — the worker reads the state from the database and continues from where it stopped, which makes redelivery safe. Temporary Gemini errors go to a wait queue with a TTL and come back (up to three attempts); poison messages go to a dead-letter queue. One or two frames are generated by ordinary calls, three or more through the Batch API, which is twice as cheap. Every model call is written to a cost log with an estimate in dollars.

06Search filters · full-text · pgvector

Search without a search engine

07Inside the CMS EXIF · names · srcset · 4:3

What the CMS does with every image

On first save the EXIF rotation is applied to the pixels and the metadata is stripped. The page, not the upload API, decides the collection and the file name — a product photo is named by type, model and index. Renditions are named by their actual size and served as a WebP srcset. For ads a 4:3 JPEG is cut from the original so that the crop is slightly larger than the target and gets scaled down to exactly 4:3 — small originals would otherwise round to "almost 4:3", which the ad platform rejects.

08Screens OMS · image tasks · 1440 × 900OMS
09

Numbers

rounded
  • ~700 photos processed
  • ~300 descriptions generated
  • 5 before/after pairs shown
  • 4:3 ad-ready crop