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​