Aller au contenu principal

Gap Filling Modules (GFM)

Les Gap Filling Modules sont les elements constitutifs du moteur de calcul EOS. Chaque module est une unite specialisee et autonome qui gere un aspect specifique du calcul d'incidence environnementale.

Que sont les Gap Filling Modules ?

Dans le monde reel, les donnees sur les produits alimentaires sont souvent incompletes. Un produit peut avoir :

  • Un nom mais pas de liste d'ingredients
  • Des ingredients mais pas d'informations sur l'origine
  • Une origine mais pas de details sur le transport
  • Des donnees nutritionnelles partielles

Les GFM resolvent ce probleme en comblant automatiquement les lacunes dans les donnees produit a l'aide de modeles scientifiques, de bases de donnees et de valeurs par defaut intelligentes.

Le concept GFM

4983b38890efe35bf9668dfb86dc7c0a

Chaque GFM se compose de :

  1. Logique de planification - Determine si le module est pertinent pour un noeud donne
  2. Verification de disponibilite - Verifie que toutes les dependances sont satisfaites
  3. Execution - La logique de calcul qui comble les lacunes et met a jour le graphe

Modules disponibles

EOS comprend 28 GFM specialises organises par fonction :

Modules de correspondance

Font correspondre les noms de produits et ingredients aux entrees de la base de donnees :

ModuleObjectif
match_product_name_gfmFait correspondre les noms de produits aux entrees de la base de donnees
attach_food_tags_gfmAttache les etiquettes de classification alimentaire
link_term_to_activity_node_gfmLie les termes aux activites ACV
link_food_categories_gfmAttribue les categories alimentaires

Modules de localisation

Gerent les donnees geographiques et d'origine :

ModuleObjectif
origin_gfmDetermine l'origine du produit
location_gfmGestion de la localisation geographique
transportation_decision_gfmDetermine les modes de transport
transportation_mode_distance_gfmCalcule les distances de transport

Modules de cycle de vie

Modelisent la transformation et la chaine d'approvisionnement :

ModuleObjectif
processing_gfmIncidences de la transformation alimentaire
greenhouse_gfmCalculs des gaz a effet de serre
conservation_gfmStockage et conservation
perishability_gfmDuree de conservation et facteurs de perte

Modules d'evaluation de l'incidence

Calculent les metriques environnementales :

ModuleObjectif
impact_assessment_gfmAgrege les calculs d'incidence
water_scarcity_gfmCalcul de l'empreinte hydrique
rainforest_gfmIncidence sur la deforestation
vitascore_gfmScore nutritionnel

Modules d'agregation

Combinent les resultats entre ingredients :

ModuleObjectif
aggregation_gfmAgrege les incidences des ingredients
ingredient_splitter_gfmDecompose les ingredients composes
ingredient_amount_estimator_gfmEstime les quantites d'ingredients

Architecture des modules

Chaque GFM suit le patron Factory/Worker :

# Factory - initialise une fois par service, gere les workers
class ExampleGapFillingFactory(AbstractGapFillingFactory):
def __init__(self, postgres_db, service_provider):
super().__init__(postgres_db, service_provider)
self.cache = {} # Cache persistant entre les calculs

async def init_cache(self):
# Charger les donnees requises en memoire
pass

def spawn_worker(self, node):
return ExampleGapFillingWorker(node)

# Worker - cree par noeud, execute le calcul
class ExampleGapFillingWorker(AbstractGapFillingWorker):
def should_be_scheduled(self) -> bool:
# Ce GFM est-il pertinent pour ce noeud ?
return self.node.needs_processing()

def can_run_now(self) -> GapFillingWorkerStatusEnum:
# Les dependances sont-elles satisfaites ?
if self.node.has_required_data():
return GapFillingWorkerStatusEnum.ready
return GapFillingWorkerStatusEnum.reschedule

async def run(self, calc_graph):
# Executer la logique de comblement des lacunes
result = await self.calculate()
self.node.set_property("result", result)

Pourquoi Factory/Worker ?

AvantageDescription
IsolationChaque calcul s'execute dans sa propre instance de worker
Mise en cacheFactory maintient les caches entre les calculs
EvolutiviteLes workers peuvent etre distribues
TestsLes workers peuvent etre testes independamment

Orchestration

L'orchestrateur coordonne l'execution des GFM :

0843e52304130398589902f5d9f555c7

Boucle de planification

  1. Ajout de noeud - Lorsque des noeuds sont ajoutes au CalcGraph, l'orchestrateur cree des workers
  2. Verification de planification - Le should_be_scheduled() de chaque worker est appele
  3. Verification de disponibilite - can_run_now() verifie les dependances
  4. Execution - Les workers prets s'executent de maniere asynchrone
  5. Mises a jour du graphe - Les resultats sont ecrits dans les proprietes du noeud
  6. Propagation - De nouveaux noeuds peuvent declencher des GFM supplementaires

Dependances des modules

Les modules dependent des sorties d'autres modules :

2e33ab327eeb195a73729de52783aa64

Les dependances sont resolues automatiquement via la boucle de planification de l'orchestrateur.

Gestion de l'etat

Les GFM suivent leur etat d'execution par noeud :

# Etat par noeud stocke dans GfmStateProp (worker_states)
# Les valeurs proviennent de NodeGfmStateEnum : "S" (planifie), "F" (termine), "C" (annule)
gfm_state = {
"MatchProductNameGapFillingWorker": "F", # termine
"OriginGapFillingWorker": "F", # termine
"GreenhouseGapFillingWorker": "S", # planifie (en cours)
"ImpactAssessmentGapFillingWorker": "S" # planifie (en attente)
}

Valeurs d'etat

L'etat du GFM est suivi a l'aide de NodeGfmStateEnum :

EtatCodeDescription
scheduledSLe GFM est planifie pour s'executer sur ce noeud
finishedFLe GFM s'est termine avec succes
canceledCLe GFM a ete annule (non applicable ou echec)

Gestion des erreurs

Les GFM implementent une gestion gracieuse des erreurs :

async def run(self, calc_graph):
try:
result = await self.calculate()
self.node.set_property("result", result)
except Exception as e:
# Journaliser l'erreur avec contexte
logger.error("Echec du GFM",
gfm=self.__class__.__name__,
node_uid=self.node.uid,
error=str(e))
# Creer une DataError pour le suivi
error = DataError(
node_uid=self.node.uid,
gfm_name=self.__class__.__name__,
message=str(e),
classification=ErrorClassification.calculation_error
)
self.node.add_error(error)

Strategie de repli

Lorsqu'un module echoue :

  1. Journaliser l'erreur - Journalisation structuree avec contexte
  2. Creer une DataError - Suivi pour le rapport
  3. Continuer le traitement - Les autres modules peuvent toujours s'executer
  4. Signaler l'incertitude - Marquer le resultat avec une confiance reduite

Prochaines etapes