Stack Python - Implémentation
Date : 2026-01-24
Statut : ✅ Infrastructure Complétée - Production Ready
Dernière mise à jour : 2026-01-24
🚀 Optimisations Récentes (2026-01-24)
- ✅ Build Docker optimisé : PaddleOCR optionnel (build rapide ~2-3 minutes avec EasyOCR par défaut)
- ✅ Permissions corrigées : Installation dans
/usr/localpour utilisateur non-root - ✅ Structure Python :
app/config/__init__.pypour éviter conflit de noms - ✅ Compatibilité : sentence-transformers mis à jour pour compatibilité avec huggingface_hub
🎯 Objectif
Intégrer une stack Python pour des cas d'usage avancés (ML, embeddings, analytics) qui bénéficient de l'écosystème Python, tout en conservant l'architecture NestJS/BullMQ existante.
✅ Ce qui a été fait
1. Service Python FastAPI
Structure créée
- ✅ Service FastAPI :
python-service/avec structure modulaire - ✅ Embeddings Service : Service pour générer des embeddings avec sentence-transformers
- ✅ Health checks : Endpoints de santé et readiness
- ✅ Configuration : Settings avec Pydantic
- ✅ Dockerfile : Image Docker optimisée
Endpoints disponibles
GET /health- Health checkGET /health/ready- Readiness checkPOST /api/embeddings/text- Générer un embedding pour un textePOST /api/embeddings/texts- Générer des embeddings pour plusieurs textes (batch)
2. Worker NestJS (worker-ml)
Modules créés
- ✅ WorkerMlModule : Module principal du worker ML
- ✅ PythonMlService : Service HTTP pour communiquer avec le service Python
- ✅ MlEmbedTextProcessor : Processor pour les jobs
ml:embed_text - ✅ MlEmbedTextsProcessor : Processor pour les jobs
ml:embed_texts(batch)
Intégration
- ✅ Queue PYTHON_ML : Nouvelle queue BullMQ pour les jobs Python
- ✅ WorkersQueueService : Méthodes
enqueueMlEmbedText()etenqueueMlEmbedTexts() - ✅ Types et schémas : Payloads
MlEmbedTextPayloadetMlEmbedTextsPayloadavec validation Zod - ✅ WorkerModule : Intégration du
WorkerMlModuledans le worker principal
3. Infrastructure Docker
Services ajoutés
- ✅ python-ml-service : Service Python FastAPI
- ✅ qdrant : Base de données vectorielle (prête pour utilisation future)
Configuration
- ✅ Variables d'environnement pour le service Python
- ✅ Dépendances entre services (worker → python-ml-service)
- ✅ Volumes persistants pour Qdrant
📊 Architecture
┌─────────────┐
│ NestJS │
│ Backend │
└──────┬──────┘
│ BullMQ Jobs (ml:embed_text, ml:embed_texts)
↓
┌─────────────────┐
│ Worker NestJS │
│ (worker-ml) │
└──────┬──────────┘
│ HTTP REST
↓
┌─────────────────┐
│ Python Service │
│ (FastAPI) │
│ │
│ - Embeddings │
│ - ML │
└─────────────────┘
│
↓
┌─────────────────┐
│ Qdrant │
│ (Vector DB) │
└─────────────────┘
🚀 Utilisation
Enqueueer un job d'embedding
import { WorkersQueueService } from "@/workers/workers-queue.service";
// Embedding d'un seul texte
const jobId = await workersQueueService.enqueueMlEmbedText({
v: 1,
orgId: "org-uuid",
userId: "user-uuid",
entityId: "entity-uuid",
text: "Ceci est un texte à embedder",
model: "sentence-transformers/all-MiniLM-L6-v2", // Optionnel
requestId: "request-uuid", // Pour tracking via JobRunsService
});
// Embedding de plusieurs textes (batch)
const jobId = await workersQueueService.enqueueMlEmbedTexts({
v: 1,
orgId: "org-uuid",
userId: "user-uuid",
entityId: "entity-uuid",
texts: ["Texte 1", "Texte 2", "Texte 3"],
model: "sentence-transformers/all-MiniLM-L6-v2", // Optionnel
requestId: "request-uuid",
});
Polling du statut
Le job est tracké via JobRunsService comme tous les autres jobs :
import { useJobRun } from "@/client/job-runs/useJobRuns";
const { data: jobRun, isLoading } = useJobRun(requestId);
// jobRun.result contient { embedding, model, dimension }
📋 Variables d'environnement
Backend (NestJS)
PYTHON_ML_SERVICE_URL=http://python-ml-service:8000
Python Service
DEBUG=false
EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
EMBEDDING_DEVICE=cpu # ou cuda si GPU disponible
QDRANT_HOST=qdrant
QDRANT_PORT=6333
QDRANT_GRPC_PORT=6334
✅ Phase 2 : Intégration Qdrant (Complétée)
Services créés
- ✅ QdrantService : Service Python pour gérer Qdrant
- ✅ Endpoints Qdrant : CRUD complet pour les collections et points
- ✅ Processors NestJS : 4 processors pour les opérations Qdrant
- ✅ Types et schémas : Payloads complets avec validation Zod
Opérations disponibles
- ✅
ml:qdrant:create_collection- Créer une collection - ✅
ml:qdrant:upsert- Indexer des embeddings - ✅
ml:qdrant:search- Rechercher des embeddings similaires - ✅
ml:qdrant:delete- Supprimer des points
Exemple d'utilisation
// 1. Créer une collection
await workersQueueService.enqueueMlQdrantCreateCollection({
v: 1,
orgId: "org-uuid",
entityId: "collection-uuid",
collectionName: "sessions-embeddings",
vectorSize: 384, // Dimension des embeddings
distance: "Cosine",
});
// 2. Générer des embeddings et les indexer
const embeddings = await workersQueueService.enqueueMlEmbedTexts({
v: 1,
orgId: "org-uuid",
entityId: "batch-uuid",
texts: ["Session 1", "Session 2", "Session 3"],
});
// 3. Indexer les embeddings dans Qdrant
await workersQueueService.enqueueMlQdrantUpsert({
v: 1,
orgId: "org-uuid",
entityId: "upsert-uuid",
collectionName: "sessions-embeddings",
points: embeddings.embeddings.map((emb, idx) => ({
id: `session-${idx}`,
vector: emb,
payload: { text: texts[idx], orgId: "org-uuid" },
})),
});
// 4. Rechercher des embeddings similaires
await workersQueueService.enqueueMlQdrantSearch({
v: 1,
orgId: "org-uuid",
entityId: "search-uuid",
collectionName: "sessions-embeddings",
queryVector: queryEmbedding,
limit: 10,
scoreThreshold: 0.7,
filter: { orgId: "org-uuid" },
});
✅ Phase 3 : Recherche Sémantique dans les Sessions (Complétée)
Fonctionnalités implémentées
- ✅ SessionsSemanticSearchService : Service complet pour la recherche sémantique
- ✅ Endpoint API :
GET /api/sessions/search/semantic?q=... - ✅ Indexation automatique : Les nouvelles sessions sont indexées automatiquement
- ✅ Ré-indexation : Les sessions sont ré-indexées lors de modifications (title, notes, tags, etc.)
- ✅ Script de migration : Script pour indexer les sessions existantes
Utilisation
Recherche sémantique via API
GET /api/sessions/search/semantic?q=consultation%20anxiété&limit=10&scoreThreshold=0.7
Indexer les sessions existantes
npx tsx backend/src/sessions/scripts/index-sessions-for-semantic-search.ts <orgId> [batchSize]
Exemple de résultat
{
"query": "consultation anxiété",
"results": [
{
"session": { /* SessionWithRelations */ },
"score": 0.89
},
{
"session": { /* SessionWithRelations */ },
"score": 0.82
}
],
"count": 2
}
✅ Phase 3 : Recherche Sémantique dans les Sessions (Complétée)
Voir PYTHON_ML_FEATURES_COMPLETE.md pour la documentation complète.
✅ Phase 5 : OCR Avancé avec Python (Complétée)
Service OCR Python
- ✅ OCR Service : Service Python avec EasyOCR et PaddleOCR
- ✅ Endpoints API :
/api/ocr/extract,/api/ocr/extract-base64,/api/ocr/extract-simple - ✅ Processor BullMQ :
MlOcrProcessorpour traiter les jobsml:ocr - ✅ Intégration : Intégration avec le workflow OCR existant (fallback vers Tesseract.js)
Fonctionnalités
- ✅ Support multi-moteurs : EasyOCR (par défaut) et PaddleOCR
- ✅ Multi-langues : Support de plusieurs langues (en, fr, etc.)
- ✅ Détails optionnels : Bounding boxes et scores de confiance
- ✅ Fallback automatique : Si Python OCR échoue, utilise Tesseract.js
Configuration
# Activer/désactiver Vision OCR (GPT-4o) - par défaut: activé
USE_VISION_OCR=true
Utilisation
Le système utilise GPT-4o Vision API pour l'OCR si USE_VISION_OCR=true et si l'utilisateur a une clé API OpenAI configurée. En cas d'échec ou si l'utilisateur n'a pas de clé API, le système bascule automatiquement vers Tesseract.js.
Voir PYTHON_ML_FEATURES_COMPLETE.md pour tous les détails.
Fonctionnalités implémentées
- ✅ SessionsSemanticSearchService : Service complet pour la recherche sémantique
- ✅ Endpoint API :
GET /api/sessions/search/semantic?q=... - ✅ Indexation automatique : Les nouvelles sessions sont indexées automatiquement
- ✅ Ré-indexation : Les sessions sont ré-indexées lors de modifications (title, notes, tags, etc.)
- ✅ Script de migration : Script pour indexer les sessions existantes
✅ Phase 4 : Fonctionnalités Avancées (Complétées)
Recherche Sémantique dans les Contacts
- ✅ ContactsSemanticSearchService : Service complet
- ✅ Endpoint API :
GET /api/contacts/search/semantic?q=... - ✅ Indexation automatique : Création/modification/suppression
Suggestions de Sessions Similaires
- ✅ Endpoint API :
GET /api/sessions/:id/similar - ✅ Recommandations automatiques : Trouve des sessions similaires
Classification Automatique de Documents
- ✅ DocumentsClassificationService : Service de classification
- ✅ Endpoint API :
POST /api/documents/:id/classify - ✅ Types supportés : INVOICE, CONTRACT, QUESTIONNAIRE, OTHER
Voir PYTHON_ML_FEATURES_COMPLETE.md pour tous les détails.
Phase 3 : Cas d'usage avancés ✅ (Complété)
- ✅ Classification automatique de documents
- ✅ Recherche sémantique dans les sessions/contacts
- ✅ Recommandations basées sur les embeddings (sessions similaires)
Phase 4 : OCR Avancé ✅ (Complété)
- ✅ Évaluation PaddleOCR vs EasyOCR (EasyOCR par défaut, PaddleOCR optionnel)
- ✅ Service OCR Python implémenté (EasyOCR/PaddleOCR avec fallback Tesseract.js)
- ✅ Comparaison avec Tesseract.js (fallback automatique si Python OCR échoue)
📚 Documentation
- Planification Stack Python - Plan initial et cas d'usage
- Python ML Features Complete - Documentation complète des fonctionnalités ML
- Python Stack Final Status - Statut final production-ready
- Python Stack Deployment - Guide de déploiement production
- Workers Architecture - Architecture générale des workers
🎉 Conclusion
L'infrastructure de base pour la stack Python est maintenant opérationnelle. Le service Python peut générer des embeddings localement, réduisant les coûts OpenAI. L'architecture est prête pour l'intégration de Qdrant et d'autres fonctionnalités ML avancées.