seo-generator-server/lib/main_modulaire.js

422 lines
15 KiB
JavaScript

// ========================================
// MAIN MODULAIRE - PIPELINE ARCHITECTURALE MODERNE
// Responsabilité: Orchestration workflow avec architecture modulaire complète
// Usage: node main_modulaire.js [rowNumber] [stackType]
// ========================================
const { logSh } = require('./lib/ErrorReporting');
const { tracer } = require('./lib/trace');
// Imports pipeline de base
const { readInstructionsData, selectPersonalityWithAI, getPersonalities } = require('./lib/BrainConfig');
const { extractElementsFromXML } = require('./lib/ElementExtraction');
const { generateMissingKeywords } = require('./lib/MissingKeywords');
const { generateDirectElements } = require('./lib/generation/DirectGeneration');
const { injectContentIntoTemplate } = require('./lib/ContentAssembly');
const { compileAndStoreArticle } = require('./lib/ArticleStorage');
// Imports modules modulaires
const { applySelectiveLayer } = require('./lib/selective-enhancement/SelectiveCore');
const {
applyPredefinedStack,
applyAdaptiveLayers,
getAvailableStacks
} = require('./lib/selective-enhancement/SelectiveLayers');
const {
applyAdversarialLayer
} = require('./lib/adversarial-generation/AdversarialCore');
const {
applyPredefinedStack: applyAdversarialStack
} = require('./lib/adversarial-generation/AdversarialLayers');
/**
* WORKFLOW MODULAIRE PRINCIPAL
*/
async function handleModularWorkflow(config = {}) {
return await tracer.run('MainModulaire.handleModularWorkflow()', async () => {
const {
rowNumber = 2,
selectiveStack = 'standardEnhancement', // lightEnhancement, standardEnhancement, fullEnhancement, personalityFocus, fluidityFocus, adaptive
adversarialMode = 'light', // none, light, standard, heavy, adaptive
source = 'main_modulaire'
} = config;
await tracer.annotate({
modularWorkflow: true,
rowNumber,
selectiveStack,
adversarialMode,
source
});
const startTime = Date.now();
logSh(`🚀 WORKFLOW MODULAIRE DÉMARRÉ`, 'INFO');
logSh(` 📊 Ligne: ${rowNumber} | Selective: ${selectiveStack} | Adversarial: ${adversarialMode}`, 'INFO');
try {
// ========================================
// PHASE 1: PRÉPARATION DONNÉES
// ========================================
logSh(`📋 PHASE 1: Préparation données`, 'INFO');
const csvData = await readInstructionsData(rowNumber);
if (!csvData) {
throw new Error(`Impossible de lire les données ligne ${rowNumber}`);
}
const personalities = await getPersonalities();
const selectedPersonality = await selectPersonalityWithAI(
csvData.mc0,
csvData.t0,
personalities
);
csvData.personality = selectedPersonality;
logSh(` ✅ Données: ${csvData.mc0} | Personnalité: ${selectedPersonality.nom}`, 'DEBUG');
// ========================================
// PHASE 2: EXTRACTION ÉLÉMENTS
// ========================================
logSh(`📝 PHASE 2: Extraction éléments XML`, 'INFO');
const elements = await extractElementsFromXML(csvData.xmlTemplate);
logSh(`${Object.keys(elements).length} éléments extraits`, 'DEBUG');
// ========================================
// PHASE 3: GÉNÉRATION MOTS-CLÉS MANQUANTS
// ========================================
logSh(`🔍 PHASE 3: Génération mots-clés manquants`, 'INFO');
const enhancedCsvData = await generateMissingKeywords(csvData);
logSh(` ✅ Mots-clés complétés`, 'DEBUG');
// ========================================
// PHASE 4: GÉNÉRATION CONTENU DE BASE
// ========================================
logSh(`💫 PHASE 4: Génération contenu de base`, 'INFO');
const generatedContent = await generateDirectElements(elements, enhancedCsvData, {
source: 'main_modulaire',
usePersonality: true
});
logSh(`${Object.keys(generatedContent).length} éléments générés`, 'DEBUG');
// ========================================
// PHASE 5: SELECTIVE ENHANCEMENT MODULAIRE
// ========================================
logSh(`🔧 PHASE 5: Selective Enhancement Modulaire (${selectiveStack})`, 'INFO');
let selectiveResult;
switch (selectiveStack) {
case 'adaptive':
selectiveResult = await applyAdaptiveLayers(generatedContent, {
maxIntensity: 1.1,
analysisThreshold: 0.3,
csvData: enhancedCsvData
});
break;
case 'technical':
case 'transitions':
case 'style':
selectiveResult = await applySelectiveLayer(generatedContent, {
layerType: selectiveStack,
llmProvider: 'auto',
intensity: 1.0,
csvData: enhancedCsvData
});
break;
default:
// Stack prédéfini
selectiveResult = await applyPredefinedStack(generatedContent, selectiveStack, {
csvData: enhancedCsvData,
analysisMode: true
});
}
const enhancedContent = selectiveResult.content;
logSh(` ✅ Selective: ${selectiveResult.stats.elementsEnhanced || selectiveResult.stats.totalModifications || 0} améliorations`, 'INFO');
// ========================================
// PHASE 6: ADVERSARIAL ENHANCEMENT (OPTIONNEL)
// ========================================
let finalContent = enhancedContent;
let adversarialStats = null;
if (adversarialMode !== 'none') {
logSh(`🎯 PHASE 6: Adversarial Enhancement (${adversarialMode})`, 'INFO');
let adversarialResult;
switch (adversarialMode) {
case 'adaptive':
// Utiliser adversarial adaptatif
adversarialResult = await applyAdversarialLayer(enhancedContent, {
detectorTarget: 'general',
method: 'hybrid',
intensity: 0.8,
analysisMode: true
});
break;
case 'light':
case 'standard':
case 'heavy':
// Utiliser stack adversarial prédéfini
const stackMapping = {
light: 'lightDefense',
standard: 'standardDefense',
heavy: 'heavyDefense'
};
adversarialResult = await applyAdversarialStack(enhancedContent, stackMapping[adversarialMode], {
csvData: enhancedCsvData
});
break;
}
if (adversarialResult && !adversarialResult.fallback) {
finalContent = adversarialResult.content;
adversarialStats = adversarialResult.stats;
logSh(` ✅ Adversarial: ${adversarialStats.elementsModified || adversarialStats.totalModifications || 0} modifications`, 'INFO');
} else {
logSh(` ⚠️ Adversarial fallback: contenu selective préservé`, 'WARNING');
}
}
// ========================================
// PHASE 7: ASSEMBLAGE ET STOCKAGE
// ========================================
logSh(`🔗 PHASE 7: Assemblage et stockage`, 'INFO');
const assembledContent = await injectContentIntoTemplate(finalContent, enhancedCsvData.xmlTemplate);
const storageResult = await compileAndStoreArticle(assembledContent, {
...enhancedCsvData,
source: `${source}_${selectiveStack}${adversarialMode !== 'none' ? `_${adversarialMode}` : ''}`
});
logSh(` ✅ Stocké: ${storageResult.compiledLength} caractères`, 'DEBUG');
// ========================================
// RÉSUMÉ FINAL
// ========================================
const totalDuration = Date.now() - startTime;
const finalStats = {
rowNumber,
selectiveStack,
adversarialMode,
totalDuration,
elementsGenerated: Object.keys(generatedContent).length,
selectiveEnhancements: selectiveResult.stats.elementsEnhanced || selectiveResult.stats.totalModifications || 0,
adversarialModifications: adversarialStats?.elementsModified || adversarialStats?.totalModifications || 0,
finalLength: storageResult.compiledLength,
personality: selectedPersonality.nom,
source
};
logSh(`✅ WORKFLOW MODULAIRE TERMINÉ (${totalDuration}ms)`, 'INFO');
logSh(` 📊 ${finalStats.elementsGenerated} générés | ${finalStats.selectiveEnhancements} selective | ${finalStats.adversarialModifications} adversarial`, 'INFO');
logSh(` 🎭 Personnalité: ${finalStats.personality} | Taille finale: ${finalStats.finalLength} chars`, 'INFO');
await tracer.event('Workflow modulaire terminé', finalStats);
return {
success: true,
stats: finalStats,
content: finalContent,
assembledContent,
storageResult,
selectiveResult,
adversarialResult: adversarialStats ? { stats: adversarialStats } : null
};
} catch (error) {
const duration = Date.now() - startTime;
logSh(`❌ WORKFLOW MODULAIRE ÉCHOUÉ après ${duration}ms: ${error.message}`, 'ERROR');
logSh(`Stack trace: ${error.stack}`, 'ERROR');
await tracer.event('Workflow modulaire échoué', {
error: error.message,
duration,
rowNumber,
selectiveStack,
adversarialMode
});
throw error;
}
}, { config });
}
/**
* BENCHMARK COMPARATIF STACKS
*/
async function benchmarkStacks(rowNumber = 2) {
console.log('\n⚡ === BENCHMARK STACKS MODULAIRES ===\n');
const stacks = getAvailableStacks();
const adversarialModes = ['none', 'light', 'standard'];
const results = [];
for (const stack of stacks.slice(0, 3)) { // Tester 3 stacks principaux
for (const advMode of adversarialModes.slice(0, 2)) { // 2 modes adversarial
console.log(`🧪 Test: ${stack.name} + adversarial ${advMode}`);
try {
const startTime = Date.now();
const result = await handleModularWorkflow({
rowNumber,
selectiveStack: stack.name,
adversarialMode: advMode,
source: 'benchmark'
});
const duration = Date.now() - startTime;
results.push({
stack: stack.name,
adversarial: advMode,
duration,
success: true,
selectiveEnhancements: result.stats.selectiveEnhancements,
adversarialModifications: result.stats.adversarialModifications,
finalLength: result.stats.finalLength
});
console.log(`${duration}ms | ${result.stats.selectiveEnhancements} selective | ${result.stats.adversarialModifications} adversarial`);
} catch (error) {
results.push({
stack: stack.name,
adversarial: advMode,
success: false,
error: error.message
});
console.log(` ❌ Échoué: ${error.message}`);
}
}
}
// Résumé benchmark
console.log('\n📊 RÉSUMÉ BENCHMARK:');
const successful = results.filter(r => r.success);
if (successful.length > 0) {
const avgDuration = successful.reduce((sum, r) => sum + r.duration, 0) / successful.length;
const bestPerf = successful.reduce((best, r) => r.duration < best.duration ? r : best);
const mostEnhancements = successful.reduce((best, r) =>
(r.selectiveEnhancements + r.adversarialModifications) > (best.selectiveEnhancements + best.adversarialModifications) ? r : best
);
console.log(` ⚡ Durée moyenne: ${avgDuration.toFixed(0)}ms`);
console.log(` 🏆 Meilleure perf: ${bestPerf.stack} + ${bestPerf.adversarial} (${bestPerf.duration}ms)`);
console.log(` 🔥 Plus d'améliorations: ${mostEnhancements.stack} + ${mostEnhancements.adversarial} (${mostEnhancements.selectiveEnhancements + mostEnhancements.adversarialModifications})`);
}
return results;
}
/**
* INTERFACE LIGNE DE COMMANDE
*/
async function main() {
const args = process.argv.slice(2);
const command = args[0] || 'workflow';
try {
switch (command) {
case 'workflow':
const rowNumber = parseInt(args[1]) || 2;
const selectiveStack = args[2] || 'standardEnhancement';
const adversarialMode = args[3] || 'light';
console.log(`\n🚀 Exécution workflow modulaire:`);
console.log(` 📊 Ligne: ${rowNumber}`);
console.log(` 🔧 Stack selective: ${selectiveStack}`);
console.log(` 🎯 Mode adversarial: ${adversarialMode}`);
const result = await handleModularWorkflow({
rowNumber,
selectiveStack,
adversarialMode
});
console.log('\n✅ WORKFLOW MODULAIRE RÉUSSI');
console.log(`📈 Stats: ${JSON.stringify(result.stats, null, 2)}`);
break;
case 'benchmark':
const benchRowNumber = parseInt(args[1]) || 2;
console.log(`\n⚡ Benchmark stacks (ligne ${benchRowNumber})`);
const benchResults = await benchmarkStacks(benchRowNumber);
console.log('\n📊 Résultats complets:');
console.table(benchResults);
break;
case 'stacks':
console.log('\n📦 STACKS SELECTIVE DISPONIBLES:');
const availableStacks = getAvailableStacks();
availableStacks.forEach(stack => {
console.log(`\n 🔧 ${stack.name}:`);
console.log(` 📝 ${stack.description}`);
console.log(` 📊 ${stack.layersCount} couches`);
console.log(` 🎯 Couches: ${stack.layers ? stack.layers.map(l => `${l.type}(${l.llm})`).join(' → ') : 'N/A'}`);
});
console.log('\n🎯 MODES ADVERSARIAL DISPONIBLES:');
console.log(' - none: Pas d\'adversarial');
console.log(' - light: Défense légère');
console.log(' - standard: Défense standard');
console.log(' - heavy: Défense intensive');
console.log(' - adaptive: Adaptatif intelligent');
break;
case 'help':
default:
console.log('\n🔧 === MAIN MODULAIRE - USAGE ===');
console.log('\nCommandes disponibles:');
console.log(' workflow [ligne] [stack] [adversarial] - Exécuter workflow complet');
console.log(' benchmark [ligne] - Benchmark stacks');
console.log(' stacks - Lister stacks disponibles');
console.log(' help - Afficher cette aide');
console.log('\nExemples:');
console.log(' node main_modulaire.js workflow 2 fullEnhancement standard');
console.log(' node main_modulaire.js workflow 3 adaptive light');
console.log(' node main_modulaire.js benchmark 2');
console.log(' node main_modulaire.js stacks');
break;
}
} catch (error) {
console.error('\n❌ ERREUR MAIN MODULAIRE:', error.message);
console.error(error.stack);
process.exit(1);
}
}
// Export pour usage programmatique
module.exports = {
handleModularWorkflow,
benchmarkStacks
};
// Exécution CLI si appelé directement
if (require.main === module) {
main().catch(error => {
console.error('❌ ERREUR FATALE:', error.message);
process.exit(1);
});
}