Ë
    KµCj¡  ã                   óž   — d Z ddlmZ ddlmZ ddlZddlmZ ddlm	Z	 ddl
mZ  e«       Z ee«      Zdd	d
ddddœZ G d„ d«      Z e«       Zy)uú  
ML model loader.

Production rule: if a model fails to load at startup, the application
MUST refuse to start, not start in a half-working state and fail on the
first real request. A health check that says "I'm up" while secretly
missing the yield model is worse than a crash â€” it's a silent SLA
violation the client discovers from a support ticket, not from monitoring.

All 6 models are loaded once, here, and held in memory for the lifetime
of the worker process. They are never reloaded per-request.
é    )ÚPath)ÚAnyN)Úget_settings)ÚModelNotLoadedError)Ú
get_loggerzsarimax_climate.pklzxgb_feasibility.pklzxgb_yield.pklzdt_trend.pklzrf_recommendation.pklzsarimax_market.pkl)Úsarimax_climateÚxgb_feasibilityÚ	xgb_yieldÚdt_trendÚrf_recommendationÚsarimax_marketc                   ór   — e Zd ZdZdd„Zdd„Zdd„Zdd„Zdede	fd	„Z
edefd
„«       Zedee   fd„«       Zy)ÚModelRegistryz?Holds every loaded model in memory and exposes typed accessors.ÚreturnNc                 ó\   — i | _         d| _        t        t        j                  «      | _        y )NF)Ú_modelsÚ_loadedr   ÚsettingsÚ	MODEL_DIRÚ
_model_dir©Úselfs    úGC:\Crop_Prediction\Backend\crop-ai-system\app\models_loader\registry.pyÚ__init__zModelRegistry.__init__'   s"   € Ø')ˆŒØˆŒÜœx×1Ñ1Ó2ˆ�ó    c                 óÀ  — t         j                  d| j                  › d�«       g }g }t        j	                  «       D ]}  \  }}| j                  |z  }|j                  «       s|j                  t        |«      «       Œ@	 t        j                  |«      | j                  |<   t         j                  d|› d|› �«       Œ |rt        dd|› �¬«      ‚|rt        dd	|› �¬«      ‚| j                  «        d
| _        t         j                  dt        | j                  «      › d�«       y # t        $ r0}|j                  t        |«      t        |«      f«       Y d }~�Œd }~ww xY w)NzLoading models from z ...zLoaded model 'z' from z;Required model files are missing. The service cannot start.zMissing files: ©ÚmessageÚdetailzAOne or more model files failed to load. The service cannot start.zFailed to load: TzAll z models loaded successfully)ÚloggerÚinfor   ÚREQUIRED_MODEL_FILESÚitemsÚexistsÚappendÚstrÚjoblibÚloadr   Ú	Exceptionr   Ú_validate_loaded_modelsr   Úlen)r   ÚmissingÚfailedÚkeyÚfilenameÚpathÚexcs          r   Úload_allzModelRegistry.load_all,   sC  € Ü�‰Ð*¨4¯?©?Ð*;¸4Ð@ÔAØˆØˆä1×7Ñ7Ó9ò 		5‰MˆC�Ø—?‘? XÑ-ˆDØ—;‘;”=Ø—‘œs 4›yÔ)Øð5Ü$*§K¡K°Ó$5�—‘˜SÑ!Ü—‘˜n¨S¨E°¸¸Ð?Õ@ð		5ñ Ü%ØUØ(¨¨	Ð2ôð ñ Ü%Ø[Ø)¨&¨Ð2ôð ð
 	×$Ñ$Ô&ØˆŒÜ�‰�dœ3˜tŸ|™|Ó,Ð-Ð-HÐIÕJøô! ò 5Ø—‘œs 4›y¬#¨c«(Ð3×4Ò4ûð5ús   Á==D$Ä$	EÄ-%EÅEc           
      óL  — g d¢}|D ]M  }| j                   j                  |«      }t        |t        «      rd|vsŒ3t	        dd|› dt        |«      › �¬«      ‚ dD ]I  }| j                   j                  |«      }t        |t        «      rŒ/t	        dd|› dt        |«      › �¬«      ‚ y	)
a3  
        Sanity-check the structure of each loaded artifact. Catches the case
        where a .pkl file loads without raising an exception but doesn't
        contain what the inference code expects (e.g. wrong dict shape from
        a bad training run accidentally copied to the model directory).
        )r	   r
   r   r   Úmodelz2A model file is present but has an invalid format.ú'z&' expected dict with 'model' key, got r   )r   r   z,' expected dict of {key: fitted_model}, got N)r   ÚgetÚ
isinstanceÚdictr   Útype)r   Úbundle_modelsr.   Úobjs       r   r*   z%ModelRegistry._validate_loaded_modelsK   s»   € ò ZˆØ ò 	ˆCØ—,‘,×"Ñ" 3Ó'ˆCÜ˜c¤4Ô(¨G¸3Ò,>Ü)ØPØ˜s˜eÐ#IÌ$ÈsË)ÈÐUôð ð	ð 9ò 	ˆCØ—,‘,×"Ñ" 3Ó'ˆCÜ˜c¤4Õ(Ü)ØPØ˜s˜eÐ#QÔRVÐWZÓR[ÐQ\Ð]ôð ñ	r   c                 ó6   — | j                   st        dd¬«      ‚y )Nz2Models are not yet loaded. Service is starting up.z2ModelRegistry accessed before load_all() completedr   )r   r   r   s    r   Ú_ensure_loadedzModelRegistry._ensure_loadedc   s!   € Ø�|Š|Ü%ØLØKôð ð r   r.   c                 ó|   — | j                  «        || j                  vrt        d|› d�¬«      ‚| j                  |   S )NzModel 'z' was not loaded)r   )r=   r   r   )r   r.   s     r   r6   zModelRegistry.getj   s>   € Ø×ÑÔØ�d—l‘lÑ"Ü%°¸°uÐ<LÐ.MÔNÐNØ�|‰|˜CÑ Ð r   c                 ó   — | j                   S ©N)r   r   s    r   Úis_readyzModelRegistry.is_readyp   s   € à�|‰|Ðr   c                 óH   — t        | j                  j                  «       «      S r@   )Úlistr   Úkeysr   s    r   Úloaded_model_keyszModelRegistry.loaded_model_keyst   s   € ä�D—L‘L×%Ñ%Ó'Ó(Ð(r   )r   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r2   r*   r=   r&   r   r6   ÚpropertyÚboolrA   rC   rE   © r   r   r   r   $   sg   „ ÙIó3ó
Kó>ó0ð!�sð !˜só !ð ð˜$ò ó ðð ð) 4¨¡9ò )ó ñ)r   r   )rI   Úpathlibr   Útypingr   r'   Úapp.core.configr   Úapp.core.exceptionsr   Úapp.core.logging_configr   r   rF   r    r"   r   Úmodel_registryrL   r   r   ú<module>rS      sa   ðñõ Ý ã å (Ý 3Ý .á‹>€Ù	�HÓ	€ð -Ø,Ø ØØ0Ø*ñÐ ÷R)ñ R)ñn “�r   