Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- client/pages/nutri.py +62 -8
- client/pages/user__course_list.py +70 -9
client/pages/nutri.py
CHANGED
@@ -17,13 +17,16 @@ from server.db.dbmanager import (
|
|
17 |
delete_conversation,
|
18 |
load_chatbot_suggestions,
|
19 |
save_chatbot_suggestions,
|
|
|
|
|
20 |
)
|
|
|
21 |
import logging
|
22 |
|
|
|
23 |
logging.basicConfig(level=logging.INFO, handlers=[logging.StreamHandler()])
|
24 |
logger = logging.getLogger(__name__)
|
25 |
|
26 |
-
|
27 |
# 🔹 Chargement des variables de session pour éviter les rechargements inutiles
|
28 |
if "id_conversation" not in st.session_state:
|
29 |
st.session_state.id_conversation = None
|
@@ -57,7 +60,7 @@ except Exception as e:
|
|
57 |
# 🔹 Chargement de la base de données
|
58 |
db_manager = st.session_state["db_manager"]
|
59 |
user_id = st.session_state["user_id"]
|
60 |
-
|
61 |
if "chatbot_suggestions" not in st.session_state:
|
62 |
st.session_state["chatbot_suggestions"] = load_chatbot_suggestions(
|
63 |
db_manager, user_id
|
@@ -242,8 +245,6 @@ if prompt := st.chat_input("Dîtes quelque-chose"):
|
|
242 |
|
243 |
time.sleep(0.03)
|
244 |
|
245 |
-
# 🔹 Vérifier si la réponse contient une suggestion de recette
|
246 |
-
|
247 |
# 🔹 Vérifier si la réponse contient des suggestions de recettes
|
248 |
keywords = ["recette", "plat", "préparer", "ingrédients"]
|
249 |
|
@@ -278,18 +279,55 @@ if prompt := st.chat_input("Dîtes quelque-chose"):
|
|
278 |
save_chatbot_suggestions(
|
279 |
db_manager, user_id, new_recipes
|
280 |
)
|
|
|
281 |
except Exception as e:
|
282 |
print(
|
283 |
f"❌ Erreur lors de l'extraction des suggestions : {e}"
|
284 |
)
|
285 |
|
286 |
break # On ne veut ajouter qu'une seule suggestion par réponse
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
|
288 |
-
|
289 |
-
# latency = round(end_time - start_time, 2) # 🔹 Calcul de la latence
|
290 |
|
291 |
-
|
292 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
except Exception as e:
|
294 |
if hasattr(e, "status_code") and e.status_code == 429:
|
295 |
retries += 1
|
@@ -368,3 +406,19 @@ if prompt := st.chat_input("Dîtes quelque-chose"):
|
|
368 |
"🤖 Entraînement du guardrail à reconnaître le prompt comme dangereux effectué avec succès"
|
369 |
)
|
370 |
st.stop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
delete_conversation,
|
18 |
load_chatbot_suggestions,
|
19 |
save_chatbot_suggestions,
|
20 |
+
save_recipes_with_ingredients,
|
21 |
+
add_ingredients_column_if_not_exists
|
22 |
)
|
23 |
+
|
24 |
import logging
|
25 |
|
26 |
+
|
27 |
logging.basicConfig(level=logging.INFO, handlers=[logging.StreamHandler()])
|
28 |
logger = logging.getLogger(__name__)
|
29 |
|
|
|
30 |
# 🔹 Chargement des variables de session pour éviter les rechargements inutiles
|
31 |
if "id_conversation" not in st.session_state:
|
32 |
st.session_state.id_conversation = None
|
|
|
60 |
# 🔹 Chargement de la base de données
|
61 |
db_manager = st.session_state["db_manager"]
|
62 |
user_id = st.session_state["user_id"]
|
63 |
+
add_ingredients_column_if_not_exists(db_manager)
|
64 |
if "chatbot_suggestions" not in st.session_state:
|
65 |
st.session_state["chatbot_suggestions"] = load_chatbot_suggestions(
|
66 |
db_manager, user_id
|
|
|
245 |
|
246 |
time.sleep(0.03)
|
247 |
|
|
|
|
|
248 |
# 🔹 Vérifier si la réponse contient des suggestions de recettes
|
249 |
keywords = ["recette", "plat", "préparer", "ingrédients"]
|
250 |
|
|
|
279 |
save_chatbot_suggestions(
|
280 |
db_manager, user_id, new_recipes
|
281 |
)
|
282 |
+
|
283 |
except Exception as e:
|
284 |
print(
|
285 |
f"❌ Erreur lors de l'extraction des suggestions : {e}"
|
286 |
)
|
287 |
|
288 |
break # On ne veut ajouter qu'une seule suggestion par réponse
|
289 |
+
time.sleep(1)
|
290 |
+
# 🔹 EXTRACTION ET ENREGISTREMENT DES RECETTES
|
291 |
+
# 🔍 Vérifier si la réponse contient des suggestions de recettes
|
292 |
+
# 🔹 EXTRACTION ET ENREGISTREMENT DES RECETTES
|
293 |
+
# 🔍 Vérifier si la réponse contient des suggestions de recettes
|
294 |
+
for word in keywords:
|
295 |
+
if word in response.lower():
|
296 |
+
try:
|
297 |
+
print("🔍 Détection de recettes, extraction en cours...")
|
298 |
+
|
299 |
+
# 🔹 Utiliser `extract_recipes_and_ingredients` pour extraire plusieurs recettes
|
300 |
+
extracted_recipes = mistral.extract_recipes_and_ingredients(response)
|
301 |
+
|
302 |
+
if extracted_recipes:
|
303 |
+
print(f"✅ {len(extracted_recipes)} recettes détectées : {extracted_recipes}")
|
304 |
+
|
305 |
+
# 🔹 Sauvegarder les recettes et leurs ingrédients dans la base de données
|
306 |
+
for recipe in extracted_recipes:
|
307 |
+
title = recipe["titre"].lstrip("-").strip() # Supprime les tirets et espaces inutiles
|
308 |
+
ingredients = recipe["ingredients"].strip()
|
309 |
+
|
310 |
+
# 🔹 Supprimer une virgule finale si présente dans le titre
|
311 |
+
title_cleaned = title.rstrip(",") # Enlève uniquement la virgule à la fin
|
312 |
|
313 |
+
print(f"💾 Enregistrement de la recette '{title_cleaned}' avec les ingrédients : {ingredients}")
|
|
|
314 |
|
315 |
+
save_recipes_with_ingredients(db_manager, user_id, title_cleaned, ingredients)
|
316 |
+
|
317 |
+
else:
|
318 |
+
print("⚠️ Aucune recette détectée.")
|
319 |
+
|
320 |
+
except Exception as e:
|
321 |
+
print(f"❌ Erreur lors de l'extraction des recettes et ingrédients : {e}")
|
322 |
+
|
323 |
+
break # Éviter d'ajouter plusieurs fois la même recette
|
324 |
+
|
325 |
+
|
326 |
+
end_time = time.time() # 🔹 Fin du chronomètre
|
327 |
+
latency = round(end_time - start_time, 2) # 🔹 Calcul de la latence
|
328 |
+
|
329 |
+
print(f"✅ Réponse générée en {latency} secondes.")
|
330 |
+
print(f"✅ Nombre de tokens de sortie : {output_tokens}")
|
331 |
except Exception as e:
|
332 |
if hasattr(e, "status_code") and e.status_code == 429:
|
333 |
retries += 1
|
|
|
406 |
"🤖 Entraînement du guardrail à reconnaître le prompt comme dangereux effectué avec succès"
|
407 |
)
|
408 |
st.stop()
|
409 |
+
# def check_if_ingredients_saved(db_manager, user_id):
|
410 |
+
# query = "SELECT repas_suggestion, ingredients FROM suggestions_repas WHERE id_utilisateur = ?"
|
411 |
+
# recipes = db_manager.execute_safe(query, (user_id,), fetch=True)
|
412 |
+
|
413 |
+
# if recipes:
|
414 |
+
# print("✅ Recettes enregistrées en base :")
|
415 |
+
# for recipe in recipes:
|
416 |
+
# recette_nom = recipe[0]
|
417 |
+
# ingredients = recipe[1] if recipe[1] else "⚠️ Aucun ingrédient enregistré"
|
418 |
+
# print(f"📌 {recette_nom} - Ingrédients : {ingredients}")
|
419 |
+
# else:
|
420 |
+
# print("⚠️ Aucune recette enregistrée.")
|
421 |
+
|
422 |
+
# # Appel pour tester
|
423 |
+
# check_if_ingredients_saved(db_manager, user_id)
|
424 |
+
|
client/pages/user__course_list.py
CHANGED
@@ -1,17 +1,78 @@
|
|
1 |
import streamlit as st
|
2 |
-
|
|
|
|
|
3 |
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
# Page des courses
|
6 |
def course_list():
|
7 |
-
|
|
|
|
|
|
|
|
|
8 |
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
-
if
|
12 |
-
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
else:
|
15 |
-
st.
|
|
|
|
|
|
|
16 |
|
17 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import unicodedata
|
4 |
+
from server.db.dbmanager import get_db_manager
|
5 |
|
6 |
+
def normalize_text(text):
|
7 |
+
"""Normalise un texte en supprimant les accents et en le mettant en minuscules"""
|
8 |
+
text = unicodedata.normalize("NFKD", text).encode("ASCII", "ignore").decode("utf-8").strip().lower()
|
9 |
+
return text
|
10 |
|
|
|
11 |
def course_list():
|
12 |
+
# Récupérer l'ID utilisateur
|
13 |
+
user_id = st.session_state.get("user_id")
|
14 |
+
if not user_id:
|
15 |
+
st.warning("⚠️ Vous devez être connecté pour voir votre liste de courses.")
|
16 |
+
return
|
17 |
|
18 |
+
# Charger la base de données
|
19 |
+
db_manager = get_db_manager()
|
20 |
+
|
21 |
+
# Charger les recettes et leurs ingrédients depuis la base de données
|
22 |
+
query = "SELECT repas_suggestion, ingredients FROM suggestions_repas WHERE id_utilisateur = ?"
|
23 |
+
raw_recipes = db_manager.execute_safe(query, (user_id,), fetch=True)
|
24 |
|
25 |
+
if not raw_recipes:
|
26 |
+
st.warning("⚠️ Aucune recette enregistrée pour générer une liste de courses.")
|
27 |
+
return
|
28 |
+
|
29 |
+
# ✅ Normalisation et suppression des doublons
|
30 |
+
recipes = {}
|
31 |
+
formatted_titles = {}
|
32 |
+
|
33 |
+
for recipe in raw_recipes:
|
34 |
+
title, ingredients = recipe["repas_suggestion"], recipe["ingredients"]
|
35 |
+
normalized_title = normalize_text(title)
|
36 |
+
|
37 |
+
if normalized_title not in recipes or (not recipes[normalized_title] and ingredients):
|
38 |
+
recipes[normalized_title] = ingredients
|
39 |
+
formatted_titles[normalized_title] = title
|
40 |
+
|
41 |
+
recipe_titles = list(formatted_titles.values())
|
42 |
+
|
43 |
+
# Sélectionner des recettes
|
44 |
+
selected_recipes = st.multiselect("📌 Sélectionnez une ou plusieurs recettes", recipe_titles)
|
45 |
+
|
46 |
+
# Initialiser all_ingredients pour éviter UnboundLocalError
|
47 |
+
all_ingredients = []
|
48 |
+
|
49 |
+
# Récupérer les ingrédients des recettes sélectionnées
|
50 |
+
selected_ingredients = []
|
51 |
+
for recipe in selected_recipes:
|
52 |
+
normalized_recipe = normalize_text(recipe)
|
53 |
+
ingredients = recipes.get(normalized_recipe)
|
54 |
+
if ingredients:
|
55 |
+
selected_ingredients.extend(ingredients.split(", "))
|
56 |
+
|
57 |
+
# ✅ Option pour afficher la liste complète de courses
|
58 |
+
if st.checkbox("👀 Afficher la liste complète des courses"):
|
59 |
+
all_ingredients = list({ing for ing_list in recipes.values() if ing_list for ing in ing_list.split(", ")})
|
60 |
+
|
61 |
+
# Affichage des ingrédients récupérés
|
62 |
+
ingredients_to_display = selected_ingredients if selected_ingredients else all_ingredients
|
63 |
+
if ingredients_to_display:
|
64 |
+
st.subheader("📋 Ingrédients nécessaires")
|
65 |
+
for ingredient in ingredients_to_display:
|
66 |
+
st.write(f"🛒 {ingredient}")
|
67 |
else:
|
68 |
+
st.warning("⚠️ Aucun ingrédient enregistré.")
|
69 |
+
|
70 |
+
# 📥 Exporter la liste des courses
|
71 |
+
df = pd.DataFrame({"Ingrédients": ingredients_to_display})
|
72 |
|
73 |
+
if st.download_button(
|
74 |
+
label="📥 Télécharger la liste des courses",
|
75 |
+
data=df.to_csv(index=False, sep=";").encode("utf-8-sig"),
|
76 |
+
file_name="liste_courses.csv",
|
77 |
+
mime="text/csv"):
|
78 |
+
st.success("✅ Liste des courses exportée en CSV avec succès !")
|