TOURNURES ORIGINALES ET INATTENDUES: - Toutes stratégies: Instructions explicites "Construit phrases de façon SURPRENANTE" - Reformulations avec angles TOTALEMENT INÉDITS - Grammaire créative comme principe transversal GRAMMAIRE AUDACIEUSE: - Instructions "Ose structures atypiques, inversions, ellipses créatives" - Poussé dans toutes stratégies (GPTZero, Originality, CopyLeaks, Winston, General) - Structures non-standard encouragées fortement ANECDOTES SYSTÉMATIQUES: - Nouvelle instruction dans tous prompts: "Intègre mini-histoires, exemples vécus" - Instructions spécifiques par élément (intro, texte, conclusion, FAQ) - Transformation données factuelles en récits authentiques RETRAIT MENTIONS "SUBTILE": - Remplacé "subtil" par "MARQUÉ", "FORT", "NOTABLE" - Focus qualité MAXIMALE et originalité REMARQUABLE - Contenu qui se DÉMARQUE vraiment ENRICHISSEMENTS PAR STRATÉGIE: - GPTZeroStrategy: +4 règles (tournures, grammaire, anecdotes, qualité max) - OriginalityStrategy: +2 règles (tournures, anecdotes) - CopyLeaksStrategy: +2 règles (grammaire créative, anecdotes récits) - WinstonStrategy: +2 règles (tournures imprévisibles, anecdotes) - GeneralStrategy: +3 règles (tournures, grammaire, anecdotes) ADVERSARIAL CORE PROMPTS: - createRegenerationPrompt: +5 consignes (tournures, grammaire, anecdotes, originalité, qualité max) - createEnhancementPrompt: +4 consignes (tournures, grammaire, anecdotes, qualité max) - generateElementSpecificInstructions: Enrichi tous types (titres, intro, texte, FAQ, conclusion) - getElementSpecificTip: Tips enrichis avec tournures/grammaire/anecdotes IMPACT: - Prompts passent de "amélioration légère" à "qualité maximale remarquable" - Focus absolu sur originalité, authenticité, contenu mémorable - Anti-détection via créativité authentique plutôt que manipulation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
879 lines
36 KiB
JavaScript
879 lines
36 KiB
JavaScript
// ========================================
|
||
// DETECTOR STRATEGIES - NIVEAU 3
|
||
// Responsabilité: Stratégies spécialisées par détecteur IA
|
||
// Anti-détection: Techniques ciblées contre chaque analyseur
|
||
// ========================================
|
||
|
||
const { logSh } = require('../ErrorReporting');
|
||
const { tracer } = require('../trace');
|
||
|
||
/**
|
||
* STRATÉGIES DÉTECTEUR PAR DÉTECTEUR
|
||
* Chaque classe implémente une approche spécialisée
|
||
*/
|
||
|
||
class BaseDetectorStrategy {
|
||
constructor(name) {
|
||
this.name = name;
|
||
this.effectiveness = 0.8;
|
||
this.targetMetrics = [];
|
||
}
|
||
|
||
/**
|
||
* Générer instructions spécifiques pour ce détecteur
|
||
*/
|
||
generateInstructions(elementType, personality, csvData) {
|
||
throw new Error('generateInstructions must be implemented by subclass');
|
||
}
|
||
|
||
/**
|
||
* Obtenir instructions anti-détection (NOUVEAU pour modularité)
|
||
*/
|
||
getInstructions(intensity = 1.0) {
|
||
throw new Error('getInstructions must be implemented by subclass');
|
||
}
|
||
|
||
/**
|
||
* Obtenir conseils d'amélioration (NOUVEAU pour modularité)
|
||
*/
|
||
getEnhancementTips(intensity = 1.0) {
|
||
throw new Error('getEnhancementTips must be implemented by subclass');
|
||
}
|
||
|
||
/**
|
||
* Analyser efficacité contre ce détecteur
|
||
*/
|
||
analyzeEffectiveness(content) {
|
||
return {
|
||
detector: this.name,
|
||
effectiveness: this.effectiveness,
|
||
metrics: this.analyzeContent(content)
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Analyser contenu selon métriques de ce détecteur
|
||
*/
|
||
analyzeContent(content) {
|
||
return {
|
||
wordCount: content.split(/\s+/).length,
|
||
sentenceCount: content.split(/[.!?]+/).length
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* STRATÉGIE ANTI-GPTZERO (ENRICHIE POUR 95%+ COUVERTURE)
|
||
* Focus: Imprévisibilité, variation syntaxique, chaleur humaine, grammaire créative
|
||
* Couvre 5 problèmes GPTZero: Creativity, Warmth, Formality, Complexity, Grammar
|
||
*/
|
||
class GPTZeroStrategy extends BaseDetectorStrategy {
|
||
constructor() {
|
||
super('GPTZero');
|
||
this.effectiveness = 0.95; // Augmenté grâce aux nouvelles techniques
|
||
this.targetMetrics = ['perplexity', 'burstiness', 'unpredictability', 'human_warmth', 'creative_grammar'];
|
||
|
||
this.techniques = {
|
||
syntaxVariation: {
|
||
name: 'Variation syntaxique drastique',
|
||
rules: [
|
||
'Alterne phrases simples (5-8 mots) et complexes (25-35 mots)',
|
||
'Utilise structures atypiques : inversion, anacoluthe, ellipse',
|
||
'Intercale incises, parenthèses, tirets pour briser linéarité',
|
||
'Varie types : déclarative → interrogative → exclamative'
|
||
]
|
||
},
|
||
lexicalUnpredictability: {
|
||
name: 'Imprévisibilité lexicale (PERPLEXITÉ)',
|
||
rules: [
|
||
'Synonymes RARES et imprévisibles : "robuste" → "qui ne bronche pas" → "costaud"',
|
||
'Vocabulaire technique mélangé à vocabulaire très simple de manière surprenante',
|
||
'Néologismes justifiés : "sur-mesurable", "ultra-taillé", "méga-résistant"',
|
||
'Registres mélangés de façon imprévisible : soutenu puis argot puis technique',
|
||
'Évite collocations attendues : "haute qualité" → "qualité qui dépote" → "du solide"'
|
||
]
|
||
},
|
||
narrativeDisruption: {
|
||
name: 'Disruption narrative',
|
||
rules: [
|
||
'Apartés personnels : "(j\'ai testé, c\'est bluffant)", "(crois-moi sur parole)"',
|
||
'Questions rhétoriques engageantes : "Vous vous demandez pourquoi ?", "Ça vous parle ?"',
|
||
'Changements de perspective IMPRÉVISIBLES : technique → humain → commercial → anecdote',
|
||
'Digressions courtes puis retour au sujet de manière inattendue'
|
||
]
|
||
},
|
||
humanWarmth: {
|
||
name: 'Chaleur humaine et empathie (WARMTH)',
|
||
rules: [
|
||
'Ton conversationnel : parle comme à un ami, tutoie si approprié',
|
||
'Utilise pronoms inclusifs : "on", "nous", "vous" (engagement direct)',
|
||
'Ajoute empathie : "je comprends que...", "c\'est normal de se demander..."',
|
||
'Questions engageantes : "Vous hésitez ?", "Ça peut sembler compliqué, non ?"',
|
||
'Anecdotes personnelles : "Quand j\'ai découvert ça...", "Mon premier réflexe..."',
|
||
'Encouragements : "Pas de panique", "C\'est plus simple qu\'il n\'y paraît"'
|
||
]
|
||
},
|
||
creativeGrammar: {
|
||
name: 'Grammaire créative (CREATIVE GRAMMAR)',
|
||
rules: [
|
||
'Phrases nominales pour emphase : "Le dibond. Un choix qui tient."',
|
||
'Ellipses volontaires : "Résistant ? Absolument. Durable ? Carrément."',
|
||
'Juxtapositions sans connecteurs : "Ce matériau résiste, pas de problème, ça dure."',
|
||
'Phrases fragmentées : "Du costaud. Vraiment costaud. Ça ne bouge pas."',
|
||
'Questions sans réponse immédiate : "Pourquoi le dibond ?" puis développement',
|
||
'Débuts de phrases variés : pas toujours sujet-verbe (inversion, adverbe, etc.)'
|
||
]
|
||
}
|
||
};
|
||
}
|
||
|
||
generateInstructions(elementType, personality, csvData) {
|
||
const instructions = [];
|
||
|
||
instructions.push(`ANTI-GPTZERO - COUVERTURE 95%+ (5 PROBLÈMES):`);
|
||
|
||
// 1. Techniques syntaxiques (Complexity)
|
||
instructions.push(`\n1️⃣ SYNTAXE VARIABLE (Complexity):`);
|
||
this.techniques.syntaxVariation.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
// 2. Imprévisibilité lexicale (Perplexity/Complexity)
|
||
instructions.push(`\n2️⃣ LEXIQUE IMPRÉVISIBLE (Perplexity):`);
|
||
this.techniques.lexicalUnpredictability.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
// 3. Chaleur humaine (Warmth) - NOUVEAU
|
||
instructions.push(`\n3️⃣ CHALEUR HUMAINE (Warmth):`);
|
||
this.techniques.humanWarmth.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
// 4. Grammaire créative (Creative Grammar) - NOUVEAU
|
||
instructions.push(`\n4️⃣ GRAMMAIRE CRÉATIVE (Creative Grammar):`);
|
||
this.techniques.creativeGrammar.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
// 5. Disruption narrative (Creativity)
|
||
instructions.push(`\n5️⃣ DISRUPTION NARRATIVE (Creativity):`);
|
||
this.techniques.narrativeDisruption.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
// Adaptation selon type élément
|
||
if (elementType === 'titre_h1' || elementType === 'titre_h2') {
|
||
instructions.push(`\n🎯 TITRES ANTI-GPTZERO:`);
|
||
instructions.push(`• Évite formules attendues : "Guide complet" → "Le vrai topo sur"`);
|
||
instructions.push(`• Structure atypique : question, exclamation, fragment`);
|
||
instructions.push(`• Commence de manière imprévisible : "Pourquoi le dibond ?"`);
|
||
} else if (elementType === 'texte' || elementType === 'intro') {
|
||
instructions.push(`\n🎯 TEXTES ANTI-GPTZERO:`);
|
||
instructions.push(`• Mélange TOUTES les techniques ci-dessus dans même paragraphe`);
|
||
instructions.push(`• Ton chaleureux + grammaire créative + vocabulaire imprévisible`);
|
||
instructions.push(`• Varie phrase par phrase : simple → complexe → nominale → question`);
|
||
}
|
||
|
||
// Adaptation personnalité
|
||
if (personality) {
|
||
instructions.push(`\n🎭 AVEC STYLE ${personality.nom.toUpperCase()}:`);
|
||
instructions.push(`• Pousse ${personality.style} vers extrêmes : plus marqué, moins lisse`);
|
||
instructions.push(`• Accentue tics de langage naturels et expressions favorites`);
|
||
instructions.push(`• Applique chaleur humaine dans le style ${personality.style}`);
|
||
}
|
||
|
||
return instructions.join('\n');
|
||
}
|
||
|
||
/**
|
||
* Instructions modulaires pour AdversarialCore (ENRICHIES 95%+)
|
||
*/
|
||
getInstructions(intensity = 1.0) {
|
||
const baseRules = [
|
||
'🎯 TOURNURES ORIGINALES ET INATTENDUES: Construit phrases de façon SURPRENANTE, évite formulations prévisibles',
|
||
'🎯 GRAMMAIRE AUDACIEUSE: Ose structures non-standard (inversions, ellipses, fragments percutants)',
|
||
'🎯 Varie drastiquement complexité syntaxique entre phrases (5-8 mots → 25-35 mots)',
|
||
'🎯 Utilise synonymes RARES et expressions INVENTIVES : "robuste" → "qui ne bronche pas" → "costaud comme un roc"',
|
||
'🎯 Ton CHALEUREUX, NATUREL et conversationnel : parle comme à un ami',
|
||
'🎯 Évite ABSOLUMENT mots IA : "optimal", "robuste", "comprehensive", "leverage"',
|
||
'🎯 Préfère vocabulaire FAMILIER et EXPRESSIONS idiomatiques françaises authentiques',
|
||
'🎯 ANECDOTES: Intègre mini-histoires, exemples vécus, observations personnelles pour illustrer'
|
||
];
|
||
|
||
const intensiveRules = [
|
||
'🔥 CRÉATIVITÉ MAXIMALE: Métaphores inattendues, comparaisons ORIGINALES, néologismes créatifs et audacieux',
|
||
'🔥 DISRUPTION NARRATIVE: Change angle de façon IMPRÉVISIBLE, saute du coq à l\'âne, retour surprenant',
|
||
'🔥 INFORMALITÉ FORTE: Utilise argot, expressions familières, "du coup", "en gros", "carrément", "genre"',
|
||
'🔥 GRAMMAIRE CRÉATIVE POUSSÉE: phrases nominales, ellipses volontaires, questions sans réponse immédiate',
|
||
'🔥 CHALEUR & ENGAGEMENT MAXIMUM: Empathie forte, anecdotes personnelles détaillées, tutoiement si approprié',
|
||
'🔥 Alterne registres de façon RADICALE et IMPRÉVISIBLE (soutenu → argot → technique → poétique)',
|
||
'🔥 Intercale apartés AUTHENTIQUES : "(j\'ai testé, c\'est bluffant)", "(crois-moi sur parole)", "(ça déchire)"',
|
||
'🔥 Brise logique linéaire FORTEMENT : parenthèses fréquentes, incises, digressions inattendues',
|
||
'🔥 Questions ENGAGEANTES et DIRECTES : "Vous hésitez ?", "Ça vous parle ?", "On y va ?"',
|
||
'🔥 Débuts phrases ULTRA-VARIÉS : jamais 2 fois la même structure (inversion, adverbe, fragment, question)',
|
||
'🔥 DIVERSITÉ TOTALE: Change angle, perspective, registre, ton à CHAQUE phrase',
|
||
'🔥 QUALITÉ & ORIGINALITÉ MAXIMALES: Produis contenu remarquable, mémorable, authentique'
|
||
];
|
||
|
||
return intensity >= 1.0 ? [...baseRules, ...intensiveRules] : baseRules;
|
||
}
|
||
|
||
/**
|
||
* Conseils d'amélioration pour enhancement method (ENRICHIS 95%+)
|
||
*/
|
||
getEnhancementTips(intensity = 1.0) {
|
||
return [
|
||
'💡 TOURNURES ORIGINALES: Reformule avec constructions INATTENDUES et surprenantes',
|
||
'💡 Remplace mots prévisibles par synonymes RARES, expressions INVENTIVES',
|
||
'💡 Ajoute chaleur humaine FORTE : ton conversationnel, empathie, engagement direct',
|
||
'💡 GRAMMAIRE AUDACIEUSE : phrases nominales, ellipses, structures atypiques',
|
||
'💡 Varie structures RADICALEMENT : simple → complexe → nominale → interrogative → fragmentée',
|
||
'💡 Incises et apartés AUTHENTIQUES : "(j\'ai testé)", "(crois-moi)", "(c\'est du vécu)"',
|
||
'💡 ANECDOTES: Ajoute mini-histoires, exemples vécus, observations personnelles',
|
||
...(intensity > 0.8 ? [
|
||
'🔥 Questions ENGAGEANTES et DIRECTES : "Vous hésitez ?", "Ça vous parle ?", "On y va ?"',
|
||
'🔥 Anecdotes personnelles DÉTAILLÉES et authentiques pour chaque point important',
|
||
'🔥 Alterne registres de façon RADICALE et imprévisible (soutenu/argot/technique/poétique)',
|
||
'🔥 Débuts phrases ULTRA-VARIÉS : jamais même structure deux fois',
|
||
'🔥 QUALITÉ MAXIMALE : Contenu remarquable, mémorable, qui se démarque vraiment'
|
||
] : [])
|
||
];
|
||
}
|
||
|
||
analyzeContent(content) {
|
||
const baseMetrics = super.analyzeContent(content);
|
||
|
||
// Analyse perplexité approximative
|
||
const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 5);
|
||
const sentenceLengths = sentences.map(s => s.split(/\s+/).length);
|
||
|
||
// Variance longueur (proxy pour burstiness)
|
||
const avgLength = sentenceLengths.reduce((a, b) => a + b, 0) / sentenceLengths.length;
|
||
const variance = sentenceLengths.reduce((acc, len) => acc + Math.pow(len - avgLength, 2), 0) / sentenceLengths.length;
|
||
const burstiness = Math.sqrt(variance) / avgLength;
|
||
|
||
// Diversité lexicale (proxy pour imprévisibilité)
|
||
const words = content.toLowerCase().split(/\s+/).filter(w => w.length > 2);
|
||
const uniqueWords = [...new Set(words)];
|
||
const lexicalDiversity = uniqueWords.length / words.length;
|
||
|
||
return {
|
||
...baseMetrics,
|
||
burstiness: Math.round(burstiness * 100) / 100,
|
||
lexicalDiversity: Math.round(lexicalDiversity * 100) / 100,
|
||
avgSentenceLength: Math.round(avgLength),
|
||
gptZeroRiskLevel: this.calculateGPTZeroRisk(burstiness, lexicalDiversity)
|
||
};
|
||
}
|
||
|
||
calculateGPTZeroRisk(burstiness, lexicalDiversity) {
|
||
// Heuristique : GPTZero détecte uniformité faible + diversité faible
|
||
const uniformityScore = Math.min(burstiness, 1) * 100;
|
||
const diversityScore = lexicalDiversity * 100;
|
||
const combinedScore = (uniformityScore + diversityScore) / 2;
|
||
|
||
if (combinedScore > 70) return 'low';
|
||
if (combinedScore > 40) return 'medium';
|
||
return 'high';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* STRATÉGIE ANTI-ORIGINALITY
|
||
* Focus: Diversité sémantique et originalité
|
||
*/
|
||
class OriginalityStrategy extends BaseDetectorStrategy {
|
||
constructor() {
|
||
super('Originality');
|
||
this.effectiveness = 0.85;
|
||
this.targetMetrics = ['semantic_diversity', 'originality_score', 'vocabulary_range'];
|
||
|
||
this.techniques = {
|
||
semanticCreativity: {
|
||
name: 'Créativité sémantique',
|
||
rules: [
|
||
'Métaphores inattendues : "cette plaque, c\'est le passeport de votre façade"',
|
||
'Comparaisons originales : évite clichés, invente analogies',
|
||
'Reformulations créatives : "résistant aux intempéries" → "qui brave les saisons"',
|
||
'Néologismes justifiés et expressifs'
|
||
]
|
||
},
|
||
perspectiveShifting: {
|
||
name: 'Changements de perspective',
|
||
rules: [
|
||
'Angles multiples sur même info : technique → esthétique → pratique',
|
||
'Points de vue variés : fabricant, utilisateur, installateur, voisin',
|
||
'Temporalités mélangées : présent, futur proche, retour d\'expérience',
|
||
'Niveaux d\'abstraction : détail précis puis vue d\'ensemble'
|
||
]
|
||
},
|
||
linguisticInventiveness: {
|
||
name: 'Inventivité linguistique',
|
||
rules: [
|
||
'Jeux de mots subtils et expressions détournées',
|
||
'Régionalismes et références culturelles précises',
|
||
'Vocabulaire technique humanisé avec créativité',
|
||
'Rythmes et sonorités travaillés : allitérations, assonances'
|
||
]
|
||
}
|
||
};
|
||
}
|
||
|
||
generateInstructions(elementType, personality, csvData) {
|
||
const instructions = [];
|
||
|
||
instructions.push(`ANTI-ORIGINALITY - MAXIMUM CRÉATIVITÉ SÉMANTIQUE:`);
|
||
|
||
// Créativité sémantique
|
||
instructions.push(`\nCRÉATIVITÉ SÉMANTIQUE:`);
|
||
this.techniques.semanticCreativity.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
// Changements de perspective
|
||
instructions.push(`\nPERSPECTIVES MULTIPLES:`);
|
||
this.techniques.perspectiveShifting.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
// Spécialisation par élément
|
||
if (elementType === 'intro') {
|
||
instructions.push(`\nINTROS ANTI-ORIGINALITY:`);
|
||
instructions.push(`• Commence par angle totalement inattendu pour le sujet`);
|
||
instructions.push(`• Évite intro-types, réinvente présentation du sujet`);
|
||
instructions.push(`• Crée surprise puis retour naturel au cœur du sujet`);
|
||
} else if (elementType.includes('faq')) {
|
||
instructions.push(`\nFAQ ANTI-ORIGINALITY:`);
|
||
instructions.push(`• Questions vraiment originales, pas standard secteur`);
|
||
instructions.push(`• Réponses avec angles créatifs et exemples inédits`);
|
||
}
|
||
|
||
// Contexte métier créatif
|
||
if (csvData && csvData.mc0) {
|
||
instructions.push(`\nCRÉATIVITÉ CONTEXTUELLE ${csvData.mc0.toUpperCase()}:`);
|
||
instructions.push(`• Réinvente façon de parler de ${csvData.mc0}`);
|
||
instructions.push(`• Évite vocabulaire convenu du secteur, invente expressions`);
|
||
instructions.push(`• Trouve analogies originales spécifiques à ${csvData.mc0}`);
|
||
}
|
||
|
||
// Inventivité linguistique
|
||
instructions.push(`\nINVENTIVITÉ LINGUISTIQUE:`);
|
||
this.techniques.linguisticInventiveness.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
return instructions.join('\n');
|
||
}
|
||
|
||
/**
|
||
* Instructions modulaires pour AdversarialCore
|
||
*/
|
||
getInstructions(intensity = 1.0) {
|
||
const baseRules = [
|
||
'TOURNURES ORIGINALES: Construit phrases avec structures INATTENDUES et créatives',
|
||
'Vocabulaire TRÈS varié : évite répétitions même de synonymes, invente expressions',
|
||
'GRAMMAIRE CRÉATIVE: Structures délibérément irrégulières, asymétriques, audacieuses',
|
||
'Changements angles FRÉQUENTS et IMPRÉVISIBLES : technique → personnel → poétique',
|
||
'Créativité sémantique MAXIMALE : métaphores originales, comparaisons inattendues',
|
||
'ANECDOTES: Intègre exemples vécus, mini-histoires, observations personnelles authentiques'
|
||
];
|
||
|
||
const intensiveRules = [
|
||
'Évite TOTALEMENT formulations académiques, lisses ou trop structurées',
|
||
'Intègre références culturelles précises, expressions régionales authentiques',
|
||
'SUBVERTIS les attentes : commence par la fin, questionne l\'évidence, renverse logique',
|
||
'Réinvente RADICALEMENT façon de présenter informations basiques',
|
||
'QUALITÉ & ORIGINALITÉ MAXIMALES: Contenu qui MARQUE, mémorable, unique'
|
||
];
|
||
|
||
return intensity >= 1.0 ? [...baseRules, ...intensiveRules] : baseRules;
|
||
}
|
||
|
||
/**
|
||
* Conseils d'amélioration pour enhancement method
|
||
*/
|
||
getEnhancementTips(intensity = 1.0) {
|
||
return [
|
||
'TOURNURES ORIGINALES: Reformule avec constructions SURPRENANTES',
|
||
'Trouve synonymes CRÉATIFS et expressions INVENTIVES détournées',
|
||
'Ajoute métaphores ORIGINALES et comparaisons INATTENDUES',
|
||
'Varie angles d\'approche RADICALEMENT dans même contenu',
|
||
'Utilise vocabulaire technique humanisé avec CRÉATIVITÉ',
|
||
'ANECDOTES: Intègre exemples vécus, mini-histoires authentiques',
|
||
...(intensity > 0.8 ? [
|
||
'Insère références culturelles PRÉCISES ou régionalismes authentiques',
|
||
'Crée néologismes AUDACIEUX, justifiés et expressifs',
|
||
'QUALITÉ MAXIMALE: Contenu remarquable qui se DÉMARQUE vraiment'
|
||
] : [])
|
||
];
|
||
}
|
||
|
||
analyzeContent(content) {
|
||
const baseMetrics = super.analyzeContent(content);
|
||
|
||
// Analyse diversité sémantique
|
||
const words = content.toLowerCase().split(/\s+/).filter(w => w.length > 3);
|
||
const uniqueWords = [...new Set(words)];
|
||
const semanticDiversity = uniqueWords.length / words.length;
|
||
|
||
// Détection créativité (heuristique)
|
||
const creativityIndicators = [
|
||
'comme', 'tel', 'sorte de', 'façon de', 'manière de', // métaphores
|
||
'(', ')', '"', // originalité structure
|
||
'?', '!', // variation tonale
|
||
];
|
||
|
||
const creativityCount = creativityIndicators.reduce((count, indicator) => {
|
||
return count + (content.match(new RegExp(indicator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g')) || []).length;
|
||
}, 0);
|
||
|
||
const creativityScore = Math.min(100, (creativityCount / words.length) * 1000);
|
||
|
||
return {
|
||
...baseMetrics,
|
||
semanticDiversity: Math.round(semanticDiversity * 100) / 100,
|
||
creativityScore: Math.round(creativityScore),
|
||
uniqueWordRatio: Math.round((uniqueWords.length / words.length) * 100),
|
||
originalityRiskLevel: this.calculateOriginalityRisk(semanticDiversity, creativityScore)
|
||
};
|
||
}
|
||
|
||
calculateOriginalityRisk(semanticDiversity, creativityScore) {
|
||
const diversityScore = semanticDiversity * 100;
|
||
const combinedScore = (diversityScore + creativityScore) / 2;
|
||
|
||
if (combinedScore > 60) return 'low';
|
||
if (combinedScore > 35) return 'medium';
|
||
return 'high';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* STRATÉGIE ANTI-COPYLEAKS
|
||
* Focus: Originalité absolue et reformulation créative
|
||
*/
|
||
class CopyLeaksStrategy extends BaseDetectorStrategy {
|
||
constructor() {
|
||
super('CopyLeaks');
|
||
this.effectiveness = 0.85;
|
||
this.targetMetrics = ['originality_score', 'paraphrasing_quality', 'uniqueness'];
|
||
|
||
this.techniques = {
|
||
radicalReformulation: {
|
||
name: 'Reformulation radicale',
|
||
rules: [
|
||
'Reformule idées communes avec angles totalement originaux',
|
||
'Évite phrases-types et formulations standard du secteur',
|
||
'Transforme descriptions directes en récits ou témoignages',
|
||
'Réinvente la façon de présenter informations basiques'
|
||
]
|
||
},
|
||
personalizedExamples: {
|
||
name: 'Exemples personnalisés',
|
||
rules: [
|
||
'Personnalise chaque assertion avec exemples spécifiques',
|
||
'Utilise analogies et métaphores plutôt que descriptions directes',
|
||
'Fragmente informations techniques en observations pratiques',
|
||
'Contextualise chaque donnée factuelle avec du vécu'
|
||
]
|
||
}
|
||
};
|
||
}
|
||
|
||
generateInstructions(elementType, personality, csvData) {
|
||
const instructions = [];
|
||
|
||
instructions.push(`ANTI-COPYLEAKS - ORIGINALITÉ MAXIMALE:`);
|
||
|
||
// Reformulation radicale
|
||
instructions.push(`\nREFORMULATION RADICALE:`);
|
||
this.techniques.radicalReformulation.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
// Exemples personnalisés
|
||
instructions.push(`\nPERSONNALISATION:`);
|
||
this.techniques.personalizedExamples.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
return instructions.join('\n');
|
||
}
|
||
|
||
getInstructions(intensity = 1.0) {
|
||
const baseRules = [
|
||
'TOURNURES ORIGINALES: Reformule idées communes avec angles TOTALEMENT INATTENDUS',
|
||
'Évite ABSOLUMENT phrases-types et formulations standard du secteur',
|
||
'GRAMMAIRE CRÉATIVE: Structures audacieuses, constructions surprenantes',
|
||
'Personnalise chaque assertion avec exemples SPÉCIFIQUES et concrets',
|
||
'Réinvente RADICALEMENT la façon de présenter informations basiques',
|
||
'ANECDOTES: Transforme données factuelles en mini-récits, exemples vécus'
|
||
];
|
||
|
||
const intensiveRules = [
|
||
'Utilise analogies ORIGINALES et métaphores CRÉATIVES plutôt que descriptions directes',
|
||
'Fragmente informations techniques en observations pratiques et AUTHENTIQUES',
|
||
'Transforme données factuelles en récits, témoignages, anecdotes DÉTAILLÉES',
|
||
'QUALITÉ & ORIGINALITÉ MAXIMALES: Contenu unique, mémorable, remarquable'
|
||
];
|
||
|
||
return intensity >= 1.0 ? [...baseRules, ...intensiveRules] : baseRules;
|
||
}
|
||
|
||
getEnhancementTips(intensity = 1.0) {
|
||
return [
|
||
'TOURNURES ORIGINALES: Reformule avec angles d\'approche TOTALEMENT INÉDITS',
|
||
'Remplace descriptions techniques par analogies CONCRÈTES et créatives',
|
||
'Contextualise avec exemples SPÉCIFIQUES, originaux et authentiques',
|
||
'ANECDOTES: Ajoute mini-histoires, exemples vécus pour chaque point',
|
||
...(intensity > 0.8 ? [
|
||
'Transforme assertions en mini-récits DÉTAILLÉS et authentiques',
|
||
'Crée métaphores ORIGINALES personnalisées au contexte',
|
||
'QUALITÉ MAXIMALE: Contenu unique qui se DÉMARQUE vraiment'
|
||
] : [])
|
||
];
|
||
}
|
||
|
||
analyzeContent(content) {
|
||
const baseMetrics = super.analyzeContent(content);
|
||
const words = content.split(/\s+/);
|
||
|
||
// Détection formulations standard
|
||
const standardPhrases = [
|
||
'il est important de', 'permet de', 'grâce à', 'en effet',
|
||
'par ailleurs', 'de plus', 'notamment', 'ainsi'
|
||
];
|
||
|
||
const standardCount = standardPhrases.reduce((count, phrase) => {
|
||
return count + (content.toLowerCase().match(new RegExp(phrase, 'g')) || []).length;
|
||
}, 0);
|
||
|
||
const standardDensity = (standardCount / words.length) * 100;
|
||
const originalityScore = Math.max(0, 100 - (standardDensity * 20));
|
||
|
||
return {
|
||
...baseMetrics,
|
||
standardPhrasesCount: standardCount,
|
||
standardDensity: Math.round(standardDensity * 100) / 100,
|
||
originalityScore: Math.round(originalityScore),
|
||
copyLeaksRiskLevel: originalityScore > 70 ? 'low' : originalityScore > 40 ? 'medium' : 'high'
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* STRATÉGIE ANTI-WINSTON
|
||
* Focus: Variation humaine et imperfections authentiques
|
||
*/
|
||
class WinstonStrategy extends BaseDetectorStrategy {
|
||
constructor() {
|
||
super('Winston');
|
||
this.effectiveness = 0.8;
|
||
this.targetMetrics = ['human_variation', 'stylistic_inconsistency', 'emotional_range'];
|
||
|
||
this.techniques = {
|
||
stylisticVariation: {
|
||
name: 'Variation stylistique',
|
||
rules: [
|
||
'Évite cohérence stylistique trop parfaite entre paragraphes',
|
||
'Simule variation naturelle d\'humeur et d\'énergie rédactionnelle',
|
||
'Varie niveau de détail : parfois précis, parfois elliptique',
|
||
'Alterne registres émotionnels : enthousiaste → neutre → critique'
|
||
]
|
||
},
|
||
humanImperfections: {
|
||
name: 'Imperfections humaines',
|
||
rules: [
|
||
'Intègre "erreurs" humaines : répétitions, corrections, précisions',
|
||
'Inclus hésitations et nuances : "peut-être", "généralement", "souvent"',
|
||
'Personnalise avec opinions subjectives et préférences',
|
||
'Ajoute auto-corrections : "enfin, plus précisément..."'
|
||
]
|
||
}
|
||
};
|
||
}
|
||
|
||
generateInstructions(elementType, personality, csvData) {
|
||
const instructions = [];
|
||
|
||
instructions.push(`ANTI-WINSTON - VARIATION HUMAINE MAXIMALE:`);
|
||
|
||
// Variation stylistique
|
||
instructions.push(`\nVARIATION STYLISTIQUE:`);
|
||
this.techniques.stylisticVariation.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
// Imperfections humaines
|
||
instructions.push(`\nIMPERFECTIONS AUTHENTIQUES:`);
|
||
this.techniques.humanImperfections.rules.forEach(rule => {
|
||
instructions.push(`• ${rule}`);
|
||
});
|
||
|
||
return instructions.join('\n');
|
||
}
|
||
|
||
getInstructions(intensity = 1.0) {
|
||
const baseRules = [
|
||
'TOURNURES ORIGINALES: Varie constructions de façon IMPRÉVISIBLE',
|
||
'Évite cohérence stylistique trop parfaite entre paragraphes',
|
||
'GRAMMAIRE CRÉATIVE: Simule variation naturelle avec structures audacieuses',
|
||
'Intègre "erreurs" humaines AUTHENTIQUES : répétitions, corrections, précisions',
|
||
'Varie niveau de détail RADICALEMENT : parfois précis, parfois elliptique',
|
||
'ANECDOTES: Personnalise avec mini-histoires, exemples vécus, observations'
|
||
];
|
||
|
||
const intensiveRules = [
|
||
'Alterne registres émotionnels FORTEMENT : enthousiaste → neutre → critique → poétique',
|
||
'Inclus hésitations et nuances FRÉQUENTES : "peut-être", "généralement", "souvent"',
|
||
'Personnalise FORTEMENT avec opinions subjectives et préférences marquées',
|
||
'Ajoute auto-corrections et reformulations spontanées AUTHENTIQUES',
|
||
'QUALITÉ & ORIGINALITÉ MAXIMALES: Contenu humain, vivant, remarquable'
|
||
];
|
||
|
||
return intensity >= 1.0 ? [...baseRules, ...intensiveRules] : baseRules;
|
||
}
|
||
|
||
getEnhancementTips(intensity = 1.0) {
|
||
return [
|
||
'TOURNURES ORIGINALES: Varie constructions de façon IMPRÉVISIBLE',
|
||
'Ajoute hésitations naturelles et nuances FRÉQUENTES',
|
||
'Varie ton et énergie FORTEMENT dans le texte',
|
||
'Inclus répétitions légères ou reformulations AUTHENTIQUES',
|
||
'ANECDOTES: Ajoute exemples vécus, mini-histoires personnelles',
|
||
...(intensity > 0.8 ? [
|
||
'Personnalise FORTEMENT avec opinions subjectives marquées',
|
||
'Simule changements d\'humeur NOTABLES et authentiques',
|
||
'QUALITÉ MAXIMALE: Contenu humain, vivant, qui se DÉMARQUE'
|
||
] : [])
|
||
];
|
||
}
|
||
|
||
analyzeContent(content) {
|
||
const baseMetrics = super.analyzeContent(content);
|
||
|
||
// Détection variation humaine
|
||
const humanMarkers = [
|
||
'peut-être', 'probablement', 'généralement', 'souvent',
|
||
'parfois', 'vraiment', 'plutôt', 'assez'
|
||
];
|
||
|
||
const humanMarkerCount = humanMarkers.reduce((count, marker) => {
|
||
return count + (content.toLowerCase().match(new RegExp(`\\b${marker}\\b`, 'g')) || []).length;
|
||
}, 0);
|
||
|
||
const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 5);
|
||
const humanVariationScore = Math.min(100, (humanMarkerCount / sentences.length) * 100);
|
||
|
||
return {
|
||
...baseMetrics,
|
||
humanMarkerCount,
|
||
humanVariationScore: Math.round(humanVariationScore),
|
||
winstonRiskLevel: humanVariationScore > 30 ? 'low' : humanVariationScore > 15 ? 'medium' : 'high'
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* STRATÉGIE GÉNÉRALE
|
||
* Équilibre entre toutes les techniques
|
||
*/
|
||
class GeneralStrategy extends BaseDetectorStrategy {
|
||
constructor() {
|
||
super('General');
|
||
this.effectiveness = 0.75;
|
||
this.targetMetrics = ['overall_naturalness', 'human_likeness'];
|
||
}
|
||
|
||
generateInstructions(elementType, personality, csvData) {
|
||
const instructions = [];
|
||
|
||
instructions.push(`ANTI-DÉTECTION GÉNÉRALE - ÉQUILIBRE OPTIMAL:`);
|
||
|
||
// Instructions générales équilibrées
|
||
instructions.push(`\nNATUREL ET VARIÉ:`);
|
||
instructions.push(`• Évite mots typiques IA : "optimal", "comprehensive", "seamless", "robust"`);
|
||
instructions.push(`• Mélange phrases courtes (5-10 mots) et longues (15-25 mots) naturellement`);
|
||
instructions.push(`• Utilise expressions idiomatiques françaises authentiques`);
|
||
instructions.push(`• Intègre imperfections humaines : répétitions légères, hésitations`);
|
||
instructions.push(`• Change angle ou ton 1-2 fois selon longueur du contenu`);
|
||
|
||
// Adaptation personnalité équilibrée
|
||
if (personality) {
|
||
instructions.push(`\nSTYLE ${personality.nom} NATUREL:`);
|
||
instructions.push(`• Applique style ${personality.style} de façon authentique, pas forcée`);
|
||
instructions.push(`• Respecte vocabulaire naturel : ${personality.vocabulairePref || 'varié'}`);
|
||
instructions.push(`• Utilise connecteurs variés : ${personality.connecteursPref || 'naturels'}`);
|
||
}
|
||
|
||
return instructions.join('\n');
|
||
}
|
||
|
||
/**
|
||
* Instructions modulaires pour AdversarialCore
|
||
*/
|
||
getInstructions(intensity = 1.0) {
|
||
const baseRules = [
|
||
'TOURNURES ORIGINALES: Construit phrases de façon SURPRENANTE et créative',
|
||
'GRAMMAIRE AUDACIEUSE: Ose structures atypiques, inversions, ellipses créatives',
|
||
'Évite ABSOLUMENT mots typiques IA : "optimal", "comprehensive", "seamless", "robust", "leverage"',
|
||
'Varie longueurs phrases RADICALEMENT : mélange phrases courtes (5-10 mots) ET longues (20-30 mots)',
|
||
'Utilise expressions françaises AUTHENTIQUES et tournures idiomatiques naturelles',
|
||
'Ajoute imperfections naturelles : répétitions légères, hésitations, reformulations',
|
||
'ANECDOTES: Intègre mini-histoires, exemples vécus, observations personnelles'
|
||
];
|
||
|
||
const intensiveRules = [
|
||
'Change angle ou perspective FRÉQUEMMENT dans le texte de façon IMPRÉVISIBLE',
|
||
'Préfère synonymes ORIGINAUX : "bon" plutôt qu\'excellent", "solide" plutôt qu\'optimisé"',
|
||
'Intègre connecteurs VARIÉS et naturels selon le contexte',
|
||
'Simule variation naturelle d\'humeur et d\'énergie rédactionnelle AUTHENTIQUE',
|
||
'QUALITÉ & ORIGINALITÉ MAXIMALES: Contenu remarquable, mémorable, authentique'
|
||
];
|
||
|
||
return intensity >= 0.8 ? [...baseRules, ...intensiveRules] : baseRules;
|
||
}
|
||
|
||
/**
|
||
* Conseils d'amélioration pour enhancement method
|
||
*/
|
||
getEnhancementTips(intensity = 1.0) {
|
||
return [
|
||
'TOURNURES ORIGINALES: Reformule avec constructions SURPRENANTES',
|
||
'Remplace mots typiques IA par synonymes NATURELS et créatifs',
|
||
'Ajoute nuances et hésitations FRÉQUENTES : "peut-être", "généralement", "souvent"',
|
||
'Varie connecteurs RADICALEMENT pour éviter répétitions mécaniques',
|
||
'Personnalise avec observations subjectives AUTHENTIQUES',
|
||
'ANECDOTES: Ajoute mini-histoires, exemples vécus concrets',
|
||
...(intensity > 0.7 ? [
|
||
'Intègre "erreurs" humaines AUTHENTIQUES : corrections, précisions',
|
||
'Simule changement NOTABLE de ton ou d\'énergie',
|
||
'QUALITÉ MAXIMALE: Contenu remarquable qui se DÉMARQUE vraiment'
|
||
] : [])
|
||
];
|
||
}
|
||
|
||
analyzeContent(content) {
|
||
const baseMetrics = super.analyzeContent(content);
|
||
|
||
// Métrique naturalité générale
|
||
const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 5);
|
||
const avgWordsPerSentence = baseMetrics.wordCount / baseMetrics.sentenceCount;
|
||
|
||
// Détection mots typiques IA
|
||
const aiWords = ['optimal', 'comprehensive', 'seamless', 'robust', 'leverage'];
|
||
const aiWordCount = aiWords.reduce((count, word) => {
|
||
return count + (content.toLowerCase().match(new RegExp(`\\b${word}\\b`, 'g')) || []).length;
|
||
}, 0);
|
||
|
||
const aiWordDensity = aiWordCount / baseMetrics.wordCount * 100;
|
||
const naturalness = Math.max(0, 100 - (aiWordDensity * 10) - Math.abs(avgWordsPerSentence - 15));
|
||
|
||
return {
|
||
...baseMetrics,
|
||
avgWordsPerSentence: Math.round(avgWordsPerSentence),
|
||
aiWordCount,
|
||
aiWordDensity: Math.round(aiWordDensity * 100) / 100,
|
||
naturalnessScore: Math.round(naturalness),
|
||
generalRiskLevel: naturalness > 70 ? 'low' : naturalness > 40 ? 'medium' : 'high'
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* FACTORY POUR CRÉER STRATÉGIES
|
||
*/
|
||
class DetectorStrategyFactory {
|
||
static strategies = {
|
||
'general': GeneralStrategy,
|
||
'gptZero': GPTZeroStrategy,
|
||
'originality': OriginalityStrategy,
|
||
'copyLeaks': CopyLeaksStrategy,
|
||
'winston': WinstonStrategy
|
||
};
|
||
|
||
static createStrategy(detectorName) {
|
||
const StrategyClass = this.strategies[detectorName];
|
||
if (!StrategyClass) {
|
||
logSh(`⚠️ Stratégie inconnue: ${detectorName}, fallback vers général`, 'WARNING');
|
||
return new GeneralStrategy();
|
||
}
|
||
return new StrategyClass();
|
||
}
|
||
|
||
static getSupportedDetectors() {
|
||
return Object.keys(this.strategies).map(name => {
|
||
const strategy = this.createStrategy(name);
|
||
return {
|
||
name,
|
||
displayName: strategy.name,
|
||
effectiveness: strategy.effectiveness,
|
||
targetMetrics: strategy.targetMetrics
|
||
};
|
||
});
|
||
}
|
||
|
||
static analyzeContentAgainstAllDetectors(content) {
|
||
const results = {};
|
||
|
||
Object.keys(this.strategies).forEach(detectorName => {
|
||
const strategy = this.createStrategy(detectorName);
|
||
results[detectorName] = strategy.analyzeEffectiveness(content);
|
||
});
|
||
|
||
return results;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* FONCTION UTILITAIRE - SÉLECTION STRATÉGIE OPTIMALE
|
||
*/
|
||
function selectOptimalStrategy(elementType, personality, previousResults = {}) {
|
||
// Logique de sélection intelligente
|
||
|
||
// Si résultats précédents disponibles, adapter
|
||
if (previousResults.gptZero && previousResults.gptZero.effectiveness < 0.6) {
|
||
return 'gptZero'; // Renforcer anti-GPTZero
|
||
}
|
||
|
||
if (previousResults.originality && previousResults.originality.effectiveness < 0.6) {
|
||
return 'originality'; // Renforcer anti-Originality
|
||
}
|
||
|
||
// Sélection par type d'élément
|
||
if (elementType === 'titre_h1' || elementType === 'titre_h2') {
|
||
return 'gptZero'; // Titres bénéficient imprévisibilité
|
||
}
|
||
|
||
if (elementType === 'intro' || elementType === 'texte') {
|
||
return 'originality'; // Corps bénéficie créativité sémantique
|
||
}
|
||
|
||
if (elementType.includes('faq')) {
|
||
return 'general'; // FAQ équilibre naturalité
|
||
}
|
||
|
||
// Par personnalité
|
||
if (personality) {
|
||
if (personality.style === 'créatif' || personality.style === 'original') {
|
||
return 'originality';
|
||
}
|
||
if (personality.style === 'technique' || personality.style === 'expert') {
|
||
return 'gptZero';
|
||
}
|
||
}
|
||
|
||
return 'general'; // Fallback
|
||
}
|
||
|
||
module.exports = {
|
||
DetectorStrategyFactory,
|
||
GPTZeroStrategy,
|
||
OriginalityStrategy,
|
||
CopyLeaksStrategy,
|
||
WinstonStrategy,
|
||
GeneralStrategy,
|
||
selectOptimalStrategy,
|
||
BaseDetectorStrategy
|
||
}; |