xcenic commited on
Commit
28927dd
·
verified ·
1 Parent(s): f6330ad

Upload 19 files

Browse files
Files changed (1) hide show
  1. core/models.py +29 -9
core/models.py CHANGED
@@ -15,14 +15,23 @@ from .constants import ENFORCE_TR0_RESILIENTES
15
  warnings.filterwarnings("ignore")
16
 
17
  # ------------------------------------------------------------------
18
- # Disponibilidad de librerías de IA (no obligatorias para el núcleo CPM).
 
19
  # ------------------------------------------------------------------
20
  try:
21
- from transformers import pipeline as _hf_pipeline # noqa: F401
22
- from sklearn.ensemble import RandomForestRegressor # noqa: F401
23
- IA_DISPONIBLE = True
24
  except ImportError:
25
- IA_DISPONIBLE = False
 
 
 
 
 
 
 
 
 
26
 
27
  # Singletons perezosos (se rellenan al primer uso).
28
  _nlp_classifier = None
@@ -30,6 +39,9 @@ _nlp_cargado = False
30
  _ml_tr_model = None
31
  _ml_cargado = False
32
 
 
 
 
33
 
34
  def get_nlp_model():
35
  """Carga perezosa del clasificador zero-shot. Devuelve None si no se puede."""
@@ -37,7 +49,7 @@ def get_nlp_model():
37
  if _nlp_cargado:
38
  return _nlp_classifier
39
  _nlp_cargado = True
40
- if not IA_DISPONIBLE:
41
  _nlp_classifier = None
42
  return None
43
  try:
@@ -66,7 +78,7 @@ def _entrenar_modelo_termodinamico():
66
  Entrena al Random Forest para que devuelva HORAS de secado respondiendo
67
  correctamente a la temperatura y humedad.
68
  """
69
- if not IA_DISPONIBLE:
70
  return None
71
  from sklearn.ensemble import RandomForestRegressor
72
  np.random.seed(42)
@@ -190,8 +202,16 @@ def calcular_tr_y_ic_dinamico(lluvia_mm, temp_c, humedad_pct, tipo_suelo_ic, usa
190
 
191
  suelo_cat = 1 if tipo_suelo_ic >= 3.0 else (2 if tipo_suelo_ic >= 2.0 else 3)
192
 
193
- # La IA ahora predice HORAS reales
194
- tr_horas = ml_tr_model.predict([[lluvia_mm, temp_c, humedad_pct, suelo_cat]])[0]
 
 
 
 
 
 
 
 
195
 
196
  # [AUD-07] Penalización dinámica del coeficiente — Ec. 6.22 de la tesis:
197
  # Ic_dinámico = Q(Ic) = Ic_base + Tr/48 (constante de normalización 48 h)
 
15
  warnings.filterwarnings("ignore")
16
 
17
  # ------------------------------------------------------------------
18
+ # Disponibilidad de librerías de IA (independientes entre sí).
19
+ # El Random Forest solo necesita sklearn; el NLP necesita transformers.
20
  # ------------------------------------------------------------------
21
  try:
22
+ from sklearn.ensemble import RandomForestRegressor # noqa: F401
23
+ ML_DISPONIBLE = True
 
24
  except ImportError:
25
+ ML_DISPONIBLE = False
26
+
27
+ try:
28
+ from transformers import pipeline as _hf_pipeline # noqa: F401
29
+ NLP_DISPONIBLE = True
30
+ except ImportError:
31
+ NLP_DISPONIBLE = False
32
+
33
+ # Compatibilidad: "hay IA" si al menos uno de los dos modelos está disponible.
34
+ IA_DISPONIBLE = ML_DISPONIBLE or NLP_DISPONIBLE
35
 
36
  # Singletons perezosos (se rellenan al primer uso).
37
  _nlp_classifier = None
 
39
  _ml_tr_model = None
40
  _ml_cargado = False
41
 
42
+ # Caché de predicciones del Random Forest (clave: entradas redondeadas).
43
+ _TR_CACHE: dict = {}
44
+
45
 
46
  def get_nlp_model():
47
  """Carga perezosa del clasificador zero-shot. Devuelve None si no se puede."""
 
49
  if _nlp_cargado:
50
  return _nlp_classifier
51
  _nlp_cargado = True
52
+ if not NLP_DISPONIBLE:
53
  _nlp_classifier = None
54
  return None
55
  try:
 
78
  Entrena al Random Forest para que devuelva HORAS de secado respondiendo
79
  correctamente a la temperatura y humedad.
80
  """
81
+ if not ML_DISPONIBLE:
82
  return None
83
  from sklearn.ensemble import RandomForestRegressor
84
  np.random.seed(42)
 
202
 
203
  suelo_cat = 1 if tipo_suelo_ic >= 3.0 else (2 if tipo_suelo_ic >= 2.0 else 3)
204
 
205
+ # La IA predice HORAS reales. Cacheamos la predicción con las entradas redondeadas:
206
+ # sklearn tarda ~3.8 ms por predicción de UNA muestra, y el motor la invoca una vez
207
+ # por día lluvioso; en un proyecto grande eso son decenas de miles de llamadas
208
+ # idénticas. El redondeo (0.5 mm / 0.5 °C / 0.5 %) deja Tr prácticamente igual y
209
+ # colapsa miles de llamadas a unas pocas. Resultado: hasta cientos de veces más rápido.
210
+ key = (round(lluvia_mm * 2) / 2, round(temp_c * 2) / 2, round(humedad_pct * 2) / 2, suelo_cat)
211
+ tr_horas = _TR_CACHE.get(key)
212
+ if tr_horas is None:
213
+ tr_horas = float(ml_tr_model.predict([[key[0], key[1], key[2], suelo_cat]])[0])
214
+ _TR_CACHE[key] = tr_horas
215
 
216
  # [AUD-07] Penalización dinámica del coeficiente — Ec. 6.22 de la tesis:
217
  # Ic_dinámico = Q(Ic) = Ic_base + Tr/48 (constante de normalización 48 h)