Rim BACCOUR commited on
Commit
ba70fb9
·
unverified ·
1 Parent(s): 787f4ea

finalize the final prompting for scenarii ombrage avec et sans comparison

Browse files
Files changed (4) hide show
  1. compute_yield.py +49 -27
  2. prompts/summary_prompt.py +27 -22
  3. summary_test.py +62 -17
  4. 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
- culture = "Colza d'hiver"
172
- scenario = "pessimist"
173
- shading_coef = 0.2
174
- monthly_forecast = compute_yield_forecast(
175
- latitude=47,
176
- longitude=5,
177
- culture=culture,
178
- scenario=scenario,
179
- shading_coef=0.,
180
- )
181
- # print(monthly_forecast.head())
182
-
183
- yield_forecast = get_annual_yield(monthly_forecast)
184
- # print(yield_forecast)
185
-
186
- monthly_forecast_with_shading = compute_yield_forecast(
187
- latitude=47,
188
- longitude=5,
189
- culture=culture,
190
- scenario=scenario,
191
- shading_coef=shading_coef,
192
- )
193
- # print(monthly_forecast_with_shading.head())
194
-
195
- yield_forecast_with_shading = get_annual_yield(monthly_forecast_with_shading)
196
- # print(yield_forecast)
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
- Tu es un expert agronome et spécialiste en agrivoltaïsme chez Ombrea (entreprise spécialisée en agrivoltaisme).
31
- Ta mission est d’analyser et de comparer deux scénarios agricoles :
32
- Un avec ombrage statique apporté par les panneaux photovoltaïques sur la culture et un sans ombrage.
33
- Tu dois conseiller un agriculteur sur la meilleure solution pour optimiser son rendement agricole.
34
- Il faut se concentrer sur la vision long terme qui prend en compte les aléas climatiques.
35
- Tu dois baser ton analyse sur les données suivantes :
36
- * Caractéristiques du sol : [pH, texture, teneur en matière organique, capacité de rétention d’eau, etc.]
37
- * Type de culture : [Nom de la culture et ses besoins spécifiques en lumière, température et eau]
38
- * Besoins hydriques : [Quantité d’eau requise et sensibilité au stress hydrique]
39
- * Projections climatiques : [Température moyenne, précipitations, risques de sécheresse, vagues de chaleur, etc.]
40
-
41
- Ton analyse devra inclure :
42
- - Comparaison des rendements agricoles : Différences de productivité avec et sans ombrage agrivoltaïque.
43
- - Impact sur la consommation d’eau : Évaluation des économies d’eau potentielles grâce à la régulation thermique et l’ombrage.
44
- - Effet sur la qualité des cultures : Influence des conditions microclimatiques créées par l’agrivoltaïsme.
45
- - Bilan économique : Gains estimés en production et en coûts d’irrigation.
 
 
46
 
47
- Formule une réponse détaillée et pédagogique pour l’agriculteur, en expliquant pourquoi l’un des scénarios est plus avantageux.
48
- Par exp: Grâce à l’ombrage : Le rendement agricole serait de +X%, Les besoins en eau seraient donc [réduit] de X%.
49
- Tu devras vulgariser les concepts techniques pour une meilleure compréhension, en te basant sur des données input et des retours d’expérience.
50
- L'utilisateur te founira le nom de la culture, les caractéristiques du sol dans la région en question et les données des rendements avec et sans ombrage.
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 process_all_data_for_meterological_summary(scenario: str, lat: float = 47.0, lon:float = 5.0):
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)[["Near Surface Air Temperature (°C)", "Surface Downwelling Shortwave Radiation (W/m²)", "Precipitation (kg m-2 s-1)"]].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)[["air_temperature_mean", "irradiance", "precipitation"]].mean().reset_index()
30
  new_historical_df = new_historical_df[new_historical_df["year"] < 2024]
31
 
32
- temperature_df = pd.concat([new_historical_df[["year", "air_temperature_mean"]].rename(columns={"air_temperature_mean": "Near Surface Air Temperature (°C)"}),
33
- new_forecast_df[["year", "Near Surface Air Temperature (°C)"]]], axis=0)
 
 
 
 
 
34
 
35
- irradiance_df = pd.concat([new_historical_df[["year", "irradiance"]].rename(columns={"irradiance": "Surface Downwelling Shortwave Radiation (W/m²)"}),
36
- new_forecast_df[["year", "Surface Downwelling Shortwave Radiation (W/m²)"]]], axis=0)
37
 
38
- rain_df = pd.concat([new_historical_df[["year", "precipitation"]].rename(columns={"precipitation": "Precipitation (kg m-2 s-1)"}),
39
- new_forecast_df[["year", "Precipitation (kg m-2 s-1)"]]], axis=0)
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
- temperature_df, rain_df, irradiance_df = process_all_data_for_meterological_summary(scenario, lat, lon)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
- meterological_summary = get_meterological_summary(scenario=scenario,
51
- temperature_df=temperature_df,
52
- irradiance_df=irradiance_df,
53
- rain_df=rain_df)
54
- print(meterological_summary)
 
 
 
 
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, region:str, agri_yield_df: pd.DataFrame, soil_df: pd.DataFrame, climate_df: pd.DataFrame, water_df: pd.DataFrame):
53
-
54
- agricultural_yield = agri_yield_df.head(len(agri_yield_df)).to_string(index=False)
 
 
 
 
 
 
 
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)