Spaces:
Sleeping
Sleeping
| """ | |
| Ce module contient les fonctions de service pour la prédiction de rendement et la recommandation de cultures. | |
| - predict_yield: Prédit la production de la culture en fonction des données d'entrée. | |
| - recommend: Recommande les meilleures cultures à planter en fonction des conditions d'entrée. | |
| """ | |
| from src.recommendations.recommender import recommend_best_crop | |
| import pandas as pd | |
| import numpy as np | |
| def predict_yield(model, input_data: dict, crops_by_area: dict): | |
| """ | |
| Prédit le rendement d'une culture en fonction des données d'entrée. | |
| Si la zone ou la culture spécifiée dans les données d'entrée n'est pas présente dans crops_by_area, une exception ValueError est levée avec un message d'erreur approprié. | |
| args: | |
| - model: Le modèle de prédiction pré-entraîné. | |
| - input_data: Un dictionnaire contenant les données d'entrée pour la prédiction. | |
| - crops_by_area: Un dictionnaire contenant les cultures disponibles par zone. | |
| returns: | |
| - float: La prédiction du rendement de la culture. | |
| """ | |
| # ========================= | |
| # Validation métier | |
| # ========================= | |
| area = input_data.get("area") | |
| crop = input_data.get("item") | |
| if area is None: | |
| raise ValueError("Le champ 'area' est requis") | |
| if crop is None: | |
| raise ValueError("Le champ 'item' est requis") | |
| all_areas = { | |
| area_ | |
| for areas in crops_by_area.values() | |
| for area_ in areas | |
| } | |
| if area not in all_areas: | |
| raise ValueError(f"Pays inconnu ou non présent dans les données : {area}") | |
| if crop not in crops_by_area: | |
| raise ValueError(f"Culture inconnue : {crop}") | |
| if area not in crops_by_area[crop]: | |
| raise ValueError( | |
| f"La culture '{crop}' n'est pas observée dans le pays '{area}'" | |
| ) | |
| # ========================= | |
| # Préparation des données | |
| # ========================= | |
| df = pd.DataFrame([input_data]) | |
| df["temp_rainfall"] = df["temp"] * df["rainfall_mm"] | |
| df["temp_pesticides"] = df["temp"] * df["pesticides"] | |
| df["rainfall_pesticides"] = df["rainfall_mm"] * df["pesticides"] | |
| # ========================= | |
| # Prédiction | |
| # ========================= | |
| pred_log = model.predict(df)[0] | |
| pred_real = float(np.expm1(pred_log)) | |
| return pred_real | |
| def recommend(model, input_data, crops_by_area): | |
| """ | |
| Recommande les meilleures cultures à planter en fonction des conditions d'entrée. | |
| Si la zone spécifiée dans les données d'entrée n'est pas présente dans crops_by_area, une exception ValueError est levée avec un message d'erreur approprié. | |
| args: | |
| - model: Le modèle de recommandation pré-entraîné | |
| - input_data: Un dictionnaire contenant les données d'entrée pour la recommandation | |
| - crops_by_area: Un dictionnaire contenant les cultures disponibles par zone | |
| returns: | |
| - tuple: Un tuple contenant le meilleur choix de culture et le classement des cultures | |
| """ | |
| if input_data["area"] not in { | |
| area for areas in crops_by_area.values() for area in areas | |
| }: | |
| raise ValueError(f"Pays inconnu ou non présent dans les données : {input_data['area']}") | |
| best_crop, ranking_df = recommend_best_crop( | |
| model=model, | |
| input_conditions=input_data, | |
| crops_by_area=crops_by_area, | |
| top_k=5 | |
| ) | |
| # Conversion en types Python natifs pour FastAPI / JSON | |
| best_crop_dict = { | |
| key: ( | |
| float(value) if isinstance(value, (np.float32, np.float64)) else | |
| int(value) if isinstance(value, (np.int32, np.int64)) else | |
| value | |
| ) | |
| for key, value in best_crop.to_dict().items() | |
| } | |
| ranking = ranking_df.to_dict(orient="records") | |
| for row in ranking: | |
| for key, value in row.items(): | |
| if isinstance(value, (np.float32, np.float64)): | |
| row[key] = float(value) | |
| elif isinstance(value, (np.int32, np.int64)): | |
| row[key] = int(value) | |
| return best_crop_dict, ranking | |