seo-generator-server/plan_implem_initialGen.md
StillHammer acb993cde4 docs: Add implementation plan for InitialGeneration reintegration
Plan détaillé pour réintégrer la logique de génération par couples
et contraintes de longueur du système legacy.

Analyse COT complète avec:
- Comparaison plan initial vs legacy code
- Identification erreurs de conception
- 2 options d'implémentation (Option A recommandée)
- Risques et mitigations
- Critères de succès
- Stratégie de rollback

Status: EN ATTENTE VALIDATION UTILISATEUR
Action requise: Analyser buildSmartHierarchy() output

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 08:23:33 +08:00

429 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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