|
@@ -3,114 +3,183 @@ import os
|
|
|
from dotenv import load_dotenv
|
|
from dotenv import load_dotenv
|
|
|
import uuid
|
|
import uuid
|
|
|
|
|
|
|
|
-load_dotenv()
|
|
|
|
|
|
|
+# --- CONFIGURATION INITIALE ---
|
|
|
|
|
+st.set_page_config(page_title="Actuariat GPT", page_icon="📊")
|
|
|
|
|
|
|
|
-# Import de tes fonctions (assure-toi que ton code précédent est dans le même dossier)
|
|
|
|
|
-# Ici je regroupe tout pour que ce soit fonctionnel
|
|
|
|
|
|
|
+load_dotenv()
|
|
|
|
|
|
|
|
-# Tes infos utilisateur
|
|
|
|
|
|
|
+# Infos utilisateur
|
|
|
user_infos = {
|
|
user_infos = {
|
|
|
"username": "user123",
|
|
"username": "user123",
|
|
|
"mdps": "pass123"
|
|
"mdps": "pass123"
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-def login_page():
|
|
|
|
|
-
|
|
|
|
|
- col1, col2 , col3 = st.columns([5,2,2])
|
|
|
|
|
- with col1 :
|
|
|
|
|
- st.image("logo Dataltist.png" , width=150)
|
|
|
|
|
|
|
+def login_page():
|
|
|
|
|
+ # --- INJECTION CSS (GRENAT & GRIS) ---
|
|
|
|
|
+ st.markdown("""
|
|
|
|
|
+ <style>
|
|
|
|
|
+ .stApp {
|
|
|
|
|
+ background-color: #F2F2F2;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- with col2 :
|
|
|
|
|
- st.write("")
|
|
|
|
|
|
|
+ .login-box {
|
|
|
|
|
+ background-color: white;
|
|
|
|
|
+ padding: 40px;
|
|
|
|
|
+ border-radius: 15px;
|
|
|
|
|
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08);
|
|
|
|
|
+ border-top: 5px solid #6B0D0D;
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- with col3 :
|
|
|
|
|
- st.link_button("🌐 Notre Site","https://dataltist.fr/")
|
|
|
|
|
-
|
|
|
|
|
|
|
+ .main-title {
|
|
|
|
|
+ color: #6B0D0D;
|
|
|
|
|
+ font-family: 'Helvetica Neue', sans-serif;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ margin-bottom: 30px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .stat-card {
|
|
|
|
|
+ background: white;
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+ border-radius: 12px;
|
|
|
|
|
+ box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ border-bottom: 4px solid #4A4A4A;
|
|
|
|
|
+ }
|
|
|
|
|
+ .stat-val {
|
|
|
|
|
+ font-size: 26px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #6B0D0D;
|
|
|
|
|
+ }
|
|
|
|
|
+ .stat-label {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ color: #4A4A4A;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Style des boutons de navigation du Header */
|
|
|
|
|
+/* Style des boutons de navigation du Header */
|
|
|
|
|
+ .nav-button {
|
|
|
|
|
+ background-color: #6B0D0D; /* Fond Grenat par défaut */
|
|
|
|
|
+ color: white !important; /* Texte blanc */
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ padding: 8px 18px;
|
|
|
|
|
+ border-radius: 20px;
|
|
|
|
|
+ text-decoration: none !important; /* SUPPRIME LE SOULIGNÉ */
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ transition: 0.3s;
|
|
|
|
|
+ margin-left: 10px;
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .nav-button:hover {
|
|
|
|
|
+ background-color: #4A0808; /* Grenat plus foncé au survol */
|
|
|
|
|
+ color: white !important;
|
|
|
|
|
+ text-decoration: none !important;
|
|
|
|
|
+ transform: translateY(-1px); /* Petit effet de levier */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Bouton Connexion */
|
|
|
|
|
+ div.stButton > button:first-child {
|
|
|
|
|
+ background-color: #6B0D0D !important;
|
|
|
|
|
+ color: white !important;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ padding: 10px 20px;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ transition: 0.3s;
|
|
|
|
|
+ }
|
|
|
|
|
+ div.stButton > button:first-child:hover {
|
|
|
|
|
+ background-color: #4A0808 !important;
|
|
|
|
|
+ }
|
|
|
|
|
+ </style>
|
|
|
|
|
+ """, unsafe_allow_html=True)
|
|
|
|
|
+
|
|
|
|
|
+ # --- HEADER / LOGO & NAV ---
|
|
|
|
|
+ header_col1, header_col2 = st.columns([2, 8])
|
|
|
|
|
+ with header_col1:
|
|
|
|
|
+ try:
|
|
|
|
|
+ st.image("logo Dataltist.png", width=130)
|
|
|
|
|
+ except:
|
|
|
|
|
+ st.markdown("<h3 style='color:#6B0D0D; margin:0;'>DATALTIST</h3>", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
- st.title("Connexion au Chatbot")
|
|
|
|
|
- username = st.text_input("Nom d'utilisateur")
|
|
|
|
|
- password = st.text_input("Mot de passe", type="password")
|
|
|
|
|
-
|
|
|
|
|
- if st.button("Se Connecter"):
|
|
|
|
|
- if username == user_infos["username"] and password == user_infos["mdps"]:
|
|
|
|
|
- st.session_state["is_logged_in"] = True # On utilise la même clé
|
|
|
|
|
- st.success("Connexion réussie !")
|
|
|
|
|
- st.rerun()
|
|
|
|
|
- else :
|
|
|
|
|
- st.error("Identifiants incorrects")
|
|
|
|
|
-
|
|
|
|
|
-# --- LOGIQUE DE VÉRIFICATION ---
|
|
|
|
|
-
|
|
|
|
|
-# 1. Initialisation si la clé n'existe pas encore
|
|
|
|
|
-if "is_logged_in" not in st.session_state:
|
|
|
|
|
- st.session_state["is_logged_in"] = False
|
|
|
|
|
|
|
+ st.markdown("<br>", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
-# 2. Affichage conditionnel
|
|
|
|
|
-if not st.session_state["is_logged_in"]:
|
|
|
|
|
|
|
+ # --- SECTION CENTRALE : LOGIN ---
|
|
|
|
|
+ left_co, cent_co, last_co = st.columns([1, 5, 1])
|
|
|
|
|
+
|
|
|
|
|
+ with cent_co:
|
|
|
|
|
+
|
|
|
|
|
+ st.markdown('<h2 class="main-title"> Login </h2>', unsafe_allow_html=True)
|
|
|
|
|
+ st.markdown("<br>", unsafe_allow_html=True)
|
|
|
|
|
+ st.markdown("<br>", unsafe_allow_html=True)
|
|
|
|
|
+
|
|
|
|
|
+ username = st.text_input("👤 Nom d'utilisateur", placeholder="votre email")
|
|
|
|
|
+ password = st.text_input("🔑 Mot de passe", type="password", placeholder="••••••••")
|
|
|
|
|
+
|
|
|
|
|
+ st.markdown("<br>", unsafe_allow_html=True)
|
|
|
|
|
+
|
|
|
|
|
+ if st.button("Se Connecter", use_container_width=True):
|
|
|
|
|
+ if username == user_infos["username"] and password == user_infos["mdps"]:
|
|
|
|
|
+ st.session_state["is_logged_in"] = True
|
|
|
|
|
+ st.rerun()
|
|
|
|
|
+ else :
|
|
|
|
|
+ st.error("Identifiants incorrects")
|
|
|
|
|
+ st.markdown('</div>', unsafe_allow_html=True)
|
|
|
|
|
+
|
|
|
|
|
+ st.markdown("<br><br>", unsafe_allow_html=True)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# --- INITIALISATION SESSION ---
|
|
|
|
|
+if "is_logged_in" not in st.session_state:
|
|
|
|
|
+ st.session_state["is_logged_in"] = False
|
|
|
|
|
+
|
|
|
|
|
+if not st.session_state["is_logged_in"]:
|
|
|
login_page()
|
|
login_page()
|
|
|
-else:
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- st.set_page_config(page_title="Actuariat GPT", page_icon="📊")
|
|
|
|
|
|
|
+else:
|
|
|
|
|
+ # --- INTERFACE CHATBOT ---
|
|
|
|
|
+ st.markdown("""<style>.stApp { background-color: #F2F2F2; }</style>""", unsafe_allow_html=True)
|
|
|
|
|
+
|
|
|
|
|
+ h_col1, h_col2 = st.columns([3, 1])
|
|
|
|
|
+ with h_col1:
|
|
|
|
|
+ try: st.image("logo Dataltist.png", width=100)
|
|
|
|
|
+ except: st.markdown("<h3 style='color:#6B0D0D; margin:0;'>DATALTIST GPT</h3>", unsafe_allow_html=True)
|
|
|
|
|
+ with h_col2:
|
|
|
|
|
+ if st.button("🚪 Déconnexion"):
|
|
|
|
|
+ st.session_state["is_logged_in"] = False
|
|
|
|
|
+ st.rerun()
|
|
|
|
|
|
|
|
- st.title("📊 Assistant Expert en Actuariat")
|
|
|
|
|
- st.markdown("Interrogez la base de 455 000 mémoires et thèses d'assurance.")
|
|
|
|
|
|
|
+
|
|
|
|
|
+ st.markdown("<h2 style='color:#4A4A4A; text-align:center;'> Assistant Expert en Actuariat</h2>", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
- # Initialisation de l'agent (on utilise @st.cache_resource pour ne pas recharger 455k lignes à chaque clic)
|
|
|
|
|
|
|
+ # Logique Agent
|
|
|
@st.cache_resource
|
|
@st.cache_resource
|
|
|
def get_agent():
|
|
def get_agent():
|
|
|
- # C'est ici qu'on appelle ta fonction create_agent()
|
|
|
|
|
- # Note : Assure-toi que les fonctions (get_vector_db, etc.) sont définies au-dessus
|
|
|
|
|
from tools import create_agent
|
|
from tools import create_agent
|
|
|
return create_agent()
|
|
return create_agent()
|
|
|
|
|
|
|
|
- try:
|
|
|
|
|
- with st.spinner("Initialisation de la base de données (cela peut être long la première fois)..."):
|
|
|
|
|
- agent_executor = get_agent()
|
|
|
|
|
- st.success("Agent prêt !")
|
|
|
|
|
- except Exception as e:
|
|
|
|
|
- st.error(f"Erreur d'initialisation : {e}")
|
|
|
|
|
- st.stop()
|
|
|
|
|
|
|
+ agent_executor = get_agent()
|
|
|
|
|
|
|
|
- # Gestion de l'historique des messages
|
|
|
|
|
if "messages" not in st.session_state:
|
|
if "messages" not in st.session_state:
|
|
|
- st.session_state.messages = []
|
|
|
|
|
|
|
+ st.session_state.messages = []
|
|
|
|
|
|
|
|
- # Affichage des messages
|
|
|
|
|
for message in st.session_state.messages:
|
|
for message in st.session_state.messages:
|
|
|
with st.chat_message(message["role"]):
|
|
with st.chat_message(message["role"]):
|
|
|
st.markdown(message["content"])
|
|
st.markdown(message["content"])
|
|
|
|
|
|
|
|
- # Zone de saisie
|
|
|
|
|
- # Zone de saisie
|
|
|
|
|
if prompt := st.chat_input("Posez votre question actuarielle..."):
|
|
if prompt := st.chat_input("Posez votre question actuarielle..."):
|
|
|
st.session_state.messages.append({"role": "user", "content": prompt})
|
|
st.session_state.messages.append({"role": "user", "content": prompt})
|
|
|
with st.chat_message("user"):
|
|
with st.chat_message("user"):
|
|
|
st.markdown(prompt)
|
|
st.markdown(prompt)
|
|
|
|
|
|
|
|
with st.chat_message("assistant"):
|
|
with st.chat_message("assistant"):
|
|
|
- # 1. On crée un conteneur vide pour la réponse finale
|
|
|
|
|
- response_placeholder = st.empty()
|
|
|
|
|
-
|
|
|
|
|
- # 2. On affiche le spinner pendant la réflexion
|
|
|
|
|
- with st.spinner("L'expert analyse les mémoires et prépare une réponse..."):
|
|
|
|
|
- try:
|
|
|
|
|
- # Configuration de la session (mémoire)
|
|
|
|
|
- config = {"configurable": {"thread_id": st.session_state.get("thread_id", "1")}}
|
|
|
|
|
- input_data = {"messages": [("user", prompt)]}
|
|
|
|
|
-
|
|
|
|
|
- # Exécution de l'agent
|
|
|
|
|
- result = agent_executor.invoke(input_data, config)
|
|
|
|
|
-
|
|
|
|
|
- # Extraction de la réponse
|
|
|
|
|
- full_response = result["messages"][-1].content
|
|
|
|
|
-
|
|
|
|
|
- # 3. Affichage final dans le placeholder
|
|
|
|
|
- response_placeholder.markdown(full_response)
|
|
|
|
|
-
|
|
|
|
|
- # Sauvegarde dans l'historique
|
|
|
|
|
- st.session_state.messages.append({"role": "assistant", "content": full_response})
|
|
|
|
|
-
|
|
|
|
|
- except Exception as e:
|
|
|
|
|
- st.error(f"Désolé, une erreur est survenue : {e}")
|
|
|
|
|
|
|
+ with st.spinner("Analyse des mémoires..."):
|
|
|
|
|
+ config = {"configurable": {"thread_id": st.session_state.get("thread_id", str(uuid.uuid4()))}}
|
|
|
|
|
+ result = agent_executor.invoke({"messages": [("user", prompt)]}, config)
|
|
|
|
|
+ response = result["messages"][-1].content
|
|
|
|
|
+ st.markdown(response)
|
|
|
|
|
+ st.session_state.messages.append({"role": "assistant", "content": response})
|