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)
|