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
Chaque GFM se compose de :
- Logique de planification - Determine si le module est pertinent pour un noeud donne
- Verification de disponibilite - Verifie que toutes les dependances sont satisfaites
- 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 :
| Module | Objectif |
|---|---|
match_product_name_gfm | Fait correspondre les noms de produits aux entrees de la base de donnees |
attach_food_tags_gfm | Attache les etiquettes de classification alimentaire |
link_term_to_activity_node_gfm | Lie les termes aux activites ACV |
link_food_categories_gfm | Attribue les categories alimentaires |
Modules de localisation
Gerent les donnees geographiques et d'origine :
| Module | Objectif |
|---|---|
origin_gfm | Determine l'origine du produit |
location_gfm | Gestion de la localisation geographique |
transportation_decision_gfm | Determine les modes de transport |
transportation_mode_distance_gfm | Calcule les distances de transport |
Modules de cycle de vie
Modelisent la transformation et la chaine d'approvisionnement :
| Module | Objectif |
|---|---|
processing_gfm | Incidences de la transformation alimentaire |
greenhouse_gfm | Calculs des gaz a effet de serre |
conservation_gfm | Stockage et conservation |
perishability_gfm | Duree de conservation et facteurs de perte |
Modules d'evaluation de l'incidence
Calculent les metriques environnementales :
| Module | Objectif |
|---|---|
impact_assessment_gfm | Agrege les calculs d'incidence |
water_scarcity_gfm | Calcul de l'empreinte hydrique |
rainforest_gfm | Incidence sur la deforestation |
vitascore_gfm | Score nutritionnel |
Modules d'agregation
Combinent les resultats entre ingredients :
| Module | Objectif |
|---|---|
aggregation_gfm | Agrege les incidences des ingredients |
ingredient_splitter_gfm | Decompose les ingredients composes |
ingredient_amount_estimator_gfm | Estime 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 ?
| Avantage | Description |
|---|---|
| Isolation | Chaque calcul s'execute dans sa propre instance de worker |
| Mise en cache | Factory maintient les caches entre les calculs |
| Evolutivite | Les workers peuvent etre distribues |
| Tests | Les workers peuvent etre testes independamment |
Orchestration
L'orchestrateur coordonne l'execution des GFM :
Boucle de planification
- Ajout de noeud - Lorsque des noeuds sont ajoutes au CalcGraph, l'orchestrateur cree des workers
- Verification de planification - Le
should_be_scheduled()de chaque worker est appele - Verification de disponibilite -
can_run_now()verifie les dependances - Execution - Les workers prets s'executent de maniere asynchrone
- Mises a jour du graphe - Les resultats sont ecrits dans les proprietes du noeud
- Propagation - De nouveaux noeuds peuvent declencher des GFM supplementaires
Dependances des modules
Les modules dependent des sorties d'autres modules :
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 :
| Etat | Code | Description |
|---|---|---|
scheduled | S | Le GFM est planifie pour s'executer sur ce noeud |
finished | F | Le GFM s'est termine avec succes |
canceled | C | Le 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 :
- Journaliser l'erreur - Journalisation structuree avec contexte
- Creer une DataError - Suivi pour le rapport
- Continuer le traitement - Les autres modules peuvent toujours s'executer
- Signaler l'incertitude - Marquer le resultat avec une confiance reduite
Prochaines etapes
- Fonctionnement des GFM - Mecanismes detailles
- Catalogue des modules - Tous les modules disponibles
- SDK GFM (bientot disponible) - Construire des modules personnalises