// ======================================== // FICHIER: PatternBreakingCore.js // RESPONSABILITÉ: Orchestrateur principal Pattern Breaking // Niveau 2: Casser les patterns syntaxiques typiques des LLMs // ======================================== const { logSh } = require('../ErrorReporting'); const { tracer } = require('../trace'); const { varyStructures, splitLongSentences, mergeShorter } = require('./SyntaxVariations'); const { replaceLLMFingerprints, detectLLMPatterns } = require('./LLMFingerprints'); const { humanizeTransitions, replaceConnectors } = require('./NaturalConnectors'); /** * CONFIGURATION PAR DÉFAUT PATTERN BREAKING */ const DEFAULT_CONFIG = { syntaxVariationEnabled: true, llmFingerprintReplacement: true, naturalConnectorsEnabled: true, intensityLevel: 0.5, // Intensité globale (0-1) preserveReadability: true, // Maintenir lisibilité maxModificationsPerElement: 4, // Limite modifications par élément qualityThreshold: 0.6 // Seuil qualité minimum }; /** * ORCHESTRATEUR PRINCIPAL - Pattern Breaking Layer * @param {object} content - Contenu généré à traiter * @param {object} options - Options de pattern breaking * @returns {object} - { content, stats, fallback } */ async function applyPatternBreakingLayer(content, options = {}) { return await tracer.run('PatternBreakingCore.applyPatternBreakingLayer()', async () => { const startTime = Date.now(); await tracer.annotate({ contentKeys: Object.keys(content).length, intensityLevel: options.intensityLevel, personality: options.csvData?.personality?.nom }); logSh(`🔧 PATTERN BREAKING - Début traitement`, 'INFO'); logSh(` 📊 ${Object.keys(content).length} éléments | Intensité: ${options.intensityLevel || DEFAULT_CONFIG.intensityLevel}`, 'DEBUG'); try { // Configuration fusionnée const config = { ...DEFAULT_CONFIG, ...options }; // Stats de pattern breaking const patternStats = { elementsProcessed: 0, syntaxModifications: 0, llmFingerprintReplacements: 0, connectorReplacements: 0, totalModifications: 0, fallbackUsed: false, patternsDetected: 0 }; // Contenu traité let processedContent = { ...content }; // ======================================== // TRAITEMENT PAR ÉLÉMENT // ======================================== for (const [elementKey, elementContent] of Object.entries(content)) { await tracer.run(`PatternBreaking.processElement(${elementKey})`, async () => { logSh(` 🎯 Traitement élément: ${elementKey}`, 'DEBUG'); let currentContent = elementContent; let elementModifications = 0; try { // 1. Détection patterns LLM const detectedPatterns = detectLLMPatterns(currentContent); patternStats.patternsDetected += detectedPatterns.count; if (detectedPatterns.count > 0) { logSh(` 🔍 ${detectedPatterns.count} patterns LLM détectés: ${detectedPatterns.patterns.slice(0, 3).join(', ')}`, 'DEBUG'); } // 2. Variation syntaxique if (config.syntaxVariationEnabled) { const syntaxResult = await applySyntaxVariation(currentContent, config); currentContent = syntaxResult.content; elementModifications += syntaxResult.modifications; patternStats.syntaxModifications += syntaxResult.modifications; logSh(` 📝 Syntaxe: ${syntaxResult.modifications} variations appliquées`, 'DEBUG'); } // 3. Remplacement fingerprints LLM if (config.llmFingerprintReplacement && detectedPatterns.count > 0) { const fingerprintResult = await applyLLMFingerprints(currentContent, config); currentContent = fingerprintResult.content; elementModifications += fingerprintResult.modifications; patternStats.llmFingerprintReplacements += fingerprintResult.modifications; logSh(` 🤖 LLM Fingerprints: ${fingerprintResult.modifications} remplacements`, 'DEBUG'); } // 4. Connecteurs naturels if (config.naturalConnectorsEnabled) { const connectorResult = await applyNaturalConnectors(currentContent, config); currentContent = connectorResult.content; elementModifications += connectorResult.modifications; patternStats.connectorReplacements += connectorResult.modifications; logSh(` 🔗 Connecteurs: ${connectorResult.modifications} humanisés`, 'DEBUG'); } // 5. Validation qualité const qualityCheck = validatePatternBreakingQuality(elementContent, currentContent, config.qualityThreshold); if (qualityCheck.acceptable) { processedContent[elementKey] = currentContent; patternStats.elementsProcessed++; patternStats.totalModifications += elementModifications; logSh(` ✅ Élément traité: ${elementModifications} modifications totales`, 'DEBUG'); } else { // Fallback: garder contenu original processedContent[elementKey] = elementContent; patternStats.fallbackUsed = true; logSh(` ⚠️ Qualité insuffisante, fallback vers contenu original`, 'WARNING'); } } catch (elementError) { logSh(` ❌ Erreur pattern breaking élément ${elementKey}: ${elementError.message}`, 'WARNING'); processedContent[elementKey] = elementContent; // Fallback patternStats.fallbackUsed = true; } }, { elementKey, originalLength: elementContent?.length }); } // ======================================== // RÉSULTATS FINAUX // ======================================== const duration = Date.now() - startTime; const success = patternStats.elementsProcessed > 0 && !patternStats.fallbackUsed; logSh(`🔧 PATTERN BREAKING - Terminé (${duration}ms)`, 'INFO'); logSh(` ✅ ${patternStats.elementsProcessed}/${Object.keys(content).length} éléments traités`, 'INFO'); logSh(` 📊 ${patternStats.syntaxModifications} syntaxe | ${patternStats.llmFingerprintReplacements} fingerprints | ${patternStats.connectorReplacements} connecteurs`, 'INFO'); logSh(` 🎯 Patterns détectés: ${patternStats.patternsDetected} | Fallback: ${patternStats.fallbackUsed ? 'OUI' : 'NON'}`, 'INFO'); await tracer.event('Pattern Breaking terminé', { success, duration, stats: patternStats }); return { content: processedContent, stats: patternStats, fallback: patternStats.fallbackUsed, duration }; } catch (error) { const duration = Date.now() - startTime; logSh(`❌ PATTERN BREAKING ÉCHOUÉ (${duration}ms): ${error.message}`, 'ERROR'); await tracer.event('Pattern Breaking échoué', { error: error.message, duration, contentKeys: Object.keys(content).length }); // Fallback complet return { content, stats: { fallbackUsed: true, error: error.message }, fallback: true, duration }; } }, { contentElements: Object.keys(content).length, intensityLevel: options.intensityLevel }); } /** * APPLICATION VARIATION SYNTAXIQUE */ async function applySyntaxVariation(content, config) { const syntaxResult = varyStructures(content, config.intensityLevel, { preserveReadability: config.preserveReadability, maxModifications: Math.floor(config.maxModificationsPerElement / 2) }); return { content: syntaxResult.content, modifications: syntaxResult.modifications || 0 }; } /** * APPLICATION REMPLACEMENT LLM FINGERPRINTS */ async function applyLLMFingerprints(content, config) { const fingerprintResult = replaceLLMFingerprints(content, { intensity: config.intensityLevel, preserveContext: true, maxReplacements: Math.floor(config.maxModificationsPerElement / 2) }); return { content: fingerprintResult.content, modifications: fingerprintResult.replacements || 0 }; } /** * APPLICATION CONNECTEURS NATURELS */ async function applyNaturalConnectors(content, config) { const connectorResult = humanizeTransitions(content, { intensity: config.intensityLevel, preserveMeaning: true, maxReplacements: Math.floor(config.maxModificationsPerElement / 2) }); return { content: connectorResult.content, modifications: connectorResult.replacements || 0 }; } /** * VALIDATION QUALITÉ PATTERN BREAKING */ function validatePatternBreakingQuality(originalContent, processedContent, qualityThreshold) { if (!originalContent || !processedContent) { return { acceptable: false, reason: 'Contenu manquant' }; } // Métriques de base const lengthDiff = Math.abs(processedContent.length - originalContent.length) / originalContent.length; const wordCountOriginal = originalContent.split(/\s+/).length; const wordCountProcessed = processedContent.split(/\s+/).length; const wordCountDiff = Math.abs(wordCountProcessed - wordCountOriginal) / wordCountOriginal; // Vérifications qualité const checks = { lengthPreserved: lengthDiff < 0.3, // Pas plus de 30% de différence wordCountPreserved: wordCountDiff < 0.2, // Pas plus de 20% de différence noEmpty: processedContent.trim().length > 0, // Pas de contenu vide readableStructure: processedContent.includes('.') // Structure lisible }; const passedChecks = Object.values(checks).filter(Boolean).length; const score = passedChecks / Object.keys(checks).length; const acceptable = score >= qualityThreshold; logSh(` 🎯 Validation Pattern Breaking: ${acceptable ? 'ACCEPTÉ' : 'REJETÉ'} (score: ${score.toFixed(2)})`, acceptable ? 'DEBUG' : 'WARNING'); return { acceptable, score, checks, reason: acceptable ? 'Qualité acceptable' : 'Score qualité insuffisant' }; } // ============= EXPORTS ============= module.exports = { applyPatternBreakingLayer, applySyntaxVariation, applyLLMFingerprints, applyNaturalConnectors, validatePatternBreakingQuality, DEFAULT_CONFIG };