SmartWatch est un pipeline d'extraction de données conçu pour extraire, analyser, et comparer les horaires d'ouverture de divers établissements publics de la Métropole de Lyon (mairies, piscines, médiathèques), à partir de leurs sites web. Il utilise des modèles de langage pour interpréter le contenu et comparer les horaires d'ouverture extraits à des données de référence (issues de data.grandlyon.com), puis génère et envoie par mail des rapports HTML interactifs pour visualiser les résultats.
- Collecte de données : charge les URLs des établissements à analyser depuis un fichier CSV.
- Conversion des données : converti les pages web en Markdown et nettoie ce dernier pour ne garder que l'essentiel
- Filtrage de contenu intelligent : utilise des embeddings (via
jina-embeddings-v3
) pour identifier et extraire uniquement les sections de page web relatives aux horaires, optimisant ainsi les appels aux LLM. - Extraction par LLM : interroge des LLM (compatibles OpenAI ou Mistral) pour extraire les horaires dans un format structuré customisé (JSON).
- Suivi de la consommation carbone : mesure les émissions de CO2 des appels aux LLM (extraction et embeddings) grâce à
codecarbon
et les affiche dans les rapports. - Comparaison automatisée : compare les horaires extraits par le LLM avec des données de référence (depuis data.grandlyon.com) pour détecter les divergences.
- Rapports détaillés : génère des rapports HTML interactifs, permettant de visualiser les statistiques globales, les statuts de traitement, et les détails de chaque URL.
- Orchestration : un pipeline assure une exécution séquentielle et contrôlée.
- Conteneurisation : prêt à l'emploi avec Docker et Docker Compose pour un déploiement simplifié.
[ main.py ] (Orchestrateur)
│
├─> A. Charge la configuration [ core.ConfigManager ] (depuis .env)
│ └─> Agrège [ config.* ] (LLMConfig, DatabaseConfig, etc.)
│
├─> B. Instancie les processeurs principaux avec la configuration
│
└─> C. Exécute séquentiellement le pipeline :
│
├─> [1] Création : [ processing.DatabaseProcessor ]
│ (Créé la base de données et les tables nécessaires)
|
├─> [2] Initialisation : [ utils.CSVToPolars ] -> [ processing.SetupProcessor ]
│ (Charge les URLs depuis le CSV et prépare une nouvelle exécution)
│
├─> [3] Extraction URL : [ processing.URLProcessor ]
│ (Récupère le contenu des URLs)
│ └─> Utilise [ utils.HtmlToMarkdown ] pour la conversion
│
├─> [4] Nettoyage : [ utils.MarkdownCleaner ]
│ (Nettoie le Markdown brut)
│
├─> [5] Filtrage : [ core.MarkdownProcessor ]
│ (Filtre le Markdown sémantiquement par embeddings, pour ne garder que les sections pertinentes)
│ └─> Utilise [ core.LLMClient ] pour les embeddings
│
├─> [6] Extraction LLM : [ processing.LLMProcessor ]
│ (Extrait par LLM et au format JSON les horaires du Markdown filtré)
│ ├─> Utilise [ core.LLMClient ] pour l'appel au LLM
│ └─> Utilise [ utils.CustomJsonToOSM ] pour convertir le JSON en format OSM
│
├─> [7] Comparaison : [ processing.ComparisonProcessor ]
│ (Compare les horaires extraits (OSM) avec les données de référence issues de data.grandlyon.com)
│ └─> Utilise [ core.ComparateurHoraires ] pour la logique de comparaison
│
└─> [8] Rapport : [ reporting.ReportManager ]
(Génère et envoie le rapport final)
├─> Utilise [ reporting.GenererRapportHTML ] pour créer le fichier HTML
└─> Utilise [ core.EmailSender ] pour envoyer l'email avec pièces jointes
- [ core.Logger ] : utilisé par tous les modules pour la journalisation.
- [ core.ErrorHandler ] : utilisé pour une gestion centralisée des erreurs.
- [ core.DatabaseManager ] : utilisé pour lire et écrire les résultats dans la base de données SQLite.
- [ codecarbon ] : mesure les émissions de CO2 des appels aux LLM.
- [ data_models.schema_bdd ] : définit la structure de la base de données pour SQLAlchemy.
- [ data_models.opening_hours_schema.json ] : modèle JSON spécifique décrivant des horaires d'ouverture.
- [ assets.templates.ReportTemplate.html ] : modèle html pour le rapport envoyé en pièce jointe du mail.
- [ assets.templates.SimpleReportTemplate.html ] : modèle html pour le corps du mail.
L'extraction des horaires d'ouverture depuis les pages web (via un Markdown nettoyé et filtré) est soumise au fonctionnement du LLM choisi.
Le modèle JSON sera automatiquement passé en argument du prompt et assure normalement une sortie structurée et reproductible. Ce modèle est passé en argument au LLM, en tant que response_format
pour les modèles compatibles OpenAI, et en tant que tool_params
pour les modèles Mistral via API (cf processing.llm_processor.py
).
-
Clonez le dépôt :
git clone https://github.com/datagora-erasme/smart_watch cd smart_watch
-
Créez un environnement virtuel et installez les dépendances :
-
Avec
pip
(méthode classique) :# Créez et activez l'environnement virtuel python -m venv .venv source .venv/bin/activate # Sur Windows: .venv\Scripts\activate # Installez les dépendances pip install -r requirements.txt
-
Avec
uv
(méthode recommandée, plus rapide) :# Créez, activez et installez les dépendances en une seule commande uv sync
Pour activer l'environnement par la suite :
source .venv/bin/activate
(ou.venv\Scripts\activate
sur Windows).
-
-
Installez les navigateurs Playwright :
python -m playwright install
Sur Linux, si des dépendances système sont manquantes, exécutez d'abord :
python -m playwright install-deps
Sur Windows, la commande
install
suffit généralement.
- Créez un fichier
.env
à la racine du projet en vous basant sur le modèleenv.model
. - Configurez les variables d'environnement requises :
CSV_URL_HORAIRES
: l'URL ou le chemin local du fichier CSV contenant les lieux à analyser.- Configuration LLM : renseignez les URL, clés API et le modèle pour le fournisseur de votre choix (OpenAI, Mistral, etc.).
- Configuration Email : paramétrez les emails et informations SMTP pour l'envoi des rapports.
Pour lancer le pipeline complet, exécutez le script principal :
python main.py
Le programme effectuera les actions suivantes :
- initialisera la base de données SQLite (
data/SmartWatch.db
). - traitera chaque URL, filtrera le contenu, et extraiera les horaires via le LLM.
- comparera les résultats et stockera tout en base de données.
- enverra un rapport et les logs par mail.
- écrira les logs dans
logs/SmartWatch.log
.
Pour lancer l'application avec Docker, la méthode recommandée est d'utiliser docker-compose
, qui simplifie la gestion du conteneur et des variables d'environnement.
-
Assurez-vous que votre fichier
.env
est présent à la racine du projet. -
Construisez l'image et lancez le conteneur avec
docker-compose
:docker-compose up --build
Cette commande va :
- Construire l'image Docker en se basant sur le
Dockerfile
. - Créer et démarrer le conteneur.
- Charger automatiquement les variables d'environnement depuis le fichier
.env
.
Les rapports et la base de données seront générés dans les dossiers
data
etlogs
de votre machine hôte. - Construire l'image Docker en se basant sur le
Si vous souhaitez améliorer ce projet, veuillez suivre les étapes ci-dessous :
-
Forkez le projet : Cliquez sur le bouton "Fork" en haut à droite de cette page pour créer une copie du projet dans votre propre compte GitHub.
-
Créez une branche : Créez une branche pour votre nouvelle fonctionnalité ou votre correctif.
git checkout -b feature/ma-nouvelle-feature
-
Faites vos modifications : Apportez les modifications souhaitées au code.
-
Formatez votre code : Avant de commiter, assurez-vous que votre code est correctement formaté en utilisant
ruff
. Les règles de formatage sont définies dans le fichierpyproject.toml
:line-length = 88
indent-width = 4
quote-style = "double"
preview = false
-
Commitez vos changements :
git commit -m "Ajout de ma nouvelle fonctionnalité"
-
Poussez vers votre branche :
git push origin feature/ma-nouvelle-feature
-
Ouvrez une Pull Request : Rendez-vous sur la page du dépôt original et ouvrez une "Pull Request" pour que vos modifications soient examinées et intégrées.
Ce projet est sous licence MIT. Voir le fichier LICENSE