root 5d8ad901d1 Initial commit: Pipeline notarial complet
- Infrastructure complète de traitement de documents notariaux
- API FastAPI d'ingestion et d'orchestration
- Pipelines Celery pour le traitement asynchrone
- Support des formats PDF, JPEG, PNG, TIFF, HEIC
- OCR avec Tesseract et correction lexicale
- Classification automatique des documents avec Ollama
- Extraction de données structurées
- Indexation dans AnythingLLM et OpenSearch
- Système de vérifications et contrôles métier
- Base de données PostgreSQL pour le métier
- Stockage objet avec MinIO
- Base de données graphe Neo4j
- Recherche plein-texte avec OpenSearch
- Supervision avec Prometheus et Grafana
- Scripts d'installation pour Debian
- Documentation complète
- Tests unitaires et de performance
- Service systemd pour le déploiement
- Scripts de déploiement automatisés
2025-09-08 22:05:22 +02:00

128 lines
3.9 KiB
Python

"""
Pipeline de préprocessing des documents
"""
import os
import logging
from PIL import Image
import tempfile
from utils.storage import get_local_temp_file, cleanup_temp_file, store_artifact
logger = logging.getLogger(__name__)
def run(doc_id: str, ctx: dict):
"""
Étape de préprocessing d'un document
"""
logger.info(f"Préprocessing du document {doc_id}")
try:
# Récupération du document original
content = get_document(doc_id)
ctx["original_content"] = content
# Détermination du type de fichier
mime_type = ctx.get("mime_type", "application/pdf")
if mime_type == "application/pdf":
# Traitement PDF
_preprocess_pdf(doc_id, ctx)
elif mime_type.startswith("image/"):
# Traitement d'image
_preprocess_image(doc_id, ctx)
else:
raise ValueError(f"Type de fichier non supporté: {mime_type}")
# Stockage des métadonnées de préprocessing
preprocessing_meta = {
"original_size": len(content),
"mime_type": mime_type,
"preprocessing_completed": True
}
ctx["preprocessing_meta"] = preprocessing_meta
logger.info(f"Préprocessing terminé pour le document {doc_id}")
except Exception as e:
logger.error(f"Erreur lors du préprocessing du document {doc_id}: {e}")
raise
def _preprocess_pdf(doc_id: str, ctx: dict):
"""
Préprocessing spécifique aux PDF
"""
try:
# Création d'un fichier temporaire
temp_pdf = get_local_temp_file(doc_id, ".pdf")
try:
# Vérification de la validité du PDF
import PyPDF2
with open(temp_pdf, 'rb') as file:
pdf_reader = PyPDF2.PdfReader(file)
# Métadonnées du PDF
pdf_meta = {
"page_count": len(pdf_reader.pages),
"has_text": False,
"is_scanned": True
}
# Vérification de la présence de texte
for page in pdf_reader.pages:
text = page.extract_text().strip()
if text:
pdf_meta["has_text"] = True
pdf_meta["is_scanned"] = False
break
ctx["pdf_meta"] = pdf_meta
ctx["temp_pdf_path"] = temp_pdf
logger.info(f"PDF {doc_id}: {pdf_meta['page_count']} pages, texte: {pdf_meta['has_text']}")
finally:
# Le fichier temporaire sera nettoyé plus tard
pass
except Exception as e:
logger.error(f"Erreur lors du préprocessing PDF pour {doc_id}: {e}")
raise
def _preprocess_image(doc_id: str, ctx: dict):
"""
Préprocessing spécifique aux images
"""
try:
# Création d'un fichier temporaire
temp_image = get_local_temp_file(doc_id, ".jpg")
try:
# Ouverture de l'image avec PIL
with Image.open(temp_image) as img:
# Métadonnées de l'image
image_meta = {
"width": img.width,
"height": img.height,
"mode": img.mode,
"format": img.format
}
# Conversion en RGB si nécessaire
if img.mode != 'RGB':
img = img.convert('RGB')
img.save(temp_image, 'JPEG', quality=95)
ctx["image_meta"] = image_meta
ctx["temp_image_path"] = temp_image
logger.info(f"Image {doc_id}: {image_meta['width']}x{image_meta['height']}, mode: {image_meta['mode']}")
finally:
# Le fichier temporaire sera nettoyé plus tard
pass
except Exception as e:
logger.error(f"Erreur lors du préprocessing image pour {doc_id}: {e}")
raise