## 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>
279 lines
11 KiB
JavaScript
279 lines
11 KiB
JavaScript
// ========================================
|
|
// SMART TECHNICAL LAYER - Améliorations techniques CIBLÉES
|
|
// Responsabilité: Appliquer UNIQUEMENT les améliorations techniques identifiées par analyse
|
|
// LLM: GPT-4o-mini (précision technique)
|
|
// Architecture: Phase 2 de SelectiveSmartTouch (post-analyse)
|
|
// ========================================
|
|
|
|
const { callLLM } = require('../LLMManager');
|
|
const { logSh } = require('../ErrorReporting');
|
|
const { tracer } = require('../trace');
|
|
|
|
/**
|
|
* SMART TECHNICAL LAYER
|
|
* Applique améliorations techniques précises identifiées par SmartAnalysisLayer
|
|
*/
|
|
class SmartTechnicalLayer {
|
|
constructor() {
|
|
this.name = 'SmartTechnical';
|
|
this.defaultLLM = 'gpt-4o-mini';
|
|
}
|
|
|
|
/**
|
|
* APPLIQUER AMÉLIORATIONS TECHNIQUES CIBLÉES
|
|
* @param {string} content - Contenu original
|
|
* @param {object} analysis - Analyse de SmartAnalysisLayer
|
|
* @param {object} context - Contexte (mc0, personality, intensity)
|
|
* @returns {object} - { content, modifications }
|
|
*/
|
|
async applyTargeted(content, analysis, context = {}) {
|
|
return await tracer.run('SmartTechnical.applyTargeted()', async () => {
|
|
const { mc0, personality, intensity = 1.0, contentContext } = context;
|
|
|
|
// Si aucune amélioration technique nécessaire, skip
|
|
if (!analysis.technical.needed || analysis.improvements.length === 0) {
|
|
logSh(`⏭️ SMART TECHNICAL: Aucune amélioration nécessaire (score: ${analysis.technical.score.toFixed(2)})`, 'DEBUG');
|
|
return {
|
|
content,
|
|
modifications: 0,
|
|
skipped: true,
|
|
reason: 'No technical improvements needed'
|
|
};
|
|
}
|
|
|
|
// === GARDE-FOU 1: Détection contenu déjà trop technique ===
|
|
if (contentContext?.techLevel === 'too_high') {
|
|
logSh(`🛡️ GARDE-FOU: Contenu déjà trop technique (level: ${contentContext.techLevel}), SKIP amélioration`, 'WARN');
|
|
return {
|
|
content,
|
|
modifications: 0,
|
|
skipped: true,
|
|
reason: 'Content already too technical - avoided over-engineering'
|
|
};
|
|
}
|
|
|
|
// === GARDE-FOU 2: Comptage specs techniques existantes ===
|
|
const existingSpecs = (content.match(/\d+\s*(mm|cm|kg|°C|%|watt|lumen|J\/cm²|K⁻¹)/g) || []).length;
|
|
const existingNorms = (content.match(/(ISO|ASTM|EN\s|DIN|norme)/gi) || []).length;
|
|
|
|
if (existingSpecs > 6 || existingNorms > 3) {
|
|
logSh(`🛡️ GARDE-FOU: Trop de specs existantes (${existingSpecs} specs, ${existingNorms} normes), SKIP pour éviter surcharge`, 'WARN');
|
|
return {
|
|
content,
|
|
modifications: 0,
|
|
skipped: true,
|
|
reason: `Specs overload (${existingSpecs} specs, ${existingNorms} norms) - avoided adding more`
|
|
};
|
|
}
|
|
|
|
// === GARDE-FOU 3: Si B2C + niveau high, limiter portée ===
|
|
if (contentContext?.audience === 'B2C' && contentContext.techLevel === 'high') {
|
|
logSh(`🛡️ GARDE-FOU: B2C + niveau technique déjà high, limitation de la portée`, 'INFO');
|
|
// Réduire nombre d'améliorations à appliquer
|
|
analysis.improvements = analysis.improvements.slice(0, 2); // Max 2 améliorations
|
|
}
|
|
|
|
await tracer.annotate({
|
|
smartTechnical: true,
|
|
contentLength: content.length,
|
|
improvementsCount: analysis.improvements.length,
|
|
intensity,
|
|
guardrailsApplied: true,
|
|
existingSpecs,
|
|
existingNorms
|
|
});
|
|
|
|
// ✅ Utiliser LLM fourni dans context, sinon fallback sur defaultLLM
|
|
const llmToUse = context.llmProvider || this.defaultLLM;
|
|
|
|
const startTime = Date.now();
|
|
logSh(`🔧 SMART TECHNICAL: Application de ${analysis.improvements.length} améliorations ciblées avec ${llmToUse}`, 'DEBUG');
|
|
|
|
try {
|
|
const prompt = this.createTargetedPrompt(content, analysis, context);
|
|
|
|
const response = await callLLM(llmToUse, prompt, {
|
|
temperature: 0.4, // Précision technique
|
|
maxTokens: 2500
|
|
}, personality);
|
|
|
|
const improvedContent = this.cleanResponse(response);
|
|
|
|
// Calculer nombre de modifications
|
|
const modifications = this.countModifications(content, improvedContent);
|
|
|
|
const duration = Date.now() - startTime;
|
|
logSh(`✅ SMART TECHNICAL terminé: ${modifications} modifications appliquées (${duration}ms)`, 'DEBUG');
|
|
|
|
await tracer.event('Smart Technical appliqué', {
|
|
duration,
|
|
modifications,
|
|
improvementsRequested: analysis.improvements.length
|
|
});
|
|
|
|
return {
|
|
content: improvedContent,
|
|
modifications,
|
|
duration,
|
|
improvementsApplied: analysis.improvements
|
|
};
|
|
|
|
} catch (error) {
|
|
const duration = Date.now() - startTime;
|
|
logSh(`❌ SMART TECHNICAL ÉCHOUÉ (${duration}ms): ${error.message}`, 'ERROR');
|
|
|
|
return {
|
|
content, // Fallback: contenu original
|
|
modifications: 0,
|
|
error: error.message,
|
|
fallback: true
|
|
};
|
|
}
|
|
}, { contentLength: content.length, analysis });
|
|
}
|
|
|
|
/**
|
|
* CRÉER PROMPT CIBLÉ (instructions précises, exemples génériques)
|
|
*/
|
|
createTargetedPrompt(content, analysis, context) {
|
|
const { mc0, personality, intensity = 1.0, contentContext } = context;
|
|
|
|
// Extraire uniquement les améliorations techniques de la liste globale
|
|
const technicalImprovements = analysis.improvements.filter(imp =>
|
|
imp.toLowerCase().includes('technique') ||
|
|
imp.toLowerCase().includes('données') ||
|
|
imp.toLowerCase().includes('chiffr') ||
|
|
imp.toLowerCase().includes('précision') ||
|
|
imp.toLowerCase().includes('spécif') ||
|
|
analysis.technical.missing.some(missing => imp.includes(missing))
|
|
);
|
|
|
|
// === ADAPTER PROMPT SELON CONTEXTE (B2C vs B2B) ===
|
|
const isB2C = contentContext?.audience === 'B2C';
|
|
const isTechnicalContent = contentContext?.contentType === 'technical';
|
|
|
|
let technicalGuidelines = '';
|
|
if (isB2C && !isTechnicalContent) {
|
|
technicalGuidelines = `
|
|
⚠️ CONTEXTE: Contenu B2C grand public - SIMPLICITÉ MAXIMALE
|
|
- Ajoute UNIQUEMENT 2-3 spécifications SIMPLES et UTILES pour un client
|
|
- ÉVITE absolument: normes ISO/ASTM/EN, coefficients techniques, jargon industriel
|
|
- PRIVILÉGIE: dimensions pratiques, matériaux compréhensibles, bénéfices concrets
|
|
- INTERDICTION: termes comme "coefficient", "résistance à la corrosion", "norme", "conformité"
|
|
- MAX 1-2 données chiffrées pertinentes (ex: taille, poids, durée)`;
|
|
} else if (isTechnicalContent) {
|
|
technicalGuidelines = `
|
|
📋 CONTEXTE: Contenu technique - Précision acceptable
|
|
- Ajoute spécifications techniques précises si nécessaire
|
|
- Normes et standards acceptables si pertinents
|
|
- Garde équilibre entre précision et lisibilité`;
|
|
} else {
|
|
technicalGuidelines = `
|
|
🎯 CONTEXTE: Contenu standard - Équilibre
|
|
- Ajoute 2-4 spécifications pertinentes
|
|
- Évite jargon technique excessif
|
|
- Privilégie clarté et accessibilité`;
|
|
}
|
|
|
|
return `MISSION: Améliore UNIQUEMENT les aspects techniques PRÉCIS listés ci-dessous.
|
|
|
|
CONTENU ORIGINAL:
|
|
"${content}"
|
|
|
|
${mc0 ? `CONTEXTE SUJET: ${mc0}` : ''}
|
|
${personality ? `PERSONNALITÉ: ${personality.nom} (${personality.style})` : ''}
|
|
INTENSITÉ: ${intensity.toFixed(1)} (0.5=léger, 1.0=standard, 1.5=intensif)
|
|
${technicalGuidelines}
|
|
|
|
AMÉLIORATIONS TECHNIQUES À APPLIQUER:
|
|
${technicalImprovements.map((imp, i) => `${i + 1}. ${imp}`).join('\n')}
|
|
|
|
${analysis.technical.missing.length > 0 ? `
|
|
ÉLÉMENTS MANQUANTS IDENTIFIÉS:
|
|
${analysis.technical.missing.map((item, i) => `- ${item}`).join('\n')}
|
|
` : ''}
|
|
|
|
CONSIGNES STRICTES:
|
|
- Applique UNIQUEMENT les améliorations listées ci-dessus
|
|
- NE CHANGE PAS le ton, style ou structure générale
|
|
- NE TOUCHE PAS aux aspects non mentionnés
|
|
- Garde la même longueur approximative (±20%)
|
|
- Intègre les éléments manquants de façon NATURELLE
|
|
- ${isB2C ? 'PRIORITÉ ABSOLUE: Reste SIMPLE et ACCESSIBLE' : 'Reste ACCESSIBLE - pas de jargon excessif'}
|
|
|
|
EXEMPLES D'AMÉLIORATION TECHNIQUE (génériques):
|
|
${isB2C ? `
|
|
- ✅ BON (B2C): "Dimensions: 30x20cm, épaisseur 3mm" → clair et utile
|
|
- ❌ MAUVAIS (B2C): "Dimensions: 30x20cm, épaisseur 3mm, résistance 1,5 J/cm² (norme EN 12354-2)" → trop technique
|
|
- ✅ BON (B2C): "Délai de livraison: 3-5 jours" → simple
|
|
- ❌ MAUVAIS (B2C): "Conformité ISO 9001, délai d'expédition optimisé selon norme" → jargon inutile` : `
|
|
- ✅ BON: "Dimensions: 30x20cm, épaisseur 3mm" → données concrètes
|
|
- ❌ MAUVAIS: "Produit de qualité aux dimensions optimales" → vague
|
|
- ✅ BON: "Délai de livraison: 3-5 jours ouvrés" → précis
|
|
- ❌ MAUVAIS: "Livraison rapide" → imprécis`}
|
|
- ✅ BON: "Compatible avec 95% des systèmes" → chiffre concret
|
|
- ❌ MAUVAIS: "Très compatible" → vague
|
|
|
|
RÈGLES VOCABULAIRE TECHNIQUE:
|
|
- Privilégie clarté sur technicité excessive
|
|
- ${isB2C ? 'MAX 1-2 détails techniques SIMPLES' : '1-2 détails techniques pertinents par paragraphe MAX'}
|
|
- Évite le jargon pompeux inutile
|
|
- Vocabulaire accessible ${isB2C ? 'au GRAND PUBLIC' : 'à un public large'}
|
|
|
|
FORMAT RÉPONSE:
|
|
Retourne UNIQUEMENT le contenu amélioré, SANS balises, SANS métadonnées, SANS explications.`;
|
|
}
|
|
|
|
/**
|
|
* NETTOYER RÉPONSE LLM
|
|
*/
|
|
cleanResponse(response) {
|
|
if (!response) return response;
|
|
|
|
let cleaned = response.trim();
|
|
|
|
// Supprimer balises et préfixes indésirables
|
|
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 AMÉLIORÉ:\s*/gi, '');
|
|
cleaned = cleaned.replace(/^(voici\s+)?le\s+contenu\s+amélioré\s*[:.]?\s*/gi, '');
|
|
cleaned = cleaned.replace(/^(avec\s+)?amélioration[s]?\s+technique[s]?\s*[:.]?\s*/gi, '');
|
|
|
|
// Nettoyer formatage markdown
|
|
cleaned = cleaned.replace(/\*\*([^*]+)\*\*/g, '$1'); // **texte** → texte
|
|
cleaned = cleaned.replace(/\s{2,}/g, ' '); // Espaces multiples
|
|
cleaned = cleaned.trim();
|
|
|
|
return cleaned;
|
|
}
|
|
|
|
/**
|
|
* COMPTER MODIFICATIONS (comparaison contenu original vs amélioré)
|
|
*/
|
|
countModifications(original, improved) {
|
|
if (original === improved) return 0;
|
|
|
|
// Méthode simple: compter mots différents
|
|
const originalWords = original.toLowerCase().split(/\s+/);
|
|
const improvedWords = improved.toLowerCase().split(/\s+/);
|
|
|
|
let differences = 0;
|
|
|
|
// Compter ajouts/suppressions
|
|
differences += Math.abs(originalWords.length - improvedWords.length);
|
|
|
|
// Compter modifications (mots communs)
|
|
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 = { SmartTechnicalLayer };
|