Acasset45654 commited on
Commit
dd66d31
·
verified ·
1 Parent(s): 9f88210

Update refApp.py

Browse files
Files changed (1) hide show
  1. refApp.py +106 -39
refApp.py CHANGED
@@ -4,6 +4,54 @@ import copy
4
  import json
5
  import requests
6
  import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  # --- PAGE CONFIGURATION (MUST BE THE FIRST STREAMLIT COMMAND) ---
9
  # Fixed deployment issue
@@ -340,39 +388,58 @@ def save_to_local_file(new_content_json_string):
340
  st.error(f"Erreur de sauvegarde du fichier local: {e}")
341
  return False
342
 
343
- def save_editable_prompts_to_local():
 
344
  if 'editable_prompts' in st.session_state:
345
  data_to_save = _preprocess_for_saving(st.session_state.editable_prompts)
346
  try:
347
  json_string = json.dumps(data_to_save, indent=4, ensure_ascii=False)
348
- if save_to_local_file(json_string):
349
- st.toast("💾 Données sauvegardées localement!", icon="💾")
350
- else:
351
- st.warning("Sauvegarde locale échouée.")
 
 
 
 
 
 
 
 
 
 
 
352
  except Exception as e: # pragma: no cover
353
- st.error(f"Erreur préparation données pour sauvegarde locale: {e}")
354
-
355
- def load_editable_prompts_from_local():
356
- raw_content = get_local_file_content()
 
 
 
 
 
357
  if raw_content:
358
  try:
359
  loaded_data = json.loads(raw_content)
360
  if not loaded_data or not isinstance(loaded_data, dict):
361
- raise ValueError("Contenu fichier local vide ou mal structuré.")
362
  return _postprocess_after_loading(loaded_data)
363
  except (json.JSONDecodeError, TypeError, ValueError) as e:
364
- st.info(f"Erreur chargement fichier local ('{str(e)[:50]}...'). Initialisation avec modèles par défaut.")
365
  else:
366
- st.info("Fichier local vide ou inaccessible. Initialisation avec modèles par défaut.")
367
  initial_data = copy.deepcopy(INITIAL_PROMPT_TEMPLATES)
368
  if raw_content is None or raw_content == "{}":
369
  data_to_save_init = _preprocess_for_saving(initial_data)
370
  try:
371
  json_string_init = json.dumps(data_to_save_init, indent=4, ensure_ascii=False)
372
- if save_to_local_file(json_string_init):
373
- st.info("Modèles par défaut sauvegardés localement pour initialisation.")
 
 
374
  except Exception as e: # pragma: no cover
375
- st.error(f"Erreur sauvegarde initiale locale: {e}")
376
  return initial_data
377
 
378
  # --- ACCESS CODE VERIFICATION ---
@@ -444,7 +511,7 @@ if not st.session_state.access_granted:
444
 
445
  # --- Session State Initialization ---
446
  if 'editable_prompts' not in st.session_state:
447
- st.session_state.editable_prompts = load_editable_prompts_from_local()
448
  if 'view_mode' not in st.session_state:
449
  st.session_state.view_mode = "accueil" # Nouvelle vue par défaut
450
 
@@ -675,7 +742,7 @@ with tab_edition_generation:
675
  st.error(f"Le métier '{new_family_name.strip()}' existe déjà.")
676
  else:
677
  st.session_state.editable_prompts[new_family_name.strip()] = {}
678
- save_editable_prompts_to_local()
679
  st.success(f"Métier '{new_family_name.strip()}' créée.")
680
  st.session_state.force_select_family_name = new_family_name.strip()
681
  st.session_state.use_case_selector_edition = None
@@ -698,7 +765,7 @@ with tab_edition_generation:
698
  st.error(f"Un métier nommé '{renamed_family_name}' existe déjà.")
699
  else:
700
  st.session_state.editable_prompts[renamed_family_name] = st.session_state.editable_prompts.pop(current_selected_family_for_edit_logic)
701
- save_editable_prompts_to_local()
702
  st.success(f"Métier '{current_selected_family_for_edit_logic}' renommé en '{renamed_family_name}'.")
703
  st.session_state.force_select_family_name = renamed_family_name
704
  if st.session_state.library_selected_family_for_display == current_selected_family_for_edit_logic:
@@ -717,7 +784,7 @@ with tab_edition_generation:
717
  if st.button(_text_confirm_delete, type="primary", key=f"confirm_del_fam_sb_{current_selected_family_for_edit_logic}", use_container_width=True):
718
  deleted_fam_name = current_selected_family_for_edit_logic
719
  del st.session_state.editable_prompts[current_selected_family_for_edit_logic]
720
- save_editable_prompts_to_local()
721
  st.success(f"Métier '{deleted_fam_name}' supprimée.")
722
  st.session_state.confirming_delete_family_name = None
723
  st.session_state.family_selector_edition = None
@@ -786,7 +853,7 @@ with tab_edition_generation:
786
  "variables": [], "tags": [],
787
  "usage_count": 0, "created_at": now_iso_create, "updated_at": now_iso_update
788
  }
789
- save_editable_prompts_to_local()
790
  st.success(f"Cas d'usage '{uc_name_val}' créé avec succès dans '{parent_family_val}'.")
791
  st.session_state.show_create_new_use_case_form = False
792
  st.session_state.force_select_family_name = parent_family_val
@@ -1078,7 +1145,7 @@ elif st.session_state.view_mode == "library":
1078
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["created_at"] = now_iso_dup_create
1079
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["updated_at"] = now_iso_dup_update
1080
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["usage_count"] = 0
1081
- save_editable_prompts_to_local()
1082
  st.success(f"Cas d'usage '{original_uc_name_for_dup}' dupliqué en '{new_uc_name_val_from_form}' dans la famille '{target_family_on_submit}'.")
1083
 
1084
  st.session_state.duplicating_use_case_details = None
@@ -1105,7 +1172,7 @@ elif st.session_state.view_mode == "library":
1105
  deleted_uc_name_for_msg = details['use_case']
1106
  deleted_uc_fam_for_msg = details['family']
1107
  del st.session_state.editable_prompts[details["family"]][details["use_case"]]
1108
- save_editable_prompts_to_local()
1109
  st.success(f"'{deleted_uc_name_for_msg}' supprimé de '{deleted_uc_fam_for_msg}'.")
1110
  st.session_state.confirming_delete_details = None
1111
  st.rerun()
@@ -1258,7 +1325,7 @@ elif st.session_state.view_mode == "edit":
1258
  st.balloons()
1259
  current_prompt_config["usage_count"] = current_prompt_config.get("usage_count", 0) + 1
1260
  current_prompt_config["updated_at"] = datetime.now().isoformat()
1261
- save_editable_prompts_to_local()
1262
 
1263
  except Exception as e: # Garder un catch-all pour les erreurs imprévues
1264
  st.error(f"Erreur inattendue lors de la génération du prompt : {e}") # pragma: no cover
@@ -1308,7 +1375,7 @@ elif st.session_state.view_mode == "edit":
1308
  current_prompt_config['template'] = new_tpl
1309
  current_prompt_config['description'] = new_desc
1310
  current_prompt_config["updated_at"] = datetime.now().isoformat()
1311
- save_editable_prompts_to_local()
1312
  st.success("Template et Description sauvegardés!");
1313
  st.rerun()
1314
  st.markdown("---"); st.subheader("Variables du Prompt"); current_variables_list = current_prompt_config.get('variables', [])
@@ -1320,14 +1387,14 @@ elif st.session_state.view_mode == "edit":
1320
  with col_info: st.markdown(f"**{idx + 1}. {var_data.get('name', 'N/A')}** ({var_data.get('label', 'N/A')})\n*Type: `{var_data.get('type', 'N/A')}`*")
1321
  with col_up:
1322
  disable_up_button = (idx == 0)
1323
- if st.button("↑", key=f"{action_key_prefix}_up", help="Monter cette variable", disabled=disable_up_button, use_container_width=True): current_variables_list[idx], current_variables_list[idx-1] = current_variables_list[idx-1], current_variables_list[idx]; current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local(); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1324
  with col_down:
1325
  disable_down_button = (idx == len(current_variables_list) - 1)
1326
- if st.button("↓", key=f"{action_key_prefix}_down", help="Descendre cette variable", disabled=disable_down_button, use_container_width=True): current_variables_list[idx], current_variables_list[idx+1] = current_variables_list[idx+1], current_variables_list[idx]; current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local(); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1327
  with col_edit:
1328
  if st.button("Modifier", key=f"{action_key_prefix}_edit", use_container_width=True): st.session_state.editing_variable_info = { "family": final_selected_family_edition, "use_case": final_selected_use_case_edition, "index": idx, "data": copy.deepcopy(var_data) }; st.session_state.variable_type_to_create = var_data.get('type'); st.rerun()
1329
  with col_delete:
1330
- if st.button("Suppr.", key=f"{action_key_prefix}_delete", type="secondary", use_container_width=True): variable_name_to_delete = current_variables_list.pop(idx).get('name', 'Variable inconnue'); current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local(); st.success(f"Variable '{variable_name_to_delete}' supprimée."); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1331
  st.markdown("---"); st.subheader("Ajouter une Variable"); is_editing_var = False; variable_data_for_form = {"name": "", "label": "", "type": "", "options": "", "default": ""}
1332
  if st.session_state.editing_variable_info and st.session_state.editing_variable_info.get("family") == final_selected_family_edition and st.session_state.editing_variable_info.get("use_case") == final_selected_use_case_edition:
1333
  edit_var_idx = st.session_state.editing_variable_info["index"]
@@ -1430,7 +1497,7 @@ elif st.session_state.view_mode == "edit":
1430
  if var_name_val_submit in existing_var_names_in_uc: st.error(f"Une variable avec le nom technique '{var_name_val_submit}' existe déjà pour ce cas d'usage."); can_proceed_with_save = False
1431
  else: target_vars_list.append(new_var_data_to_submit); st.success(f"Variable '{var_name_val_submit}' ajoutée avec succès.")
1432
  if can_proceed_with_save:
1433
- current_prompt_config["variables"] = target_vars_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local()
1434
  if not is_editing_var: st.session_state.variable_type_to_create = None
1435
  st.rerun()
1436
 
@@ -1444,7 +1511,7 @@ elif st.session_state.view_mode == "edit":
1444
  st.rerun()
1445
  st.markdown("---"); st.subheader("🏷️ Tags"); current_tags_str = ", ".join(current_prompt_config.get("tags", []))
1446
  new_tags_str_input = st.text_input("Tags (séparés par des virgules):", value=current_tags_str, key=f"tags_input_{final_selected_family_edition}_{final_selected_use_case_edition}")
1447
- if st.button("Sauvegarder Tags", key=f"save_tags_btn_{final_selected_family_edition}_{final_selected_use_case_edition}"): current_prompt_config["tags"] = sorted(list(set(t.strip() for t in new_tags_str_input.split(',') if t.strip()))); current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local(); st.success("Tags sauvegardés!"); st.rerun()
1448
 
1449
  st.markdown("---")
1450
  st.subheader("Actions sur le Cas d'Usage")
@@ -1501,7 +1568,7 @@ elif st.session_state.view_mode == "edit":
1501
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["created_at"] = now_iso_dup_create
1502
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["updated_at"] = now_iso_dup_update
1503
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["usage_count"] = 0
1504
- save_editable_prompts_to_local()
1505
  st.success(f"Cas d'usage '{original_uc_name_for_dup_form}' dupliqué en '{new_uc_name_val_from_form}' dans la famille '{target_family_on_submit}'.")
1506
 
1507
  st.session_state.duplicating_use_case_details = None
@@ -1696,7 +1763,7 @@ elif st.session_state.view_mode == "generator":
1696
  st.balloons()
1697
  current_prompt_config["usage_count"] = current_prompt_config.get("usage_count", 0) + 1
1698
  current_prompt_config["updated_at"] = datetime.now().isoformat()
1699
- save_editable_prompts_to_local()
1700
 
1701
  except Exception as e:
1702
  st.error(f"Erreur inattendue lors de la génération du prompt : {e}")
@@ -1749,7 +1816,7 @@ elif st.session_state.view_mode == "generator":
1749
  current_prompt_config['template'] = new_tpl
1750
  current_prompt_config['description'] = new_desc
1751
  current_prompt_config["updated_at"] = datetime.now().isoformat()
1752
- save_editable_prompts_to_local()
1753
  st.success("Template et Description sauvegardés!");
1754
  st.rerun()
1755
  st.markdown("---"); st.subheader("Variables du Prompt"); current_variables_list = current_prompt_config.get('variables', [])
@@ -1761,14 +1828,14 @@ elif st.session_state.view_mode == "generator":
1761
  with col_info: st.markdown(f"**{idx + 1}. {var_data.get('name', 'N/A')}** ({var_data.get('label', 'N/A')})\n*Type: `{var_data.get('type', 'N/A')}`*")
1762
  with col_up:
1763
  disable_up_button = (idx == 0)
1764
- if st.button("↑", key=f"{action_key_prefix}_up", help="Monter cette variable", disabled=disable_up_button, use_container_width=True): current_variables_list[idx], current_variables_list[idx-1] = current_variables_list[idx-1], current_variables_list[idx]; current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local(); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1765
  with col_down:
1766
  disable_down_button = (idx == len(current_variables_list) - 1)
1767
- if st.button("↓", key=f"{action_key_prefix}_down", help="Descendre cette variable", disabled=disable_down_button, use_container_width=True): current_variables_list[idx], current_variables_list[idx+1] = current_variables_list[idx+1], current_variables_list[idx]; current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local(); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1768
  with col_edit:
1769
  if st.button("Modifier", key=f"{action_key_prefix}_edit", use_container_width=True): st.session_state.editing_variable_info = { "family": generator_family, "use_case": generator_use_case, "index": idx, "data": copy.deepcopy(var_data) }; st.session_state.variable_type_to_create = var_data.get('type'); st.rerun()
1770
  with col_delete:
1771
- if st.button("Suppr.", key=f"{action_key_prefix}_delete", type="secondary", use_container_width=True): variable_name_to_delete = current_variables_list.pop(idx).get('name', 'Variable inconnue'); current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local(); st.success(f"Variable '{variable_name_to_delete}' supprimée."); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1772
  st.markdown("---"); st.subheader("Ajouter une Variable"); is_editing_var = False; variable_data_for_form = {"name": "", "label": "", "type": "", "options": "", "default": ""}
1773
  if st.session_state.editing_variable_info and st.session_state.editing_variable_info.get("family") == generator_family and st.session_state.editing_variable_info.get("use_case") == generator_use_case:
1774
  edit_var_idx = st.session_state.editing_variable_info["index"]
@@ -1871,7 +1938,7 @@ elif st.session_state.view_mode == "generator":
1871
  if var_name_val_submit in existing_var_names_in_uc: st.error(f"Une variable avec le nom technique '{var_name_val_submit}' existe déjà pour ce cas d'usage."); can_proceed_with_save = False
1872
  else: target_vars_list.append(new_var_data_to_submit); st.success(f"Variable '{var_name_val_submit}' ajoutée avec succès.")
1873
  if can_proceed_with_save:
1874
- current_prompt_config["variables"] = target_vars_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local()
1875
  if not is_editing_var: st.session_state.variable_type_to_create = None
1876
  st.rerun()
1877
 
@@ -1885,7 +1952,7 @@ elif st.session_state.view_mode == "generator":
1885
  st.rerun()
1886
  st.markdown("---"); st.subheader("🏷️ Tags"); current_tags_str = ", ".join(current_prompt_config.get("tags", []))
1887
  new_tags_str_input = st.text_input("Tags (séparés par des virgules):", value=current_tags_str, key=f"tags_input_{generator_family}_{generator_use_case}")
1888
- if st.button("Sauvegarder Tags", key=f"save_tags_btn_{generator_family}_{generator_use_case}"): current_prompt_config["tags"] = sorted(list(set(t.strip() for t in new_tags_str_input.split(',') if t.strip()))); current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local(); st.success("Tags sauvegardés!"); st.rerun()
1889
 
1890
  st.markdown("---")
1891
  st.subheader("Actions sur le Cas d'Usage")
@@ -1942,7 +2009,7 @@ elif st.session_state.view_mode == "generator":
1942
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["created_at"] = now_iso_dup_create
1943
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["updated_at"] = now_iso_dup_update
1944
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["usage_count"] = 0
1945
- save_editable_prompts_to_local()
1946
  st.success(f"Cas d'usage '{original_uc_name_for_dup_form}' dupliqué en '{new_uc_name_val_from_form}' dans la famille '{target_family_on_submit}'.")
1947
 
1948
  st.session_state.duplicating_use_case_details = None
@@ -2053,7 +2120,7 @@ elif st.session_state.view_mode == "inject_manual":
2053
  if first_new_uc_name is None:
2054
  first_new_uc_name = uc_name_stripped
2055
  if successful_injections:
2056
- save_editable_prompts_to_local()
2057
  st.success(f"{len(successful_injections)} cas d'usage injectés avec succès dans '{target_family_name}': {', '.join(successful_injections)}")
2058
  st.session_state.injection_json_text = ""
2059
  if first_new_uc_name:
 
4
  import json
5
  import requests
6
  import os
7
+ # --- Hugging Face Hub integration ---
8
+ try:
9
+ from huggingface_hub import HfApi, hf_hub_download
10
+ HF_HUB_AVAILABLE = True
11
+ except ImportError:
12
+ HF_HUB_AVAILABLE = False
13
+
14
+ HF_REPO_ID = "AIB-Research/bibliPrompt"
15
+ HF_JSON_FILENAME = "prompt_templates_data_v3.json"
16
+ HF_TOKEN = os.environ.get("HF_TOKEN", None)
17
+
18
+ # --- Save to Hugging Face Space ---
19
+ def save_to_hf_space(json_path, repo_id=HF_REPO_ID, token=HF_TOKEN):
20
+ if not HF_HUB_AVAILABLE:
21
+ st.warning("huggingface_hub n'est pas installé. Sauvegarde sur HF désactivée.")
22
+ return False
23
+ try:
24
+ api = HfApi()
25
+ api.upload_file(
26
+ path_or_fileobj=json_path,
27
+ path_in_repo=HF_JSON_FILENAME,
28
+ repo_id=repo_id,
29
+ repo_type="space",
30
+ token=token
31
+ )
32
+ st.toast("💾 Données sauvegardées sur Hugging Face Space!", icon="🤗")
33
+ return True
34
+ except Exception as e:
35
+ st.warning(f"Erreur lors de la sauvegarde sur Hugging Face: {e}")
36
+ return False
37
+
38
+ # --- Load from Hugging Face Space ---
39
+ def load_from_hf_space(repo_id=HF_REPO_ID, token=HF_TOKEN):
40
+ if not HF_HUB_AVAILABLE:
41
+ st.warning("huggingface_hub n'est pas installé. Chargement depuis HF désactivé.")
42
+ return None
43
+ try:
44
+ local_path = hf_hub_download(
45
+ repo_id=repo_id,
46
+ filename=HF_JSON_FILENAME,
47
+ repo_type="space",
48
+ token=token
49
+ )
50
+ with open(local_path, "r", encoding="utf-8") as f:
51
+ return f.read()
52
+ except Exception as e:
53
+ st.warning(f"Erreur lors du chargement depuis Hugging Face: {e}")
54
+ return None
55
 
56
  # --- PAGE CONFIGURATION (MUST BE THE FIRST STREAMLIT COMMAND) ---
57
  # Fixed deployment issue
 
388
  st.error(f"Erreur de sauvegarde du fichier local: {e}")
389
  return False
390
 
391
+ # --- Unified save/load functions ---
392
+ def save_editable_prompts_to_local_and_hf():
393
  if 'editable_prompts' in st.session_state:
394
  data_to_save = _preprocess_for_saving(st.session_state.editable_prompts)
395
  try:
396
  json_string = json.dumps(data_to_save, indent=4, ensure_ascii=False)
397
+ local_ok = save_to_local_file(json_string)
398
+ hf_ok = False
399
+ # Save to HF Space if possible
400
+ with open(LOCAL_DATA_FILENAME, 'w', encoding='utf-8') as f:
401
+ f.write(json_string)
402
+ if HF_HUB_AVAILABLE:
403
+ hf_ok = save_to_hf_space(LOCAL_DATA_FILENAME)
404
+ if local_ok and hf_ok:
405
+ st.toast("💾 Données sauvegardées localement et sur Hugging Face!", icon="💾")
406
+ elif local_ok:
407
+ st.toast("💾 Données sauvegardées localement!", icon="💾")
408
+ elif hf_ok:
409
+ st.toast("💾 Données sauvegardées sur Hugging Face!", icon="🤗")
410
+ else:
411
+ st.warning("Sauvegarde échouée.")
412
  except Exception as e: # pragma: no cover
413
+ st.error(f"Erreur préparation données pour sauvegarde: {e}")
414
+
415
+ def load_editable_prompts_from_local_or_hf():
416
+ # Try HF first, fallback to local
417
+ raw_content = None
418
+ if HF_HUB_AVAILABLE:
419
+ raw_content = load_from_hf_space()
420
+ if not raw_content:
421
+ raw_content = get_local_file_content()
422
  if raw_content:
423
  try:
424
  loaded_data = json.loads(raw_content)
425
  if not loaded_data or not isinstance(loaded_data, dict):
426
+ raise ValueError("Contenu fichier vide ou mal structuré.")
427
  return _postprocess_after_loading(loaded_data)
428
  except (json.JSONDecodeError, TypeError, ValueError) as e:
429
+ st.info(f"Erreur chargement fichier ('{str(e)[:50]}...'). Initialisation avec modèles par défaut.")
430
  else:
431
+ st.info("Fichier vide ou inaccessible. Initialisation avec modèles par défaut.")
432
  initial_data = copy.deepcopy(INITIAL_PROMPT_TEMPLATES)
433
  if raw_content is None or raw_content == "{}":
434
  data_to_save_init = _preprocess_for_saving(initial_data)
435
  try:
436
  json_string_init = json.dumps(data_to_save_init, indent=4, ensure_ascii=False)
437
+ save_to_local_file(json_string_init)
438
+ if HF_HUB_AVAILABLE:
439
+ save_to_hf_space(LOCAL_DATA_FILENAME)
440
+ st.info("Modèles par défaut sauvegardés pour initialisation.")
441
  except Exception as e: # pragma: no cover
442
+ st.error(f"Erreur sauvegarde initiale: {e}")
443
  return initial_data
444
 
445
  # --- ACCESS CODE VERIFICATION ---
 
511
 
512
  # --- Session State Initialization ---
513
  if 'editable_prompts' not in st.session_state:
514
+ st.session_state.editable_prompts = load_editable_prompts_from_local_or_hf()
515
  if 'view_mode' not in st.session_state:
516
  st.session_state.view_mode = "accueil" # Nouvelle vue par défaut
517
 
 
742
  st.error(f"Le métier '{new_family_name.strip()}' existe déjà.")
743
  else:
744
  st.session_state.editable_prompts[new_family_name.strip()] = {}
745
+ save_editable_prompts_to_local_and_hf()
746
  st.success(f"Métier '{new_family_name.strip()}' créée.")
747
  st.session_state.force_select_family_name = new_family_name.strip()
748
  st.session_state.use_case_selector_edition = None
 
765
  st.error(f"Un métier nommé '{renamed_family_name}' existe déjà.")
766
  else:
767
  st.session_state.editable_prompts[renamed_family_name] = st.session_state.editable_prompts.pop(current_selected_family_for_edit_logic)
768
+ save_editable_prompts_to_local_and_hf()
769
  st.success(f"Métier '{current_selected_family_for_edit_logic}' renommé en '{renamed_family_name}'.")
770
  st.session_state.force_select_family_name = renamed_family_name
771
  if st.session_state.library_selected_family_for_display == current_selected_family_for_edit_logic:
 
784
  if st.button(_text_confirm_delete, type="primary", key=f"confirm_del_fam_sb_{current_selected_family_for_edit_logic}", use_container_width=True):
785
  deleted_fam_name = current_selected_family_for_edit_logic
786
  del st.session_state.editable_prompts[current_selected_family_for_edit_logic]
787
+ save_editable_prompts_to_local_and_hf()
788
  st.success(f"Métier '{deleted_fam_name}' supprimée.")
789
  st.session_state.confirming_delete_family_name = None
790
  st.session_state.family_selector_edition = None
 
853
  "variables": [], "tags": [],
854
  "usage_count": 0, "created_at": now_iso_create, "updated_at": now_iso_update
855
  }
856
+ save_editable_prompts_to_local_and_hf()
857
  st.success(f"Cas d'usage '{uc_name_val}' créé avec succès dans '{parent_family_val}'.")
858
  st.session_state.show_create_new_use_case_form = False
859
  st.session_state.force_select_family_name = parent_family_val
 
1145
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["created_at"] = now_iso_dup_create
1146
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["updated_at"] = now_iso_dup_update
1147
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["usage_count"] = 0
1148
+ save_editable_prompts_to_local_and_hf()
1149
  st.success(f"Cas d'usage '{original_uc_name_for_dup}' dupliqué en '{new_uc_name_val_from_form}' dans la famille '{target_family_on_submit}'.")
1150
 
1151
  st.session_state.duplicating_use_case_details = None
 
1172
  deleted_uc_name_for_msg = details['use_case']
1173
  deleted_uc_fam_for_msg = details['family']
1174
  del st.session_state.editable_prompts[details["family"]][details["use_case"]]
1175
+ save_editable_prompts_to_local_and_hf()
1176
  st.success(f"'{deleted_uc_name_for_msg}' supprimé de '{deleted_uc_fam_for_msg}'.")
1177
  st.session_state.confirming_delete_details = None
1178
  st.rerun()
 
1325
  st.balloons()
1326
  current_prompt_config["usage_count"] = current_prompt_config.get("usage_count", 0) + 1
1327
  current_prompt_config["updated_at"] = datetime.now().isoformat()
1328
+ save_editable_prompts_to_local_and_hf()
1329
 
1330
  except Exception as e: # Garder un catch-all pour les erreurs imprévues
1331
  st.error(f"Erreur inattendue lors de la génération du prompt : {e}") # pragma: no cover
 
1375
  current_prompt_config['template'] = new_tpl
1376
  current_prompt_config['description'] = new_desc
1377
  current_prompt_config["updated_at"] = datetime.now().isoformat()
1378
+ save_editable_prompts_to_local_and_hf()
1379
  st.success("Template et Description sauvegardés!");
1380
  st.rerun()
1381
  st.markdown("---"); st.subheader("Variables du Prompt"); current_variables_list = current_prompt_config.get('variables', [])
 
1387
  with col_info: st.markdown(f"**{idx + 1}. {var_data.get('name', 'N/A')}** ({var_data.get('label', 'N/A')})\n*Type: `{var_data.get('type', 'N/A')}`*")
1388
  with col_up:
1389
  disable_up_button = (idx == 0)
1390
+ if st.button("↑", key=f"{action_key_prefix}_up", help="Monter cette variable", disabled=disable_up_button, use_container_width=True): current_variables_list[idx], current_variables_list[idx-1] = current_variables_list[idx-1], current_variables_list[idx]; current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf(); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1391
  with col_down:
1392
  disable_down_button = (idx == len(current_variables_list) - 1)
1393
+ if st.button("↓", key=f"{action_key_prefix}_down", help="Descendre cette variable", disabled=disable_down_button, use_container_width=True): current_variables_list[idx], current_variables_list[idx+1] = current_variables_list[idx+1], current_variables_list[idx]; current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf(); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1394
  with col_edit:
1395
  if st.button("Modifier", key=f"{action_key_prefix}_edit", use_container_width=True): st.session_state.editing_variable_info = { "family": final_selected_family_edition, "use_case": final_selected_use_case_edition, "index": idx, "data": copy.deepcopy(var_data) }; st.session_state.variable_type_to_create = var_data.get('type'); st.rerun()
1396
  with col_delete:
1397
+ if st.button("Suppr.", key=f"{action_key_prefix}_delete", type="secondary", use_container_width=True): variable_name_to_delete = current_variables_list.pop(idx).get('name', 'Variable inconnue'); current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf(); st.success(f"Variable '{variable_name_to_delete}' supprimée."); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1398
  st.markdown("---"); st.subheader("Ajouter une Variable"); is_editing_var = False; variable_data_for_form = {"name": "", "label": "", "type": "", "options": "", "default": ""}
1399
  if st.session_state.editing_variable_info and st.session_state.editing_variable_info.get("family") == final_selected_family_edition and st.session_state.editing_variable_info.get("use_case") == final_selected_use_case_edition:
1400
  edit_var_idx = st.session_state.editing_variable_info["index"]
 
1497
  if var_name_val_submit in existing_var_names_in_uc: st.error(f"Une variable avec le nom technique '{var_name_val_submit}' existe déjà pour ce cas d'usage."); can_proceed_with_save = False
1498
  else: target_vars_list.append(new_var_data_to_submit); st.success(f"Variable '{var_name_val_submit}' ajoutée avec succès.")
1499
  if can_proceed_with_save:
1500
+ current_prompt_config["variables"] = target_vars_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf()
1501
  if not is_editing_var: st.session_state.variable_type_to_create = None
1502
  st.rerun()
1503
 
 
1511
  st.rerun()
1512
  st.markdown("---"); st.subheader("🏷️ Tags"); current_tags_str = ", ".join(current_prompt_config.get("tags", []))
1513
  new_tags_str_input = st.text_input("Tags (séparés par des virgules):", value=current_tags_str, key=f"tags_input_{final_selected_family_edition}_{final_selected_use_case_edition}")
1514
+ if st.button("Sauvegarder Tags", key=f"save_tags_btn_{final_selected_family_edition}_{final_selected_use_case_edition}"): current_prompt_config["tags"] = sorted(list(set(t.strip() for t in new_tags_str_input.split(',') if t.strip()))); current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf(); st.success("Tags sauvegardés!"); st.rerun()
1515
 
1516
  st.markdown("---")
1517
  st.subheader("Actions sur le Cas d'Usage")
 
1568
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["created_at"] = now_iso_dup_create
1569
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["updated_at"] = now_iso_dup_update
1570
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["usage_count"] = 0
1571
+ save_editable_prompts_to_local_and_hf()
1572
  st.success(f"Cas d'usage '{original_uc_name_for_dup_form}' dupliqué en '{new_uc_name_val_from_form}' dans la famille '{target_family_on_submit}'.")
1573
 
1574
  st.session_state.duplicating_use_case_details = None
 
1763
  st.balloons()
1764
  current_prompt_config["usage_count"] = current_prompt_config.get("usage_count", 0) + 1
1765
  current_prompt_config["updated_at"] = datetime.now().isoformat()
1766
+ save_editable_prompts_to_local_and_hf()
1767
 
1768
  except Exception as e:
1769
  st.error(f"Erreur inattendue lors de la génération du prompt : {e}")
 
1816
  current_prompt_config['template'] = new_tpl
1817
  current_prompt_config['description'] = new_desc
1818
  current_prompt_config["updated_at"] = datetime.now().isoformat()
1819
+ save_editable_prompts_to_local_and_hf()
1820
  st.success("Template et Description sauvegardés!");
1821
  st.rerun()
1822
  st.markdown("---"); st.subheader("Variables du Prompt"); current_variables_list = current_prompt_config.get('variables', [])
 
1828
  with col_info: st.markdown(f"**{idx + 1}. {var_data.get('name', 'N/A')}** ({var_data.get('label', 'N/A')})\n*Type: `{var_data.get('type', 'N/A')}`*")
1829
  with col_up:
1830
  disable_up_button = (idx == 0)
1831
+ if st.button("↑", key=f"{action_key_prefix}_up", help="Monter cette variable", disabled=disable_up_button, use_container_width=True): current_variables_list[idx], current_variables_list[idx-1] = current_variables_list[idx-1], current_variables_list[idx]; current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf(); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1832
  with col_down:
1833
  disable_down_button = (idx == len(current_variables_list) - 1)
1834
+ if st.button("↓", key=f"{action_key_prefix}_down", help="Descendre cette variable", disabled=disable_down_button, use_container_width=True): current_variables_list[idx], current_variables_list[idx+1] = current_variables_list[idx+1], current_variables_list[idx]; current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf(); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1835
  with col_edit:
1836
  if st.button("Modifier", key=f"{action_key_prefix}_edit", use_container_width=True): st.session_state.editing_variable_info = { "family": generator_family, "use_case": generator_use_case, "index": idx, "data": copy.deepcopy(var_data) }; st.session_state.variable_type_to_create = var_data.get('type'); st.rerun()
1837
  with col_delete:
1838
+ if st.button("Suppr.", key=f"{action_key_prefix}_delete", type="secondary", use_container_width=True): variable_name_to_delete = current_variables_list.pop(idx).get('name', 'Variable inconnue'); current_prompt_config["variables"] = current_variables_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf(); st.success(f"Variable '{variable_name_to_delete}' supprimée."); st.session_state.editing_variable_info = None; st.session_state.variable_type_to_create = None; st.rerun()
1839
  st.markdown("---"); st.subheader("Ajouter une Variable"); is_editing_var = False; variable_data_for_form = {"name": "", "label": "", "type": "", "options": "", "default": ""}
1840
  if st.session_state.editing_variable_info and st.session_state.editing_variable_info.get("family") == generator_family and st.session_state.editing_variable_info.get("use_case") == generator_use_case:
1841
  edit_var_idx = st.session_state.editing_variable_info["index"]
 
1938
  if var_name_val_submit in existing_var_names_in_uc: st.error(f"Une variable avec le nom technique '{var_name_val_submit}' existe déjà pour ce cas d'usage."); can_proceed_with_save = False
1939
  else: target_vars_list.append(new_var_data_to_submit); st.success(f"Variable '{var_name_val_submit}' ajoutée avec succès.")
1940
  if can_proceed_with_save:
1941
+ current_prompt_config["variables"] = target_vars_list; current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf()
1942
  if not is_editing_var: st.session_state.variable_type_to_create = None
1943
  st.rerun()
1944
 
 
1952
  st.rerun()
1953
  st.markdown("---"); st.subheader("🏷️ Tags"); current_tags_str = ", ".join(current_prompt_config.get("tags", []))
1954
  new_tags_str_input = st.text_input("Tags (séparés par des virgules):", value=current_tags_str, key=f"tags_input_{generator_family}_{generator_use_case}")
1955
+ if st.button("Sauvegarder Tags", key=f"save_tags_btn_{generator_family}_{generator_use_case}"): current_prompt_config["tags"] = sorted(list(set(t.strip() for t in new_tags_str_input.split(',') if t.strip()))); current_prompt_config["updated_at"] = datetime.now().isoformat(); save_editable_prompts_to_local_and_hf(); st.success("Tags sauvegardés!"); st.rerun()
1956
 
1957
  st.markdown("---")
1958
  st.subheader("Actions sur le Cas d'Usage")
 
2009
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["created_at"] = now_iso_dup_create
2010
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["updated_at"] = now_iso_dup_update
2011
  st.session_state.editable_prompts[target_family_on_submit][new_uc_name_val_from_form]["usage_count"] = 0
2012
+ save_editable_prompts_to_local_and_hf()
2013
  st.success(f"Cas d'usage '{original_uc_name_for_dup_form}' dupliqué en '{new_uc_name_val_from_form}' dans la famille '{target_family_on_submit}'.")
2014
 
2015
  st.session_state.duplicating_use_case_details = None
 
2120
  if first_new_uc_name is None:
2121
  first_new_uc_name = uc_name_stripped
2122
  if successful_injections:
2123
+ save_editable_prompts_to_local_and_hf()
2124
  st.success(f"{len(successful_injections)} cas d'usage injectés avec succès dans '{target_family_name}': {', '.join(successful_injections)}")
2125
  st.session_state.injection_json_text = ""
2126
  if first_new_uc_name: