seo-generator-server/lib/adversarial-generation/DetectorStrategies.js
StillHammer 6335a16f99 feat(adversarial): Tournures originales + grammaire audacieuse + anecdotes - Qualité maximale
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>
2025-10-16 20:56:23 +08:00

879 lines
36 KiB
JavaScript
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.

// ========================================
// 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
};