AbraBen97 commited on
Commit
f6102e2
1 Parent(s): 3f61189

version 1 de mon apli

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ data.pkl filter=lfs diff=lfs merge=lfs -text
__pycache__/config.cpython-310.pyc ADDED
Binary file (168 Bytes). View file
 
__pycache__/donnees.cpython-310.pyc ADDED
Binary file (294 Bytes). View file
 
__pycache__/fonction.cpython-310.pyc ADDED
Binary file (5.4 kB). View file
 
__pycache__/fonction_recom.cpython-310.pyc ADDED
Binary file (2.18 kB). View file
 
app.py ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ from fonction import prediction, prediction_embe
4
+ from dotenv import load_dotenv
5
+ import os
6
+ import config
7
+
8
+ from donnees import data_parfum, data_binaire
9
+
10
+
11
+
12
+ model = config.model
13
+ st.set_page_config(layout="wide")
14
+
15
+ st.title('Bienvenue sur AKIA PARFUM !')
16
+
17
+ ##################################################################################################
18
+ # Barre latérale pour les entrées
19
+ with st.sidebar:
20
+ st.markdown("<h1>SAISISSEZ VOS INFORMATIONS</h1>", unsafe_allow_html=True)
21
+
22
+ nombre = st.number_input(label='Nombre de parfums souhaités :', step=1, format='%d')
23
+ nombre = int(nombre)
24
+
25
+
26
+ parfums_prefere = st.multiselect(
27
+ "Sélectionnez vos parfums préférés.",
28
+ list(data_binaire.index)
29
+ )
30
+
31
+
32
+ details_rechercher = st.text_input("Décrivez le parfum de vos rêves.")
33
+
34
+ parfums_detestes = st.multiselect(
35
+ "Sélectionnez des parfums que vous n'aimez pas.",
36
+ list(data_binaire.index)
37
+ )
38
+
39
+
40
+
41
+ if parfums_detestes:
42
+ liste_deteste = list(prediction(parfums_detestes, data_binaire)[0:10].index)
43
+ liste_deteste.extend(parfums_detestes)
44
+ ######################################################################################################
45
+ # Diviser la page en deux colonnes
46
+ col1, col2 = st.columns([1, 4])
47
+
48
+ # Dans la colonne (col2), afficher les résultats
49
+ with col2:
50
+ st.markdown("<h3>NOS SUGGESTIONS</h3>", unsafe_allow_html=True)
51
+ parfums_suggeres = None
52
+ p = 0 #la variable p sera utiliser dans la suite du code, elle permet de pouvoir noter les parfums apres les recommandation
53
+
54
+ ####################################################################
55
+ #EVALUATION DES DEUX MODELS ET PREDICTIONS
56
+
57
+ if parfums_prefere:
58
+ prediction_caracteristique = prediction(parfums_prefere, data_binaire)
59
+
60
+ if details_rechercher:
61
+ prediction_desciption = prediction_embe(details_rechercher, data_parfum, model)
62
+
63
+
64
+
65
+
66
+ ####################################################################
67
+ #ELEMENTS A AFFICHES
68
+
69
+ #####CAS 1 : Liste de parfums favoris et description du parfum de reve
70
+ if parfums_prefere and details_rechercher:
71
+ data = pd.concat([prediction_caracteristique, prediction_desciption])
72
+ predictions = data.groupby(level=0)['probabilite'].mean()
73
+ predictions = predictions.drop(parfums_prefere)
74
+
75
+ if parfums_detestes:
76
+ liste_deteste = list(prediction(parfums_detestes, data_binaire)[0:10].index)
77
+ liste_deteste.extend(parfums_detestes)
78
+ predictions = predictions.drop(liste_deteste)
79
+
80
+ predictions = predictions.sort_values(ascending=False)
81
+ parfums_suggeres = predictions[0:nombre]
82
+ p = 1
83
+ st.write(parfums_suggeres)
84
+
85
+
86
+ ##### CAS 2 : description du parfum de reve
87
+ if not parfums_prefere and details_rechercher:
88
+ if parfums_detestes:
89
+ prediction_desciption = prediction_desciption.drop(liste_deteste)
90
+ parfums_suggeres = prediction_desciption[0:nombre]
91
+ p = 1
92
+ st.write(parfums_suggeres)
93
+
94
+
95
+ ##### CAS 3 : Liste de parfums favoris
96
+ if not details_rechercher and parfums_prefere:
97
+ if parfums_detestes:
98
+ prediction_caracteristique = prediction_caracteristique.drop(liste_deteste)
99
+ parfums_suggeres = prediction_caracteristique[0:nombre]
100
+ p = 1
101
+ st.write(parfums_suggeres)
102
+ if not details_rechercher and not parfums_prefere:
103
+ st.write('Bienvenue ! Veuillez choisir les parfums que vous aimez ou décrire le parfum de vos rêves.')
104
+
105
+
106
+ #############################################################################################
107
+
108
+ ### NOTEZ NOS SUGGESTIONS
109
+ liste = []
110
+ description_ = ''
111
+
112
+ with st.sidebar:
113
+ st.markdown("<h1>Notez nos suggestions sur 10</h1>", unsafe_allow_html=True)
114
+ if p == 1:
115
+ form_counter = 0
116
+ form_counter += 1
117
+ with st.form(key=f'rating_form_{form_counter}'):
118
+ parfum = st.selectbox("Choisir un parfum :", list(parfums_suggeres.index))
119
+ note = st.number_input("Entrez une note :", min_value=1, max_value=10)
120
+ nom = st.text_input("Entrer votre nom.")
121
+ if parfum:
122
+ if parfums_prefere :
123
+ liste = parfums_prefere
124
+ if not details_rechercher:
125
+ proba = parfums_suggeres.loc[parfum].values[0]
126
+
127
+ if details_rechercher:
128
+ description_ = details_rechercher
129
+ if not parfums_prefere:
130
+ proba = parfums_suggeres.loc[parfum].values[0]
131
+
132
+ #proba = parfums_suggeres.loc[parfum].values[0]
133
+
134
+ if details_rechercher and parfums_prefere:
135
+ proba = parfums_suggeres.loc[parfum]
136
+
137
+ submitted = st.form_submit_button("Enregistrer la note")
138
+ if submitted:
139
+ with open("notes.txt", "a") as file:
140
+ file.write(f"{nom},{liste},{description_},{parfum},{proba},{note}\n")
141
+ st.success("Note enregistrée avec succès !")
142
+ else:
143
+ st.write('En notant nos recommandations, vous contribuez à améliorer la qualité des suggestions qui vous sont proposées.')
config.py ADDED
@@ -0,0 +1 @@
 
 
1
+ model = 'models/embedding-001'
data.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7b93fd6100ccde27a1e140293dede6b22b24694fc2cffbdc42348ec4e576ba9a
3
+ size 19730237
donnee_binaire.csv ADDED
The diff for this file is too large to render. See raw diff
 
donnees.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+
3
+ data_parfum = pd.read_pickle("data.pkl") #Donner des description et des vecteurs de embedding
4
+
5
+ data_binaire = pd.read_csv('donnee_binaire.csv', index_col='nom_parfum') ## donnee des carracteristiques avec des 0 et 1
6
+
7
+
fonction.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ from scipy.spatial.distance import pdist, squareform
4
+ from sklearn.metrics.pairwise import cosine_similarity
5
+ import os
6
+ import google.generativeai as genai
7
+ import config
8
+ from dotenv import load_dotenv
9
+
10
+ load_dotenv()
11
+
12
+
13
+
14
+ def prediction(liste_parfums, df):
15
+
16
+ """
17
+ Cette fonction effectue une prédiction de recommandation de parfums basée sur la similarité de Jaccard.
18
+
19
+ Elle prend en entrée une liste de parfums aimés par un utilisateur,
20
+ calcule un nouveau profil utilisateur en agrégeant les embeddings correspondants à ces parfums,
21
+ puis calcule la similarité de Jaccard entre ce nouveau profil utilisateur et les autres profils de parfums.
22
+ Enfin, elle retourne les parfums recommandés triés par ordre décroissant de similarité de Jaccard.
23
+
24
+ Args:
25
+ liste_parfums (list): La liste des parfums aimés par l'utilisateur.
26
+ df (pandas.DataFrame): Le DataFrame contenant les embeddings des parfums.
27
+
28
+ Returns:
29
+ pandas.DataFrame: Un DataFrame contenant les parfums recommandés et leur probabilité de similarité.
30
+
31
+ Raises:
32
+ ValueError: Si la liste des parfums est vide ou si le DataFrame des embeddings est vide.
33
+ KeyError: Si la colonne 'Embeddings' n'est pas présente dans le DataFrame.
34
+ """
35
+
36
+ new_user = np.zeros(df.shape[1]) # Initialisation d'une série de zéros pour un nouveau profil utilisateur
37
+
38
+ # Calcul du nouveau profil utilisateur
39
+ for parfum in liste_parfums:
40
+ new_user += df.loc[parfum]
41
+ new_user[new_user > 1] = 1
42
+ df.loc['new_user'] = new_user
43
+
44
+
45
+ # Calcul de la similarité de Jaccard
46
+ jaccard_distances = pdist(df.values, metric='jaccard')
47
+ jaccard_similarity_array = 1 - squareform(jaccard_distances)
48
+ jaccard_similarity_df = pd.DataFrame(jaccard_similarity_array, index=df.index, columns=df.index)
49
+
50
+ # Récupération des similarités pour le nouvel utilisateur
51
+ jaccard_similarity_series = jaccard_similarity_df.loc['new_user']
52
+
53
+ # Suppression des parfums d'entrée
54
+ jaccard_similarity_series = jaccard_similarity_series.drop(list(liste_parfums))
55
+
56
+ # Trier les valeurs de similarité de la plus élevée à la plus basse
57
+ ordered_similarities = jaccard_similarity_series.sort_values(ascending=False)
58
+
59
+ # Supprimer le profil utilisateur après la prédiction
60
+ df = df.drop(index='new_user')
61
+
62
+ dict_of_dicts = ordered_similarities.to_dict()
63
+ data = pd.DataFrame(list(dict_of_dicts.values()), index=list(dict_of_dicts.keys()), columns=['probabilite'])
64
+ return data.iloc[1:]
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+ ma_cle = os.getenv('gemini_key')
73
+ genai.configure(api_key=ma_cle)
74
+ model = config.model
75
+
76
+ def calcul_emb(description_utilisateur, model):
77
+ """
78
+ Calcule l'embedding d'une description utilisateur en utilisant un modèle spécifié.
79
+ Args:
80
+ description_utilisateur (str): La description de l'utilisateur pour laquelle l'embedding doit être calculé.
81
+ model (str): Le modèle utilisé pour calculer l'embedding.
82
+ Returns:
83
+ numpy.ndarray: L'embedding de la description utilisateur, représenté sous forme de tableau NumPy.
84
+
85
+ Raises:
86
+ ValueError: Si le modèle spécifié n'est pas valide ou si la description utilisateur est vide.
87
+ """
88
+
89
+ embedding = genai.embed_content(model=model,
90
+ content=description_utilisateur,
91
+ task_type="retrieval_document")
92
+ return np.array(embedding["embedding"]).reshape(1, -1)
93
+
94
+
95
+
96
+
97
+ def calcul_similarite(embedding_utilisateur, embedding):
98
+ """
99
+ Calcule la similarité cosinus entre deux vecteurs d'embeddings.
100
+ Args:
101
+ embedding_utilisateur (numpy.ndarray): L'embedding de la desciption de l'utilisateur, représenté sous forme de tableau NumPy.
102
+ embedding (numpy.ndarray): L'embedding à comparer avec l'embedding de l'utilisateur, représenté sous forme de tableau NumPy.
103
+ Returns:
104
+ float: La similarité cosinus entre les deux embeddings.
105
+
106
+ Raises:
107
+ ValueError: Si l'une des embeddings n'est pas valide ou si elles n'ont pas la même dimension.
108
+ """
109
+ embedding = np.array(embedding).reshape(1, -1) # Convertir en tableau NumPy avant de remodeler
110
+ return cosine_similarity(embedding, np.array(embedding_utilisateur).reshape(1, -1))[0][0]
111
+
112
+
113
+
114
+ def prediction_embe(description_utilisateur, df, model):
115
+ """
116
+ Cette fonction effectue une prédiction basée sur l'embedding de la description utilisateur.
117
+
118
+ Elle calcule l'embedding de la description utilisateur en utilisant le modèle spécifié,
119
+ puis calcule la similarité cosinus entre cet embedding et les embeddings stockés dans le DataFrame.
120
+ Enfin, elle classe les résultats par ordre décroissant de similarité.
121
+
122
+ Args:
123
+ description_utilisateur (str): La description de l'utilisateur pour laquelle la prédiction doit être effectuée.
124
+ df (pandas.DataFrame): Le DataFrame contenant les embeddings des parfums et d'autres informations.
125
+ model (str): Le modèle utilisé pour calculer l'embedding de la description utilisateur.
126
+
127
+ Returns:
128
+ pandas.DataFrame: Un DataFrame contenant les noms des parfums et les probabilités de similarité, classés par ordre décroissant de similarité.
129
+
130
+ Raises:
131
+ ValueError: Si le modèle spécifié n'est pas valide ou si la description utilisateur est vide.
132
+ KeyError: Si la colonne 'Embeddings' n'est pas présente dans le DataFrame.
133
+ """
134
+ vecteur_utilisateur = calcul_emb(description_utilisateur, model)
135
+ df['probabilite'] = df['Embeddings'].map(lambda emb: calcul_similarite(emb, vecteur_utilisateur))
136
+ data = df[['nom_parfum', 'probabilite']]
137
+ data.set_index('nom_parfum', inplace=True)
138
+ data = data.sort_values(by='probabilite', ascending=False)
139
+ return data
140
+
notes.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
requirements.txt ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ altair==5.3.0
2
+ annotated-types==0.6.0
3
+ attrs==23.2.0
4
+ blinker==1.8.2
5
+ cachetools==5.3.3
6
+ certifi==2024.2.2
7
+ charset-normalizer==3.3.2
8
+ click==8.1.7
9
+ gitdb==4.0.11
10
+ GitPython==3.1.43
11
+ google-ai-generativelanguage==0.6.3
12
+ google-api-core==2.19.0
13
+ google-api-python-client==2.129.0
14
+ google-auth==2.29.0
15
+ google-auth-httplib2==0.2.0
16
+ google-generativeai==0.5.3
17
+ googleapis-common-protos==1.63.0
18
+ grpcio==1.63.0
19
+ grpcio-status==1.62.2
20
+ httplib2==0.22.0
21
+ idna==3.7
22
+ Jinja2==3.1.4
23
+ joblib==1.4.2
24
+ jsonschema==4.22.0
25
+ jsonschema-specifications==2023.12.1
26
+ markdown-it-py==3.0.0
27
+ MarkupSafe==2.1.5
28
+ mdurl==0.1.2
29
+ numpy==1.26.4
30
+ packaging==24.0
31
+ pandas==2.2.2
32
+ pillow==10.3.0
33
+ proto-plus==1.23.0
34
+ protobuf==4.25.3
35
+ pyarrow==16.1.0
36
+ pyasn1==0.6.0
37
+ pyasn1_modules==0.4.0
38
+ pydantic==2.7.1
39
+ pydantic_core==2.18.2
40
+ pydeck==0.9.1
41
+ Pygments==2.18.0
42
+ pyparsing==3.1.2
43
+ python-dateutil==2.9.0.post0
44
+ python-dotenv==1.0.1
45
+ pytz==2024.1
46
+ referencing==0.35.1
47
+ requests==2.31.0
48
+ rich==13.7.1
49
+ rpds-py==0.18.1
50
+ rsa==4.9
51
+ scikit-learn==1.4.2
52
+ scipy==1.13.0
53
+ six==1.16.0
54
+ smmap==5.0.1
55
+ streamlit==1.34.0
56
+ tenacity==8.3.0
57
+ threadpoolctl==3.5.0
58
+ toml==0.10.2
59
+ toolz==0.12.1
60
+ tornado==6.4
61
+ tqdm==4.66.4
62
+ typing_extensions==4.11.0
63
+ tzdata==2024.1
64
+ uritemplate==4.1.1
65
+ urllib3==2.2.1
66
+ watchdog==4.0.0