Saltar al contenido principal

Gap Filling Modules (GFMs)

Los Gap Filling Modules son los bloques de construcción del motor de cálculo EOS. Cada módulo es una unidad especializada y autocontenida que maneja un aspecto específico del cálculo de impacto ambiental.

¿Qué son los Gap Filling Modules?

En el mundo real, los datos de productos alimentarios a menudo están incompletos. Un producto puede tener:

  • Un nombre pero sin lista de ingredientes
  • Ingredientes pero sin información de origen
  • Origen pero sin detalles de transporte
  • Datos nutricionales parciales

Los GFMs resuelven este problema rellenando automáticamente los "vacíos" en los datos del producto usando modelos científicos, bases de datos y valores por defecto inteligentes.

El Concepto de GFM

20728ba057f23ef10481533eab2c4bed

Cada GFM consiste en:

  1. Lógica de Programación - Determina si el módulo es relevante para un nodo dado
  2. Verificación de Disponibilidad - Verifica que todas las dependencias están satisfechas
  3. Ejecución - La lógica de cálculo que rellena vacíos y actualiza el grafo

Módulos Disponibles

EOS incluye 28 GFMs especializados organizados por función:

Módulos de Coincidencia

Coinciden nombres de productos e ingredientes con entradas de base de datos:

MóduloPropósito
match_product_name_gfmCoincide nombres de productos con entradas de base de datos
attach_food_tags_gfmAdjunta etiquetas de clasificación de alimentos
link_term_to_activity_node_gfmEnlaza términos a actividades de ACV
link_food_categories_gfmAsigna categorías de alimentos

Módulos de Ubicación

Manejan datos geográficos y de origen:

MóduloPropósito
origin_gfmDetermina origen del producto
location_gfmManejo de ubicación geográfica
transportation_decision_gfmDetermina modos de transporte
transportation_mode_distance_gfmCalcula distancias de transporte

Módulos de Ciclo de Vida

Modelan procesamiento y cadena de suministro:

MóduloPropósito
processing_gfmImpactos del procesamiento de alimentos
greenhouse_gfmCálculos de gases de efecto invernadero
conservation_gfmAlmacenamiento y conservación
perishability_gfmVida útil y factores de desperdicio

Módulos de Evaluación de Impacto

Calculan métricas ambientales:

MóduloPropósito
impact_assessment_gfmAgrega cálculos de impacto
water_scarcity_gfmCálculo de huella hídrica
rainforest_gfmImpacto de deforestación
vitascore_gfmPuntuación nutricional

Módulos de Agregación

Combinan resultados entre ingredientes:

MóduloPropósito
aggregation_gfmAgrega impactos de ingredientes
ingredient_splitter_gfmDescompone ingredientes compuestos
ingredient_amount_estimator_gfmEstima cantidades de ingredientes

Arquitectura de Módulos

Cada GFM sigue el patrón Factory/Worker:

# Factory - inicializado una vez por servicio, gestiona trabajadores
class ExampleGapFillingFactory(AbstractGapFillingFactory):
def __init__(self, postgres_db, service_provider):
super().__init__(postgres_db, service_provider)
self.cache = {} # Caché persistente entre cálculos

async def init_cache(self):
# Cargar datos requeridos en memoria
pass

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

# Worker - generado por nodo, ejecuta el cálculo
class ExampleGapFillingWorker(AbstractGapFillingWorker):
def should_be_scheduled(self) -> bool:
# ¿Es este GFM relevante para este nodo?
return self.node.needs_processing()

def can_run_now(self) -> GapFillingWorkerStatusEnum:
# ¿Están satisfechas las dependencias?
if self.node.has_required_data():
return GapFillingWorkerStatusEnum.ready
return GapFillingWorkerStatusEnum.reschedule

async def run(self, calc_graph):
# Ejecutar la lógica de relleno de vacíos
result = await self.calculate()
self.node.set_property("result", result)

¿Por qué Factory/Worker?

BeneficioDescripción
AislamientoCada cálculo se ejecuta en su propia instancia de trabajador
CachéLa Factory mantiene cachés entre cálculos
EscalabilidadLos trabajadores pueden distribuirse
PruebasLos trabajadores pueden probarse independientemente

Orquestación

El orquestador coordina la ejecución de GFM:

191178d8f287a548a643ca923750e9fd

Bucle de Programación

  1. Adición de Nodo - Cuando se añaden nodos al CalcGraph, el orquestador genera trabajadores
  2. Verificación de Programación - Se llama al should_be_scheduled() de cada trabajador
  3. Verificación de Disponibilidad - can_run_now() verifica dependencias
  4. Ejecución - Los trabajadores listos se ejecutan de forma asíncrona
  5. Actualizaciones del Grafo - Los resultados se escriben de vuelta a las propiedades del nodo
  6. Propagación - Nuevos nodos pueden activar GFMs adicionales

Dependencias de Módulos

Los módulos dependen de salidas de otros módulos:

a6b24ca66e47dc50a4fdcab2018cc677

Las dependencias se resuelven automáticamente a través del bucle de programación del orquestador.

Gestión de Estado

Los GFMs rastrean su estado de ejecución por nodo:

# Estado por nodo almacenado en GfmStateProp (worker_states)
# Los valores son de NodeGfmStateEnum: "S" (programado), "F" (finalizado), "C" (cancelado)
gfm_state = {
"MatchProductNameGapFillingWorker": "F", # finalizado
"OriginGapFillingWorker": "F", # finalizado
"GreenhouseGapFillingWorker": "S", # programado (ejecutando)
"ImpactAssessmentGapFillingWorker": "S" # programado (pendiente)
}

Valores de Estado

El estado del GFM se rastrea usando NodeGfmStateEnum:

EstadoCódigoDescripción
scheduledSEl GFM está programado para ejecutarse en este nodo
finishedFEl GFM ha completado exitosamente
canceledCEl GFM fue cancelado (no aplicable o falló)

Manejo de Errores

Los GFMs implementan manejo de errores elegante:

async def run(self, calc_graph):
try:
result = await self.calculate()
self.node.set_property("result", result)
except Exception as e:
# Registrar error con contexto
logger.error("GFM falló",
gfm=self.__class__.__name__,
node_uid=self.node.uid,
error=str(e))
# Crear DataError para seguimiento
error = DataError(
node_uid=self.node.uid,
gfm_name=self.__class__.__name__,
message=str(e),
classification=ErrorClassification.calculation_error
)
self.node.add_error(error)

Estrategia de Respaldo

Cuando un módulo falla:

  1. Registrar el error - Registro estructurado con contexto
  2. Crear DataError - Rastrear para informes
  3. Continuar procesamiento - Otros módulos pueden seguir ejecutándose
  4. Marcar incertidumbre - Marcar resultado con confianza reducida

Siguientes Pasos