TD9991 commited on
Commit
03df0fa
1 Parent(s): c112ea6

second commit

Browse files
APIs/__pycache__/geolocation.cpython-311.pyc ADDED
Binary file (2.93 kB). View file
 
APIs/__pycache__/meteo.cpython-311.pyc ADDED
Binary file (5.02 kB). View file
 
APIs/geolocation.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import re
3
+
4
+
5
+ def get_geolocation(adresse, latitude, longitude):
6
+ """Return latitude, longitude & code INSEE from an adress. Latitude & longitude only if they are not specified in the function.
7
+
8
+ Args:
9
+ adresse (str): Adress or city for example
10
+
11
+ Returns:
12
+ Tuple(float, float, str): latitude, longitude & code INSEE
13
+ """
14
+ if latitude is not None and longitude is not None:
15
+ url = f"https://data.geopf.fr/geocodage/reverse?lon={longitude}&lat={latitude}&index=parcel"
16
+ else:
17
+ url = f"https://data.geopf.fr/geocodage/search?q={adresse}"
18
+
19
+ response = requests.get(url)
20
+ if response.status_code == 200:
21
+ data = response.json()["features"][0]
22
+ if 'parcel' in url:
23
+ properties = data["properties"]
24
+ code_insee = properties["departmentcode"] + \
25
+ properties["municipalitycode"]
26
+ else:
27
+ coordinates = data["geometry"]["coordinates"]
28
+ latitude, longitude = coordinates[1], coordinates[0]
29
+ code_insee = data["properties"]["citycode"]
30
+ return latitude, longitude, code_insee
31
+ return None, None, None
32
+
33
+
34
+ def get_risques(code_insee):
35
+ """Get list of risks from a 'code INSEE'
36
+
37
+ Args:
38
+ code_insee (str): Code INSEE
39
+
40
+ Returns:
41
+ List[str]: List of risks
42
+ """
43
+ requete = f"https://georisques.gouv.fr/api/v1/gaspar/risques?code_insee={code_insee}"
44
+ response = requests.get(requete)
45
+ if response.status_code == 200:
46
+ risques = eval(response.content.decode().replace("null", "-1"))
47
+ if risques["results"] > 0:
48
+ risques = risques["data"]
49
+ risques = [r["libelle_risque_long"]
50
+ for r in risques[0]["risques_detail"]]
51
+ else:
52
+ risques = []
53
+ else:
54
+ risques = None
55
+ return risques
56
+
57
+
58
+ if __name__ == "__main__":
59
+ lon, lat, code_insee = get_geolocation(
60
+ "6 allée de chartres 91370 Verrieres le Buisson", None, None)
61
+
62
+ print(get_risques(code_insee))
APIs/meteo.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openmeteo_requests
2
+ import requests_cache
3
+ import pandas as pd
4
+ from retry_requests import retry
5
+
6
+
7
+ # Setup the Open-Meteo API client with cache and retry on error
8
+ cache_session = requests_cache.CachedSession('.cache', expire_after=3600)
9
+ retry_session = retry(cache_session, retries=5, backoff_factor=0.2)
10
+ openmeteo = openmeteo_requests.Client(session=retry_session)
11
+
12
+
13
+ def get_info_meteo(latitude, longitude):
14
+ """Function that creates a Json file containing the weather data of the location
15
+ ARGS:
16
+ latitude (Float) : latitude coordinate
17
+ longitude (Float): longitude coordinate
18
+
19
+ """
20
+
21
+ url = "https://api.open-meteo.com/v1/forecast"
22
+ params = {
23
+ "latitude": latitude,
24
+ "longitude": longitude,
25
+ "hourly": {"relative_humidity_2m", "soil_temperature_0cm", "soil_moisture_0_to_1cm"},
26
+ "daily": {"temperature_2m_max", "precipitation_sum", "wind_speed_10m_max", "sunshine_duration"},
27
+ "past_days": 30,
28
+ "forecast_days": 7
29
+
30
+ }
31
+
32
+ responses = openmeteo.weather_api(url, params=params)
33
+ response = responses[0]
34
+
35
+ # Hourly dataframe
36
+ hourly = response.Hourly()
37
+ hourly_relative_humidity_2m = hourly.Variables(0).ValuesAsNumpy()
38
+ hourly_soil_temperature_0cm = hourly.Variables(1).ValuesAsNumpy()
39
+ hourly_soil_moisture_0_to_1cm = hourly.Variables(2).ValuesAsNumpy()
40
+
41
+ hourly_data = {"date": pd.date_range(
42
+ start=pd.to_datetime(hourly.Time(), unit="s", utc=True),
43
+ end=pd.to_datetime(hourly.TimeEnd(), unit="s", utc=True),
44
+ freq=pd.Timedelta(seconds=hourly.Interval()),
45
+ inclusive="left"
46
+ )}
47
+
48
+ hourly_data["relative_humidity_2m_%"] = hourly_relative_humidity_2m
49
+ hourly_data["soil_temperature_0cm_C"] = hourly_soil_temperature_0cm
50
+ hourly_data["soil_moisture_0_to_1cm_m³"] = hourly_soil_moisture_0_to_1cm
51
+
52
+ hourly_dataframe = pd.DataFrame(data=hourly_data)
53
+
54
+ # Average hourly data per day
55
+ hourly_dataframe['day_date'] = hourly_dataframe['date'].dt.strftime(
56
+ '%Y-%m-%d')
57
+
58
+ tmp = hourly_dataframe.groupby('day_date')[
59
+ ['relative_humidity_2m_%', 'soil_temperature_0cm_C', 'soil_moisture_0_to_1cm_m³']].mean()
60
+
61
+ avg_hourly_dataframe = tmp.rename(columns={'relative_humidity_2m_%': 'avg_hourly_relative_humidity_2m_%',
62
+ 'soil_temperature_0cm_C': 'avg_hourly_soil_temperature_0cm_C', 'soil_moisture_0_to_1cm_m³': 'avg_hourly_soil_moisture_0_to_1cm_m³'})
63
+
64
+ # Daily dataframe
65
+ daily = response.Daily()
66
+ daily_temperature_2m_max = daily.Variables(0).ValuesAsNumpy()
67
+ daily_precipitation_sum = daily.Variables(1).ValuesAsNumpy()
68
+ daily_wind_speed_10m_max = daily.Variables(2).ValuesAsNumpy()
69
+ daily_sunshine_duration = daily.Variables(3).ValuesAsNumpy()
70
+
71
+ daily_data = {"date": pd.date_range(
72
+ start=pd.to_datetime(daily.Time(), unit="s", utc=True),
73
+ end=pd.to_datetime(daily.TimeEnd(), unit="s", utc=True),
74
+ freq='D',
75
+ inclusive="left"
76
+ )}
77
+
78
+ daily_data["daily_temperature_2m_max_C"] = daily_temperature_2m_max
79
+ daily_data["daily_precipitation_sum_mm"] = daily_precipitation_sum
80
+ daily_data["daily_wind_speed_10m_max_km/h"] = daily_wind_speed_10m_max
81
+ daily_data["daily_sunshine_duration_sec"] = daily_sunshine_duration
82
+
83
+ daily_dataframe = pd.DataFrame(data=daily_data)
84
+
85
+ daily_dataframe['day_date'] = daily_dataframe['date'].dt.strftime(
86
+ '%Y-%m-%d')
87
+ total_df = pd.merge(daily_dataframe, avg_hourly_dataframe,
88
+ on="day_date", how="left")
89
+
90
+ total_df['date'] = total_df['day_date']
91
+ total_df = total_df.drop('day_date', axis=1)
92
+
93
+ return total_df
94
+ #total_df.to_json("app/data/weather_data.json", orient='columns')
app.py CHANGED
@@ -1,7 +1,35 @@
1
  import gradio as gr
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- iface = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- iface.launch()
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ from utils import *
3
 
4
+ with gr.Blocks() as demo:
5
+ with gr.Row():
6
+ with gr.Column():
7
+ lat = gr.Number(value=48.832408, label="Latitude",
8
+ info="La latitude de votre élevage")
9
+ lon = gr.Number(value=2.28619, label="Longitude",
10
+ info="La longitude de votre élevage")
11
+ address = gr.Textbox(
12
+ label="Address",
13
+ info="Dans le cas ou vous ne connaissez pas vos coordonnées GPS, rentrez votre adresse !")
14
+ with gr.Column():
15
+ type_elevage = gr.CheckboxGroup(choices=[
16
+ "Bovin",
17
+ "Ovin",
18
+ "Caprin",
19
+ "Porcin",
20
+ "Volailles",
21
+ "Equin"
22
+ ], label="Type d'élevage", info="Quel est votre type d'élevage?")
23
+ with gr.Column():
24
+ btn = gr.Button(value="Submit", size="sm")
25
 
26
+ with gr.Tab("Map"):
27
+ map = gr.HTML()
28
+
29
+ with gr.Tab("Weather data"):
30
+ fig = gr.Plot(label="Météo")
31
+
32
+ demo.load(show_map, [lat, lon, address], [map, fig])
33
+ btn.click(show_map, [lat, lon, address], [map, fig])
34
+
35
+ demo.launch()
chatbot.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+
4
+ from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
5
+
6
+ from llama_index.readers.web import SimpleWebPageReader
7
+
8
+ from llama_index.llms.mistralai import MistralAI
9
+ from llama_index.embeddings.mistralai import MistralAIEmbedding
10
+
11
+ from llama_index.core import Settings
12
+ from llama_index.core.query_engine import RetrieverQueryEngine
13
+
14
+ from dotenv import load_dotenv
15
+
16
+ def print_conversation(chat_history):
17
+ """
18
+ Fonction de vérification.
19
+
20
+ Args:
21
+ chat_history (List[List[str]]): historique d'échanges avec le chatbot
22
+ """
23
+ for question, response in chat_history:
24
+ print('Question :', end = '\n')
25
+ print(question, end = '\n')
26
+ print('Response :', end = '\n')
27
+ print(response, end = '\n\n')
28
+
29
+ def main(
30
+ query_engine,
31
+ elevage,
32
+ temperature,
33
+ humidite,
34
+ meteo
35
+ ):
36
+ """
37
+ Fonction qui crée le bloc du chatbot avec gradio.
38
+ Couplage entre le
39
+
40
+ Args:
41
+ query_engine (_type_): index de recherche vectorielle.
42
+ elevage (str):
43
+ temperature (str):
44
+ humidite (str):
45
+ meteo (str):
46
+
47
+ Returns:
48
+ None
49
+ """
50
+
51
+ title = "Gaia Mistral Chat RAG URL Demo"
52
+ description = "Example of an assistant with Gradio, RAG from url and Mistral AI via its API"
53
+ placeholder = "Vous pouvez me posez une question sur ce contexte, appuyer sur Entrée pour valider"
54
+
55
+ with gr.Blocks() as demo:
56
+
57
+ chatbot = gr.Chatbot()
58
+ msg = gr.Textbox(placeholder = placeholder)
59
+ clear = gr.ClearButton([msg, chatbot])
60
+
61
+ def respond(message, chat_history):
62
+
63
+ global_message = f"""
64
+ Tu es un chatbot qui réponds en français, commence et qui dois aider à déterminer les risques parasitaires d'élevage en fonction des conditions météo, voici les conditions météo :
65
+
66
+ - élevage : {elevage}
67
+ - température moyenne : {temperature}
68
+ - humidité moyenne : {humidite}
69
+ - météo : {meteo}
70
+
71
+ {message}
72
+
73
+ Donne-moi ensuite les solutions de prévention et de traitement pour chacun d'eux indépendamment du tableau.
74
+ Tu dois impérativement répondre en français.
75
+ """
76
+
77
+ response = query_engine.query(global_message)
78
+ chat_history.append((message, str(response)))
79
+
80
+ print_conversation(chat_history)
81
+ return '', chat_history
82
+
83
+ msg.submit(respond, [msg, chatbot], [msg, chatbot])
84
+
85
+ demo.title = title
86
+ demo.launch()
87
+
88
+ if __name__ == "__main__":
89
+
90
+ #### Loading de la clef Mistral
91
+ load_dotenv()
92
+ env_api_key = os.getenv('MISTRAL_API_KEY')
93
+
94
+ ### Type du modèle
95
+ llm_model = 'mistral-small-2312'
96
+
97
+ ### Config modèle
98
+ Settings.llm = MistralAI(
99
+ max_tokens = 1024,
100
+ api_key = env_api_key
101
+ )
102
+
103
+ Settings.embed_model = MistralAIEmbedding(
104
+ model_name="mistral-embed",
105
+ api_key=env_api_key
106
+ )
107
+
108
+ ### Mise en place de l'index
109
+ documents = SimpleDirectoryReader("documents").load_data()
110
+ index = VectorStoreIndex.from_documents(documents)
111
+ query_engine = index.as_query_engine(similarity_top_k=15)
112
+
113
+ ### Précision du type d'élevage et des conditions météo
114
+ elevage = 'bovin'
115
+ temperature = '15°C'
116
+ humidite = '40%'
117
+ meteo = 'pluvieux'
118
+
119
+ ### Lancement du Gradio
120
+ main(
121
+ query_engine,
122
+ elevage,
123
+ temperature,
124
+ humidite,
125
+ meteo
126
+ )
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ mistralai
2
+ faiss-cpu
3
+ numpy
4
+ html2text
5
+ llama-index==0.10.10
6
+ llama-index-llms-mistralai
7
+ llama-index-embeddings-mistralai
8
+ llama-index-llms-huggingface
utils.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import folium
3
+ from folium import IFrame
4
+ import plotly.graph_objects as go
5
+ from APIs.geolocation import get_geolocation, get_risques
6
+ from APIs.meteo import get_info_meteo
7
+
8
+
9
+ def get_and_plot_meteo(lat, lon):
10
+ df = get_info_meteo(lat, lon)
11
+ fig = go.Figure()
12
+ fig.add_trace(go.Scatter(x=df['date'], y=df['daily_temperature_2m_max_C'],
13
+ name="Température °C", mode="lines+markers"))
14
+ fig.add_trace(go.Scatter(x=df['date'], y=df['avg_hourly_relative_humidity_2m_%'],
15
+ name="Humidité moyenne en %", mode="lines+markers", yaxis="y2"))
16
+ fig.update_layout(
17
+ title="Température maximale et humidité moyenne journalière",
18
+ xaxis_title="Date",
19
+ yaxis_title="Température (°C)",
20
+ yaxis2=dict(
21
+ title="Humidity (%)",
22
+ overlaying="y",
23
+ side="right"
24
+ )
25
+ )
26
+ return fig
27
+
28
+
29
+ def show_map(lat, lon, address):
30
+ if address:
31
+ lat_tmp, lon_tmp, code_insee = get_geolocation(address, None, None)
32
+ risques = get_risques(code_insee=code_insee)
33
+ if lat_tmp or lon_tmp:
34
+ lat, lon = lat_tmp, lon_tmp
35
+ else:
36
+ return "Adress not found. Please enter a valid address", ""
37
+ if lat and lon:
38
+ lat_tmp, lon_tmp, code_insee = get_geolocation(None, lat, lon)
39
+ risques = get_risques(code_insee=code_insee)
40
+ # Create a map centered at the input coordinates
41
+ location_map = folium.Map(location=[lat, lon], zoom_start=14)
42
+ folium.Marker([lat, lon], popup=risques).add_to(location_map)
43
+ map_html = location_map._repr_html_()
44
+ fig = get_and_plot_meteo(lat, lon)
45
+ return map_html, fig