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
Cada GFM consiste en:
- Lógica de Programación - Determina si el módulo es relevante para un nodo dado
- Verificación de Disponibilidad - Verifica que todas las dependencias están satisfechas
- 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ódulo | Propósito |
|---|---|
match_product_name_gfm | Coincide nombres de productos con entradas de base de datos |
attach_food_tags_gfm | Adjunta etiquetas de clasificación de alimentos |
link_term_to_activity_node_gfm | Enlaza términos a actividades de ACV |
link_food_categories_gfm | Asigna categorías de alimentos |
Módulos de Ubicación
Manejan datos geográficos y de origen:
| Módulo | Propósito |
|---|---|
origin_gfm | Determina origen del producto |
location_gfm | Manejo de ubicación geográfica |
transportation_decision_gfm | Determina modos de transporte |
transportation_mode_distance_gfm | Calcula distancias de transporte |
Módulos de Ciclo de Vida
Modelan procesamiento y cadena de suministro:
| Módulo | Propósito |
|---|---|
processing_gfm | Impactos del procesamiento de alimentos |
greenhouse_gfm | Cálculos de gases de efecto invernadero |
conservation_gfm | Almacenamiento y conservación |
perishability_gfm | Vida útil y factores de desperdicio |
Módulos de Evaluación de Impacto
Calculan métricas ambientales:
| Módulo | Propósito |
|---|---|
impact_assessment_gfm | Agrega cálculos de impacto |
water_scarcity_gfm | Cálculo de huella hídrica |
rainforest_gfm | Impacto de deforestación |
vitascore_gfm | Puntuación nutricional |
Módulos de Agregación
Combinan resultados entre ingredientes:
| Módulo | Propósito |
|---|---|
aggregation_gfm | Agrega impactos de ingredientes |
ingredient_splitter_gfm | Descompone ingredientes compuestos |
ingredient_amount_estimator_gfm | Estima 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?
| Beneficio | Descripción |
|---|---|
| Aislamiento | Cada cálculo se ejecuta en su propia instancia de trabajador |
| Caché | La Factory mantiene cachés entre cálculos |
| Escalabilidad | Los trabajadores pueden distribuirse |
| Pruebas | Los trabajadores pueden probarse independientemente |
Orquestación
El orquestador coordina la ejecución de GFM:
Bucle de Programación
- Adición de Nodo - Cuando se añaden nodos al CalcGraph, el orquestador genera trabajadores
- Verificación de Programación - Se llama al
should_be_scheduled()de cada trabajador - Verificación de Disponibilidad -
can_run_now()verifica dependencias - Ejecución - Los trabajadores listos se ejecutan de forma asíncrona
- Actualizaciones del Grafo - Los resultados se escriben de vuelta a las propiedades del nodo
- Propagación - Nuevos nodos pueden activar GFMs adicionales
Dependencias de Módulos
Los módulos dependen de salidas de otros módulos:
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:
| Estado | Código | Descripción |
|---|---|---|
scheduled | S | El GFM está programado para ejecutarse en este nodo |
finished | F | El GFM ha completado exitosamente |
canceled | C | El 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:
- Registrar el error - Registro estructurado con contexto
- Crear DataError - Rastrear para informes
- Continuar procesamiento - Otros módulos pueden seguir ejecutándose
- Marcar incertidumbre - Marcar resultado con confianza reducida
Siguientes Pasos
- Cómo Funcionan los GFMs - Mecánicas detalladas
- Catálogo de Módulos - Todos los módulos disponibles
- GFM SDK (próximamente) - Construir módulos personalizados