Cherryblade29 commited on
Commit
615c11f
·
verified ·
1 Parent(s): 34bc47b

Upload 4 files

Browse files
Files changed (4) hide show
  1. clean_database.py +38 -0
  2. normalisation_with_huggingface.py +468 -0
  3. patients.db +0 -0
  4. sql.sql +24 -0
clean_database.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import pandas as pd
3
+
4
+
5
+
6
+
7
+ # Suppression des doublons
8
+ def remove_duplicates(df):
9
+ df = df.drop_duplicates()
10
+ df = df.loc[:, ~df.columns.duplicated()]
11
+ return df
12
+
13
+
14
+
15
+ # 🚀 Fonction unique appelée depuis le script principal
16
+ def clean_database(db_path: str):
17
+ """
18
+ Nettoie une base SQLite sur place : lit les données, les nettoie, puis écrase le fichier.
19
+ """
20
+ conn = sqlite3.connect(db_path)
21
+ tables = pd.read_sql("SELECT name FROM sqlite_master WHERE type='table';", conn)
22
+ cleaned_data = {}
23
+
24
+ for table in tables['name']:
25
+ print(f"🧽 Nettoyage de la table : {table}")
26
+ df = pd.read_sql(f"SELECT * FROM {table};", conn)
27
+ df = remove_duplicates(df)
28
+ cleaned_data[table] = df
29
+
30
+ conn.close()
31
+
32
+ # On écrase le fichier d'origine avec la version nettoyée
33
+ conn = sqlite3.connect(db_path)
34
+ for table, df in cleaned_data.items():
35
+ df.to_sql(table, conn, if_exists='replace', index=False)
36
+ conn.close()
37
+
38
+
normalisation_with_huggingface.py ADDED
@@ -0,0 +1,468 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sqlite3
3
+ import json
4
+ import pandas as pd
5
+ import re
6
+ from transformers import pipeline
7
+ import streamlit as st
8
+ from dotenv import load_dotenv
9
+ import graphviz
10
+ from clean_database import clean_database
11
+
12
+ # Charger les variables d'environnement depuis le fichier .env
13
+ load_dotenv()
14
+
15
+ # Configurer l'API de Hugging Face
16
+ HUGGINGFACE_API_KEY = os.getenv("HUGGINGFACE_API_KEY")
17
+
18
+ # Fonctions de normalisation de la base de données
19
+ def detecter_format(fichier):
20
+ extension = os.path.splitext(fichier)[1].lower()
21
+ if extension in [".db", ".sqlite"]:
22
+ return "sqlite"
23
+ elif extension == ".json":
24
+ return "json"
25
+ elif extension == ".csv":
26
+ return "csv"
27
+ elif extension in [".xls", ".xlsx"]:
28
+ return "excel"
29
+ else:
30
+ return "inconnu"
31
+
32
+ def json_to_sqlite(fichier_json):
33
+ with open(fichier_json, 'r', encoding='utf-8') as file:
34
+ data = json.load(file)
35
+ db_name = 'temp_json.db'
36
+ conn = sqlite3.connect(db_name)
37
+ cursor = conn.cursor()
38
+ table_name = "data"
39
+ columns = ', '.join(data[0].keys())
40
+ placeholders = ', '.join('?' * len(data[0]))
41
+ cursor.execute(f"CREATE TABLE IF NOT EXISTS {table_name} ({columns})")
42
+ for row in data:
43
+ cursor.execute(f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})", tuple(row.values()))
44
+ conn.commit()
45
+ conn.close()
46
+ return db_name
47
+
48
+ def csv_to_sqlite(fichier_csv):
49
+ df = pd.read_csv(fichier_csv, encoding='utf-8')
50
+ db_name = 'temp_csv.db'
51
+ conn = sqlite3.connect(db_name)
52
+ df.to_sql('data', conn, if_exists='replace', index=False)
53
+ conn.close()
54
+ return db_name
55
+
56
+ def excel_to_sqlite(fichier_excel):
57
+ df = pd.read_excel(fichier_excel, encoding='utf-8')
58
+ db_name = 'temp_excel.db'
59
+ conn = sqlite3.connect(db_name)
60
+ df.to_sql('data', conn, if_exists='replace', index=False)
61
+ conn.close()
62
+ return db_name
63
+
64
+ def preparer_bdd(input_path):
65
+ format_detecte = detecter_format(input_path)
66
+ if format_detecte == "sqlite":
67
+ return input_path
68
+ elif format_detecte == "json":
69
+ return json_to_sqlite(input_path)
70
+ elif format_detecte == "csv":
71
+ return csv_to_sqlite(input_path)
72
+ elif format_detecte == "excel":
73
+ return excel_to_sqlite(input_path)
74
+ else:
75
+ st.error("Format non supporté. Utilisez un fichier .db, .json, .csv, .xls ou .xlsx")
76
+ return None
77
+
78
+ def extraire_bdd(db_path):
79
+ with sqlite3.connect(db_path) as conn:
80
+ cursor = conn.cursor()
81
+ tables = [table[0] for table in cursor.execute(
82
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';"
83
+ ).fetchall()]
84
+ if not tables:
85
+ st.warning("Aucune table trouvée.")
86
+ return ""
87
+ output_bdd = ""
88
+ for table in tables:
89
+ output_bdd += f"\n📌 Table `{table}` :\n"
90
+ cursor.execute(f"PRAGMA table_info({table});")
91
+ columns = cursor.fetchall()
92
+ col_names = [col[1] for col in columns]
93
+ col_types = [col[2] for col in columns]
94
+ output_bdd += f"📝 Colonnes: {', '.join(f'{name} ({ctype})' for name, ctype in zip(col_names, col_types))}\n"
95
+ cursor.execute(f"SELECT * FROM {table}")
96
+ rows = cursor.fetchall()
97
+ if rows:
98
+ output_bdd += "\n".join(f" -> {row}" for row in rows) + "\n"
99
+ else:
100
+ output_bdd += "⚠️ Aucune donnée trouvée.\n"
101
+ return output_bdd
102
+
103
+ # Création de l'agent Hugging Face pour la vérification de la normalisation
104
+ normalization_checker = pipeline("text2text-generation", model="t5-base", temperature=0, top_p=0)
105
+
106
+ def analyser_bdd(output_bdd: str):
107
+ prompt = f"""
108
+ Voici la structure et les données de la base SQLite :
109
+ {output_bdd}
110
+ Tu es un expert en base de données exécute l'algorithme suivant pour normaliser et migrer la base de données. Affiche **uniquement** le résultat final sans explication détaillée et Ne pas ajouter de nouvelles colonnes non mentionnées dans la base de données d'origine.
111
+ ---
112
+ ### **Algorithme de normalisation et migration**
113
+ Début
114
+ Initialiser une variable `resultat_final` pour accumuler les résultats.
115
+ # Analyser la structure actuelle de la base de données
116
+ Pour chaque table `T` dans la base de données faire
117
+ Détecter la clé primaire existante ou en attribuer une si nécessaire.
118
+ # Appliquer la 1NF : Atomisation des attributs
119
+ Si `T` contient des attributs non atomiques alors
120
+ Transformer les attributs en valeurs atomiques.
121
+ Assigner les clés primaires et ajouter les clés étrangères si nécessaire.
122
+ Fin Si
123
+ # Appliquer la 2NF : Éliminer les dépendances fonctionnelles partielles
124
+ Si `T` contient une clé primaire composite et des attributs qui dépendent d’une partie seulement de la clé alors
125
+ Décomposer `T` en nouvelles tables en respectant la 2NF.
126
+ Assigner les clés primaires et ajouter les clés étrangères si nécessaire.
127
+ Fin Si
128
+ # Appliquer la 3NF : Éliminer les dépendances transitives
129
+ Si `T` contient des dépendances transitives (un attribut dépend d’un autre attribut non clé) alors
130
+ Décomposer `T` en nouvelles tables pour isoler ces dépendances.
131
+ Assigner les clés primaires et ajouter les clés étrangères si nécessaire.
132
+ Fin Si
133
+ # Appliquer la BCNF : Suppression des dépendances anormales
134
+ Si `T` contient une dépendance fonctionnelle où un attribut non clé détermine une clé candidate alors
135
+ Décomposer `T` en nouvelles relations respectant la BCNF.
136
+ Assigner les clés primaires et ajouter les clés étrangères si nécessaire.
137
+ Fin Si
138
+ # Migrer les données
139
+ Pour chaque nouvelle table normalisée faire
140
+ Identifier les données à migrer depuis l'ancienne base de données.
141
+ Transformer ou réorganiser les données selon le schéma normalisé proposé.
142
+ Insérer les données transformées dans la nouvelle table normalisée.
143
+ Fin Pour
144
+ # Le résultat doit absolument respecter cette structure.
145
+ Ajouter "📝 Nouvelles tables proposées :" à `resultat_final`.
146
+ Pour chaque nouvelle table `N` créée faire
147
+ Ajouter "📌 Table `nom_nouvelle_table` :" à `resultat_final`.
148
+ Ajouter "📝 Colonnes: colonne1 (type1), colonne2 (type2), ..." à `resultat_final`.
149
+ Ajouter "🔑 Clé primaire: `colonne_PK`" si définie.
150
+ Ajouter "🔗 Clé étrangère: `colonne_FK` → `table_referencée` (`colonne_referencée`)" si applicable.
151
+ Ajouter "📋 Données :" à `resultat_final`.
152
+ Pour chaque enregistrement migré dans la table faire
153
+ Ajouter " - `valeur1`, `valeur2`, ..." à `resultat_final`.
154
+ Fin Pour
155
+ Fin Pour
156
+ # Vérification finale avant affichage
157
+ Afficher `resultat_final`
158
+ Afficher "✅ Normalisation complète et migration réussie."
159
+ Fin
160
+ ---
161
+ """
162
+ response = normalization_checker(prompt, max_length=500, num_return_sequences=1)
163
+ resultat = response[0]['generated_text'].strip()
164
+ resultat_sans_think = re.sub(r"<think>.*?</think>", "", resultat, flags=re.DOTALL).strip()
165
+ return resultat_sans_think
166
+
167
+ # Création de l'agent 2 (vérifie la proposition de normalisation)
168
+ normalization_validator = pipeline("text2text-generation", model="t5-base", temperature=0, top_p=0)
169
+
170
+ def verifier_normalisation(proposition_normalisee: str, output_bdd: str):
171
+ prompt = f"""
172
+ Voici la base de données générée après application de la normalisation :
173
+ Vérifie si la normalisation proposée correspond bien à {output_bdd}.
174
+ Voici une proposition de base de données normalisée :
175
+ {proposition_normalisee}
176
+ - Tu es un expert en base de données exécute l'algorithme suivant pour vérifier si la base obtenue correspond bien à la normalisation attendue. Affiche **uniquement** le résultat final sans explication détaillée.
177
+ ---
178
+ ### **Algorithme de vérification et correction des formes normales**
179
+ Début
180
+ Initialiser une variable `corrections_appliquees` = False
181
+ Pour chaque table dans la base de données faire
182
+ Si tous les attributs sont atomiques alors
183
+ printf("📌 Vérification de la table `nom_table`")
184
+ printf("✅ La table `nom_table` est en 1NF")
185
+ Si la table ne contient pas de dépendances fonctionnelles partielles alors
186
+ printf("✅ La table `nom_table` est en 2NF")
187
+ Si la table ne contient pas de dépendances transitives alors
188
+ printf("✅ La table `nom_table` est en 3NF")
189
+ Si chaque dépendance fonctionnelle est basée sur une clé candidate alors
190
+ printf("✅ La table `nom_table` est en BCNF")
191
+ Sinon
192
+ printf("❌ La table `nom_table` ne respecte pas la BCNF → Correction appliquée.")
193
+ Appliquer la correction en décomposant la table en relations BCNF.
194
+ corrections_appliquees = True
195
+ Fin Si
196
+ Sinon
197
+ printf("❌ La table `nom_table` ne respecte pas la 3NF → Correction appliquée.")
198
+ Appliquer la correction en éliminant les dépendances transitives.
199
+ corrections_appliquees = True
200
+ Fin Si
201
+ Sinon
202
+ printf("❌ La table `nom_table` ne respecte pas la 2NF → Correction appliquée.")
203
+ Appliquer la correction en éliminant les dépendances partielles.
204
+ corrections_appliquees = True
205
+ Fin Si
206
+ Sinon
207
+ printf("❌ La table `nom_table` ne respecte pas la 1NF → Correction appliquée.")
208
+ Appliquer la correction en atomisant les attributs.
209
+ corrections_appliquees = True
210
+ Fin Si
211
+ Fin Pour
212
+ Si corrections_appliquees == True alors
213
+ printf("⚠️ Des corrections ont été appliquées durant la vérification.")
214
+ Fin Si
215
+ printf("🔍 Normalisation terminée.")
216
+ Fin
217
+ ---
218
+ """
219
+ response = normalization_validator(prompt, max_length=500, num_return_sequences=1)
220
+ resultat = response[0]['generated_text'].strip()
221
+ resultat_sans_think = re.sub(r"<think>.*?</think>", "", resultat, flags=re.DOTALL).strip()
222
+ return resultat_sans_think
223
+
224
+ # Création de l'agent 3 (crée la nouvelle bdd normalisée)
225
+ sql_generator = pipeline("text2text-generation", model="t5-base", temperature=0, top_p=0)
226
+
227
+ def génération_des_requêtes(proposition_normalisee: str):
228
+ prompt = f"""
229
+ Voici une proposition de base de données normalisée :
230
+ {proposition_normalisee}
231
+ Génère uniquement les requêtes SQL pour créer et insérer des données dans la nouvelle base de données normalisée (crée les nouvelles tables et insère toutes les données et n'ajoute rien).
232
+ """
233
+ response = sql_generator(prompt, max_length=500, num_return_sequences=1)
234
+ resultat = response[0]['generated_text'].strip()
235
+ resultat_sans_think = re.sub(r"<think>.*?</think>", "", resultat, flags=re.DOTALL).strip()
236
+ return resultat_sans_think
237
+
238
+ def nettoyer_requetes_sql(texte):
239
+ # Expression régulière pour capturer les requêtes CREATE TABLE et INSERT INTO
240
+ pattern = r"(CREATE TABLE.*?;|INSERT INTO.*?;)"
241
+ requetes_sql = re.findall(pattern, texte, re.DOTALL | re.IGNORECASE)
242
+ return "\n\n".join(req.strip() for req in requetes_sql)
243
+
244
+ # --- Fonctions utilitaires ---
245
+ def create_sqlite_db_from_file(sql_file, db_name):
246
+ if os.path.exists(db_name):
247
+ os.remove(db_name)
248
+
249
+ conn = sqlite3.connect(db_name)
250
+ cursor = conn.cursor()
251
+
252
+ with open(sql_file, 'r') as file:
253
+ sql_script = file.read()
254
+
255
+ cursor.executescript(sql_script)
256
+ conn.commit()
257
+ conn.close()
258
+
259
+ def get_database_structure(db_name):
260
+ conn = sqlite3.connect(db_name)
261
+ cursor = conn.cursor()
262
+
263
+ # Récupérer les tables
264
+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
265
+ tables = cursor.fetchall()
266
+
267
+ structure = ""
268
+ for table in tables:
269
+ table_name = table[0]
270
+ structure += f"Table: {table_name}\n"
271
+
272
+ # Récupérer les colonnes
273
+ cursor.execute(f"PRAGMA table_info({table_name});")
274
+ columns = cursor.fetchall()
275
+ for column in columns:
276
+ structure += f" Colonne: {column[1]} (Type: {column[2]})\n"
277
+
278
+ conn.close()
279
+ return structure
280
+
281
+ def get_sample_data(db_name, limit=3):
282
+ conn = sqlite3.connect(db_name)
283
+ cursor = conn.cursor()
284
+ sample_text = ""
285
+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
286
+ tables = cursor.fetchall()
287
+ for table in tables:
288
+ table_name = table[0]
289
+ sample_text += f"\nExtrait de la table {table_name} :\n"
290
+ df = pd.read_sql_query(f"SELECT * FROM {table_name} LIMIT {limit}", conn)
291
+ sample_text += df.to_string(index=False)
292
+ sample_text += "\n"
293
+ conn.close()
294
+ return sample_text
295
+
296
+ def transform_prompt_to_sql(prompt, db_structure):
297
+ instructions = f"""
298
+ Voici la structure de la base de données :
299
+ {db_structure}
300
+ Voici la requête de l'utilisateur :
301
+ {prompt}
302
+
303
+ Transforme ce prompt en une requête SQL en utilisant la structure de la base de données fournie.
304
+ """
305
+ response = sql_transformer(instructions, max_length=500, num_return_sequences=1)
306
+ return response[0]['generated_text'].strip()
307
+
308
+ def clean_sql_query(response):
309
+ # Utiliser une expression régulière pour extraire uniquement la requête SQL
310
+ match = re.search(r'```sql\s*(.*?)\s*```', response, re.DOTALL)
311
+ if match:
312
+ return match.group(1).strip()
313
+ else:
314
+ raise ValueError("Impossible d'extraire la requête SQL de la réponse.")
315
+
316
+ def execute_sql_query(db_name, sql_query):
317
+ conn = sqlite3.connect(db_name)
318
+ cursor = conn.cursor()
319
+ cursor.execute(sql_query)
320
+ results = cursor.fetchall()
321
+ conn.close()
322
+ return results
323
+
324
+ def visualize_database_schema_from_sql(sql_file):
325
+ with open(sql_file, 'r') as file:
326
+ sql_script = file.read()
327
+
328
+ # Extraction des tables et colonnes
329
+ tables = {}
330
+ pks = {}
331
+ fks = []
332
+
333
+ create_table_pattern = re.compile(r'CREATE TABLE\s+(\w+)\s*\((.*?)\);', re.DOTALL | re.IGNORECASE)
334
+ fk_pattern = re.compile(r'FOREIGN KEY\s*\((\w+)\)\s*REFERENCES\s+(\w+)\s*\((\w+)\)', re.IGNORECASE)
335
+ pk_inline_pattern = re.compile(r'^(\w+)\s+\w+.*PRIMARY KEY', re.IGNORECASE)
336
+ pk_constraint_pattern = re.compile(r'PRIMARY KEY\s*\((.*?)\)', re.IGNORECASE)
337
+
338
+ for match in create_table_pattern.finditer(sql_script):
339
+ table_name = match.group(1)
340
+ body = match.group(2)
341
+ lines = [line.strip() for line in body.split(',') if line.strip()]
342
+ columns = []
343
+ primary_keys = []
344
+
345
+ for line in lines:
346
+ if line.upper().startswith("FOREIGN KEY"):
347
+ fk_match = fk_pattern.search(line)
348
+ if fk_match:
349
+ source_col = fk_match.group(1)
350
+ ref_table = fk_match.group(2)
351
+ ref_col = fk_match.group(3)
352
+ fks.append((table_name, source_col, ref_table, ref_col))
353
+ elif line.upper().startswith("PRIMARY KEY"):
354
+ pk_match = pk_constraint_pattern.search(line)
355
+ if pk_match:
356
+ pk_cols = [pk.strip() for pk in pk_match.group(1).split(',')]
357
+ primary_keys.extend(pk_cols)
358
+ else:
359
+ parts = line.split()
360
+ if len(parts) == 0:
361
+ continue # ligne vide ou espace
362
+ col_name = parts[0].strip("()") # on enlève les parenthèses résiduelles
363
+ if col_name.isidentifier(): # vérifie que c’est un nom valide
364
+ if col_name not in columns: # Vérifie si la colonne n'est pas déjà présente
365
+ columns.append(col_name)
366
+ inline_pk = pk_inline_pattern.match(line)
367
+ if inline_pk:
368
+ if inline_pk.group(1) not in primary_keys: # Vérifie si la clé primaire n'est pas déjà présente
369
+ primary_keys.append(inline_pk.group(1))
370
+
371
+ tables[table_name] = columns
372
+ pks[table_name] = primary_keys
373
+
374
+ # Construction du graphe avec style MERISE
375
+ dot = graphviz.Digraph(format='png')
376
+ dot.attr('node', shape='plaintext')
377
+
378
+ for table, columns in tables.items():
379
+ rows = []
380
+ for col in columns:
381
+ if col in pks.get(table, []):
382
+ rows.append(f'<TR><TD ALIGN="LEFT"><U>{col}</U></TD></TR>')
383
+ else:
384
+ rows.append(f'<TR><TD ALIGN="LEFT">{col}</TD></TR>')
385
+
386
+ label = f"""<<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0">
387
+ <TR><TD BGCOLOR="lightgray"><B>{table}</B></TD></TR>
388
+ {''.join(rows)}
389
+ </TABLE>>"""
390
+
391
+ dot.node(table, label=label)
392
+
393
+ for src_table, src_col, tgt_table, tgt_col in fks:
394
+ dot.edge(src_table, tgt_table, label=f"{src_col} → {tgt_col}")
395
+
396
+ st.graphviz_chart(dot)
397
+
398
+ # --- Config Agent ---
399
+ sql_transformer = pipeline("text2text-generation", model="t5-base", temperature=0, top_p=0)
400
+
401
+ # --- Interface Streamlit ---
402
+ st.set_page_config(page_title="Assistant SQL avec LLM", layout="wide")
403
+ st.title("🧠📊 Assistant SQL intelligent (avec LLM)")
404
+
405
+ db_name = "database.db"
406
+ sql_file = "output.sql"
407
+
408
+ # Champ de saisie pour le fichier d'entrée
409
+ input_file = st.file_uploader("Choisissez un fichier (.db, .json, .csv, .xls ou .xlsx)", type=["db", "sqlite", "json", "csv", "xls", "xlsx"])
410
+
411
+ if input_file:
412
+ # Enregistrer le fichier téléchargé temporairement
413
+ temp_file_path = f"temp_{input_file.name}"
414
+ with open(temp_file_path, "wb") as f:
415
+ f.write(input_file.getbuffer())
416
+
417
+ prepared_db_path = preparer_bdd(temp_file_path)
418
+ if prepared_db_path:
419
+ st.success(f"Base de données prête : {prepared_db_path}")
420
+ clean_database(prepared_db_path)
421
+ st.success("Base de données nettoyée.")
422
+ output_bdd = extraire_bdd(prepared_db_path)
423
+ if output_bdd:
424
+ proposition_normalisee = output_bdd
425
+ while True:
426
+ resultat = analyser_bdd(proposition_normalisee)
427
+ verification = verifier_normalisation(resultat, output_bdd)
428
+ if "⚠️ Des corrections ont été appliquées durant la vérification." in verification:
429
+ proposition_normalisee = verification
430
+ else:
431
+ st.text("\n🔍 Résultat final de l'analyse :\n" + resultat)
432
+ st.text("\n✅ Vérification de la normalisation :\n" + verification)
433
+ break
434
+
435
+ # Générer les requêtes SQL pour la nouvelle base de données normalisée
436
+ sql_content = génération_des_requêtes(resultat)
437
+ requetes_nettoyees = nettoyer_requetes_sql(sql_content)
438
+
439
+ # Écrire les requêtes SQL dans le fichier output.sql
440
+ with open(sql_file, "w", encoding='utf-8') as fichier_sql:
441
+ fichier_sql.write(requetes_nettoyees)
442
+
443
+ st.success(f"Fichier SQL généré: {sql_file}")
444
+ create_sqlite_db_from_file(sql_file, db_name)
445
+
446
+ # Visualiser le schéma de la base de données
447
+ st.subheader("Schéma des relations entre les tables")
448
+ visualize_database_schema_from_sql(sql_file)
449
+
450
+ # Champ de saisie pour les requêtes en langage naturel
451
+ prompt = st.text_input("💬 Pose ta question :", placeholder="Ex: Liste les patients atteints de diabète")
452
+
453
+ if prompt:
454
+ st.write("🛠️ Génération SQL en cours…")
455
+ structure = get_database_structure(db_name)
456
+ try:
457
+ response = transform_prompt_to_sql(prompt, structure)
458
+ sql_query = clean_sql_query(response)
459
+ st.code(sql_query, language="sql")
460
+
461
+ df = execute_sql_query(db_name, sql_query)
462
+ st.success("✅ Requête exécutée avec succès !")
463
+ st.dataframe(df)
464
+ except Exception as e:
465
+ st.error(f"❌ Erreur lors de l'exécution de la requête : {e}")
466
+
467
+
468
+ #execution streamlit run normalisation_with_huggingface.py
patients.db ADDED
Binary file (8.19 kB). View file
 
sql.sql ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ CREATE TABLE patients (
3
+ id INTEGER PRIMARY KEY ,
4
+ nom TEXT NOT NULL,
5
+ prenom TEXT NOT NULL,
6
+ age INTEGER NOT NULL,
7
+ sexe TEXT NOT NULL,
8
+ date_naissance TEXT NOT NULL,
9
+ maladies TEXT,
10
+ traitements TEXT
11
+ );
12
+
13
+ INSERT INTO patients ( nom, prenom, age, sexe, date_naissance, maladies, traitements) VALUES
14
+ ( 'Dupont', 'Jean', 45, 'M', '1978-05-12', 'Hypertension, Diabète', 'Bêta-bloquants, Diurétiques, Régime alimentaire'),
15
+ ( 'Martin', 'Claire', 38, 'F', '1985-02-28', 'Diabète de type 2, Obésité', 'Insuline, Conseils nutritionnels'),
16
+ ( 'Bernard', 'Luc', 52, 'M', '1971-08-03', 'Asthme, Hypertension', 'Corticostéroïdes, Bêta-bloquants'),
17
+ ( 'Dubois', 'Sophie', 29, 'F', '1996-07-19', 'Anxiété', 'Thérapie cognitive, Anxiolytiques'),
18
+ ( 'Leroy', 'Marc', 60, 'M', '1963-11-30', 'Arthrite, Hypercholestérolémie', 'Anti-inflammatoires, Statines'),
19
+ ( 'Moreau', 'Emma', 33, 'F', '1990-04-22', 'Migraines', 'Antidouleurs, Bêta-bloquants'),
20
+ ( 'Robert', 'Paul', 47, 'M', '1976-09-15', 'Hypothyroïdie', 'Hormones thyroïdiennes'),
21
+ ( 'Lefevre', 'Isabelle', 55, 'F', '1968-03-10', 'Hypercholestérolémie', 'Statines, Régime alimentaire'),
22
+ ( 'Garcia', 'Antoine', 40, 'M', '1983-12-05', 'Obésité', 'Conseils nutritionnels, Activité physique'),
23
+ ( 'Petit', 'Julie', 36, 'F', '1987-06-18', 'Insomnie', 'Thérapie comportementale, Hygiène du sommeil');
24
+