Merge branch 'feat/versioning-config'
This commit is contained in:
@@ -4,7 +4,7 @@ build-backend = "setuptools.backends._legacy:_Backend"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "t2a"
|
name = "t2a"
|
||||||
version = "2.0.0"
|
dynamic = ["version"]
|
||||||
description = "Pipeline de codage CIM-10/CCAM automatise pour le PMSI hospitalier"
|
description = "Pipeline de codage CIM-10/CCAM automatise pour le PMSI hospitalier"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
@@ -43,6 +43,9 @@ dev = [
|
|||||||
[project.scripts]
|
[project.scripts]
|
||||||
t2a = "src.main:main"
|
t2a = "src.main:main"
|
||||||
|
|
||||||
|
[tool.setuptools.dynamic]
|
||||||
|
version = {attr = "src.__version__.__version__"}
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
include = ["src*"]
|
include = ["src*"]
|
||||||
|
|
||||||
|
|||||||
3
src/__version__.py
Normal file
3
src/__version__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
"""Version unique du projet T2A v2 (single source of truth)."""
|
||||||
|
|
||||||
|
__version__ = "2.1.0"
|
||||||
@@ -123,6 +123,57 @@ def check_adversarial_model_config() -> tuple[bool, str]:
|
|||||||
return False, ""
|
return False, ""
|
||||||
|
|
||||||
|
|
||||||
|
def validate_config() -> list[str]:
|
||||||
|
"""Valide la configuration au démarrage et retourne la liste des warnings émis.
|
||||||
|
|
||||||
|
Vérifie :
|
||||||
|
- OLLAMA_URL défini et accessible (warning si injoignable, pas de crash)
|
||||||
|
- ANTHROPIC_API_KEY présente (warning si absente — fallback cloud indisponible)
|
||||||
|
- Modèles CPAM et validation distincts (validation adversariale)
|
||||||
|
- Au moins un modèle LLM configuré
|
||||||
|
|
||||||
|
Ne fait jamais crasher l'application.
|
||||||
|
"""
|
||||||
|
warnings_emitted: list[str] = []
|
||||||
|
|
||||||
|
# 1. Vérifier OLLAMA_URL
|
||||||
|
if not OLLAMA_URL:
|
||||||
|
msg = "OLLAMA_URL non défini — aucun LLM local disponible"
|
||||||
|
_cfg_logger.warning(msg)
|
||||||
|
warnings_emitted.append(msg)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
import requests as _req
|
||||||
|
resp = _req.get(f"{OLLAMA_URL}/api/tags", timeout=5)
|
||||||
|
resp.raise_for_status()
|
||||||
|
_cfg_logger.info("Ollama accessible sur %s", OLLAMA_URL)
|
||||||
|
except Exception as e:
|
||||||
|
msg = f"Ollama injoignable sur {OLLAMA_URL} — {e}"
|
||||||
|
_cfg_logger.warning(msg)
|
||||||
|
warnings_emitted.append(msg)
|
||||||
|
|
||||||
|
# 2. Vérifier ANTHROPIC_API_KEY
|
||||||
|
if not os.environ.get("ANTHROPIC_API_KEY"):
|
||||||
|
msg = "ANTHROPIC_API_KEY absente — fallback cloud (Haiku) indisponible"
|
||||||
|
_cfg_logger.warning(msg)
|
||||||
|
warnings_emitted.append(msg)
|
||||||
|
|
||||||
|
# 3. Vérifier modèles CPAM vs validation (adversarial)
|
||||||
|
same, adv_msg = check_adversarial_model_config()
|
||||||
|
if same:
|
||||||
|
_cfg_logger.warning(adv_msg)
|
||||||
|
warnings_emitted.append(adv_msg)
|
||||||
|
|
||||||
|
# 4. Vérifier qu'au moins un modèle LLM est configuré
|
||||||
|
has_model = bool(OLLAMA_MODEL) or any(OLLAMA_MODELS.values())
|
||||||
|
if not has_model:
|
||||||
|
msg = "Aucun modèle LLM configuré (OLLAMA_MODEL et OLLAMA_MODELS vides)"
|
||||||
|
_cfg_logger.warning(msg)
|
||||||
|
warnings_emitted.append(msg)
|
||||||
|
|
||||||
|
return warnings_emitted
|
||||||
|
|
||||||
|
|
||||||
# --- Configuration RUM / établissement ---
|
# --- Configuration RUM / établissement ---
|
||||||
|
|
||||||
FINESS = os.environ.get("T2A_FINESS", "000000000")
|
FINESS = os.environ.get("T2A_FINESS", "000000000")
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from ..config import (
|
|||||||
ALLOWED_EXTENSIONS, UPLOAD_MAX_SIZE_MB,
|
ALLOWED_EXTENSIONS, UPLOAD_MAX_SIZE_MB,
|
||||||
)
|
)
|
||||||
from .. import config as cfg
|
from .. import config as cfg
|
||||||
|
from ..__version__ import __version__ as APP_VERSION
|
||||||
from ..control.cpam_context import _assess_dossier_strength
|
from ..control.cpam_context import _assess_dossier_strength
|
||||||
from ..medical.bio_normals import BIO_NORMALS
|
from ..medical.bio_normals import BIO_NORMALS
|
||||||
from .referentiels import ReferentielManager
|
from .referentiels import ReferentielManager
|
||||||
@@ -84,6 +85,13 @@ def create_app() -> Flask:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Verification FAISS echouee : %s", e)
|
logger.error("Verification FAISS echouee : %s", e)
|
||||||
|
|
||||||
|
# Validation config au démarrage
|
||||||
|
try:
|
||||||
|
from ..config import validate_config
|
||||||
|
validate_config()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Validation config échouée : %s", e)
|
||||||
|
|
||||||
ref_manager = ReferentielManager()
|
ref_manager = ReferentielManager()
|
||||||
val_manager = ValidationManager()
|
val_manager = ValidationManager()
|
||||||
|
|
||||||
@@ -102,7 +110,12 @@ def create_app() -> Flask:
|
|||||||
rep = item
|
rep = item
|
||||||
break
|
break
|
||||||
dossier_list.append({"name": format_dossier_name(group_name), "path": rep["path_rel"]})
|
dossier_list.append({"name": format_dossier_name(group_name), "path": rep["path_rel"]})
|
||||||
return {"dossier_list": dossier_list}
|
return {"dossier_list": dossier_list, "app_version": APP_VERSION}
|
||||||
|
|
||||||
|
# --- Health check ---
|
||||||
|
@app.route("/health")
|
||||||
|
def health():
|
||||||
|
return jsonify({"status": "ok", "version": APP_VERSION})
|
||||||
|
|
||||||
# ===================================================================
|
# ===================================================================
|
||||||
# Routes principales
|
# Routes principales
|
||||||
|
|||||||
@@ -421,6 +421,9 @@
|
|||||||
<input type="text" id="sidebar-search" placeholder="Rechercher un dossier…" autocomplete="off">
|
<input type="text" id="sidebar-search" placeholder="Rechercher un dossier…" autocomplete="off">
|
||||||
<div id="sidebar-autocomplete" style="display:none;position:absolute;left:0;right:0;background:#0f172a;border:1px solid #475569;border-radius:0 0 6px 6px;max-height:250px;overflow-y:auto;z-index:100;"></div>
|
<div id="sidebar-autocomplete" style="display:none;position:absolute;left:0;right:0;background:#0f172a;border:1px solid #475569;border-radius:0 0 6px 6px;max-height:250px;overflow-y:auto;z-index:100;"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="padding:0.5rem 1rem;border-top:1px solid #334155;font-size:0.6rem;color:#475569;text-align:center;">
|
||||||
|
v{{ app_version }}
|
||||||
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<!-- Main -->
|
<!-- Main -->
|
||||||
|
|||||||
Reference in New Issue
Block a user