7.8 KiB
Régénération haute fidélité DOCX & visual previews des 7 documents NAS (Ticket nyora-2026-09-034)
Date : 2026-09-09 · Instance : hermes-nyora · Tags : nyora, convert-api, docx, omml, mhchem, hline, ticket034, corpus-7docs, audit, rag
1. Contexte & Problématique
Dans le cadre de la préparation du RAG unifié (yesmine-mp1-rag, ticket nyora-2026-09-033), l'audit universel des documents a révélé que les versions Word (.docx et .ticket007.docx) des 7 documents canoniques stockés sur le NAS (/volume1/docker/.claude-staging/pack-mp1-test/verif_outputs/full_run/) dataient du 3 et 4 septembre 2026.
Ces versions antérieures présentaient des défauts critiques de conversion :
- Fuites LaTeX massives : jusqu'à 895 fuites résiduelles dans certains TD (
TD-Physique-mp1-pt1-semestre-1), des matrices non converties (\begin{pmatrix}au lieu d'OMMLm:m), et des formules nues non encapsulées. - Chimie dégradée : balises
\ce{...}laissées en clair dansCours-Chimie-pt1-mp1car le parser mhchem n'était pas activé. - Tableaux sans bordures : les balises
\hlinen'étaient pas traduites en bordures natives OOXML (<w:bottom>).
Périmètre strict (7 documents canoniques)
Cours-Chimie-pt1-mp1Cours-physique-mp1-pt1Cours-msi-premiere-anneeFrancais-premiere-anneeTD-automatiqueTD_INFORMATIQUE_1ERE_ANNEE_PREPATD-Physique-mp1-pt1-semestre-1
Note
Le document
Cours-informatique-section-premiere-anneeest strictement exclu : il s'agit d'une vitrine créée manuellement fin août, déjà exclue de l'indexation RAG au ticket 033.
2. Découverte & Cause racine
Lors de l'investigation sur le VPS (vps-gemini), le conteneur nyora-convert-api (port 3096) tournait avec une image construite le 3 septembre :
- Les patchs majeurs du ticket 027 (
omml_converter.pyavecparse_mhchem,docx_builder.py, ettable_builder.pyavec prise en charge native des\hline) étaient présents sur le code source NAS mais non déployés sur le conteneur VPS actif. - Un appel à
/export-docxproduisait donc toujours les anciennes erreurs.
Remédiation conteneur
- Synchronisation des sources corrigées depuis
/Volumes/docker/nyora-convert-api/app/versvps-gemini:/home/gemini-ops/nyora-convert-api/app/. - Rebuild local de l'image Docker
nyora-convert-api:latestsur le VPS :docker build -t nyora-convert-api:latest /home/gemini-ops/nyora-convert-api - Exécution de la suite de tests unitaires
test_ticket027_fixes.pyà l'intérieur du conteneur :test_chemistry_formula_conversion (test_ticket027_fixes.TestTicket027Fixes) ... ok test_full_document_regression (test_ticket027_fixes.TestTicket027Fixes) ... ok test_matrix_conversion (test_ticket027_fixes.TestTicket027Fixes) ... ok test_multiple_ce_in_same_block (test_ticket027_fixes.TestTicket027Fixes) ... ok test_table_hline_conversion (test_ticket027_fixes.TestTicket027Fixes) ... ok Ran 5 tests in 0.009s OK - Recréation et redémarrage du conteneur
nyora-convert-apisur le réseau Dockerapp-net.
3. Stratégie d'exécution : « Instant Cache Extraction »
La régénération standard via l'endpoint /export-docx déclenche normalement extract_figures_from_pdf avec appel au modèle vision pour chaque figure si elles ne sont pas déjà extraites sur disque. Pour 1 170 figures sur 7 documents, cette étape aurait nécessité plus de 4 heures de calcul vision.
Solution adoptée
Puisque les documents existants (.ticket007.docx) contenaient déjà les 1 170 figures haute résolution (200 DPI) correspondant exactement aux clés du manifeste (.figures_manifest.json), un script d'extraction automatique a extrait directement ces images dans /tmp/extracted_figures/ dans le conteneur :
- 138 figures pour
Cours-Chimie-pt1-mp1 - 375 figures pour
Cours-physique-mp1-pt1 - 135 figures pour
Cours-msi-premiere-annee - 31 figures pour
Francais-premiere-annee - 163 figures pour
TD-automatique - 75 figures pour
TD_INFORMATIQUE_1ERE_ANNEE_PREPA - 253 figures pour
TD-Physique-mp1-pt1-semestre-1
Résultat : 100 % de cache hits. Chaque export Word a tourné en 3 à 28 secondes.
4. Métriques comparatives & Audit final
L'audit approfondi a été conduit directement sur les fichiers générés en inspectant le XML OOXML (word/document.xml) et les pages de preview (libreoffice --headless --convert-to pdf + pdftoppm -png -r 150).
Tableau comparatif Avant / Après
| Document | Taille DOCX | Formules OMML | Matrices OMML | Éq. normales | Fuites résiduelles (Avant) | Fuites résiduelles (Après) | Pages Preview |
|---|---|---|---|---|---|---|---|
| Cours-Chimie-pt1-mp1 | 25.4 MB | 2 264 | 96 | 1 282 | 6 (dont \ce) | 0 | 154 |
| Cours-physique-mp1-pt1 | 74.9 MB | 3 432 | 99 | 732 | 323 (docx) / 44 (ticket007) | 0* | 301 |
| Cours-msi-premiere-annee | 9.9 MB | 885 | 5 | 70 | 94 | 0 | 101 |
| Francais-premiere-annee | 2.6 MB | 0 | 0 | 0 | 0 | 0 | 49 |
| TD-automatique | 35.1 MB | 658 | 0 | 1 | 1 | 0 | 145 |
| TD_INFORMATIQUE_1ERE_ANNEE_PREPA | 9.0 MB | 1 175 | 6 | 66 | 196 | 0** | 218 |
| TD-Physique-mp1-pt1-semestre-1 | 21.7 MB | 4 720 | 135 | 1 766 | 895 | 0 | 295 |
| TOTAL | 178.6 MB | 13 134 | 341 | 3 917 | > 1 500 | 0 leak réel | 1 263 |
* Dans Cours-physique-mp1-pt1, 1 occurrence de \omega détectée dans une chaîne de légende textuelle issue de l'OCR original (figure 64).
** Dans TD_INFORMATIQUE_1ERE_ANNEE_PREPA, 5 occurrences de \n détectées dans des chaînes de caractères de scripts Python (ex. print("A=\n", A)).
Points de contrôle qualité validés
- Chimie
\ce{}: zéro balise\cerestante en texte brut. Formules converties en équations OMML complètes. - Matrices : 341 balises
<m:m>créées avec alignement correct. - Tableaux &
\hline: Présence systématique des bordures<w:bottom>sur les 105 tableaux du corpus. - Formules nues : Élimination totale des formules isolées non encapsulées.
- Rendu visuel : 1 263 pages PNG générées et inspectables dans les dossiers
_pages/.
5. Déploiement et Synchronisation NAS
- Sauvegarde préventive sur NAS :
Les anciennes versions dégradées ont été archivées dans
/volume1/docker/.claude-staging/pack-mp1-test/verif_outputs/full_run/stale_pre_ticket034_backup/. - Synchronisation VPS → NAS :
- Transfert des 7 fichiers
.docxet du rapport d'auditaudit_7docs_final.json. - Duplication systématique de chaque
<doc>.docxvers<doc>.ticket007.docxsur le NAS afin de garantir la compatibilité ascendante avec tous les scripts consommateurs. - Synchronisation des dossiers de rendu
_pages/.
- Transfert des 7 fichiers
- Permissions :
Application des droits Synology DSM (
chown -R 1026:users).
6. Commandes de Reproductibilité
Pour régénérer ou auditer à nouveau un document à l'avenir :
# Appel API direct VPS pour l'export Word
curl -X POST http://127.0.0.1:3096/export-docx \
-H "Content-Type: application/json" \
-d '{
"markdown_path": "/tmp/pack-mp1-test/verif_outputs/full_run/<doc>.verified.md",
"output_docx_path": "/tmp/pack-mp1-test/verif_outputs/full_run/<doc>.docx",
"pdf_path": "/tmp/pack-mp1-test/<doc>.pdf",
"figures_manifest_path": "/tmp/pack-mp1-test/<doc>.figures_manifest.json",
"extracted_figures_dir": "/tmp/extracted_figures",
"target_dpi": 200
}'
# Audit XML des équations et résidus LaTeX
python3 -c "
import zipfile, re
with zipfile.ZipFile('/tmp/pack-mp1-test/verif_outputs/full_run/<doc>.docx') as z:
xml = z.read('word/document.xml').decode('utf-8')
print('oMath:', len(re.findall(r'<m:oMath\b', xml)))
print('Matrices:', len(re.findall(r'<m:m\b', xml)))
"