Spaces:
Runtime error
Runtime error
version 1 de mon apli
Browse files- .gitattributes +1 -0
- __pycache__/config.cpython-310.pyc +0 -0
- __pycache__/donnees.cpython-310.pyc +0 -0
- __pycache__/fonction.cpython-310.pyc +0 -0
- __pycache__/fonction_recom.cpython-310.pyc +0 -0
- app.py +143 -0
- config.py +1 -0
- data.pkl +3 -0
- donnee_binaire.csv +0 -0
- donnees.py +7 -0
- fonction.py +140 -0
- notes.txt +1 -0
- requirements.txt +66 -0
.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
|