Published

Documentation fonctionnelle : règles de construction de l'écoscore Nudger

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 objet Score qui 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 comme ecoscorePercentOf ou ecoscoreParticipationMaxPointsOf20 pour 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 aussi ecoScoreDetails pour 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 :

  1. la map criteriasPonderation (nom du score → poids),
  2. un bloc texts multilingue (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

  1. Mesurer la couverture des sous-scores : le service VerticalsGenerationService agrège les statistiques par score via repository.scoresCoverage et 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】
  2. Choisir et pondérer les critères : sélectionner des critères présents dans availableImpactScoreCriterias et leur attribuer une pondération dont la somme vaut 1 (cf. gabarit). Les helpers de VerticalConfig permettent 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】
  3. 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】
  4. Générer et archiver la configuration : l’API /verticals-generation/{vertical}/ecoscore/ déclenche generateEcoscoreYamlConfig, qui appelle le moteur de prompts impactscore-generation pour produire un bloc impactScoreConfig prê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】
  5. 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

  1. Normalisation des sous-scores : pour chaque score déclaré dans les pondérations, AbstractScoreAggregationService construit une cardinalité globale (min, max, moyenne) au fil du batch (incrementCardinality). Lors de la phase done, 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】
  2. Somme pondérée : EcoScoreAggregationService parcourt la map criteriasPonderation, vérifie qu’un sous-score relativisé existe pour chaque critère (sinon une ValidationException est levée) et additionne valeur_relative × poids afin 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】
  3. 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 relativ avant 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】
  4. Classement spécifique écoscore : après super.done, le service trie les produits sur leur valeur d’écoscore, remplit EcoScoreRanking (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 que Score.percent(), Score.on20() et Score.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 / ecoscoreParticipationMaxPointsOf20 pour afficher la part de chaque critère et ecoScoreDetails pour 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 : ImpactScoreTexts doit ê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_QUALITY dans 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 prompts impactscore-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 »

  1. Vérifier que les sous-scores utiles existent et sont complets via les statistiques exposées par VerticalsGenerationService.
  2. Définir des poids qui totalisent 1 et couvrent l’ensemble du cycle de vie, en s’appuyant sur le catalogue _default pour les descriptions officielles.
  3. Documenter clairement les choix (objectif, analyse, limites, données) et conserver les prompts IA.
  4. Déployer la configuration via les endpoints dédiés puis relancer l’agrégation pour recalculer l’écoscore et les classements.
  5. Contrôler, côté produit, que Product.ecoscore() ainsi que les aides de VerticalConfig rendent les mêmes résultats que ceux affichés dans l’UI.