docs(nyora): capitalisation régénération DOCX et visual previews 7 documents (ticket nyora-2026-09-034)
This commit is contained in:
@@ -161,6 +161,7 @@
|
|||||||
|
|
||||||
| Runbook | Date | Tags |
|
| Runbook | Date | Tags |
|
||||||
|---------|------|------|
|
|---------|------|------|
|
||||||
|
| [Régénération haute fidélité DOCX & visual previews des 7 documents NAS (ticket nyora-2026-09-034)](hermes-nyora/runbook-regeneration-docx-corpus-7docs-ticket034.md) | 2026-09-09 | nyora, convert-api, docx, omml, mhchem, hline, ticket034, corpus-7docs, audit, rag |
|
||||||
| [Veille Nexum -- decalage image Telegram (sendPhoto), fidelite titre site/Telegram, nettoyage DeepSeek](hermes-nyora/veille-nexum-telegram-image-titre-fidelite-20260828.md) | 2026-08-28 | veille-nexum, telegram, sendphoto, fidelite-titre, deepseek, n8n |
|
| [Veille Nexum -- decalage image Telegram (sendPhoto), fidelite titre site/Telegram, nettoyage DeepSeek](hermes-nyora/veille-nexum-telegram-image-titre-fidelite-20260828.md) | 2026-08-28 | veille-nexum, telegram, sendphoto, fidelite-titre, deepseek, n8n |
|
||||||
| [Passerelle MCP dédiée NyoraNotes (multi-agent, StreamableHTTP port 3098, scoping strict par dossier, connecteur DSH validé)](common/nyora-notes-mcp-gateway-deploiement-20260826.md) | 2026-08-26 | nyora-notes-mcp, mcp, streamable-http, scoping, dsh, tailscale |
|
| [Passerelle MCP dédiée NyoraNotes (multi-agent, StreamableHTTP port 3098, scoping strict par dossier, connecteur DSH validé)](common/nyora-notes-mcp-gateway-deploiement-20260826.md) | 2026-08-26 | nyora-notes-mcp, mcp, streamable-http, scoping, dsh, tailscale |
|
||||||
| [Réduction hermes-hub en dispatcher minimal & stabilisation DSH (historique, WebSockets, mémoire NyoraNotes)](common/decommission-switcher-hub-stabilisation-dsh-20260826.md) | 2026-08-26 | dsh, hermes-hub, dispatcher, websocket, history-fix, nyora-notes |
|
| [Réduction hermes-hub en dispatcher minimal & stabilisation DSH (historique, WebSockets, mémoire NyoraNotes)](common/decommission-switcher-hub-stabilisation-dsh-20260826.md) | 2026-08-26 | dsh, hermes-hub, dispatcher, websocket, history-fix, nyora-notes |
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
# 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 :
|
||||||
|
1. **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'OMML `m:m`), et des formules nues non encapsulées.
|
||||||
|
2. **Chimie dégradée** : balises `\ce{...}` laissées en clair dans `Cours-Chimie-pt1-mp1` car le parser mhchem n'était pas activé.
|
||||||
|
3. **Tableaux sans bordures** : les balises `\hline` n'étaient pas traduites en bordures natives OOXML (`<w:bottom>`).
|
||||||
|
|
||||||
|
### Périmètre strict (7 documents canoniques)
|
||||||
|
1. `Cours-Chimie-pt1-mp1`
|
||||||
|
2. `Cours-physique-mp1-pt1`
|
||||||
|
3. `Cours-msi-premiere-annee`
|
||||||
|
4. `Francais-premiere-annee`
|
||||||
|
5. `TD-automatique`
|
||||||
|
6. `TD_INFORMATIQUE_1ERE_ANNEE_PREPA`
|
||||||
|
7. `TD-Physique-mp1-pt1-semestre-1`
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Le document `Cours-informatique-section-premiere-annee` est **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.py` avec `parse_mhchem`, `docx_builder.py`, et `table_builder.py` avec 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-docx` produisait donc toujours les anciennes erreurs.
|
||||||
|
|
||||||
|
### Remédiation conteneur
|
||||||
|
1. Synchronisation des sources corrigées depuis `/Volumes/docker/nyora-convert-api/app/` vers `vps-gemini:/home/gemini-ops/nyora-convert-api/app/`.
|
||||||
|
2. Rebuild local de l'image Docker `nyora-convert-api:latest` sur le VPS :
|
||||||
|
```bash
|
||||||
|
docker build -t nyora-convert-api:latest /home/gemini-ops/nyora-convert-api
|
||||||
|
```
|
||||||
|
3. Exécution de la suite de tests unitaires `test_ticket027_fixes.py` à l'intérieur du conteneur :
|
||||||
|
```text
|
||||||
|
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
|
||||||
|
```
|
||||||
|
4. Recréation et redémarrage du conteneur `nyora-convert-api` sur le réseau Docker `app-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
|
||||||
|
- [x] **Chimie `\ce{}`** : zéro balise `\ce` restante en texte brut. Formules converties en équations OMML complètes.
|
||||||
|
- [x] **Matrices** : 341 balises `<m:m>` créées avec alignement correct.
|
||||||
|
- [x] **Tableaux & `\hline`** : Présence systématique des bordures `<w:bottom>` sur les 105 tableaux du corpus.
|
||||||
|
- [x] **Formules nues** : Élimination totale des formules isolées non encapsulées.
|
||||||
|
- [x] **Rendu visuel** : 1 263 pages PNG générées et inspectables dans les dossiers `_pages/`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Déploiement et Synchronisation NAS
|
||||||
|
|
||||||
|
1. **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/`.
|
||||||
|
2. **Synchronisation VPS → NAS** :
|
||||||
|
- Transfert des 7 fichiers `.docx` et du rapport d'audit `audit_7docs_final.json`.
|
||||||
|
- Duplication systématique de chaque `<doc>.docx` vers `<doc>.ticket007.docx` sur le NAS afin de garantir la compatibilité ascendante avec tous les scripts consommateurs.
|
||||||
|
- Synchronisation des dossiers de rendu `_pages/`.
|
||||||
|
3. **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 :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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)))
|
||||||
|
"
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user