feat: affichage des référentiels intégrés dans la page admin RAG

Ajout d'une section listant les 6 sources built-in (CIM-10, CCAM, Guide Métho,
dictionnaires) avec compteurs de chunks et statut. Séparation claire entre
référentiels intégrés et référentiels utilisateur uploadés.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
dom
2026-02-13 19:00:44 +01:00
parent ee661dae1d
commit c838d75174
2 changed files with 92 additions and 4 deletions

View File

@@ -15,7 +15,11 @@ from werkzeug.utils import secure_filename
from collections import Counter
from ..config import STRUCTURED_DIR, OLLAMA_URL, CCAM_DICT_PATH, DossierMedical, ALLOWED_EXTENSIONS, UPLOAD_MAX_SIZE_MB
from ..config import (
STRUCTURED_DIR, OLLAMA_URL, CCAM_DICT_PATH, DossierMedical,
ALLOWED_EXTENSIONS, UPLOAD_MAX_SIZE_MB,
CIM10_PDF, GUIDE_METHODO_PDF, CCAM_PDF, CIM10_DICT_PATH, CIM10_SUPPLEMENTS_PATH,
)
from .. import config as cfg
from .referentiels import ReferentielManager
@@ -154,6 +158,43 @@ def collect_cpam_controls(groups: dict[str, list[dict]]) -> list[dict]:
return controls
def get_builtin_referentiels() -> list[dict]:
"""Retourne les infos sur les référentiels intégrés (PDFs + dicts)."""
rag_index_meta = Path(STRUCTURED_DIR).parent / "data" / "rag_index" / "metadata.json"
chunks_by_doc: dict[str, int] = {}
if rag_index_meta.exists():
try:
import json as _json
meta = _json.loads(rag_index_meta.read_text(encoding="utf-8"))
for m in meta:
doc = m.get("document", "")
chunks_by_doc[doc] = chunks_by_doc.get(doc, 0) + 1
except Exception:
pass
refs = []
builtin_sources = [
("CIM-10 FR 2026", CIM10_PDF, ".pdf", ["cim10", "cim10_alpha"]),
("Guide Méthodologique MCO 2026", GUIDE_METHODO_PDF, ".pdf", ["guide_methodo"]),
("CCAM 2025", CCAM_PDF, ".pdf", ["ccam"]),
("Dictionnaire CIM-10", CIM10_DICT_PATH, ".json", []),
("Suppléments CIM-10", CIM10_SUPPLEMENTS_PATH, ".json", []),
("Dictionnaire CCAM", CCAM_DICT_PATH, ".json", []),
]
for name, path, ext, doc_keys in builtin_sources:
size_mb = path.stat().st_size / (1024 * 1024) if path.exists() else 0
chunks = sum(chunks_by_doc.get(k, 0) for k in doc_keys)
refs.append({
"name": name,
"filename": path.name,
"extension": ext,
"size_mb": size_mb,
"chunks": chunks,
"exists": path.exists(),
})
return refs
def load_ccam_dict() -> dict[str, dict]:
"""Charge le dictionnaire CCAM pour les regroupements."""
if CCAM_DICT_PATH.exists():
@@ -424,7 +465,8 @@ def create_app() -> Flask:
@app.route("/admin/referentiels")
def admin_referentiels():
refs = ref_manager.list_all()
return render_template("admin_referentiels.html", referentiels=refs, max_size=UPLOAD_MAX_SIZE_MB)
builtin = get_builtin_referentiels()
return render_template("admin_referentiels.html", referentiels=refs, builtin_refs=builtin, max_size=UPLOAD_MAX_SIZE_MB)
@app.route("/admin/referentiels/upload", methods=["POST"])
def upload_referentiel():

View File

@@ -34,10 +34,56 @@
</p>
</div>
<!-- Tableau référentiels -->
<!-- Référentiels intégrés (built-in) -->
<div class="card" style="margin-bottom:1.5rem;">
<h3>Référentiels intégrés</h3>
<p style="font-size:0.8rem;color:#64748b;margin-bottom:0.75rem;">
Sources intégrées automatiquement dans l'index FAISS au build.
</p>
<table>
<thead>
<tr>
<th>Nom</th>
<th>Fichier</th>
<th>Type</th>
<th>Taille</th>
<th>Chunks</th>
<th>Statut</th>
</tr>
</thead>
<tbody>
{% for ref in builtin_refs %}
<tr>
<td style="font-weight:600;">{{ ref.name }}</td>
<td style="font-size:0.8rem;color:#64748b;"><code>{{ ref.filename }}</code></td>
<td><span class="badge" style="background:#f1f5f9;color:#334155;">{{ ref.extension }}</span></td>
<td>{{ "%.1f"|format(ref.size_mb) }} Mo</td>
<td>
{% if ref.chunks %}
<strong>{{ ref.chunks }}</strong>
{% else %}
<span style="color:#94a3b8;"></span>
{% endif %}
</td>
<td>
{% if not ref.exists %}
<span class="badge" style="background:#fee2e2;color:#dc2626;">Fichier absent</span>
{% elif ref.chunks %}
<span class="badge" style="background:#dcfce7;color:#16a34a;">Indexé</span>
{% else %}
<span class="badge" style="background:#f1f5f9;color:#64748b;">Dictionnaire</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Tableau référentiels utilisateur -->
<div class="card">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:0.75rem;">
<h3>Référentiels indexés</h3>
<h3>Référentiels utilisateur</h3>
<button id="rebuild-btn"
style="padding:0.35rem 0.75rem;border-radius:6px;border:1px solid #e2e8f0;background:#fff;font-size:0.75rem;cursor:pointer;">
Rebuild complet