diff --git a/plan_implem_initialGen.md b/plan_implem_initialGen.md new file mode 100644 index 0000000..68a416d --- /dev/null +++ b/plan_implem_initialGen.md @@ -0,0 +1,428 @@ +# Plan d'Implémentation : Réintégration InitialGeneration + +**Date :** 2025-10-12 +**Objectif :** Réintégrer la logique de génération par couples et contraintes de longueur du système legacy +**Auteur :** Claude Code (avec validation utilisateur requise) + +--- + +## 🧠 Analyse Chain of Thought + +### Problèmes Identifiés + +**Dans le système actuel (`generateSimple()` dans `SelectiveUtils.js`) :** + +1. ✅ Génération **élément par élément** → lent (33 appels), coûteux +2. ✅ **Prompt générique** pour tous types → pas de contraintes adaptées +3. ✅ Pas de **contraintes de longueur** → articles de 400 mots au lieu de 150 +4. ✅ Pas de **gestion des couples** → Q sans R cohérente, Titre sans Texte lié +5. ✅ MaxTokens insuffisants pour certains modèles + +**Systèmes legacy existants et fonctionnels :** + +- ✅ `InitialGeneration.js` : batch generation (chunks de 4) + détection de type + contraintes de longueur +- ✅ `buildSmartHierarchy()` : associe automatiquement couples titre/texte et paires FAQ +- ✅ `parseFAQPairsResponse()` : validation stricte de cohérence des paires + +--- + +## ❌ Erreurs dans le Plan Initial + +### 1. **Détection de type trop complexe** + +**Legacy (`InitialGeneration.js:132-146`) :** +```javascript +detectElementType(tag) { + if (tagLower.includes('titre') || tagLower.includes('h1') || tagLower.includes('h2')) { + return 'titre'; // ← STRING simple + } +} +``` + +**Mon plan initial :** +```javascript +detectElementType(tag) { + return { type: 'titre_h2', maxWords: 12, maxTokens: 30 }; // ← OBJET complexe +} +``` + +**❌ Problème :** Sur-ingénierie. Le legacy est plus simple et fonctionne. + +--- + +### 2. **Chunking sur-complexifié** + +**Legacy (`InitialGeneration.js:52`) :** +```javascript +const chunks = chunkArray(Object.entries(elementsToGenerate), 4); // Simple chunks de 4 +``` + +**Mon plan initial :** +```javascript +function groupIntoBatches(hierarchy) { + // Logique complexe : calcul tokens, groupement intelligent des FAQ, etc. + // ~60 lignes de code +} +``` + +**❌ Problème :** Réinvente la roue. Le chunking simple par 4 marche déjà. + +--- + +### 3. **Hiérarchie ignorée** + +**Point critique découvert :** + +Le pipeline utilise DÉJÀ `buildSmartHierarchy()` qui retourne cette structure : + +```javascript +{ + "H2_1": { + title: { instructions: "..." }, // ← Titre H2_1 + text: { instructions: "..." }, // ← Texte P_1 associé + questions: [] // ← Vide si pas de FAQ + }, + "q_1": { + title: null, + text: null, + questions: [ // ← q_1 et a_1 groupées ici + { type: 'Faq', level: 'q', ... }, + { type: 'Faq', level: 'a', ... } + ] + } +} +``` + +**❌ Mon erreur majeure :** Je traite `H2_1`, `P_1`, `q_1`, `a_1` comme éléments séparés au lieu d'exploiter les couples déjà identifiés par `buildSmartHierarchy()`. + +--- + +## ✅ Architecture Correcte + +### Principe de base + +**Réutiliser la logique d'`InitialGeneration.js`** qui : +1. Prépare les éléments avec type détecté +2. Groupe en chunks de 4 +3. Génère par batch avec contraintes de longueur +4. Parse les réponses avec fallback + +**MAIS** : Adapter pour respecter la structure hiérarchique créée par `buildSmartHierarchy()`. + +--- + +## 📋 Plan Révisé + +### Option A : Réutiliser InitialGenerationLayer (RECOMMANDÉ) + +**Avantages :** +- ✅ Code déjà testé et fonctionnel +- ✅ Gestion fallback robuste +- ✅ Contraintes de longueur intégrées +- ✅ Chunking optimisé + +**Modifications nécessaires :** + +#### 1. Dans `PipelineExecutor.js` (ligne 214-247) + +**Avant :** +```javascript +const result = await generateSimple(hierarchy, csvData, { llmProvider }); +``` + +**Après :** +```javascript +const { InitialGenerationLayer } = require('../generation/InitialGeneration'); +const layer = new InitialGenerationLayer(); + +// Aplatir la hiérarchie pour InitialGeneration +const flatStructure = flattenHierarchy(hierarchy); + +const result = await layer.apply(flatStructure, { + llmProvider, + temperature: 0.9, + csvData +}); +``` + +#### 2. Créer fonction `flattenHierarchy()` dans `PipelineExecutor.js` + +```javascript +function flattenHierarchy(hierarchy) { + const flat = {}; + + Object.entries(hierarchy).forEach(([sectionKey, section]) => { + // Ajouter titre si présent + if (section.title && section.title.instructions) { + const titleTag = sectionKey.includes('_') ? sectionKey : `${sectionKey}_title`; + flat[titleTag] = section.title.instructions; + } + + // Ajouter texte si présent + if (section.text && section.text.instructions) { + const textTag = sectionKey.includes('_') ? `${sectionKey}_text` : sectionKey; + flat[textTag] = section.text.instructions; + } + + // Ajouter questions FAQ + if (section.questions && section.questions.length > 0) { + section.questions.forEach((faq, index) => { + if (faq.originalElement && faq.originalElement.resolvedContent) { + const faqTag = faq.hierarchyPath || `faq_${index}`; + flat[faqTag] = faq.originalElement.resolvedContent; + } + }); + } + }); + + return flat; +} +``` + +**Impact :** Minimal, réutilise code existant + +--- + +### Option B : Adapter generateSimple() pour respecter la hiérarchie + +**Avantages :** +- ✅ Pas de changement dans PipelineExecutor +- ✅ Compatibilité maintenue + +**Inconvénients :** +- ❌ Réécriture partielle de generateSimple() +- ❌ Plus de code à tester + +#### Modifications dans `SelectiveUtils.js` + +**Ajouter détection de couples avant la boucle :** + +```javascript +async function generateSimple(hierarchy, csvData, options = {}) { + // ... début identique ... + + const batches = []; + + // Grouper éléments par couples et type + for (const [sectionKey, section] of Object.entries(hierarchy)) { + const batch = []; + + // Couple titre + texte + if (section.title && section.text) { + batch.push([`${sectionKey}_title`, section.title]); + batch.push([`${sectionKey}_text`, section.text]); + } else if (section.title) { + batch.push([`${sectionKey}_title`, section.title]); + } else if (section.text) { + batch.push([`${sectionKey}_text`, section.text]); + } + + // Paires FAQ + if (section.questions && section.questions.length > 0) { + for (let i = 0; i < section.questions.length; i += 2) { + const question = section.questions[i]; + const answer = section.questions[i + 1]; + + if (question && answer) { + batch.push([question.hierarchyPath, question]); + batch.push([answer.hierarchyPath, answer]); + } + } + } + + if (batch.length > 0) { + batches.push(batch); + } + } + + // Générer chaque batch avec prompt adapté + // ... suite similaire au plan initial mais avec couples respectés ... +} +``` + +--- + +## 🎯 Décision Requise + +### Questions Critiques + +**1. Quelle option choisir ?** +- [ ] **Option A** : Réutiliser InitialGenerationLayer (moins de code, plus sûr) +- [ ] **Option B** : Adapter generateSimple() (plus de flexibilité, plus de risque) + +**2. Structure réelle de `buildSmartHierarchy()` ?** + +Pour valider le plan, j'ai besoin de voir un exemple concret de ce que retourne `buildSmartHierarchy()` actuellement. + +**Action :** Ajouter ce log temporaire dans `PipelineExecutor.js:233` : +```javascript +const hierarchy = await buildSmartHierarchy(elementsArray); +logSh(`DEBUG HIERARCHY: ${JSON.stringify(hierarchy, null, 2)}`, 'DEBUG'); +``` + +Puis relancer une génération et me partager les logs. + +**3. Nombre d'éléments attendus ?** + +- Si `buildSmartHierarchy()` retourne **23 sections** au lieu de **33 éléments**, c'est normal (couples fusionnés) +- Si on veut 33 éléments générés, il faut aplatir la hiérarchie (Option A) + +--- + +## 📊 Comparaison Options + +| Critère | Option A (Réutiliser) | Option B (Adapter) | +|---------|----------------------|-------------------| +| **Code à écrire** | ~30 lignes | ~150 lignes | +| **Risque** | Faible | Moyen | +| **Tests nécessaires** | Minimes | Complets | +| **Maintenance** | Simple | Double système | +| **Performance** | Identique | Identique | +| **Compatibilité** | Changement PipelineExecutor | Transparent | +| **Recommandation** | ✅ **OUI** | ⚠️ Si besoin spécifique | + +--- + +## 🚀 Étapes d'Implémentation (Option A - Recommandée) + +### Phase 1 : Validation de la structure (30 min) + +1. Ajouter logs debug pour comprendre `buildSmartHierarchy()` +2. Analyser la sortie réelle +3. Valider que les couples sont bien formés + +### Phase 2 : Fonction flattenHierarchy (45 min) + +1. Créer la fonction dans `PipelineExecutor.js` +2. Tests unitaires avec fixtures +3. Validation que tous les éléments sont extraits + +### Phase 3 : Intégration InitialGenerationLayer (60 min) + +1. Importer InitialGenerationLayer dans PipelineExecutor +2. Remplacer appel à generateSimple() +3. Adapter le retour pour compatibilité + +### Phase 4 : Augmentation maxTokens (15 min) + +Mettre à jour `LLMManager.js` : +```javascript +'claude-sonnet-4-5': { maxTokens: 8000 }, +'gpt-4o-mini': { maxTokens: 6000 }, +'gpt-5-mini': { maxTokens: 10000 }, +// etc. +``` + +### Phase 5 : Tests et validation (60 min) + +1. Test génération ligne 2 production +2. Vérifier 33 éléments générés +3. Vérifier longueurs respectées +4. Vérifier cohérence FAQ +5. Mesurer temps (~40-50s attendu) + +**Temps total : 3h30** + +--- + +## 📝 Modifications de Code + +### Fichiers impactés + +1. **`lib/pipeline/PipelineExecutor.js`** (ligne 214-247) + - Import InitialGenerationLayer + - Fonction flattenHierarchy() + - Remplacement generateSimple() + +2. **`lib/LLMManager.js`** (ligne 18-67) + - Augmentation maxTokens + +3. **`lib/selective-enhancement/SelectiveUtils.js`** (optionnel) + - Marquer generateSimple() comme DEPRECATED + - Ajouter commentaire pointant vers InitialGeneration + +--- + +## ⚠️ Risques et Mitigations + +### Risque 1 : Structure hiérarchie différente de l'attendu + +**Impact :** High +**Probabilité :** Medium +**Mitigation :** Logs debug + validation avant implémentation + +### Risque 2 : Parsing échoue sur certains éléments + +**Impact :** Medium +**Probabilité :** Low (code legacy testé) +**Mitigation :** Fallback déjà présent dans InitialGenerationLayer + +### Risque 3 : Régression performance + +**Impact :** Medium +**Probabilité :** Very Low +**Mitigation :** Tests avant/après avec métriques + +### Risque 4 : Incompatibilité avec pipeline actuel + +**Impact :** High +**Probabilité :** Low +**Mitigation :** Tests complets sur environnement dev + +--- + +## ✅ Critères de Succès + +1. **Fonctionnel :** + - [ ] 33/33 éléments générés (pas de skip) + - [ ] Longueurs respectées (H2: 8-15 mots, P: 80-200 mots) + - [ ] Paires FAQ cohérentes (Q pertinente pour R) + - [ ] Aucune erreur FATAL + +2. **Performance :** + - [ ] Temps < 60s (vs ~150s actuellement) + - [ ] Coût -30% minimum + +3. **Qualité :** + - [ ] Contenu non générique + - [ ] Pas de troncature + - [ ] Style personnalité respecté + +--- + +## 🔄 Rollback Strategy + +**En cas de problème :** + +1. **Phase 1-3 :** `git revert` simple +2. **Phase 4 :** Restaurer anciennes valeurs maxTokens +3. **Phase 5 :** Si échec tests, rollback complet + +**Fallback automatique :** InitialGenerationLayer a déjà un fallback intégré par chunk. + +--- + +## 📌 TODO Immédiat + +- [ ] **DÉCISION :** Choisir Option A ou Option B +- [ ] **ACTION :** Ajouter logs debug buildSmartHierarchy() +- [ ] **PARTAGE :** Envoyer exemple output buildSmartHierarchy() +- [ ] Valider avec utilisateur avant implémentation + +--- + +## 📚 Références Code Legacy + +- `lib/generation/InitialGeneration.js` (ligne 1-284) +- `lib/ElementExtraction.js` - `buildSmartHierarchy()` (ligne 276-313) +- `lib/ElementExtraction.js` - `parseFAQPairsResponse()` (ligne 402-451) +- `lib/pipeline/PipelineExecutor.js` - `runGeneration()` (ligne 214-247) + +--- + +**Status :** ⏸️ **EN ATTENTE VALIDATION UTILISATEUR** + +Avant de commencer l'implémentation, il faut : +1. Décider de l'option (A recommandée) +2. Analyser la structure réelle de buildSmartHierarchy() +3. Valider que le plan correspond aux besoins