소스 검색

Ajout page de conexion + modif prompt systeme

Abdenbi 1 주 전
부모
커밋
b8d3f686f3
2개의 변경된 파일172개의 추가작업 그리고 83개의 파일을 삭제
  1. 147 78
      app.py
  2. 25 5
      tools.py

+ 147 - 78
app.py

@@ -3,114 +3,183 @@ import os
 from dotenv import load_dotenv
 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 = {
     "username": "user123",
     "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()
-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
     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 
         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:
-        st.session_state.messages = [] 
+        st.session_state.messages = []
 
-    # Affichage des messages
     for message in st.session_state.messages:
         with st.chat_message(message["role"]):
             st.markdown(message["content"])
 
-    # Zone de saisie
-    # Zone de saisie
     if prompt := st.chat_input("Posez votre question actuarielle..."):
         st.session_state.messages.append({"role": "user", "content": prompt})
         with st.chat_message("user"):
             st.markdown(prompt)
 
         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})

+ 25 - 5
tools.py

@@ -141,11 +141,31 @@ def create_agent():
     tools = [rag_tool, web_search_tool]
     
     system_message = """
-        Tu es un expert actuariel. Ton rôle est d'assister les utilisateurs sur des sujets d'assurance.
-        1. Utilise 'RAG_search' pour les concepts théoriques, thèses et mémoires.
-        2. Utilise 'Web_search' pour les actualités ou réglementations très récentes.
-        3. Cite toujours tes sources si disponibles dans les métadonnées (titre du mémoire).
-    """    
+    Tu es l'Expert Actuariel Senior de Dataltist (Groupe Forsides). Ton rôle est de fournir des analyses de haute précision aux actuaires et professionnels de l'assurance.
+
+    --- DIRECTIVES DE RECHERCHE ---
+    1. PRIORITÉ LOCALE : Utilise toujours 'RAG_search' en premier pour les concepts théoriques, thèses, modèles mathématiques et mémoires actuariels. C'est ta base de connaissance de référence (800+ documents).
+    2. ACTUALITÉ : Utilise 'Web_search' uniquement pour les réglementations parues après 2024, les actualités de l'ACPR/EIOPA de 2025/2026, ou les chiffres de marché récents.
+    3. HYBRIDATION : Si une question lie théorie et actualité, utilise les deux outils pour une réponse complète.
+
+    --- STRUCTURE DE RÉPONSE ---
+    - Ta réponse doit être pédagogique, structurée avec des titres (##) et des points clés.
+    - Ne fais jamais de réponses en un seul bloc de texte.
+    - Utilise des tableaux Markdown si tu dois comparer des données.
+
+    --- CITATIONS & SOURCES ---
+    - SOURCE RAG : Cite impérativement le nom du fichier ou le titre du mémoire trouvé dans les métadonnées (ex: Source : Mémoire "Modélisation du risque cyber", 2024).
+    - SOURCE WEB : Pour chaque info issue d'internet, affiche le nom du site et le lien entre parenthèses (ex: Source : [ACPR](https://acpr.banque-france.fr)).
+
+    --- FORMATAGE MATHÉMATIQUE ---
+    - STRICT : N'utilise JAMAIS de notation LaTeX (pas de $, pas de \, pas de [ ]).
+    - Écris les formules de manière textuelle et lisible (ex: "Provision = Somme des Sinistres * Facteur de développement").
+    - Utilise l'étoile (*) pour la multiplication et le chapeau (^) pour les puissances.
+
+    --- TON & POSTURE ---
+    - Sois direct, professionnel et pragmatique.
+    - Si la base de données ne contient pas l'information, fait une recherche web ou une analyse basée sur les principes actuariels généraux.
+    """
 
     return create_react_agent(
         llm_4o,