diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 3d67f94..6e5f8c0 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -9,7 +9,7 @@ on: jobs: build-windows: runs-on: windows-latest - timeout-minutes: 45 + timeout-minutes: 60 steps: - name: Checkout @@ -27,6 +27,10 @@ jobs: pip install -r requirements.txt pip install nuitka orderedset zstandard + - name: Download NER model + run: | + python -c "from ner_manager_onnx import NerModelManager; m=NerModelManager(cache_dir='models'); m.load('cmarkea/distilcamembert-base-ner'); print('Model OK:', m.is_loaded()); m.unload()" + - name: Build with Nuitka run: | python -m nuitka ` @@ -37,6 +41,7 @@ jobs: --include-module=ner_manager_onnx ` --include-module=eds_pseudo_manager ` --include-data-dir=config=config ` + --include-data-dir=models=models ` --windows-console-mode=disable ` --output-filename=Pseudonymisation.exe ` --company-name="Hopital" ` @@ -47,22 +52,15 @@ jobs: --remove-output ` Pseudonymisation_Gui_V5.py - - name: Prepare release archive - run: | - New-Item -ItemType Directory -Force -Path dist - Copy-Item Pseudonymisation.exe dist/ - Copy-Item -Recurse config dist/config - - name: Upload artifact uses: actions/upload-artifact@v4 with: name: Pseudonymisation-Windows-x64 - path: dist/ + path: Pseudonymisation.exe retention-days: 30 - name: Upload to release (on tag) if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v2 with: - files: | - dist/Pseudonymisation.exe + files: Pseudonymisation.exe diff --git a/Pseudonymisation_Gui_V5.py b/Pseudonymisation_Gui_V5.py index 4b88944..7c6c2c5 100644 --- a/Pseudonymisation_Gui_V5.py +++ b/Pseudonymisation_Gui_V5.py @@ -67,7 +67,16 @@ except ImportError: # --------------------------------------------------------------------------- APP_TITLE = "Pseudonymisation de PDF" APP_VERSION = "v5.0" -DEFAULT_CFG = Path("config/dictionnaires.yml") + +def _app_dir() -> Path: + """Répertoire racine de l'application (compatible Nuitka onefile).""" + # Nuitka onefile extrait dans un dossier temporaire + if "__compiled__" in dir(): + return Path(__file__).resolve().parent + return Path.cwd() + +DEFAULT_CFG = _app_dir() / "config" / "dictionnaires.yml" +MODELS_DIR = _app_dir() / "models" DEFAULTS_CFG_TEXT = r""" # dictionnaires.yml – valeurs par défaut (bloc littéral pour les regex) @@ -255,8 +264,8 @@ class App: self.th_per = 0.90 self.th_org = 0.90 self.th_loc = 0.90 - self._onnx_manager: Optional[Any] = NerModelManager(cache_dir=Path("models")) if NerModelManager else None - self._eds_manager: Optional[Any] = EdsPseudoManager(cache_dir=Path("models")) if EdsPseudoManager else None + self._onnx_manager: Optional[Any] = NerModelManager(cache_dir=MODELS_DIR) if NerModelManager else None + self._eds_manager: Optional[Any] = EdsPseudoManager(cache_dir=MODELS_DIR) if EdsPseudoManager else None self._active_manager: Optional[Any] = None self.cfg_data: Dict[str, Any] = {} @@ -277,6 +286,9 @@ class App: self._ensure_cfg_exists() self._load_cfg() + # --- Chargement automatique du modèle NER --- + self._auto_load_ner() + # --------------------------------------------------------------- # Thème # --------------------------------------------------------------- @@ -848,6 +860,26 @@ class App: pass return d + # --------------------------------------------------------------- + # Chargement automatique NER au démarrage + # --------------------------------------------------------------- + def _auto_load_ner(self): + """Charge le modèle NER par défaut en arrière-plan.""" + if not self._onnx_manager: + return + self.status_var.set("Chargement du modèle NER...") + threading.Thread(target=self._auto_load_ner_worker, daemon=True).start() + + def _auto_load_ner_worker(self): + try: + default_model = "cmarkea/distilcamembert-base-ner" + self._onnx_manager.load(default_model) + self._active_manager = self._onnx_manager + self.use_hf = True + self.status_var.set("Prêt — NER actif.") + except Exception as e: + self.status_var.set(f"Prêt (NER indisponible : {e})") + # --------------------------------------------------------------- # Modèles NER (API interne) # --------------------------------------------------------------- diff --git a/build_windows.bat b/build_windows.bat index ac73804..f85dd0a 100644 --- a/build_windows.bat +++ b/build_windows.bat @@ -13,6 +13,7 @@ REM ============================================================ setlocal set APP_NAME=Pseudonymisation set ENTRY=Pseudonymisation_Gui_V5.py +set MODEL_ID=cmarkea/distilcamembert-base-ner echo [build] Verification de Python... python --version || (echo Python introuvable & exit /b 1) @@ -20,7 +21,10 @@ python --version || (echo Python introuvable & exit /b 1) echo [build] Installation de Nuitka si absent... pip install nuitka orderedset zstandard 2>nul -echo [build] Compilation avec Nuitka (cela peut prendre 5-15 min)... +echo [build] Telechargement du modele NER si absent... +python -c "from ner_manager_onnx import NerModelManager; m=NerModelManager(cache_dir='models'); m.load('%MODEL_ID%'); print('Modele OK'); m.unload()" + +echo [build] Compilation avec Nuitka (cela peut prendre 10-20 min)... python -m nuitka ^ --standalone ^ --onefile ^ @@ -29,6 +33,7 @@ python -m nuitka ^ --include-module=ner_manager_onnx ^ --include-module=eds_pseudo_manager ^ --include-data-dir=config=config ^ + --include-data-dir=models=models ^ --windows-console-mode=disable ^ --output-filename=%APP_NAME%.exe ^ --company-name="Hopital" ^ @@ -45,5 +50,5 @@ if %ERRORLEVEL% NEQ 0 ( ) echo [build] OK — Executable cree : %APP_NAME%.exe -echo [build] Copiez %APP_NAME%.exe + le dossier config/ sur la machine cible. +echo [build] Le modele NER est embarque. Aucun telechargement necessaire. endlocal