Procházet zdrojové kódy

avant de rajouter le chat , fonctionne !

Abdenbi před 1 měsícem
rodič
revize
1304811057
23 změnil soubory, kde provedl 147 přidání a 44 odebrání
  1. 5 2
      03 - Scripts/Agents.py
  2. 4 0
      03 - Scripts/function_exctract.py
  3. 2 2
      03 - Scripts/main.py
  4. 66 0
      03 - Scripts/server.py
  5. 49 23
      03 - Scripts/sfcr-app/src/App.jsx
  6. 15 11
      03 - Scripts/sfcr-app/src/constants.js
  7. 6 6
      03 - Scripts/sfcr-app/src/styles.js
  8. binární
      04 - Outputs/2023/CNP_Assurances/Rapport_S.02_page_135.xlsx
  9. binární
      04 - Outputs/2023/CNP_Assurances/Rapport_S.02_page_136.xlsx
  10. binární
      04 - Outputs/2023/CNP_Assurances/Rapport_S.05_page_138.xlsx
  11. binární
      04 - Outputs/2024/CNP_Assurances/Rapport_S.02_page_142.xlsx
  12. binární
      04 - Outputs/2024/CNP_Assurances/Rapport_S.02_page_143.xlsx
  13. binární
      04 - Outputs/2024/CNP_Assurances/Rapport_S.05_page_145.xlsx
  14. binární
      04 - Outputs/2024/CNP_Assurances/Rapport_S.05_page_146.xlsx
  15. binární
      04 - Outputs/2025/CNP_Assurances/Rapport_S.17_page_91.xlsx
  16. binární
      04 - Outputs/2025/CNP_Assurances/Rapport_S.19_page_92.xlsx
  17. binární
      04 - Outputs/2025/CNP_Assurances/Rapport_S.19_page_93.xlsx
  18. binární
      04 - Outputs/2025/PREDICA/Rapport_S.17_page_62.xlsx
  19. binární
      04 - Outputs/2025/PREDICA/Rapport_S.17_page_63.xlsx
  20. binární
      04 - Outputs/2025/PREDICA/Rapport_S.17_page_64.xlsx
  21. binární
      04 - Outputs/2025/PREDICA/Rapport_S.17_page_65.xlsx
  22. binární
      04 - Outputs/2025/PREDICA/Rapport_S.19_page_66.xlsx
  23. binární
      04 - Outputs/2025/PREDICA/Rapport_S.22_page_67.xlsx

+ 5 - 2
03 - Scripts/Agents.py

@@ -205,11 +205,14 @@ def agent_builder(state: AgentState):
             df.to_excel(writer, sheet_name="QRT_Export", index=True)
             # Ajoute ici tes formats xlsxwriter si nécessaire
 
-        success_msg = f" Sauvegardé dans : {output_file}"
+        success_msg = f" Sauvegardé dans : {output_file}"
         print(success_msg)
         return {"messages": [HumanMessage(content=success_msg)]}
 
     except Exception as e:
         error_msg = f" Erreur construction Excel : {str(e)}"
         print(error_msg)
-        return {"messages": [HumanMessage(content=error_msg)]}
+        return {"messages": [HumanMessage(content=error_msg)]}
+    
+
+

+ 4 - 0
03 - Scripts/function_exctract.py

@@ -69,9 +69,13 @@ def extract_pages(filename):
     # Mapping colonnes Excel -> sections SFCR
     section_columns = {
         "S.02": "Pages S.02",
+        "S.04": "Pages S.04",
         "S.05": "Pages S.05",
         "S.12": "Pages S.12",
+        "S.17": "Pages S.17",
+        "S.19": "Pages S.19",
         "S.22": "Pages S.22",
+        "S.23": "Pages S.23",
         "S.25": "Pages S.25",
         "S.28": "Pages S.28",
     }

+ 2 - 2
03 - Scripts/main.py

@@ -1,6 +1,6 @@
 INPUTS = {
-    "Groupama Gan Vie_2025.pdf": {
-        "S.12": []
+    "PREDICA_2025.pdf": {
+        "S.22": []
     }
 }
 

+ 66 - 0
03 - Scripts/server.py

@@ -217,5 +217,71 @@ def run_extraction():
         return jsonify({"stdout": "", "stderr": f"Erreur exécution : {str(e)}", "returncode": -1})
 
 
+
+
+
+from langchain_google_genai import ChatGoogleGenerativeAI
+from langchain_core.messages import HumanMessage, SystemMessage
+from dotenv import load_dotenv 
+from langchain_groq import ChatGroq 
+
+load_dotenv() 
+
+model_llama = ChatGroq(model="llama-3.3-70b-versatile") 
+
+llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", temperature=0.2)
+
+SYSTEM_PROMPT = """Tu es un assistant spécialisé dans l'extraction de données SFCR (Solvabilité II).
+
+Ton rôle : analyser la demande de l'utilisateur et extraire les informations nécessaires pour lancer une extraction :
+- entreprises (ex: CNP Assurances, AXA France Vie...)
+- année (ex: 2023, 2024...)
+- sections SFCR (parmi : S.02, S.05, S.12, S.17, S.22, S.25, S.28)
+
+Règles :
+- Si des informations manquent, pose UNE seule question à la fois.
+- Quand tu as TOUT (entreprises + année + sections), réponds UNIQUEMENT avec un JSON :
+{
+  "ready": true,
+  "entreprises": ["CNP Assurances", "AXA France Vie"],
+  "année": 2024,
+  "sections": ["S.02", "S.25"]
+}
+- Sinon réponds normalement en français.
+- Ne demande jamais plus d'une information à la fois.
+"""
+
+@app.route("/chat-agent", methods=["POST"])
+def chat_agent():
+    data = request.json
+    history = data.get("history", [])  # liste de {role, content}
+    
+    # Construit les messages pour le LLM
+    messages = [SystemMessage(content=SYSTEM_PROMPT)]
+    for msg in history:
+        if msg["role"] == "user":
+            messages.append(HumanMessage(content=msg["content"]))
+        else:
+            messages.append(SystemMessage(content=msg["content"]))
+    
+    try:
+        response = model_llama.invoke(messages)
+        reply = response.content.strip()
+        
+        # Vérifie si le LLM a retourné un JSON "ready"
+        try:
+            parsed = json.loads(reply)
+            if parsed.get("ready"):
+                return jsonify({"reply": reply, "ready": True, "data": parsed})
+        except json.JSONDecodeError:
+            pass
+        
+        return jsonify({"reply": reply, "ready": False})
+    
+    except Exception as e:
+        return jsonify({"reply": f"Erreur : {str(e)}", "ready": False})
+    
+
 if __name__ == "__main__":
+    print(app.url_map)
     app.run(debug=True, port=5000, threaded=True)

+ 49 - 23
03 - Scripts/sfcr-app/src/App.jsx

@@ -18,7 +18,7 @@ const ExtractionStatusView = ({ progress, logs, onClose, isDone }) => {
       {/* Header */}
       <div style={styles.extractionHeader}>
         <div>
-          <h2 style={styles.pageTitle}>Analyse Multi-Agents</h2>
+          <h2 style={styles.pageTitle}>Extraction en cours</h2>
           <p style={styles.pageSubtitle}>
             {isDone ? "Extraction terminée." : "Traitement des rapports Solvabilité II en cours..."}
           </p>
@@ -42,7 +42,7 @@ const ExtractionStatusView = ({ progress, logs, onClose, isDone }) => {
                 borderColor: allDone 
                   ? (hasError ? "#ef4444" : "rgba(16,185,129,0.35)") 
                   : C.border,
-                borderWidth: hasError ? 2 : 1, // Optionnel : épaissir un peu si erreur
+                borderWidth: hasError ? 1 : 1, 
               }}>   
               {/* Company header */}
               <div style={styles.companyStatusHeader}>
@@ -392,8 +392,8 @@ export default function App() {
         <div style={styles.sidebarHeader}>
           {!sidebarCollapsed && (
             <span style={styles.brandText}>
-              <span style={styles.brandAccent}>SFCR</span>
-              <span style={styles.brandSub}>·extract</span>
+              <span style={styles.brandAccent}>FORSIDES</span>
+              <span style={styles.brandSub}>·Dataltist</span>
             </span>
           )}
           <button
@@ -408,12 +408,14 @@ export default function App() {
           {[
             { id: "search", icon: "⊕", label: "Search Sources" },
             { id: "extraction", icon: "⊞", label: "Extraction" },
+            { id: "analyse", icon: "⊗", label: "Analyse QRT's" },
           ].map((item) => (
             <button
               key={item.id}
               onClick={() => {
                 setActiveNav(item.id);
                 if (item.id === "search") setIsExtracting(false);
+                if (item.id === "analyse") setIsExtracting(false);
               }}
               style={{
                 ...styles.navBtn,
@@ -431,7 +433,8 @@ export default function App() {
 
         <div style={styles.sidebarFooter}>
           {!sidebarCollapsed && (
-            <span style={styles.footerBadge}>Beta</span>
+            <span style={styles.footerBadge}>Forsides</span>
+            
           )}
         </div>
       </aside>
@@ -446,7 +449,15 @@ export default function App() {
               Section dédiée à la recherche de sources SFCR.
             </p>
           </div>
-        ) : isExtracting ? (
+        ) : activeNav === "analyse" ? (
+            <div style={styles.placeholderPanel}>
+              <div style={styles.placeholderIcon}>⊗</div>
+              <h2 style={styles.placeholderTitle}>Analyse QRT's</h2>
+              <p style={styles.placeholderDesc}>
+                Section dédiée à l'analyse des QRT.
+              </p>
+            </div>
+          ): isExtracting ? (
           <ExtractionStatusView
             progress={progress}
             logs={logs}
@@ -731,23 +742,6 @@ export default function App() {
                   </section>
                 )}
 
-                {/* 04. PROMPT */}
-                <section style={styles.card}>
-                  <div style={styles.cardHeader}>
-                    <span style={styles.cardBadge}>04</span>
-                    <h2 style={styles.cardTitle}>Prompt d'extraction</h2>
-                  </div>
-                  <div style={styles.promptWrapper}>
-                    <textarea
-                      style={styles.promptInput}
-                      placeholder="Instructions spécifiques..."
-                      value={prompt}
-                      onChange={(e) => setPrompt(e.target.value)}
-                      rows={4}
-                    />
-                  </div>
-                </section>
-
                 {/* RECAPITULATIF */}
                 {selectedCompanies.length > 0 && (
                   <section style={styles.summaryCard}>
@@ -759,6 +753,17 @@ export default function App() {
                         </span>
                         <span style={styles.summaryItemLabel}>Entreprise(s)</span>
                       </div>
+
+                      <div style={styles.summaryItem}>
+                        <span style={styles.summaryNum}>
+                          {yearMode === "global"
+                            ? globalSections.length
+                            : "Varié"}
+                        </span>
+                        <span style={styles.summaryItemLabel}>Année(s)</span>
+                      </div>
+
+
                       <div style={styles.summaryItem}>
                         <span style={styles.summaryNum}>
                           {sectionMode === "global"
@@ -770,6 +775,27 @@ export default function App() {
                     </div>
                   </section>
                 )}
+
+                {/* 04. PROMPT */}
+                {selectedCompanies.length == 0 && (
+                  <section style={styles.card}>
+                    <div style={styles.cardHeader}>
+                      <span style={styles.cardBadge}>04</span>
+                      <h2 style={styles.cardTitle}>Prompt d'extraction</h2>
+                    </div>
+                    <div style={styles.promptWrapper}>
+                      <textarea
+                        style={styles.promptInput}
+                        placeholder="Instructions spécifiques..."
+                        value={prompt}
+                        onChange={(e) => setPrompt(e.target.value)}
+                        rows={4}
+                      />
+                    </div>
+
+                  </section> ) }
+
+
               </div>
             </div>
           </div>

+ 15 - 11
03 - Scripts/sfcr-app/src/constants.js

@@ -21,23 +21,27 @@ export const ALL_COMPANIES = [
   { id: 20, name: "MAIF Vie", logo: "MA" },
   { id: 21, name: "MMA Vie SA", logo: "MM" },
   { id: 22, name: "Prépar Vie", logo: "PR" },
-  { id: 23, name: "SMA Vie BTP", logo: "SM" },
-  { id: 24, name: "SOGECAP", logo: "SO" },
-  { id: 25, name: "SPIRICA", logo: "SP" },
-  { id: 26, name: "SURAVENIR SA", logo: "SU" },
-  { id: 27, name: "SwissLife Assurance et Patrimoine", logo: "SW" },
+  { id: 23, name: "PREDICA", logo: "PD" },
+  { id: 24, name: "SMA Vie BTP", logo: "SM" },
+  { id: 25, name: "SOGECAP", logo: "SO" },
+  { id: 26, name: "SPIRICA", logo: "SP" },
+  { id: 27, name: "SURAVENIR SA", logo: "SU" },
+  { id: 28, name: "SwissLife Assurance et Patrimoine", logo: "SW" },
 ];
 
-export const SFCR_SECTIONS = ["S.02", "S.05", "S.12", "S.17", "S.22", "S.25", "S.28"];
+export const SFCR_SECTIONS = ["S.02", "S.04", "S.05", "S.12", "S.17","S.19", "S.22","S.23", "S.25", "S.28"];
 export const YEARS = [2025, 2024, 2023, 2022, 2021, 2020, 2019];
 export const CURRENT_YEAR = 2025;
 
 export const sectionLabels = {
   "S.02": "Bilan",
-  "S.05": "Primes, sinistres et dépenses",
-  "S.12": "Provisions techniques vie",
-  "S.17": "Provisions techniques non-vie",
-  "S.22": "Impact mesures long terme",
-  "S.25": "Capital de solvabilité requis",
+  "S.04": "Primes & dépenses / ligne",
+  "S.05": "Primes & dépenses / pays",
+  "S.12": "Provisions vie",
+  "S.17": "Provisions non-vie",
+  "S.19": "Sinistres non-vie",
+  "S.22": "Garanties long terme",
+  "S.23": "Fonds propres",
+  "S.25": "SCR",
   "S.28": "MCR",
 };

+ 6 - 6
03 - Scripts/sfcr-app/src/styles.js

@@ -7,13 +7,13 @@ export const C = {
   accent: "#3b82f6",
   accentGlow: "rgba(59,130,246,0.15)",
   accentSoft: "rgba(59,130,246,0.08)",
-  gold: "#f59e0b",
+  gold: "#b93209",
   goldSoft: "rgba(245,158,11,0.12)",
   text: "#e8ecf4",
   textMuted: "#6b7594",
   textDim: "#9aa3bc",
   green: "#10b981",
-  greenSoft: "rgba(16,185,129,0.1)",
+  greenSoft: "rgba(47, 156, 20, 0.1)",
 };
 
 export const styles = {
@@ -110,8 +110,8 @@ export const styles = {
   brandAccent: {
     fontSize: 18,
     fontWeight: 800,
-    letterSpacing: "-0.5px",
-    color: C.accent,
+    letterSpacing: "-0.2px",
+    color: "C2443C",
   },
   brandSub: {
     fontSize: 13,
@@ -171,9 +171,9 @@ export const styles = {
     fontSize: 10,
     fontWeight: 700,
     letterSpacing: "1px",
-    color: C.gold,
+    color: "red",
     background: C.goldSoft,
-    border: `1px solid rgba(245,158,11,0.2)`,
+    border: `1px solid rgba(185, 34, 14, 0.2)`,
     borderRadius: 4,
     padding: "3px 8px",
     textTransform: "uppercase",

binární
04 - Outputs/2023/CNP_Assurances/Rapport_S.02_page_135.xlsx


binární
04 - Outputs/2023/CNP_Assurances/Rapport_S.02_page_136.xlsx


binární
04 - Outputs/2023/CNP_Assurances/Rapport_S.05_page_138.xlsx


binární
04 - Outputs/2024/CNP_Assurances/Rapport_S.02_page_142.xlsx


binární
04 - Outputs/2024/CNP_Assurances/Rapport_S.02_page_143.xlsx


binární
04 - Outputs/2024/CNP_Assurances/Rapport_S.05_page_145.xlsx


binární
04 - Outputs/2024/CNP_Assurances/Rapport_S.05_page_146.xlsx


binární
04 - Outputs/2025/CNP_Assurances/Rapport_S.02_page_84.xlsx → 04 - Outputs/2025/CNP_Assurances/Rapport_S.17_page_91.xlsx


binární
04 - Outputs/2025/CNP_Assurances/Rapport_S.19_page_92.xlsx


binární
04 - Outputs/2025/CNP_Assurances/Rapport_S.19_page_93.xlsx


binární
04 - Outputs/2025/PREDICA/Rapport_S.17_page_62.xlsx


binární
04 - Outputs/2025/PREDICA/Rapport_S.17_page_63.xlsx


binární
04 - Outputs/2025/PREDICA/Rapport_S.17_page_64.xlsx


binární
04 - Outputs/2025/PREDICA/Rapport_S.17_page_65.xlsx


binární
04 - Outputs/2025/PREDICA/Rapport_S.19_page_66.xlsx


binární
04 - Outputs/2025/PREDICA/Rapport_S.22_page_67.xlsx