Spaces:
Runtime error
Runtime error
Rim BACCOUR
commited on
finalize the final prompting for scenarii ombrage avec et sans comparison
Browse files- compute_yield.py +49 -27
- prompts/summary_prompt.py +27 -22
- summary_test.py +62 -17
- utils/summary.py +13 -5
compute_yield.py
CHANGED
|
@@ -168,33 +168,37 @@ def plot_yield(
|
|
| 168 |
return fig
|
| 169 |
|
| 170 |
if __name__ == '__main__':
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
n_years = 10
|
| 199 |
years = 2025 + np.arange(len(yield_forecast_with_shading))
|
| 200 |
aggregated_forecasts = yield_forecast.rolling(n_years).sum()[years % n_years == 0]
|
|
@@ -214,3 +218,21 @@ if __name__ == '__main__':
|
|
| 214 |
plt.legend()
|
| 215 |
plt.ylim(150)
|
| 216 |
plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
return fig
|
| 169 |
|
| 170 |
if __name__ == '__main__':
|
| 171 |
+
cultures = ["Colza d'hiver", "Blé tendre d'hiver", "Orge d'hiver"]
|
| 172 |
+
dfs = []
|
| 173 |
+
for culture in cultures:
|
| 174 |
+
scenario = "pessimist"
|
| 175 |
+
shading_coef = 0.2
|
| 176 |
+
monthly_forecast = compute_yield_forecast(
|
| 177 |
+
latitude=47,
|
| 178 |
+
longitude=5,
|
| 179 |
+
culture=culture,
|
| 180 |
+
scenario=scenario,
|
| 181 |
+
shading_coef=0.,
|
| 182 |
+
)
|
| 183 |
+
# print(monthly_forecast.head())
|
| 184 |
+
|
| 185 |
+
yield_forecast = get_annual_yield(monthly_forecast)
|
| 186 |
+
yield_forecast_df = yield_forecast.reset_index()
|
| 187 |
+
yield_forecast_df.columns = ["time", "yield_simple_forecast"]
|
| 188 |
+
yield_forecast_df["year"] = yield_forecast_df["time"].dt.year
|
| 189 |
+
|
| 190 |
+
print(yield_forecast_df.head())
|
| 191 |
+
|
| 192 |
+
monthly_forecast_with_shading = compute_yield_forecast(
|
| 193 |
+
latitude=47,
|
| 194 |
+
longitude=5,
|
| 195 |
+
culture=culture,
|
| 196 |
+
scenario=scenario,
|
| 197 |
+
shading_coef=shading_coef,
|
| 198 |
+
)
|
| 199 |
+
# print(monthly_forecast_with_shading.head())
|
| 200 |
+
|
| 201 |
+
<<<<<<< Updated upstream
|
| 202 |
n_years = 10
|
| 203 |
years = 2025 + np.arange(len(yield_forecast_with_shading))
|
| 204 |
aggregated_forecasts = yield_forecast.rolling(n_years).sum()[years % n_years == 0]
|
|
|
|
| 218 |
plt.legend()
|
| 219 |
plt.ylim(150)
|
| 220 |
plt.show()
|
| 221 |
+
=======
|
| 222 |
+
yield_forecast_with_shading = get_annual_yield(monthly_forecast_with_shading)
|
| 223 |
+
yield_forecast_with_shading_df = yield_forecast_with_shading.reset_index()
|
| 224 |
+
yield_forecast_with_shading_df.columns = ["time", "yield_with_shading_forecast"]
|
| 225 |
+
yield_forecast_with_shading_df["year"] = yield_forecast_with_shading_df["time"].dt.year
|
| 226 |
+
final_df = pd.merge(yield_forecast_df[["year", "yield_simple_forecast"]], yield_forecast_with_shading_df[["year", "yield_with_shading_forecast"]], on="year")
|
| 227 |
+
final_df["culture"] = culture
|
| 228 |
+
dfs.append(final_df)
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
result = pd.concat(dfs, axis=0)
|
| 232 |
+
result.to_csv("data/data_yield/rendement_forecast.csv", index=False)
|
| 233 |
+
|
| 234 |
+
# plt.plot(yield_forecast.rolling(5).mean(), label="No shading")
|
| 235 |
+
# plt.plot(yield_forecast_with_shading.rolling(5).mean(), label="20% Shading")
|
| 236 |
+
# plt.legend()
|
| 237 |
+
# plt.show()
|
| 238 |
+
>>>>>>> Stashed changes
|
prompts/summary_prompt.py
CHANGED
|
@@ -24,28 +24,33 @@ meterological_data_summary_prompt = """
|
|
| 24 |
Présente ta réponse sous un format structuré avec un résumé des tendances observées et des perspectives climatiques selon le scénario choisi."
|
| 25 |
|
| 26 |
"""
|
| 27 |
-
|
| 28 |
|
| 29 |
agricultural_yield_comparison_prompt = """
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
|
|
|
|
|
|
| 46 |
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
Présente ta réponse sous un format structuré avec un résumé des tendances observées et des perspectives climatiques selon le scénario choisi."
|
| 25 |
|
| 26 |
"""
|
| 27 |
+
# * Caractéristiques du sol : [pH, texture, teneur en matière organique, capacité de rétention d’eau, etc.]
|
| 28 |
|
| 29 |
agricultural_yield_comparison_prompt = """
|
| 30 |
+
Vous êtes un expert agronome et spécialiste en agrivoltaïsme au sein d’Ombrea, entreprise experte dans ce domaine.
|
| 31 |
+
Votre mission est d’analyser et de comparer deux scénarios agricoles afin de conseiller un agriculteur sur
|
| 32 |
+
la solution optimale pour maximiser son rendement à long terme, en tenant compte des aléas climatiques.
|
| 33 |
+
Vous devez fournir une analyse objective, non biaisée et exclusivement basée sur les données fournies.
|
| 34 |
+
Scénarios à comparer :
|
| 35 |
+
Scénario 1 : Culture bénéficiant de l’ombrage statique généré par des panneaux photovoltaïques.
|
| 36 |
+
Scénario 2 : Culture sans ombrage.
|
| 37 |
+
Données d’entrée pour l’analyse :
|
| 38 |
+
- Type de culture : [Nom de la culture et ses besoins spécifiques en lumière, température et eau]
|
| 39 |
+
- Besoins hydriques : [Conditions hydriques du sol et de la culture, sensibilité de la culture au stress hydrique]
|
| 40 |
+
- Projections climatiques : [Température moyenne, précipitations, risques de sécheresse, vagues de chaleur, etc.]
|
| 41 |
+
Ces projections se basent sur le modèle SSP5-8.5 experiment et le modèle CNRM-CM6-1 (France).
|
| 42 |
+
|
| 43 |
+
L’analyse devra aborder les points suivants :
|
| 44 |
+
- Comparaison des rendements agricoles : Analyser la différence de productivité entre les cultures avec et sans ombrage agrivoltaïque.
|
| 45 |
+
- Impact sur le stress hydrique : Évaluer l’évolution du stress hydrique et ses conséquences sur les besoins en eau des cultures dans chaque scénario.
|
| 46 |
+
- Effets microclimatiques : Examiner l’influence des conditions microclimatiques induites par l’agrivoltaïsme sur la qualité des cultures.
|
| 47 |
+
- Conclusion sur l’impact de l’ombrage : Conclure sur l’impact de l’ombrage en précisant s’il constitue ou non un levier pour la pérennisation de l’activité agricole.
|
| 48 |
|
| 49 |
+
Consignes pour la réponse :
|
| 50 |
+
- Fournir une analyse détaillée, structurée et pédagogique.
|
| 51 |
+
- S’appuyer exclusivement sur les données fournies et argumenter à l’aide d’indicateurs précis concernant l’évolution des variables.
|
| 52 |
+
- Adopter une approche objective et non biaisée, sans favoriser un scénario par anticipation.
|
| 53 |
+
- Vulgariser les concepts techniques pour assurer une compréhension optimale par l’agriculteur.
|
| 54 |
+
- Le format de sortie doit être structuré, avec des sections claires et bien définies.
|
| 55 |
+
- L’utilisateur vous fournira le nom de la culture, les caractéristiques du sol dans la région concernée ainsi que les données de rendement avec et sans ombrage
|
| 56 |
+
"""
|
summary_test.py
CHANGED
|
@@ -4,54 +4,99 @@ import pandas as pd
|
|
| 4 |
import numpy as np
|
| 5 |
from forecast import get_forecast_datasets, get_forecast_data
|
| 6 |
from data_pipelines.historical_weather_data import download_historical_weather_data, aggregate_hourly_weather_data
|
| 7 |
-
|
| 8 |
from utils.summary import get_meterological_summary, get_agricultural_yield_comparison
|
| 9 |
|
| 10 |
|
| 11 |
def get_meterological_past_data():
|
| 12 |
download_historical_weather_data(latitude, longitude, start_year, end_year)
|
| 13 |
|
| 14 |
-
def
|
| 15 |
-
|
| 16 |
start_year, end_year = 2010, 2025
|
|
|
|
| 17 |
historical_df = aggregate_hourly_weather_data(download_historical_weather_data(latitude=lat, longitude=lon, start_year=start_year, end_year= end_year))
|
| 18 |
forecast_df = get_forecast_data(scenario=scenario, longitude=lon, latitude=lat, shading_coef=0)
|
| 19 |
|
| 20 |
forecast_df["time"] = pd.to_datetime(forecast_df["time"])
|
| 21 |
forecast_df['year'] = forecast_df["time"].dt.year
|
| 22 |
-
new_forecast_df = forecast_df.groupby(by="year", as_index=False)
|
| 23 |
# new_forecast_df = new_forecast_df[new_forecast_df["year"] > 2025]
|
| 24 |
|
| 25 |
historical_df = historical_df.reset_index().rename(columns={"index": "time"}).sort_values(by="time")
|
| 26 |
historical_df["year"] = historical_df["time"].dt.year
|
| 27 |
historical_df["precipitation"] = historical_df["precipitation"] / 3600 # to transform the data to kg m2 per s
|
| 28 |
|
| 29 |
-
new_historical_df = historical_df.groupby(by="year", as_index=False)
|
| 30 |
new_historical_df = new_historical_df[new_historical_df["year"] < 2024]
|
| 31 |
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
-
irradiance_df = pd.concat([
|
| 36 |
-
|
| 37 |
|
| 38 |
-
rain_df = pd.concat([
|
| 39 |
-
|
| 40 |
|
| 41 |
return temperature_df, rain_df, irradiance_df
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
if __name__ == "__main__":
|
| 45 |
|
| 46 |
scenario = "pessimist"
|
| 47 |
lat, lon = 47.0, 5.0
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
# from utils.soil_utils import find_nearest_point
|
| 57 |
# city = "Bourgogne Franche Comté"
|
|
|
|
| 4 |
import numpy as np
|
| 5 |
from forecast import get_forecast_datasets, get_forecast_data
|
| 6 |
from data_pipelines.historical_weather_data import download_historical_weather_data, aggregate_hourly_weather_data
|
| 7 |
+
from utils.soil_utils import find_nearest_point_to_coordinates
|
| 8 |
from utils.summary import get_meterological_summary, get_agricultural_yield_comparison
|
| 9 |
|
| 10 |
|
| 11 |
def get_meterological_past_data():
|
| 12 |
download_historical_weather_data(latitude, longitude, start_year, end_year)
|
| 13 |
|
| 14 |
+
def pre_process_data(scenario: str, lat: float = 47.0, lon:float = 5.0):
|
|
|
|
| 15 |
start_year, end_year = 2010, 2025
|
| 16 |
+
|
| 17 |
historical_df = aggregate_hourly_weather_data(download_historical_weather_data(latitude=lat, longitude=lon, start_year=start_year, end_year= end_year))
|
| 18 |
forecast_df = get_forecast_data(scenario=scenario, longitude=lon, latitude=lat, shading_coef=0)
|
| 19 |
|
| 20 |
forecast_df["time"] = pd.to_datetime(forecast_df["time"])
|
| 21 |
forecast_df['year'] = forecast_df["time"].dt.year
|
| 22 |
+
new_forecast_df = forecast_df.groupby(by="year", as_index=False).mean().reset_index()
|
| 23 |
# new_forecast_df = new_forecast_df[new_forecast_df["year"] > 2025]
|
| 24 |
|
| 25 |
historical_df = historical_df.reset_index().rename(columns={"index": "time"}).sort_values(by="time")
|
| 26 |
historical_df["year"] = historical_df["time"].dt.year
|
| 27 |
historical_df["precipitation"] = historical_df["precipitation"] / 3600 # to transform the data to kg m2 per s
|
| 28 |
|
| 29 |
+
new_historical_df = historical_df.groupby(by="year", as_index=False).mean().reset_index()
|
| 30 |
new_historical_df = new_historical_df[new_historical_df["year"] < 2024]
|
| 31 |
|
| 32 |
+
return new_historical_df, new_forecast_df
|
| 33 |
+
|
| 34 |
+
def process_all_data_for_meterological_summary(historical_data: pd.DataFrame, forecast_data: pd.DataFrame):
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
temperature_df = pd.concat([historical_data[["year", "air_temperature_mean"]].rename(columns={"air_temperature_mean": "Near Surface Air Temperature (°C)"}),
|
| 38 |
+
forecast_data[["year", "Near Surface Air Temperature (°C)"]]], axis=0)
|
| 39 |
|
| 40 |
+
irradiance_df = pd.concat([historical_data[["year", "irradiance"]].rename(columns={"irradiance": "Surface Downwelling Shortwave Radiation (W/m²)"}),
|
| 41 |
+
forecast_data[["year", "Surface Downwelling Shortwave Radiation (W/m²)"]]], axis=0)
|
| 42 |
|
| 43 |
+
rain_df = pd.concat([historical_data[["year", "precipitation"]].rename(columns={"precipitation": "Precipitation (kg m-2 s-1)"}),
|
| 44 |
+
forecast_data[["year", "Precipitation (kg m-2 s-1)"]]], axis=0)
|
| 45 |
|
| 46 |
return temperature_df, rain_df, irradiance_df
|
| 47 |
|
| 48 |
+
def get_yield_data(region: str = "Bourgogne-Franche-Comté", culture: str ="Blé tendre d'hiver"):
|
| 49 |
+
|
| 50 |
+
yield_past_data = pd.read_csv("data/data_yield/data_rendement.csv")
|
| 51 |
+
# yield_forecast_data = pd.read_csv("data/data_yield/data_rendement.csv")
|
| 52 |
+
yield_past_data = yield_past_data[(yield_past_data["LIB_REG2"]==region) & (yield_past_data["LIB_SAA"].str.contains(culture)) ]
|
| 53 |
+
yield_past_data = yield_past_data[["LIB_REG2", "LIB_SAA"]+ [col for col in yield_past_data.columns if 'REND' in col ]]
|
| 54 |
+
# Transformation
|
| 55 |
+
yield_past_data = yield_past_data.melt(id_vars=["LIB_REG2", "LIB_SAA"], var_name="year", value_name="past_yield")
|
| 56 |
+
|
| 57 |
+
# Nettoyer la colonne "temps" pour enlever "REND_"
|
| 58 |
+
yield_past_data["year"] = yield_past_data["year"].str.replace("REND_", "").astype(int)
|
| 59 |
+
|
| 60 |
+
yield_forecast_data = pd.read_csv("data/data_yield/rendement_forecast.csv")
|
| 61 |
+
yield_forecast_data = yield_forecast_data[yield_forecast_data["culture"].str.contains(culture)]
|
| 62 |
+
return yield_past_data[["year", "past_yield"]], yield_forecast_data[["year", "yield_simple_forecast", "yield_with_shading_forecast"]]
|
| 63 |
+
|
| 64 |
|
| 65 |
if __name__ == "__main__":
|
| 66 |
|
| 67 |
scenario = "pessimist"
|
| 68 |
lat, lon = 47.0, 5.0
|
| 69 |
+
culture = "Blé tendre d'hiver"
|
| 70 |
+
region = "Bourgogne-Franche-Comté"
|
| 71 |
+
|
| 72 |
+
historical_df, forecast_df = pre_process_data(scenario, lat, lon)
|
| 73 |
+
|
| 74 |
+
temperature_df, rain_df, irradiance_df = process_all_data_for_meterological_summary(historical_df, forecast_df)
|
| 75 |
+
|
| 76 |
+
# meterological_summary = get_meterological_summary(scenario=scenario,
|
| 77 |
+
# temperature_df=temperature_df,
|
| 78 |
+
# irradiance_df=irradiance_df,
|
| 79 |
+
# rain_df=rain_df)
|
| 80 |
+
# print(meterological_summary)
|
| 81 |
+
|
| 82 |
+
climate_data = temperature_df.merge(rain_df, on='year').merge(irradiance_df, on='year') # meteo ok
|
| 83 |
+
closest_soil_data = find_nearest_point_to_coordinates(latitude=lat, longitude=lon) # soil ok
|
| 84 |
+
water_deficit_data = forecast_df[["time", "Water Deficit (mm/day)"]]
|
| 85 |
+
|
| 86 |
+
# add a step to transform gps coordinates into french region to be able to filter yield data
|
| 87 |
+
yield_past_data, yield_forecast_data = get_yield_data(region=region, culture=culture)
|
| 88 |
+
|
| 89 |
+
# rendement (avec et sans ombrage)
|
| 90 |
|
| 91 |
+
# print(get_agricultural_yield_comparison(culture=culture,
|
| 92 |
+
# region="bourgogne franche comté",
|
| 93 |
+
# water_df=water_deficit_data,
|
| 94 |
+
# climate_df=climate_data,
|
| 95 |
+
# soil_df=closest_soil_data,
|
| 96 |
+
# forecast_yield_df=yield_forecast_data,
|
| 97 |
+
# historical_yield_df=yield_past_data))
|
| 98 |
+
|
| 99 |
+
print(water_deficit_data)
|
| 100 |
|
| 101 |
# from utils.soil_utils import find_nearest_point
|
| 102 |
# city = "Bourgogne Franche Comté"
|
utils/summary.py
CHANGED
|
@@ -49,9 +49,16 @@ def get_meterological_summary(scenario: str, temperature_df: pd.DataFrame, rain_
|
|
| 49 |
return output_parser.parse(response)
|
| 50 |
|
| 51 |
|
| 52 |
-
def get_agricultural_yield_comparison(culture: str,
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
soil_data = soil_df.head(len(soil_df)).to_string(index=False)
|
| 56 |
water_data = water_df.head(len(water_df)).to_string(index=False)
|
| 57 |
climate_data = climate_df.head(len(climate_df)).to_string(index=False)
|
|
@@ -68,7 +75,7 @@ def get_agricultural_yield_comparison(culture: str, region:str, agri_yield_df: p
|
|
| 68 |
prompt = ChatPromptTemplate.from_messages(
|
| 69 |
[
|
| 70 |
("system", agricultural_yield_comparison_prompt),
|
| 71 |
-
("human", "Je suis agriculteur et je cultive de la {culture} à {region}. Voilà les caractéristiques du sol dans ma région {soil_data} et voilà l'historique et projections du rendement ma culture avec et sans ombrage {agricultural_yield}. J'ai aussi les donnés historiques et prévisions du stress hydrique {water_data} et des données climatiques {climate_data}. " )
|
| 72 |
]
|
| 73 |
)
|
| 74 |
chain = prompt | llm | output_parser
|
|
@@ -79,7 +86,8 @@ def get_agricultural_yield_comparison(culture: str, region:str, agri_yield_df: p
|
|
| 79 |
"soil_data": soil_data,
|
| 80 |
"water_data": water_data,
|
| 81 |
"climate_data": climate_data,
|
| 82 |
-
"agricultural_yield": agricultural_yield
|
|
|
|
| 83 |
})
|
| 84 |
|
| 85 |
return output_parser.parse(response)
|
|
|
|
| 49 |
return output_parser.parse(response)
|
| 50 |
|
| 51 |
|
| 52 |
+
def get_agricultural_yield_comparison(culture: str,
|
| 53 |
+
region:str,
|
| 54 |
+
historical_yield_df: pd.DataFrame,
|
| 55 |
+
forecast_yield_df: pd.DataFrame,
|
| 56 |
+
soil_df: pd.DataFrame,
|
| 57 |
+
climate_df: pd.DataFrame,
|
| 58 |
+
water_df: pd.DataFrame):
|
| 59 |
+
|
| 60 |
+
historical_yield = historical_yield_df.head(len(historical_yield_df)).to_string(index=False)
|
| 61 |
+
agricultural_yield = forecast_yield_df.head(len(forecast_yield_df)).to_string(index=False)
|
| 62 |
soil_data = soil_df.head(len(soil_df)).to_string(index=False)
|
| 63 |
water_data = water_df.head(len(water_df)).to_string(index=False)
|
| 64 |
climate_data = climate_df.head(len(climate_df)).to_string(index=False)
|
|
|
|
| 75 |
prompt = ChatPromptTemplate.from_messages(
|
| 76 |
[
|
| 77 |
("system", agricultural_yield_comparison_prompt),
|
| 78 |
+
("human", "Je suis agriculteur et je cultive de la {culture} à {region}. Voilà les caractéristiques du sol dans ma région {soil_data} et voilà l'historique de mon rendement {historical_yield} et projections du rendement ma culture avec et sans ombrage {agricultural_yield}. J'ai aussi les donnés historiques et prévisions du stress hydrique {water_data} et des données climatiques {climate_data}. " )
|
| 79 |
]
|
| 80 |
)
|
| 81 |
chain = prompt | llm | output_parser
|
|
|
|
| 86 |
"soil_data": soil_data,
|
| 87 |
"water_data": water_data,
|
| 88 |
"climate_data": climate_data,
|
| 89 |
+
"agricultural_yield": agricultural_yield,
|
| 90 |
+
"historical_yield": historical_yield
|
| 91 |
})
|
| 92 |
|
| 93 |
return output_parser.parse(response)
|