## SelectiveSmartTouch (NEW) - Architecture révolutionnaire: Analyse intelligente → Améliorations ciblées précises - 5 modules: SmartAnalysisLayer, SmartTechnicalLayer, SmartStyleLayer, SmartReadabilityLayer, SmartTouchCore - Système 10% segments: amélioration uniquement des segments les plus faibles (intensity-based) - Détection contexte globale pour prompts adaptatifs multi-secteurs - Intégration complète dans PipelineExecutor et PipelineDefinition ## Pipeline Validator Spec (NEW) - Spécification complète système validation qualité par LLM - 5 critères universels: Qualité, Verbosité, SEO, Répétitions, Naturalité - Échantillonnage intelligent par filtrage balises (pas XML) - Évaluation multi-versions avec justifications détaillées - Coût estimé: ~$1/validation (260 appels LLM) ## Optimizations - Réduction intensités fullEnhancement (technical 1.0→0.7, style 0.8→0.5) - Ajout gardes-fous anti-familiarité excessive dans StyleLayer - Sauvegarde étapes intermédiaires activée par défaut (pipeline-runner) ## Fixes - Fix typo critique SmartTouchCore.js:110 (determineLayers ToApply → determineLayersToApply) - Prompts généralisés multi-secteurs (e-commerce, SaaS, services, informatif) 🚀 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
211 lines
7.0 KiB
JavaScript
211 lines
7.0 KiB
JavaScript
// ========================================
|
|
// SMART READABILITY LAYER - Améliorations lisibilité CIBLÉES
|
|
// Responsabilité: Appliquer UNIQUEMENT les améliorations lisibilité identifiées par analyse
|
|
// LLM: GPT-4o-mini (clarté et structure)
|
|
// Architecture: Phase 2 de SelectiveSmartTouch (post-analyse)
|
|
// ========================================
|
|
|
|
const { callLLM } = require('../LLMManager');
|
|
const { logSh } = require('../ErrorReporting');
|
|
const { tracer } = require('../trace');
|
|
|
|
/**
|
|
* SMART READABILITY LAYER
|
|
* Applique améliorations lisibilité précises identifiées par SmartAnalysisLayer
|
|
*/
|
|
class SmartReadabilityLayer {
|
|
constructor() {
|
|
this.name = 'SmartReadability';
|
|
this.defaultLLM = 'gpt-4o-mini';
|
|
}
|
|
|
|
/**
|
|
* APPLIQUER AMÉLIORATIONS LISIBILITÉ CIBLÉES
|
|
*/
|
|
async applyTargeted(content, analysis, context = {}) {
|
|
return await tracer.run('SmartReadability.applyTargeted()', async () => {
|
|
const { mc0, personality, intensity = 1.0 } = context;
|
|
|
|
// Si aucune amélioration lisibilité nécessaire, skip
|
|
if (!analysis.readability.needed) {
|
|
logSh(`⏭️ SMART READABILITY: Aucune amélioration nécessaire (score: ${analysis.readability.score.toFixed(2)})`, 'DEBUG');
|
|
return {
|
|
content,
|
|
modifications: 0,
|
|
skipped: true,
|
|
reason: 'No readability improvements needed'
|
|
};
|
|
}
|
|
|
|
await tracer.annotate({
|
|
smartReadability: true,
|
|
contentLength: content.length,
|
|
intensity
|
|
});
|
|
|
|
// ✅ Utiliser LLM fourni dans context, sinon fallback sur defaultLLM
|
|
const llmToUse = context.llmProvider || this.defaultLLM;
|
|
|
|
const startTime = Date.now();
|
|
logSh(`📖 SMART READABILITY: Application améliorations lisibilité ciblées avec ${llmToUse}`, 'DEBUG');
|
|
|
|
try {
|
|
const prompt = this.createTargetedPrompt(content, analysis, context);
|
|
|
|
const response = await callLLM(llmToUse, prompt, {
|
|
temperature: 0.4, // Précision pour structure
|
|
maxTokens: 2500
|
|
}, personality);
|
|
|
|
const improvedContent = this.cleanResponse(response);
|
|
const modifications = this.countModifications(content, improvedContent);
|
|
|
|
const duration = Date.now() - startTime;
|
|
logSh(`✅ SMART READABILITY terminé: ${modifications} modifications appliquées (${duration}ms)`, 'DEBUG');
|
|
|
|
await tracer.event('Smart Readability appliqué', {
|
|
duration,
|
|
modifications
|
|
});
|
|
|
|
return {
|
|
content: improvedContent,
|
|
modifications,
|
|
duration
|
|
};
|
|
|
|
} catch (error) {
|
|
const duration = Date.now() - startTime;
|
|
logSh(`❌ SMART READABILITY ÉCHOUÉ (${duration}ms): ${error.message}`, 'ERROR');
|
|
|
|
return {
|
|
content,
|
|
modifications: 0,
|
|
error: error.message,
|
|
fallback: true
|
|
};
|
|
}
|
|
}, { contentLength: content.length, analysis });
|
|
}
|
|
|
|
/**
|
|
* CRÉER PROMPT CIBLÉ
|
|
*/
|
|
createTargetedPrompt(content, analysis, context) {
|
|
const { mc0, personality, intensity = 1.0 } = context;
|
|
|
|
// Extraire améliorations lisibilité
|
|
const readabilityImprovements = analysis.improvements.filter(imp =>
|
|
imp.toLowerCase().includes('lisib') ||
|
|
imp.toLowerCase().includes('phrase') ||
|
|
imp.toLowerCase().includes('connecteur') ||
|
|
imp.toLowerCase().includes('structure') ||
|
|
imp.toLowerCase().includes('fluidité')
|
|
);
|
|
|
|
return `MISSION: Améliore UNIQUEMENT la lisibilité selon les points listés.
|
|
|
|
CONTENU ORIGINAL:
|
|
"${content}"
|
|
|
|
${mc0 ? `CONTEXTE: ${mc0}` : ''}
|
|
INTENSITÉ: ${intensity.toFixed(1)}
|
|
|
|
AMÉLIORATIONS LISIBILITÉ À APPLIQUER:
|
|
${readabilityImprovements.map((imp, i) => `${i + 1}. ${imp}`).join('\n')}
|
|
|
|
${analysis.readability.complexSentences && analysis.readability.complexSentences.length > 0 ? `
|
|
PHRASES TROP COMPLEXES (à simplifier):
|
|
${analysis.readability.complexSentences.map(line => `- Ligne ${line}`).join('\n')}
|
|
` : ''}
|
|
|
|
${analysis.readability.repetitiveConnectors && analysis.readability.repetitiveConnectors.length > 0 ? `
|
|
CONNECTEURS RÉPÉTITIFS (à varier):
|
|
${analysis.readability.repetitiveConnectors.map(conn => `- "${conn}"`).join('\n')}
|
|
` : ''}
|
|
|
|
CONSIGNES STRICTES:
|
|
- Applique UNIQUEMENT les améliorations lisibilité listées
|
|
- NE CHANGE PAS le sens, ton ou style général
|
|
- GARDE le même contenu informatif
|
|
- Phrases: 15-25 mots idéalement (simplifier si > 30 mots)
|
|
- Connecteurs: variés et naturels
|
|
- Structure: fluide et logique
|
|
|
|
TECHNIQUES LISIBILITÉ:
|
|
|
|
**Simplifier phrases longues:**
|
|
- ✅ AVANT: "Ce produit, qui a été conçu par nos experts après plusieurs années de recherche, permet d'obtenir des résultats exceptionnels."
|
|
- ✅ APRÈS: "Ce produit a été conçu par nos experts après plusieurs années de recherche. Il permet d'obtenir des résultats exceptionnels."
|
|
|
|
**Varier connecteurs:**
|
|
- ✅ AVANT: "Par ailleurs... Par ailleurs... Par ailleurs..."
|
|
- ✅ APRÈS: "Par ailleurs... De plus... En outre..."
|
|
|
|
**Fluidifier structure:**
|
|
- ✅ AVANT: "Produit X. Produit Y. Produit Z." (juxtaposition sèche)
|
|
- ✅ APRÈS: "Produit X offre... Quant au produit Y, il propose... Enfin, produit Z permet..."
|
|
|
|
**Clarifier relations:**
|
|
- ✅ AVANT: "Ce service existe. Il est pratique." (lien flou)
|
|
- ✅ APRÈS: "Ce service existe. Grâce à lui, vous gagnez du temps." (lien clair)
|
|
|
|
RÈGLES LISIBILITÉ:
|
|
- Privilégie clarté immédiate
|
|
- Évite subordonnées multiples imbriquées
|
|
- Structure logique: contexte → explication → bénéfice
|
|
- Connecteurs variés: évite répétitions sur 3 phrases consécutives
|
|
|
|
FORMAT RÉPONSE:
|
|
Retourne UNIQUEMENT le contenu fluidifié, SANS balises, SANS métadonnées, SANS explications.`;
|
|
}
|
|
|
|
/**
|
|
* NETTOYER RÉPONSE
|
|
*/
|
|
cleanResponse(response) {
|
|
if (!response) return response;
|
|
|
|
let cleaned = response.trim();
|
|
|
|
// Supprimer balises
|
|
cleaned = cleaned.replace(/^TAG:\s*[^\s]+\s+/gi, '');
|
|
cleaned = cleaned.replace(/\bTAG:\s*[^\s]+\s+/gi, '');
|
|
cleaned = cleaned.replace(/^CONTENU:\s*/gi, '');
|
|
cleaned = cleaned.replace(/^CONTENU FLUIDIFIÉ:\s*/gi, '');
|
|
cleaned = cleaned.replace(/^(voici\s+)?le\s+contenu\s+(fluidifié|lisible)\s*[:.]?\s*/gi, '');
|
|
cleaned = cleaned.replace(/^(avec\s+)?amélioration[s]?\s+lisibilité\s*[:.]?\s*/gi, '');
|
|
|
|
// Nettoyer formatage
|
|
cleaned = cleaned.replace(/\*\*([^*]+)\*\*/g, '$1');
|
|
cleaned = cleaned.replace(/\s{2,}/g, ' ');
|
|
cleaned = cleaned.trim();
|
|
|
|
return cleaned;
|
|
}
|
|
|
|
/**
|
|
* COMPTER MODIFICATIONS
|
|
*/
|
|
countModifications(original, improved) {
|
|
if (original === improved) return 0;
|
|
|
|
const originalWords = original.toLowerCase().split(/\s+/);
|
|
const improvedWords = improved.toLowerCase().split(/\s+/);
|
|
|
|
let differences = 0;
|
|
differences += Math.abs(originalWords.length - improvedWords.length);
|
|
|
|
const minLength = Math.min(originalWords.length, improvedWords.length);
|
|
for (let i = 0; i < minLength; i++) {
|
|
if (originalWords[i] !== improvedWords[i]) {
|
|
differences++;
|
|
}
|
|
}
|
|
|
|
return differences;
|
|
}
|
|
}
|
|
|
|
module.exports = { SmartReadabilityLayer };
|