Documentation fonctionnelle : règles de construction de l'écoscore Nudger
1. Objectif et périmètre
Chaque produit agrégé par Nudger expose un score synthétique nommé ECOSCORE au sein de sa carte des scores (Product.scores). Ce score est accessible par Product.ecoscore(), restituable en chaîne via ecoscoreAsString() et transporté avec les autres évaluations lors des échanges API.【F:model/src/main/java/org/open4goods/model/product/Product.java†L273-L306】【F:model/src/main/java/org/open4goods/model/product/Product.java†L556-L563】
La position du produit par rapport au reste de la verticale est stockée dans EcoScoreRanking, qui mémorise rang, taille d’échantillon et identifiants des meilleurs produits afin d’alimenter les recommandations et les écrans « meilleure alternative ».【F:model/src/main/java/org/open4goods/model/product/Product.java†L838-L844】【F:model/src/main/java/org/open4goods/model/product/EcoScoreRanking.java†L1-L77】
2. Briques métier utilisées par l'écoscore
- Score unitaire (
Score) : chaque critère environnemental est encapsulé dans un objetScorequi garde la valeur brute, une cardinalité absolue (min, max, moyenne, nombre de mesures) et sa version « relativisée » utilisée pour comparer des produits. L’objet expose aussi les conversions en pourcentage, en note sur 20 et la notation A–E.【F:model/src/main/java/org/open4goods/model/product/Score.java†L1-L200】 - Normalisation : toutes les valeurs relatives sont ramenées sur une échelle commune de 0 à 5 par
StandardiserService.DEFAULT_MAX_RATING, ce qui garantit que les pondérations de l'écoscore comparent des grandeurs compatibles.【F:model/src/main/java/org/open4goods/model/StandardiserService.java†L13-L39】 - Configuration verticale : chaque verticale (
VerticalConfig) décrit ses filtres, ses sous-scores disponibles et expose des helpers commeecoscorePercentOfouecoscoreParticipationMaxPointsOf20pour calculer la part de chaque critère dans la note finale et l’exprimer sur 20 points.【F:model/src/main/java/org/open4goods/model/vertical/VerticalConfig.java†L370-L397】 Elle fournit aussiecoScoreDetailspour récupérer la liste des sous-scores réellement utilisés chez un produit donné.【F:model/src/main/java/org/open4goods/model/vertical/VerticalConfig.java†L549-L565】
3. Structure d’un écoscore de verticale
L’écoscore se déclare dans chaque fichier YAML de verticale sous la clef impactScoreConfig. Le gabarit vertical-definition.yml rappelle le format attendu (liste CRITERE: PONDERATION) et impose fonctionnellement que la somme des poids soit égale à 1 pour conserver un score sur 5 points.【F:api/src/main/resources/templates/vertical-definition.yml†L73-L104】
ImpactScoreConfig porte deux familles d’informations :
- la map
criteriasPonderation(nom du score → poids), - un bloc
textsmultilingue (ImpactScoreTexts) qui décrit l’objectif, la revue critique, les données disponibles et une analyse par critère pour la transparence utilisateur.【F:model/src/main/java/org/open4goods/model/vertical/ImpactScoreConfig.java†L1-L49】【F:model/src/main/java/org/open4goods/model/vertical/ImpactScoreTexts.java†L1-L35】
Pour assurer l’auditabilité, le fichier conserve également la requête envoyée au moteur IA (yamlPrompt) et la réponse JSON (aiJsonResponse) ayant permis de générer automatiquement la pondération.【F:model/src/main/java/org/open4goods/model/vertical/ImpactScoreConfig.java†L21-L48】
Catalogue des critères disponibles
Chaque verticale hérite du référentiel _default.yml, qui liste les critères officiellement supportés (availableImpactScoreCriterias) avec leur titre et description (classe énergétique, indice de réparabilité, consommation en marche/arrêt, durabilité de la marque, qualité de la donnée, etc.).【F:verticals/src/main/resources/verticals/_default.yml†L114-L158】 Ce catalogue sert à la fois à guider les IA génératives et à alimenter l’interface publique.
Exemple (verticale « Téléviseurs »)
Le fichier tv.yml illustre un écoscore complet : six critères pondérés (ex. 30 % pour la consommation typique, 20 % pour l’indice de réparabilité) et des textes explicatifs rédigés en français. Les prompts/réponses de génération sont archivés dans le même bloc.【F:verticals/src/main/resources/verticals/tv.yml†L1-L75】 Cette structure doit être reproduite/adaptée pour toute nouvelle verticale.
4. Procédure fonctionnelle pour définir un écoscore
- Mesurer la couverture des sous-scores : le service
VerticalsGenerationServiceagrège les statistiques par score viarepository.scoresCoverageet construit un inventaire des critères réellement disponibles pour la verticale (cléAVAILABLE_CRITERIAS).【F:api/src/main/java/org/open4goods/api/services/VerticalsGenerationService.java†L610-L678】 - Choisir et pondérer les critères : sélectionner des critères présents dans
availableImpactScoreCriteriaset leur attribuer une pondération dont la somme vaut 1 (cf. gabarit). Les helpers deVerticalConfigpermettent ensuite de restituer ces choix en pourcentage et en points sur 20 pour la communication utilisateur.【F:api/src/main/resources/templates/vertical-definition.yml†L73-L84】【F:model/src/main/java/org/open4goods/model/vertical/VerticalConfig.java†L370-L397】 - Documenter la méthode : renseigner
ImpactScoreTexts(but, analyse par critère, limites, sources de données) afin de publier les justifications dans l’UI.【F:model/src/main/java/org/open4goods/model/vertical/ImpactScoreTexts.java†L1-L35】 - Générer et archiver la configuration : l’API
/verticals-generation/{vertical}/ecoscore/déclenchegenerateEcoscoreYamlConfig, qui appelle le moteur de promptsimpactscore-generationpour produire un blocimpactScoreConfigprêt à être collé dans le YAML de la verticale, tout en conservant le prompt et la réponse JSON pour audit.【F:api/src/main/java/org/open4goods/api/controller/api/VerticalsGenerationController.java†L151-L205】【F:api/src/main/java/org/open4goods/api/services/VerticalsGenerationService.java†L610-L678】 - Mettre à jour les fichiers de config : des endpoints dédiés permettent de réinjecter automatiquement les blocs
impactScore, attributs et catégories dans les fichiers YAML (ex./verticals-generation/update/{vertical}), ce qui réduit les manipulations manuelles lors des recalibrages.【F:api/src/main/java/org/open4goods/api/controller/api/VerticalsGenerationController.java†L179-L205】
5. Algorithme de calcul de l’écoscore
- Normalisation des sous-scores : pour chaque score déclaré dans les pondérations,
AbstractScoreAggregationServiceconstruit une cardinalité globale (min, max, moyenne) au fil du batch (incrementCardinality). Lors de la phasedone, il crée des scores virtuels si besoin, attribue les valeurs absolues aux produits, puis relativise chaque valeur sur l’échelle commune (0–5) avant de calculer les classements best/worst génériques.【F:api/src/main/java/org/open4goods/api/services/aggregation/services/batch/scores/AbstractScoreAggregationService.java†L1-L214】 - Somme pondérée :
EcoScoreAggregationServiceparcourt la mapcriteriasPonderation, vérifie qu’un sous-score relativisé existe pour chaque critère (sinon uneValidationExceptionest levée) et additionnevaleur_relative × poidsafin d’obtenir une note intrinsèquement bornée entre 0 et 5 si la somme des poids vaut 1.【F:api/src/main/java/org/open4goods/api/services/aggregation/services/batch/scores/EcoScoreAggregationService.java†L40-L74】 - Neutralisation d’une deuxième relativisation : comme la valeur obtenue est déjà normalisée par construction, le service recopie la cardinalité absolue dans le champ
relativavant de déléguer au traitement générique, évitant une renormalisation contre-productive.【F:api/src/main/java/org/open4goods/api/services/aggregation/services/batch/scores/EcoScoreAggregationService.java†L80-L90】 - Classement spécifique écoscore : après
super.done, le service trie les produits sur leur valeur d’écoscore, remplitEcoScoreRanking(position, total, meilleur produit, produit juste supérieur) et stocke ces informations pour alimenter les comparaisons rapides dans les UIs.【F:api/src/main/java/org/open4goods/api/services/aggregation/services/batch/scores/EcoScoreAggregationService.java†L92-L113】【F:model/src/main/java/org/open4goods/model/product/EcoScoreRanking.java†L6-L77】
6. Restitution et exploitation
Product.ecoscore()donne accès au score global, tandis queScore.percent(),Score.on20()etScore.letter()fournissent les représentations attendues (pourcentage, note sur 20, lettre A–E).【F:model/src/main/java/org/open4goods/model/product/Product.java†L273-L305】【F:model/src/main/java/org/open4goods/model/product/Score.java†L120-L200】Product.ecoscoreAsString()retourne la note sur 5 en texte (X/5), ce qui simplifie les exports ou messages courts.【F:model/src/main/java/org/open4goods/model/product/Product.java†L556-L563】- Les écrans d’impact utilisent
VerticalConfig.ecoscorePercentOf/ecoscoreParticipationMaxPointsOf20pour afficher la part de chaque critère etecoScoreDetailspour afficher les sous-scores réellement présents, assurant ainsi la cohérence entre calcul technique et pédagogie utilisateur.【F:model/src/main/java/org/open4goods/model/vertical/VerticalConfig.java†L370-L397】【F:model/src/main/java/org/open4goods/model/vertical/VerticalConfig.java†L549-L565】
7. Exigences métier et contrôles
- Somme des poids : même si le code n’impose pas encore une validation stricte, le gabarit YAML et les helpers partent du principe que les poids totalisent 1. Un non-respect entraînerait un score hors échelle.【F:api/src/main/resources/templates/vertical-definition.yml†L73-L84】
- Disponibilité des sous-scores : toute pondération pointant vers un critère absent provoque une erreur bloquante (
ValidationException) et empêche l’écriture d’un écoscore incohérent.【F:api/src/main/java/org/open4goods/api/services/aggregation/services/batch/scores/EcoScoreAggregationService.java†L60-L67】 - Transparence et audit :
ImpactScoreTextsdoit être renseigné (purpose, analyse, limites, données disponibles) et les prompts IA conservés pour justifier les coefficients publiés.【F:model/src/main/java/org/open4goods/model/vertical/ImpactScoreConfig.java†L21-L48】【F:model/src/main/java/org/open4goods/model/vertical/ImpactScoreTexts.java†L1-L35】 - Critère « Qualité de la donnée » : la présence du critère
DATA_QUALITYdans le référentiel par défaut rappelle qu’un produit incomplet voit sa note pénalisée, ce qui incite à enrichir les données avant toute comparaison.【F:verticals/src/main/resources/verticals/_default.yml†L152-L157】
8. Maintenance et outils automatisés
- L’endpoint
/verticals-generation/{vertical}/ecoscore/génère une proposition d’écoscore basée sur les données réelles (couverture des scores existants + nom de la verticale) via le service de promptsimpactscore-generation. Le bloc YAML retourné inclut directement les pondérations, la documentation et les traces IA.【F:api/src/main/java/org/open4goods/api/controller/api/VerticalsGenerationController.java†L151-L159】【F:api/src/main/java/org/open4goods/api/services/VerticalsGenerationService.java†L610-L678】 - Pour appliquer les modifications dans le dépôt de configurations, des routes d’« update » permettent d’insérer automatiquement les blocs
impactScore, attributs et mappings de catégories dans les fichiers physiques (chemin configurable dans le service).【F:api/src/main/java/org/open4goods/api/controller/api/VerticalsGenerationController.java†L179-L205】 - Lors d’un recalibrage, rejouer les étapes « couverture des sous-scores → génération IA → revue humaine → commit YAML » garantit que les pondérations reflètent bien les données disponibles et que les justifications affichées au public sont alignées sur le calcul réel.
9. Synthèse « mode d’emploi »
- Vérifier que les sous-scores utiles existent et sont complets via les statistiques exposées par
VerticalsGenerationService. - Définir des poids qui totalisent 1 et couvrent l’ensemble du cycle de vie, en s’appuyant sur le catalogue
_defaultpour les descriptions officielles. - Documenter clairement les choix (objectif, analyse, limites, données) et conserver les prompts IA.
- Déployer la configuration via les endpoints dédiés puis relancer l’agrégation pour recalculer l’écoscore et les classements.
- Contrôler, côté produit, que
Product.ecoscore()ainsi que les aides deVerticalConfigrendent les mêmes résultats que ceux affichés dans l’UI.