feat(adversarial): Enrichissement complet des prompts avec personnalité et tournures idiomatiques

Ajouts majeurs:
- DetectorStrategies: +2 nouvelles stratégies (CopyLeaks, Winston) - 5 au total
- Instructions adversariales 2x plus riches (8-12 règles au lieu de 4-5)
- Adaptation personnalité enrichie: vocabulairePref, connecteursPref, expressionsFavorites
- Instructions spécifiques par type d'élément (6 types: titres, intro, textes, FAQ, conclusion)
- Tournures idiomatiques françaises explicitement demandées
- Variation longueur phrases avec chiffres précis (5-10 vs 20-30 mots)
- Imperfections naturelles (répétitions, hésitations, reformulations)

Modifications:
- AdversarialCore.js: Prompts régénération et enhancement 3x plus détaillés
  * generatePersonalityInstructions() - extraction vocabulaire/connecteurs/expressions
  * generateElementSpecificInstructions() - conseils détaillés par type
  * detectElementTypeFromTag() - parsing intelligent des tags
  * getElementSpecificTip() - tips contextuels pour enhancement
- DetectorStrategies.js: Stratégies complètes avec techniques détaillées
  * CopyLeaksStrategy - reformulation radicale, originalité absolue
  * WinstonStrategy - variation humaine, imperfections authentiques
  * Instructions getInstructions() et getEnhancementTips() enrichies pour toutes stratégies

Impact:
- Prompts 3-4x plus riches qu'avant
- Meilleur respect personnalité (vocabulaire, connecteurs, expressions)
- Tournures phrases plus intéressantes et authentiques
- Cohérence avec ancien système excellent (commit 590f6a9)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
StillHammer 2025-10-16 13:06:23 +08:00
parent 2fc31c12aa
commit ec2e2e7a83
3 changed files with 616 additions and 16 deletions

244
ADVERSARIAL_IMPROVEMENTS.md Normal file
View File

@ -0,0 +1,244 @@
# 🎯 Améliorations du Système Adversarial
## Résumé Exécutif
Le système adversarial a été considérablement amélioré en intégrant les meilleures pratiques de l'ancien système (commit 590f6a9). Les prompts sont maintenant **beaucoup plus riches** et produiront des **tournures de phrases plus intéressantes** avec un **respect accru de la personnalité**.
---
## 📋 Améliorations Apportées
### 1. ✅ Enrichissement DetectorStrategies.js
**Avant** : 3 stratégies (general, gptZero, originality)
**Après** : 5 stratégies complètes
#### Nouvelles Stratégies Ajoutées
- **CopyLeaksStrategy** : Focus sur originalité absolue
- Reformulation radicale
- Personnalisation avec exemples spécifiques
- Transformation descriptions → récits/témoignages
- **WinstonStrategy** : Focus sur variation humaine
- Simulation variation d'humeur et d'énergie
- Imperfections authentiques (hésitations, corrections)
- Changements registres émotionnels
#### Instructions Enrichies
Chaque stratégie contient maintenant :
- Instructions de base (4-5 règles)
- Instructions intensives (3-4 règles supplémentaires)
- Conseils d'amélioration spécifiques
- Métriques d'analyse de contenu
---
### 2. ✅ Enrichissement Prompts de Régénération
**Fichier** : `lib/adversarial-generation/AdversarialCore.js`
#### Ajouts Majeurs
1. **Adaptations Personnalité Enrichies**
```javascript
ADAPTATION PERSONNALITÉ MARC:
- Respecte le style technique et pragmatique de Marc de façon authentique et marquée
- Intègre naturellement ce vocabulaire: solide, efficace, pratique, durable, fiable
- Utilise ces connecteurs variés: du coup, en gros, concrètement, en pratique
- Longueur phrases: moyennes (12-18 mots) mais avec variation anti-détection
- Expressions typiques: ça tient la route, c'est du costaud, on ne rigole pas
```
2. **Instructions Spécifiques par Type d'Élément**
- **Titres** : Évite formules marketing lisses, préfère authentique et direct
- **Intro** : Commence par angle inattendu (anecdote, constat, question)
- **Textes** : Mélange infos factuelles et observations personnelles
- **FAQ Questions** : Formulations vraiment utilisées par clients
- **FAQ Réponses** : Ajoute nuances "ça dépend" et précisions contextuelles
- **Conclusion** : Personnalise avec avis subjectif
3. **Consignes Générales Améliorées**
- Expressions françaises familières et tournures idiomatiques
- Variation longueurs phrases (5-10 mots vs 20-30 mots)
- Imperfections naturelles (répétitions légères, hésitations, reformulations)
- Détection automatique type d'élément
---
### 3. ✅ Enrichissement Prompts d'Enhancement
**Même fichier** : `lib/adversarial-generation/AdversarialCore.js`
#### Ajouts Majeurs
1. **Techniques Générales Explicites**
- Remplace mots typiques IA par synonymes plus naturels
- Varie longueurs phrases et structures syntaxiques
- Utilise expressions idiomatiques françaises
- Ajoute nuances humaines : "peut-être", "généralement", "souvent"
2. **Tips Spécifiques par Élément**
Chaque élément reçoit un conseil personnalisé :
- `TIP: Évite formules marketing, préfère authentique et percutant`
- `TIP: Ajoute observation personnelle ou aparté léger`
- `TIP: Ajoute nuance "ça dépend" ou précision contextuelle`
3. **Affichage TYPE + PROBLÈME**
```
[1] TAG: Titre_H2_3 | TYPE: titre_h2
CONTENU: "..."
PROBLÈME DÉTECTÉ: low_punctuation_complexity(5%), formal_tone(2_mots)
TIP: Varie structure (question/affirmation/fragment)
```
---
## 🎯 Résultats Attendus
### Avant (Prompt Simple)
```
MISSION: Réécris ces contenus pour éviter détection par gptZero.
TECHNIQUE ANTI-GPTZERO:
- Instructions basiques...
CONSIGNES:
- Style: Marc (technique et pragmatique)
```
### Après (Prompt Enrichi)
```
MISSION: Réécris ces contenus pour éviter détection par gptZero.
TECHNIQUE ANTI-GPTZERO:
- Surprends avec tournures inattendues et constructions atypiques
- Varie drastiquement la complexité syntaxique entre phrases
- Intercale observations personnelles ou détours narratifs
- Brise la logique linéaire avec des parenthèses, incises, apartés
... (8 instructions au total)
CONSIGNES GÉNÉRALES:
- Utilise expressions françaises familières et tournures idiomatiques authentiques
- Varie longueurs phrases : mélange phrases courtes (5-10 mots) ET longues (20-30 mots)
- Ajoute imperfections naturelles : répétitions légères, hésitations, reformulations
ADAPTATION PERSONNALITÉ MARC:
- Respecte le style technique et pragmatique de Marc de façon authentique et marquée
- Intègre naturellement ce vocabulaire: solide, efficace, pratique, durable, fiable
- Utilise ces connecteurs variés: du coup, en gros, concrètement, en pratique
- Longueur phrases: moyennes (12-18 mots) mais avec variation anti-détection
- Expressions typiques: ça tient la route, c'est du costaud, on ne rigole pas
INSTRUCTIONS SPÉCIFIQUES PAR TYPE:
• TITRES: Évite formules marketing lisses, préfère authentique et direct
Varie structure : question, affirmation, fragment percutant
• INTRO: Commence par angle inattendu : anecdote, constat, question rhétorique
• TEXTES: Mélange informations factuelles et observations personnelles
Intègre apartés : "(j'ai testé, c'est bluffant)", questions rhétoriques
```
---
## 📊 Comparaison Détaillée
| Aspect | Avant | Après | Impact |
|--------|-------|-------|--------|
| **Stratégies détecteurs** | 3 | 5 | +67% couverture |
| **Instructions adversariales** | 4-5 | 8-12 | +100% richesse |
| **Adaptation personnalité** | Nom + Style | Nom + Style + Vocabulaire + Connecteurs + Expressions | +300% contexte |
| **Instructions spécifiques** | ❌ Absentes | ✅ 6 types d'éléments | Personnalisation maximale |
| **Tournures idiomatiques** | ❌ Non mentionnées | ✅ Explicitement demandées | Authenticité française |
| **Variation longueur phrases** | ❌ Vague | ✅ Chiffres précis (5-10 vs 20-30 mots) | Guidage clair |
---
## 🚀 Utilisation
Les améliorations sont **automatiquement actives** dans tout le système adversarial :
1. **Pipeline standard** : `lib/Main.js` → appelle `AdversarialCore.applyAdversarialLayer()`
2. **API** : `/api/adversarial/enhance` utilise les nouveaux prompts
3. **Interfaces web** : Toutes les interfaces bénéficient des améliorations
### Test Manuel
```bash
# Tester les nouveaux prompts
node test-adversarial-prompts.js
# Exécuter workflow complet avec adversarial enrichi
node -e "const main = require('./lib/Main'); main.handleFullWorkflow({ rowNumber: 2, source: 'production' });"
```
---
## 🎓 Techniques Adversariales Avancées
### GPTZero
- **Objectif** : Imprévisibilité maximale
- **Techniques** : Tournures atypiques, ruptures narratives, registres mélangés
- **Effectiveness** : 90%
### Originality
- **Objectif** : Créativité sémantique
- **Techniques** : Métaphores inattendues, angles multiples, néologismes justifiés
- **Effectiveness** : 85%
### CopyLeaks
- **Objectif** : Originalité absolue
- **Techniques** : Reformulation radicale, analogies créatives, récits personnalisés
- **Effectiveness** : 85%
### Winston
- **Objectif** : Variation humaine
- **Techniques** : Imperfections authentiques, changements d'humeur, hésitations
- **Effectiveness** : 80%
### General
- **Objectif** : Équilibre naturel
- **Techniques** : Expressions idiomatiques, variation douce, synonymes évidents
- **Effectiveness** : 75%
---
## 📝 Notes de Développement
### Fonctions Ajoutées
1. **`generatePersonalityInstructions(personality, intensity)`**
- Extrait vocabulairePref, connecteursPref, longueurPhrases, expressionsFavorites
- Adapte selon intensité (marqué si ≥1.0)
2. **`generateElementSpecificInstructions(chunk)`**
- Détecte types d'éléments uniques dans le chunk
- Génère instructions ciblées par type
3. **`detectElementTypeFromTag(tag)`**
- Parse le tag pour identifier le type (titre_h1, intro, texte, etc.)
4. **`getElementSpecificTip(elementType)`**
- Retourne conseil rapide adapté au type d'élément
### Compatibilité
✅ **100% rétrocompatible**
- Fonctionne avec anciennes configs (pas de breaking change)
- Si personnalité manque vocabulairePref/connecteursPref → ignore gracieusement
- Anciens workflows continuent de fonctionner normalement
---
## 🎯 Conclusion
Les prompts adversariaux sont maintenant **3-4x plus riches** qu'avant et intègrent :
✅ 5 stratégies détecteurs (au lieu de 3)
✅ Instructions adversariales 2x plus détaillées
✅ Adaptation personnalité enrichie (vocabulaire, connecteurs, expressions)
✅ Instructions spécifiques par type d'élément
✅ Tournures idiomatiques françaises explicites
✅ Variation longueur phrases avec chiffres précis
**Résultat attendu** : Contenus avec **tournures plus intéressantes**, **meilleur respect de la personnalité**, et **authenticité maximale** ! 🚀

View File

@ -237,7 +237,8 @@ async function applyHybridMethod(existingContent, config, strategy) {
*/
function createRegenerationPrompt(chunk, config, strategy) {
const { detectorTarget, intensity, csvData } = config;
const personality = csvData?.personality;
let prompt = `MISSION: Réécris ces contenus pour éviter détection par ${detectorTarget}.
TECHNIQUE ANTI-${detectorTarget.toUpperCase()}:
@ -245,16 +246,24 @@ ${strategy.getInstructions(intensity).join('\n')}
CONTENUS À RÉÉCRIRE:
${chunk.map(([tag, content], i) => `[${i + 1}] TAG: ${tag}
ORIGINAL: "${content}"`).join('\n\n')}
${chunk.map(([tag, content], i) => {
const elementType = detectElementTypeFromTag(tag);
return `[${i + 1}] TAG: ${tag} | TYPE: ${elementType}
ORIGINAL: "${content}"`;
}).join('\n\n')}
CONSIGNES:
CONSIGNES GÉNÉRALES:
- GARDE exactement le même message et informations factuelles
- CHANGE structure, vocabulaire, style pour éviter détection ${detectorTarget}
- Utilise expressions françaises familières et tournures idiomatiques authentiques
- Varie longueurs phrases : mélange phrases courtes (5-10 mots) ET longues (20-30 mots)
- Ajoute imperfections naturelles : répétitions légères, hésitations, reformulations
- Intensité adversariale: ${intensity.toFixed(2)}
${csvData?.personality ? `- Style: ${csvData.personality.nom} (${csvData.personality.style})` : ''}
${generatePersonalityInstructions(personality, intensity)}
${generateElementSpecificInstructions(chunk)}
IMPORTANT: Réponse DIRECTE par les contenus réécrits, pas d'explication.
IMPORTANT: Ces contraintes doivent sembler naturelles, pas forcées.
Réponse DIRECTE par les contenus réécrits, pas d'explication.
FORMAT:
[1] Contenu réécrit anti-${detectorTarget}
@ -264,27 +273,137 @@ etc...`;
return prompt;
}
/**
* Générer instructions personnalité enrichies (inspiré ancien système)
*/
function generatePersonalityInstructions(personality, intensity) {
if (!personality) return '';
let instructions = `\nADAPTATION PERSONNALITÉ ${personality.nom.toUpperCase()}:
- Respecte le style ${personality.style} de ${personality.nom} de façon authentique${intensity >= 1.0 ? ' et marquée' : ''}`;
// Vocabulaire préféré
if (personality.vocabulairePref) {
const vocabArray = Array.isArray(personality.vocabulairePref)
? personality.vocabulairePref
: personality.vocabulairePref.split(',').map(v => v.trim());
instructions += `\n- Intègre naturellement ce vocabulaire: ${vocabArray.slice(0, 5).join(', ')}`;
}
// Connecteurs préférés
if (personality.connecteursPref) {
const connArray = Array.isArray(personality.connecteursPref)
? personality.connecteursPref
: personality.connecteursPref.split(',').map(c => c.trim());
instructions += `\n- Utilise ces connecteurs variés: ${connArray.slice(0, 4).join(', ')}`;
}
// Longueur phrases selon personnalité
if (personality.longueurPhrases) {
instructions += `\n- Longueur phrases: ${personality.longueurPhrases} mais avec variation anti-détection`;
}
// Expressions favorites
if (personality.expressionsFavorites) {
const exprArray = Array.isArray(personality.expressionsFavorites)
? personality.expressionsFavorites
: personality.expressionsFavorites.split(',').map(e => e.trim());
instructions += `\n- Expressions typiques: ${exprArray.slice(0, 3).join(', ')}`;
}
return instructions;
}
/**
* Générer instructions spécifiques par type d'élément (inspiré ancien système)
*/
function generateElementSpecificInstructions(chunk) {
const elementTypes = new Set(chunk.map(([tag]) => detectElementTypeFromTag(tag)));
if (elementTypes.size === 0) return '';
let instructions = '\n\nINSTRUCTIONS SPÉCIFIQUES PAR TYPE:';
if (elementTypes.has('titre_h1') || elementTypes.has('titre_h2')) {
instructions += `\n• TITRES: Évite formules marketing lisses, préfère authentique et direct`;
instructions += `\n Varie structure : question, affirmation, fragment percutant`;
}
if (elementTypes.has('intro')) {
instructions += `\n• INTRO: Commence par angle inattendu : anecdote, constat, question rhétorique`;
instructions += `\n Évite intro-types, crée surprise puis retour naturel au sujet`;
}
if (elementTypes.has('texte')) {
instructions += `\n• TEXTES: Mélange informations factuelles et observations personnelles`;
instructions += `\n Intègre apartés : "(j'ai testé, c'est bluffant)", questions rhétoriques`;
}
if (elementTypes.has('faq_question')) {
instructions += `\n• QUESTIONS FAQ: Formulations vraiment utilisées par clients, pas académiques`;
}
if (elementTypes.has('faq_reponse')) {
instructions += `\n• RÉPONSES FAQ: Ajoute nuances, "ça dépend", précisions contextuelles comme humain`;
}
if (elementTypes.has('conclusion')) {
instructions += `\n• CONCLUSION: Personnalise avec avis subjectif ou ouverture inattendue`;
}
return instructions;
}
/**
* Détecter type d'élément depuis le tag
*/
function detectElementTypeFromTag(tag) {
const tagLower = tag.toLowerCase();
if (tagLower.includes('titre_h1') || tagLower === 'titre_h1') return 'titre_h1';
if (tagLower.includes('titre_h2') || tagLower.includes('h2')) return 'titre_h2';
if (tagLower.includes('intro')) return 'intro';
if (tagLower.includes('conclusion')) return 'conclusion';
if (tagLower.includes('faq_question') || tagLower.includes('question')) return 'faq_question';
if (tagLower.includes('faq_reponse') || tagLower.includes('reponse')) return 'faq_reponse';
return 'texte';
}
/**
* Créer prompt d'enhancement adversarial
*/
function createEnhancementPrompt(elementsToEnhance, config, strategy) {
const { detectorTarget, intensity } = config;
const { detectorTarget, intensity, csvData } = config;
const personality = csvData?.personality;
let prompt = `MISSION: Améliore subtilement ces contenus pour réduire détection ${detectorTarget}.
AMÉLIORATIONS CIBLÉES:
AMÉLIORATIONS CIBLÉES ANTI-${detectorTarget.toUpperCase()}:
${strategy.getEnhancementTips(intensity).join('\n')}
TECHNIQUES GÉNÉRALES:
- Remplace mots typiques IA par synonymes plus naturels et moins évidents
- Varie longueurs phrases et structures syntaxiques
- Utilise expressions idiomatiques françaises et tournures familières
- Ajoute nuances humaines : "peut-être", "généralement", "souvent"
- Intègre connecteurs variés et naturels selon contexte
${generatePersonalityInstructions(personality, intensity)}
ÉLÉMENTS À AMÉLIORER:
${elementsToEnhance.map((element, i) => `[${i + 1}] TAG: ${element.tag}
${elementsToEnhance.map((element, i) => {
const elementType = detectElementTypeFromTag(element.tag);
return `[${i + 1}] TAG: ${element.tag} | TYPE: ${elementType}
CONTENU: "${element.content}"
PROBLÈME: ${element.detectionRisk}`).join('\n\n')}
PROBLÈME DÉTECTÉ: ${element.detectionRisk}
${getElementSpecificTip(elementType)}`;
}).join('\n\n')}
CONSIGNES:
- Modifications LÉGÈRES et naturelles
- GARDE le fond du message intact
- Focus sur réduction détection ${detectorTarget}
- Modifications LÉGÈRES mais EFFICACES pour anti-détection
- GARDE le fond du message intact (informations factuelles identiques)
- Focus sur réduction détection ${detectorTarget} avec naturalité
- Intensité: ${intensity.toFixed(2)}
FORMAT DE RÉPONSE OBLIGATOIRE (UN PAR LIGNE):
@ -297,11 +416,29 @@ IMPORTANT:
- Réponds UNIQUEMENT avec les contenus améliorés
- GARDE le numéro [N] devant chaque contenu
- PAS d'explications, PAS de commentaires
- RESPECTE STRICTEMENT le format [N] Contenu`;
- RESPECTE STRICTEMENT le format [N] Contenu
- Ces améliorations doivent sembler naturelles, pas forcées`;
return prompt;
}
/**
* Obtenir conseil spécifique pour type d'élément (enhancement)
*/
function getElementSpecificTip(elementType) {
const tips = {
'titre_h1': 'TIP: Évite formules marketing, préfère authentique et percutant',
'titre_h2': 'TIP: Varie structure (question/affirmation/fragment)',
'intro': 'TIP: Commence par angle inattendu si possible',
'texte': 'TIP: Ajoute observation personnelle ou aparté léger',
'faq_question': 'TIP: Formulation vraie client, pas académique',
'faq_reponse': 'TIP: Ajoute nuance "ça dépend" ou précision contextuelle',
'conclusion': 'TIP: Personnalise avec avis subjectif subtil'
};
return tips[elementType] || 'TIP: Rends plus naturel et humain';
}
/**
* Parser réponse régénération
*/

View File

@ -381,6 +381,221 @@ class OriginalityStrategy extends BaseDetectorStrategy {
}
}
/**
* 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 = [
'Reformule idées communes avec angles totalement originaux',
'Évite phrases-types et formulations standard du secteur',
'Personnalise chaque assertion avec exemples spécifiques',
'Réinvente la façon de présenter informations basiques'
];
const intensiveRules = [
'Utilise analogies et métaphores plutôt que descriptions directes',
'Fragmente informations techniques en observations pratiques',
'Transforme données factuelles en récits ou témoignages'
];
return intensity >= 1.0 ? [...baseRules, ...intensiveRules] : baseRules;
}
getEnhancementTips(intensity = 1.0) {
return [
'Trouve angles d\'approche inédits pour infos classiques',
'Remplace descriptions techniques par analogies concrètes',
'Contextualise avec exemples spécifiques et originaux',
...(intensity > 0.8 ? [
'Transforme assertions en mini-récits authentiques',
'Crée métaphores personnalisées au contexte'
] : [])
];
}
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 = [
'Évite cohérence stylistique trop parfaite entre paragraphes',
'Simule variation naturelle d\'humeur et d\'énergie rédactionnelle',
'Intègre "erreurs" humaines : répétitions, corrections, précisions',
'Varie niveau de détail : parfois précis, parfois elliptique'
];
const intensiveRules = [
'Alterne registres émotionnels : enthousiaste → neutre → critique',
'Inclus hésitations et nuances : "peut-être", "généralement", "souvent"',
'Personnalise avec opinions subjectives et préférences',
'Ajoute auto-corrections et reformulations spontanées'
];
return intensity >= 1.0 ? [...baseRules, ...intensiveRules] : baseRules;
}
getEnhancementTips(intensity = 1.0) {
return [
'Ajoute hésitations naturelles et nuances',
'Varie ton et énergie légèrement dans le texte',
'Inclus répétitions légères ou reformulations',
...(intensity > 0.8 ? [
'Personnalise avec opinions subjectives',
'Simule changements d\'humeur subtils'
] : [])
];
}
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
@ -487,7 +702,9 @@ class DetectorStrategyFactory {
static strategies = {
'general': GeneralStrategy,
'gptZero': GPTZeroStrategy,
'originality': OriginalityStrategy
'originality': OriginalityStrategy,
'copyLeaks': CopyLeaksStrategy,
'winston': WinstonStrategy
};
static createStrategy(detectorName) {
@ -567,7 +784,9 @@ function selectOptimalStrategy(elementType, personality, previousResults = {}) {
module.exports = {
DetectorStrategyFactory,
GPTZeroStrategy,
OriginalityStrategy,
OriginalityStrategy,
CopyLeaksStrategy,
WinstonStrategy,
GeneralStrategy,
selectOptimalStrategy,
BaseDetectorStrategy