Pipeline : du livre scanne a la meta-grammaire

Brihaddesi (Sharma 1992-94 IGNCA) -- 274 pages

Voici les 6 etapes du pipeline. Chaque etape a un numero stable : on s'y refere comme "etape 4a" ou "etape 2c". Une etape obligatoire ne peut pas etre sautee : les etapes en aval seraient construites sur du texte non valide. Les sous-etapes necessitant un input humain sont marquees (toi).
Etape Quoi Acteur Cout IA Status Compteurs
0 Preparation des images
decoupe le PDF scanne en pages PNG, puis split chaque double-page en LEFT (devanagari) + RIGHT (anglais)
script Python (PyMuPDF + PIL) aucun ✅ fait 0 pages PNG, 548 demi-pages LEFT/RIGHT
1 OCR des pages
le scanner lit le texte dans les images
Surya local (PC2) aucun (modele local, gratuit) ✅ fait 274 / 274 pages
2a Verification linguistique automatique
flagge les mots suspects (orthographe, dico)
script Python aucun 🔮 pas commence 0 pages, 1196 flags
2a-bis Extraction bboxes word-level
re-passe Surya en mode layout sur chaque demi-page flagee : produit pour CHAQUE mot ses coordonnees precises (x,y). Prerequis pour un decoupage 2b correct (sinon 2b retombe en heuristique grossiere = ~33% crops defaillants).
Surya local (CPU) aucun 🔮 pas commence 384 / 548 demi-pages indexees
2b Decoupage des crops (bbox-precis)
decoupe un PNG autour de chaque flag : bbox de la ligne entiere (de 2a-bis) + 2 lignes au-dessus + 2 lignes en-dessous. Sert d'input a 2c (IA) ET a 2d (toi).
Si 2a-bis manquant : retombe en heuristique grossiere (qualite degradee).
script Python (PIL) aucun (decoupage d'image) 🔮 pas commence 0 / 0 crops generes
2c IA visuelle arbitre les crops
demande a l'IA ce qui est ECRIT dans chaque crop. Verdicts : OCR-a-raison / dico-a-raison / Vision-a-lu-autre-chose / illisible.
Pre-filtre : les crops ou Vision confirme le dico sont retires de la queue de 2d.
Claude Haiku Vision 🔮 pas commence 0 flags arbitres
0 auto-resolus (0.0%)
0 a reviewer humainement
2d Review humaine (toi)
tu tranches les cas que l'IA n'a pas auto-resolus, en regardant le crop (2b) + verdict IA (2c) + texte OCR surligne.
→ ouvrir la queue de review
toi (humain) aucun ✅ fait 276 reviews humaines
0 restants en queue (apres auto-skip orphelins+dico)
2e Auto-apprentissage du dico
chaque accept dans 2d ecrit la correction dans le dico (mecaniquement applique aux occurrences suivantes de la meme session de review)
script Python (auto) aucun ✅ fait 155 corrections uniques
158 validations totales
2f Application des corrections au texte
parcourt le texte OCR brut et applique mecaniquement toutes les corrections validees du dico (2e). Sortie : texte "assaini" dans surya_txt_clean/.
Run via python -m src.v3_grammar.ocr_validation.apply_corrections.
script Python aucun 🔮 a lancer apres 2d 0 fichiers assaini
(token + line replacements)
2g.1 Extraction layout Surya
re-passe Surya en mode LayoutPredictor sur chaque demi-page flagee : produit pour chaque region son type (Text / Footnote / SectionHeader / PageHeader / PageFooter / Caption / ListItem / Table). Tourne sur PC2.
Surya local (PC2) aucun ⏳ en cours 384 / 548 demi-pages
2g.2 Tagging du role de chaque ligne
mapping geometrique line bbox (de 2a-bis) → bloc layout (de 2g.1) → role par ligne :
main (vers/prose principale) | annotation_inline (commentaire interligne, hauteur reduite) | editorial_bracket (entre [...] ou marqueur ° / ॰) | footnote / page_header / page_footer / section_header / caption / list_item / table.
Heuristiques sur cas que Surya layout rate (annotations interlignes courtes).
script Python aucun ⏳ en cours 384 / 548 demi-pages tagguees
2g.3 Rattachement annotation → ligne parente
pour chaque ligne annotation_inline ou editorial_bracket, identifie la ligne main la plus proche (preference au-dessus) qu'elle commente. Sortie : champ parent_line_num par ligne.
Permet aux etapes 3+ de regrouper (vers + ses commentaires) au lieu de les melanger.
script Python aucun ⏳ avec 2g.2 co-extrait avec 2g.2
2g.4 Detection des exposants / indices inline
Cas type १४१षड्जधैवतयोः : Surya OCR fond les chiffres en exposant dans le mot suivant. Detecte via la hauteur des bboxes word-level (de 2a-bis) : un mot dont la bbox est plus petite que la mediane = exposant. Re-emballe en <sup>...</sup>.
Tourne sur surya_txt_clean (de 2f) → output surya_txt_after_2g4.
script Python aucun 🔮 pas commence 0 fichiers traites
2g.5 Cleanup balises Surya + capture semantique
Strip <i>, <math>, <sub>, <br> du texte. Preserve <sup> (deja wrap par 2g.4). Capture la semantique en sidecar metadata (italique = potentiel terme Sanskrit dans contexte english).
script Python aucun 🔮 pas commence 0 fichiers + sidecar metadata
2g.7 Remap caracteres Surya substitues
Surya confond parfois caracteres devanagari avec lookalikes latins :
: (ASCII) ↔ (visarga U+0903) — 1445 cas remappes dans ce corpus
l/I (single danda)
ll/II (double danda)
o/O (abreviation)
script Python aucun 🔮 pas commence 0 fichiers traites
2g.9 Tokenizer notation musicale (svaras)
Surya OCR colle parfois les notes musicales consecutives :
attendu : सा रि ग म प ध नि → Surya : सारिगमपधनि (gluees)
Decompose chaque mot en svaras via longest-match si la decomposition entiere donne >= 3 svaras.
script Python aucun 🔮 pas commence 0 fichiers traites
2g.8 Re-OCR Vision sur lignes avec orphelins
Pour les ~95 lignes contenant des diacritiques orphelins (signe-voyelle ou virama sans consonne porteuse — auto-skippes pendant 2d), envoie le crop de la ligne a Claude Vision pour re-lecture pixel-precise. Capture les °/ rates et les autres marqueurs editoriaux.
Claude Haiku Vision 🔮 pas commence 0 fichiers traites
2g.6 Calibration humaine (5 pages echantillon) (toi)
tu reviewes 5 pages au hasard taggees par 2g.1-5 et confirmes/infirmes les roles attribues a chaque ligne. On calcule precision et recall.
→ Lancer la calibration · Voir rapport
toi (humain) aucun ✅ 3 run(s) 3 runs
derniere accuracy : 64%
3 Structuration en fiches multilingues
range chaque page : devanagari + anglais + flags + arbitrages, format propre
script Python aucun ✅ fait 274 / 274 fiches
4★ Filtre anti-fabrication (mecanisme transversal des etapes 4b / 4c / 6)
A chaque etape qui utilise l'IA pour extraire du contenu, on verifie qu'une trace verbatim du contenu existe dans le texte source. Sinon, on rejette. Ca garantit que rien n'est invente. Les rejets sont des candidats pour audit humain ou IA : → /audit.
script Python (filtre) aucun ✅ actif Cumule sur 4b+4c+6 : 0 gardes, 0 rejetes (0.0%)
4b : 0 / 0 | 4c : 0 / 0 | 6 : 0 / 0
audit des rejets : /audit
4★b Audit IA des rejets restants (passe 2 du filtre)
Apres le filtre syntaxique 4★, Claude examine un par un les rejets restants. Pour chaque, il decide : invention (rejet definitif) / recuperable tel quel / recuperable apres reformulation (avec la forme verbatim du texte source). Les recuperables sont reintegres aux concepts/affirmations/fiches.
Claude Haiku (audit batch) 🔮 a lancer 0 decisions enregistrees
4a Concepts connus (matching dico)
repere mecaniquement les mots du vocabulaire ICM (svara, raga, jati...) : zero invention
script Python aucun 🔮 pas commence 0 / 274 fiches indexees
4b Concepts nouveaux (IA)
l'IA repere noms propres / lieux / traites cites pas dans le dico, avec garde-fou : seulement des mots qui existent dans le texte (verification substring exact post-LLM)
Claude Haiku 🔮 pas commence 0 / 274 pages
0 concepts gardes
0 hallucines droppes (anti-fab)
4c Affirmations typees (IA)
l'IA identifie ce que dit le texte (definition / structural / relation / enumeration / attribution / citation), avec garde-fou : chaque affirmation doit avoir un supporting_quote substring exact du source
Claude Haiku 🔮 pas commence 0 / 274 pages
0 affirmations gardees
0 non-supportees droppees (anti-fab)
4cd Alignement attestations bilingue
pour chaque affirmation 4c, retrouve le segment verbatim de l'autre langue (sanskrit ↔ anglais Sharma). Permet d'afficher l'attestation des DEUX cotes dans /book. Anti-fab : dual_quote doit etre substring exact. Idempotent.
Claude Haiku ✅ fait 1924 / 3187 affirmations alignees (60.4%)
stocke en table affirmations.dual_quote
4d Deduplication + mapping dico Sem-A
regroupe les variants graphiques (mūrchanā / mūrchanāḥ / mūrchanānām → meme cluster) via normalisation NFC + stem-strip Sanskrit. Mappe vers le dico Sem-A (88 entries) si match exact iast/devanagari ou stem.
script Python (deterministe) aucun 🔮 pas commence 0 clusters uniques
0 matches dico Sem-A
0 avec >=1 affirmation
0 dans >=5 pages (noyau)
4e Structures Vision (tableaux, diagrammes, gammes)
Vision Claude sur les pages-images qui contiennent du contenu structurel (tableaux de mūrchanā-maṇḍala, listes ordonnees de tānas avec rotation, diagrammes śruti-maṇḍala...). Surya OCR aplatit ces structures 2D en lignes texte ; Vision les reconstruit. 6 kinds : ordered_sequence_list, table, shifted_sequence_table, diagram, scale, phrase. Complète l'extraction 4c (peer, pas sous-tâche de 6).
Claude Opus Vision ✅ fait (119 pages, 364 structures) 119 pages, 364 structures extraites
scope = top-50 pages structural. Voir BACKLOG B-005a/b/c pour les trous.
5 Graphe de connaissance
nodes = clusters concepts (4d), edges derives des affirmations 4c (relation / enumeration / attribution / citation) par scan des claims + supporting_quotes pour mentions d'autres clusters. Pas d'IA, pure deterministe.
script Python (deterministe) aucun 🔮 pas commence 0 nodes, 0 edges
0 connectes (0%)
0% affirmations -> edges
6 Grammaire intra-source
par famille de concepts (svara_name/svara_role/alankara/giti/raga_class/...), extrait le schema reutilisable (slots typiques) + remplit le record de chaque instance avec ses valeurs de slots (cf gāndhārī : amsa=gāndhāra, nyasa=madhyama). Anti-fab : chaque (slot, value) doit pointer vers un supporting_quote 4c. Distinct du graphe (5) qui est juste relation-instance-instance.
Claude Haiku (structurant) 🔮 pas commence 0 familles processees
0 instances avec records
0 slots verifies (anti-fab)
6b Règles génératives (synthèse depuis affirmations + structures)
à partir des ~2700 affirmations 4c typées + structures 4e (tables, mūrchanās, prastāras), extrait les règles opérantes (transformation, dérivation, composition, classification, assignment, validation) interprétables par une machine. Sous-tâche de 6 (grammaire intra) : 6a = formes lexicales, 6b = règles opérantes. Anti-fab : chaque règle attestée par >=1 verbatim quote. Chaque règle est rattachée à un concept (colonne cluster_id) → liens concept↔règle exploitables via API et UI.
Claude Opus ✅ fait (1087 règles) 1087 règles (fichier JSON)
1087 insérées en DB
812 concepts liés (table generative_rules.cluster_id indexée)
agent Opus hardened terminé
4d-bis ↺ Dédup avancé (boucle de raffinement)
détecte les clusters fragmentés (variantes graphiques : singulier/pluriel, casse, suffixes Sanskrit) que 4d a manqués. Cascade SQL atomique : remap cluster_id sur affirmations + generative_rules + grammar_instance_records + edges. Boucle — re-lancée à chaque tour 6c → feedback. Invalide les outputs 6c.1, 6c.2 (à re-runner derrière).
script Python (deterministe) aucun 🔮 pas commence 0 merges, 0 affirmations remappées
boucle de raffinement — déclenché par 6c
6c.1 Découpage en domaines (Leiden community detection)
algorithme Leiden (Traag 2019, successeur de Louvain) sur le graphe des edges concept↔concept. Trouve les communautés naturelles (modularité > 0.3 = structure réelle). Identifie les "domaines musicaux" sans intervention humaine — base pour la grammaire formelle 6c.2-6c.4. Reproductible sur n'importe quel ouvrage.
script Python (deterministe, Leiden) aucun ✅ fait (787 communautés) 787 communautés
modularité 0.482
top: #0(170) · #1(132) · #2(110) · #3(104) · #4(97) · #5(91)
6c.2 Hiérarchie + schémas (Formal Concept Analysis)
FCA (Wille 1982) sur la matrice concept × profil-sémantique (catégories de règles + types d'affirmations + co-mentions) par domaine → treillis de Galois canonique = hiérarchie de types + schémas. Pose mathématiquement, pas heuristique. Implém Python : `concepts`.
script Python (deterministe, FCA) aucun ✅ fait (741 types) 11 domaines
741 types formels
11 domaines analysés
6c.3 Opérations + contraintes (LLM par domaine)
1 agent Opus par domaine 6c.1. Synthèse des règles 6b en : opérations exécutables (transformation, derivation, composition) + contraintes (validation, invariants). Output: 1 module Python par domaine.
Claude Opus (1 agent par domaine) 🔮 pas commence — attend lancement
6c.4 Assemblage en grammaire formelle unifiée
merge des modules 6c.3 + types 6c.2 + arêtes inter-domaines. Output : module Python formal_grammar/ + JSON Schema + EBNF + diagramme.
Claude Opus (assembleur) 🔮 pas commence — attend lancement
7 Persist en base SQLite
consolide tous les outputs (3 + 4b + 4c + 4d + 5 + 6) en une DB SQLite unique : 10 tables (sources, pages avec contenu textuel, concept_clusters, variants, affirmations, edges, grammar_families/slots/records). Devient l'autorite pour le frontend.
script Python (deterministe) aucun ✅ fait 6.64 MB
0p, 0 clusters, 0 affirms
0 edges, 0 grammar records
8 Meta-grammaire (cross-source)
comparer les grammaires intra-source des 3 ouvrages (Brihaddesi + vdMeer + Schofield) pour : detecter les invariants (ce que tous reconnaissent), les conflits (ce qui est dispute), les schemas evolutifs (slots ajoutes/retires entre epoques). Necessite que les 2 autres ouvrages aient fait 1-6.
script + Claude 🔮 attend 2/3 ouvrages traites Brihaddesi : ✅ 1-6 fait
vdMeer : 🔮 a faire
Schofield : 🔮 a faire
Legende