// ======================================== // ÉTAPE 2: ENHANCEMENT TECHNIQUE ADVERSARIAL // Responsabilité: Améliorer la précision technique avec GPT-4 + anti-détection // LLM: GPT-4o-mini (température 0.4) + Prompts adversariaux // ======================================== const { callLLM } = require('../LLMManager'); const { logSh } = require('../ErrorReporting'); const { tracer } = require('../trace'); const { createAdversarialPrompt } = require('./AdversarialPromptEngine'); const { DetectorStrategyManager } = require('./DetectorStrategies'); /** * MAIN ENTRY POINT - ENHANCEMENT TECHNIQUE ADVERSARIAL * Input: { content: {}, csvData: {}, context: {}, adversarialConfig: {} } * Output: { content: {}, stats: {}, debug: {} } */ async function enhanceTechnicalTermsAdversarial(input) { return await tracer.run('AdversarialTechnicalEnhancement.enhanceTechnicalTermsAdversarial()', async () => { const { content, csvData, context = {}, adversarialConfig = {} } = input; // Configuration adversariale par défaut const config = { detectorTarget: adversarialConfig.detectorTarget || 'general', intensity: adversarialConfig.intensity || 1.0, enableAdaptiveStrategy: adversarialConfig.enableAdaptiveStrategy || true, contextualMode: adversarialConfig.contextualMode !== false, ...adversarialConfig }; // Initialiser manager détecteur const detectorManager = new DetectorStrategyManager(config.detectorTarget); await tracer.annotate({ step: '2/4', llmProvider: 'gpt4', elementsCount: Object.keys(content).length, mc0: csvData.mc0 }); const startTime = Date.now(); logSh(`🎯 ÉTAPE 2/4 ADVERSARIAL: Enhancement technique (GPT-4 + ${config.detectorTarget})`, 'INFO'); logSh(` 📊 ${Object.keys(content).length} éléments à analyser`, 'INFO'); try { // 1. Analyser tous les éléments pour détecter termes techniques (adversarial) const technicalAnalysis = await analyzeTechnicalTermsAdversarial(content, csvData, config, detectorManager); // 2. Filter les éléments qui ont besoin d'enhancement const elementsNeedingEnhancement = technicalAnalysis.filter(item => item.needsEnhancement); logSh(` 📋 Analyse: ${elementsNeedingEnhancement.length}/${Object.keys(content).length} éléments nécessitent enhancement`, 'INFO'); if (elementsNeedingEnhancement.length === 0) { logSh(`✅ ÉTAPE 2/4: Aucun enhancement nécessaire`, 'INFO'); return { content, stats: { processed: Object.keys(content).length, enhanced: 0, duration: Date.now() - startTime }, debug: { llmProvider: 'gpt4', step: 2, enhancementsApplied: [] } }; } // 3. Améliorer les éléments sélectionnés avec prompts adversariaux const enhancedResults = await enhanceSelectedElementsAdversarial(elementsNeedingEnhancement, csvData, config, detectorManager); // 4. Merger avec contenu original const finalContent = { ...content }; let actuallyEnhanced = 0; Object.keys(enhancedResults).forEach(tag => { if (enhancedResults[tag] !== content[tag]) { finalContent[tag] = enhancedResults[tag]; actuallyEnhanced++; } }); const duration = Date.now() - startTime; const stats = { processed: Object.keys(content).length, enhanced: actuallyEnhanced, candidate: elementsNeedingEnhancement.length, duration }; logSh(`✅ ÉTAPE 2/4 TERMINÉE: ${stats.enhanced} éléments améliorés (${duration}ms)`, 'INFO'); await tracer.event(`Enhancement technique terminé`, stats); return { content: finalContent, stats, debug: { llmProvider: 'gpt4', step: 2, enhancementsApplied: Object.keys(enhancedResults), technicalTermsFound: elementsNeedingEnhancement.map(e => e.technicalTerms), adversarialConfig: config, detectorTarget: config.detectorTarget, intensity: config.intensity } }; } catch (error) { const duration = Date.now() - startTime; logSh(`❌ ÉTAPE 2/4 ÉCHOUÉE après ${duration}ms: ${error.message}`, 'ERROR'); throw new Error(`TechnicalEnhancement failed: ${error.message}`); } }, input); } /** * Analyser tous les éléments pour détecter termes techniques (adversarial) */ async function analyzeTechnicalTermsAdversarial(content, csvData, adversarialConfig, detectorManager) { logSh(`🎯 Analyse termes techniques adversarial batch`, 'DEBUG'); const contentEntries = Object.keys(content); const analysisPrompt = `MISSION: Analyser ces ${contentEntries.length} contenus et identifier leurs termes techniques. CONTEXTE: ${csvData.mc0} - Secteur: signalétique/impression CONTENUS À ANALYSER: ${contentEntries.map((tag, i) => `[${i + 1}] TAG: ${tag} CONTENU: "${content[tag]}"`).join('\n\n')} CONSIGNES: - Identifie UNIQUEMENT les vrais termes techniques métier/industrie - Évite mots génériques (qualité, service, pratique, personnalisé) - Focus: matériaux, procédés, normes, dimensions, technologies - Si aucun terme technique → "AUCUN" EXEMPLES VALIDES: dibond, impression UV, fraisage CNC, épaisseur 3mm EXEMPLES INVALIDES: durable, pratique, personnalisé, moderne FORMAT RÉPONSE: [1] dibond, impression UV OU AUCUN [2] AUCUN [3] aluminium, fraisage CNC OU AUCUN etc...`; try { // Générer prompt adversarial pour analyse const adversarialAnalysisPrompt = createAdversarialPrompt(analysisPrompt, { detectorTarget: adversarialConfig.detectorTarget, intensity: adversarialConfig.intensity * 0.8, // Intensité modérée pour analyse elementType: 'technical_analysis', personality: csvData.personality, contextualMode: adversarialConfig.contextualMode, csvData: csvData, debugMode: false }); const analysisResponse = await callLLM('gpt4', adversarialAnalysisPrompt, { temperature: 0.3, maxTokens: 2000 }, csvData.personality); return parseAnalysisResponse(analysisResponse, content, contentEntries); } catch (error) { logSh(`❌ Analyse termes techniques échouée: ${error.message}`, 'ERROR'); throw error; } } /** * Améliorer les éléments sélectionnés avec prompts adversariaux */ async function enhanceSelectedElementsAdversarial(elementsNeedingEnhancement, csvData, adversarialConfig, detectorManager) { logSh(`🎯 Enhancement adversarial ${elementsNeedingEnhancement.length} éléments`, 'DEBUG'); const enhancementPrompt = `MISSION: Améliore UNIQUEMENT la précision technique de ces contenus. CONTEXTE: ${csvData.mc0} - Secteur signalétique/impression PERSONNALITÉ: ${csvData.personality?.nom} (${csvData.personality?.style}) CONTENUS À AMÉLIORER: ${elementsNeedingEnhancement.map((item, i) => `[${i + 1}] TAG: ${item.tag} CONTENU: "${item.content}" TERMES TECHNIQUES: ${item.technicalTerms.join(', ')}`).join('\n\n')} CONSIGNES: - GARDE même longueur, structure et ton ${csvData.personality?.style} - Intègre naturellement les termes techniques listés - NE CHANGE PAS le fond du message - Vocabulaire expert mais accessible - Termes secteur: dibond, aluminium, impression UV, fraisage, PMMA FORMAT RÉPONSE: [1] Contenu avec amélioration technique [2] Contenu avec amélioration technique etc...`; try { // Générer prompt adversarial pour enhancement const adversarialEnhancementPrompt = createAdversarialPrompt(enhancementPrompt, { detectorTarget: adversarialConfig.detectorTarget, intensity: adversarialConfig.intensity, elementType: 'technical_enhancement', personality: csvData.personality, contextualMode: adversarialConfig.contextualMode, csvData: csvData, debugMode: false }); const enhancedResponse = await callLLM('gpt4', adversarialEnhancementPrompt, { temperature: 0.4, maxTokens: 5000 }, csvData.personality); return parseEnhancementResponse(enhancedResponse, elementsNeedingEnhancement); } catch (error) { logSh(`❌ Enhancement éléments échoué: ${error.message}`, 'ERROR'); throw error; } } /** * Parser réponse analyse */ function parseAnalysisResponse(response, content, contentEntries) { const results = []; const regex = /\[(\d+)\]\s*([^[]*?)(?=\[\d+\]|$)/gs; let match; const parsedItems = {}; while ((match = regex.exec(response)) !== null) { const index = parseInt(match[1]) - 1; const termsText = match[2].trim(); parsedItems[index] = termsText; } contentEntries.forEach((tag, index) => { const termsText = parsedItems[index] || 'AUCUN'; const hasTerms = !termsText.toUpperCase().includes('AUCUN'); const technicalTerms = hasTerms ? termsText.split(',').map(t => t.trim()).filter(t => t.length > 0) : []; results.push({ tag, content: content[tag], technicalTerms, needsEnhancement: hasTerms && technicalTerms.length > 0 }); logSh(`🔍 [${tag}]: ${hasTerms ? technicalTerms.join(', ') : 'aucun terme technique'}`, 'DEBUG'); }); return results; } /** * Parser réponse enhancement */ function parseEnhancementResponse(response, elementsNeedingEnhancement) { const results = {}; const regex = /\[(\d+)\]\s*([^[]*?)(?=\[\d+\]|$)/gs; let match; let index = 0; while ((match = regex.exec(response)) && index < elementsNeedingEnhancement.length) { let enhancedContent = match[2].trim(); const element = elementsNeedingEnhancement[index]; // Nettoyer le contenu généré enhancedContent = cleanEnhancedContent(enhancedContent); if (enhancedContent && enhancedContent.length > 10) { results[element.tag] = enhancedContent; logSh(`✅ Enhanced [${element.tag}]: "${enhancedContent.substring(0, 100)}..."`, 'DEBUG'); } else { results[element.tag] = element.content; logSh(`⚠️ Fallback [${element.tag}]: contenu invalide`, 'WARNING'); } index++; } // Compléter les manquants while (index < elementsNeedingEnhancement.length) { const element = elementsNeedingEnhancement[index]; results[element.tag] = element.content; index++; } return results; } /** * Nettoyer contenu amélioré */ function cleanEnhancedContent(content) { if (!content) return content; // Supprimer préfixes indésirables content = content.replace(/^(Bon,?\s*)?(alors,?\s*)?pour\s+/gi, ''); content = content.replace(/\*\*[^*]+\*\*/g, ''); content = content.replace(/\s{2,}/g, ' '); content = content.trim(); return content; } module.exports = { enhanceTechnicalTermsAdversarial, // ← MAIN ENTRY POINT ADVERSARIAL analyzeTechnicalTermsAdversarial, enhanceSelectedElementsAdversarial, parseAnalysisResponse, parseEnhancementResponse };