Limoges Habitat
Aperçu du projet
Limoges Habitat est une entreprise de gestion locative sociale. Lors de mon stage (avril à juin 2026), j'ai participé au développement de la phase 4 de leur système GED interne (Gestion Électronique de Documents).
L'objectif était de créer un système capable de centraliser, indexer et retrouver les documents internes (baux, correspondances, dossiers administratifs) de manière intelligente. Ma phase 4 a spécifiquement porté sur l'affinage du pipeline de traitement textuel : extraction robuste des données depuis des PDFs et images, normalisation du texte, suppression des éléments parasites, vérification orthographique, et finalement une couche d'analyse sémantique pour regrouper automatiquement les documents similaires.
Fonctionnalités principales
- Pipeline textCleaner.js en 6 étapes : protection des motifs sensibles, suppression du bruit, tokenization agressif français, stopwords (~200 mots français), vérification dictionnaire (Levenshtein ≤ 2), filtre sémantique
- Extraction PDF/image via Apache Tika 3.3.0 avec OCR Tesseract intégré nativement
- Orchestration worker asynchrone RabbitMQ : 3 files de priorité (urgent / normal / bulk) via canal.get()
- Gestion des erreurs distribuées : nack + requeue pour les erreurs infrastructure, ack + marquage FAILED en base pour les erreurs métier
- Indexation sémantique OpenSearch avec analyzer custom français (lowercase + asciifolding)
- Calibrage automatique du seuil de similarité vectorielle (all-MiniLM-L6-v2) à 0.20 après testing
- Détection de type de document via dossier d'accueil en répertoire partagé (workerDossier)
- Tests Jest + Babel pour validation de chaque étape du flux
Technologies utilisées
Backend : Node.js (API + workers asynchrones), PostgreSQL avec migrations Knex.js, RabbitMQ pour l'orchestration des tâches en arrière-plan.
Stockage & indexation : Garage (S3-compatible) pour les fichiers bruts, OpenSearch pour l'indexation textuelle et vectorielle.
Traitement textuel : Apache Tika 3.3.0 (extraction multiformat), nspell + Grammalecte (vérification orthographique française), @xenova/transformers / all-MiniLM-L6-v2 (embeddings sémantiques).
Tests : Jest + Babel pour valider le pipeline à chaque étape.
Mon rôle
J'ai implémenté l'ensemble du pipeline textCleaner.js en cohérence avec l'architecture existante. Cela comprenait la conception de 6 étapes d'ordre critique : protection des motifs sensibles (numéros, dates), suppression du bruit (accents, caractères parasites), tokenization agressif, application d'une liste de stopwords de ~200 mots français, vérification dictionnaire avec distance Levenshtein, et enfin un filtre sémantique basé sur les embeddings.
J'ai aussi intégré Apache Tika 3.3.0 pour extraire le texte et les images des PDFs, orchestré les workers RabbitMQ pour gérer l'asynchrone sur 3 niveaux de priorité, calibré le seuil de similarité sémantique à 0.20 après test empirique, et configuré OpenSearch avec un analyzer français custom pour l'indexation. Déboguer un système distribué impliquant des files, des workers, une API et un index a demandé rigueur et persévérance.
Compétence BUT démontrée
Limoges Habitat — Phase 4 du système GED
Niveau estimé : 4 — AutonomieDescription : Dans le cadre d'un vrai stage en entreprise, j'ai développé la phase 4 d'un système GED conçu pour centraliser et retrouver des documents internes. L'enjeu était de créer un pipeline de traitement textuel robuste capable de gérer des documents de qualité variable (PDFs scannés, images mal orientées, texte corrompu) et de les préparer pour l'indexation sémantique. Cela m'a imposé d'adapter ma solution à un contexte métier réel : comprendre les besoins des utilisateurs PSI, respecter l'architecture existante, déboguer en environnement de production, et itérer sur le seuil sémantique en fonction des cas réels.
Mon rôle : J'ai pris en charge la conception et l'implémentation du pipeline textCleaner.js, l'intégration d'Apache Tika et Tesseract, l'orchestration des workers RabbitMQ (gestion des 3 files et des erreurs), le calibrage du seuil de similarité (0.20 validé empiriquement), la configuration d'OpenSearch avec analyzer français, et le debugging systématique du flux de bout en bout. J'ai aussi collaboré avec le superviseur Nicolas Bartkowiak (développeur) et l'équipe PSI pour valider les décisions architecturales et répondre aux questions métier.
Analyse réflexive
Ce stage m'a montré la différence entre « faire du code » et « adapter une solution à un contexte réel ». Un bug qu'on débogue en 10 minutes en labo peut prendre 2 heures en production quand 50 documents arrivent simultanément dans 3 files différentes et qu'on ne sait pas d'où vient l'erreur. J'ai appris à instrumenter correctement (logs structurés, traces d'exécution), à documenter les décisions (pourquoi 0.20 et pas 0.15 pour le seuil ?), et à communiquer avec des utilisateurs finaux qui ne sont pas des développeurs. C'est aussi ici que j'ai vraiment compris que le NLP appliqué, ce n'est pas juste « passer du texte dans un modèle » — c'est des dizaines de décisions d'ordre et de seuil qui impactent l'expérience réelle.
Apprentissages
Ce stage m'a apporté une expertise solide en traitement de texte appliqué : extraction multiformat (PDF, image, OCR), normalisation robuste, vectorisation sémantique et seuillage empirique.
J'ai aussi découvert l'architecture scalable avec RabbitMQ et les workers asynchrones — comment penser en termes de files, de retry, de deadline, et de gestion d'erreurs distribuées. PostgreSQL + Knex.js en contexte réel (migrations versionnées, contraintes, indexation intelligente) m'a donné une rigueur que je n'aurais pas eue en dev perso.
Enfin, la communication technique dans une vraie boîte — réunions de suivi, discuter des choix architecturaux avec l'équipe, répondre aux questions des utilisateurs — a renforcé mes soft skills. Je me suis rendu compte que bien expliquer une décision technique à un non-dev est un talent qui se cultive.