Retour aux projets
Documenté Pipeline data + IA · Analytics

Tokenverse — Classification IA

Pipeline data orchestré en 7 étapes. Classification automatique d'artistes MidJourney en 51 catégories sémantiques via GPT-4.

Contexte

MidJourney est une communauté de centaines de milliers d'artistes IA qui publient des prompts et des images. La donnée est ouverte mais éparpillée. Aucun outil ne permet de répondre à des questions simples comme "qui sont les meilleurs créateurs de style cyberpunk ?" ou "quelles catégories explosent ces 30 derniers jours ?".

J'ai construit Tokenverse pour répondre à ces questions à grande échelle : scraping, enrichissement par LLM, et exposition d'analytics utilisateur (leaderboards, profils enrichis, tendances temporelles) via un JSON distribué sur CDN.

Le challenge technique

Le vrai défi n'était pas le scraping — c'était l'orchestration. 7 étapes séquentielles (scrape → download → tag GPT → JSON → analytics → upload CDN → cleanup) à exécuter en parallèle sur des centaines d'utilisateurs sans saturer les rate limits API (OpenAI : 3 req/s par tier, Cloudflare R2 : illimité mais coût upload). Solution : queue manager avec locks SQLite.

Le flow opérationnel — en 7 étapes

Le pipeline transforme une URL de profil MidJourney en analytics utilisateur exposées via CDN. Chaque étape verrouille sa zone via un queue manager SQLite pour qu'un même profil ne soit jamais traité en double :

  1. 1. Input — un user_id + une URL de profil MidJourney à traiter.
  2. 2. Scraping — Puppeteer extrait les prompts et images publics du profil.
  3. 3. Download multi-format — images ET vidéos téléchargées. Chaque image est régénérée en 4 tailles (thumb 320, preview 640, detail 1280, full) via Sharp.js + PIL. Les vidéos sont transcodées dans les formats adaptés au frontend (poster + mp4 optimisé).
  4. 4. Tagging IA — GPT-4 classifie chaque image dans une taxonomie de 51 catégories sémantiques (3 calls parallèles, retry exponentiel sur rate limit).
  5. 5. Build du JSON — données structurées par parts de 1000 images, pré-indexées pour requêtage rapide côté frontend.
  6. 6. Analytics utilisateur — calcul du profil enrichi : leaderboards, scores de productivité/diversité, tendances temporelles par catégorie.
  7. 7. Distribution CDN — upload Cloudflare R2 (gzip), exposition via CDN global. Latence frontend < 100 ms.
flowchart TB A["1. Input
user_id + URL MidJourney"] A --> B["2. Scraping Puppeteer
prompts + images"] B --> C["3. Download multi-format
4 tailles via Sharp.js + PIL"] C --> D["4. Tagging GPT-4
51 catégories sémantiques
images + vidéos"] D --> E["5. Build JSON structuré
parts de 1000 images"] E --> F["6. Analytics utilisateur
leaderboards / scores / tendances"] F --> G["7. Upload Cloudflare R2
gzip + CDN global"] G --> H["Frontend Lovable
latence < 100 ms"] Q[("Queue Manager
SQLite locks")] B -.lock.-> Q D -.lock.-> Q G -.lock.-> Q

Stack technique

Scraping + processing
  • Node.js 18+ avec Puppeteer headless
  • Python + PIL (image processing)
  • Sharp.js (compression multi-format)
  • 4 tailles : thumb 320 / preview 640 / detail 1280 / full
Classification IA
  • GPT-4 via API OpenAI
  • Taxonomie 51 catégories sémantiques
  • 3 calls GPT en parallèle (rate limit safe)
  • Retry exponentiel sur 429
Orchestration
  • Master orchestrator (Node.js)
  • Queue manager + locks SQLite
  • Better-sqlite3 (synchrone, performance)
  • Parallélisme contrôlé : 1 scrape, 3 GPT, 3 uploads
Distribution
  • Cloudflare R2 (S3-compatible) avec gzip
  • JSON par parts de 1000 images
  • CDN global, latence < 100 ms
  • Frontend no-code Lovable consommateur

3 décisions d'architecture clés

1. JSON pré-indexé vs API REST

La tentation était de construire une vraie API. Mauvaise idée : trop de latence, trop de coût d'infra. J'ai opté pour des JSON pré-calculés et pré-indexés stockés sur R2, organisés par parts de 1000 images. Le frontend pioche directement le JSON correspondant à la vue demandée. Latence < 100 ms, coût marginal proche de zéro, scalabilité illimitée.

2. SQLite locks pour la concurrence, pas Redis

Pour empêcher 2 jobs de tagger le même user en parallèle, on pourrait utiliser Redis. J'ai préféré better-sqlite3 en synchrone avec un table "locks" — moins exotique, zéro dépendance externe, suffisamment performant pour cette charge. C'est le pattern Salesforce SOQL avec FOR UPDATE appliqué à un pipeline local.

3. Image processing en 4 formats à la source

Plutôt que de redimensionner à la volée côté frontend (coût bandwidth, latence, SEO), je génère les 4 formats à l'étape 2 du pipeline et je les uploade tous sur R2. Le frontend choisit le bon format selon le contexte d'affichage. C'est une optimisation prématurée assumée — elle paie dès les premiers utilisateurs.

Résultats

51
catégories sémantiques (taxonomie GPT)
7
étapes orchestrées avec locks
4
formats d'images générés à la source
< 100ms
latence frontend via R2 CDN

Lien direct avec Salesforce

Tokenverse est un mini-Einstein. Voici la cartographie :

Lessons learned

← ALLIN Projet suivant : Moon List →