UNPKG

smart-thinking-mcp

Version:

Un serveur MCP avancé pour le raisonnement multi-dimensionnel, adaptatif et collaboratif

871 lines 44.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.VerificationService = void 0; const math_evaluator_1 = require("../utils/math-evaluator"); const config_1 = require("../config"); /** * Classe LRUCache optimisée pour la mise en cache des résultats * @template K Type de clé * @template V Type de valeur */ class LRUCache { capacity; cache = new Map(); /** * Crée une nouvelle instance de LRUCache * @param capacity Capacité maximale du cache */ constructor(capacity) { this.capacity = capacity; } /** * Récupère une valeur du cache * @param key Clé à rechercher * @returns Valeur associée à la clé ou undefined si non trouvée */ get(key) { if (!this.cache.has(key)) return undefined; // Déplacer l'élément à la fin pour le LRU const value = this.cache.get(key); this.cache.delete(key); this.cache.set(key, value); return value; } /** * Ajoute ou met à jour une entrée dans le cache * @param key Clé de l'entrée * @param value Valeur à stocker */ put(key, value) { // Supprimer l'élément s'il existe déjà if (this.cache.has(key)) { this.cache.delete(key); } // Supprimer le plus ancien si la capacité est atteinte else if (this.cache.size >= this.capacity) { const oldestKey = this.cache.keys().next().value; // Vérifier que oldestKey n'est pas undefined avant de l'utiliser if (oldestKey !== undefined) { this.cache.delete(oldestKey); } } // Ajouter le nouvel élément this.cache.set(key, value); } /** * Vide le cache */ clear() { this.cache.clear(); } /** * Retourne la taille actuelle du cache */ get size() { return this.cache.size; } /** * Vérifie si une clé existe dans le cache * @param key Clé à vérifier * @returns true si la clé existe, false sinon */ has(key) { return this.cache.has(key); } } /** * Service optimisé pour la vérification des informations * Utilise des expressions régulières précompilées, un cache LRU, et des promesses optimisées */ class VerificationService { toolIntegrator; metricsCalculator; verificationMemory; /** * Expressions régulières précompilées et mises en cache * pour une détection optimisée des caractéristiques */ static REGEX_CACHE = { FACTUAL_CLAIMS: new RegExp('\\b(est|sont|a été|ont été|existe|existait|a démontré|montre|prouve|confirme|indique|révèle)\\b', 'i'), STATISTICS: new RegExp('\\b(\\d+\\s*%|moyenne|médiane|écart.type|statistique|données|étude|sondage|enquête)\\b', 'i'), OPINIONS: new RegExp('\\b(je pense|selon moi|à mon avis|je crois|il me semble|pourrait|devrait|semble|apparemment|probablement|peut-être)\\b', 'i'), EXTERNAL_REFS: new RegExp('(https?:\\/\\/[^\\s]+|selon\\s+[^,.]+|d\'après\\s+[^,.]+|\\bcit[eé]\\b|d\'(une|l\') étude|référence|source|publié|rapport|article)', 'i'), CALCULATIONS: new RegExp('(\\d+\\s*[\\+\\-\\*\\/]\\s*\\d+\\s*=|\\d+(?:[\\³\\²\\¹])|calcul\\s*(?:complexe|avancé)?\\s*:?\\s*([^=]+)=\\s*\\d+|=\\s*[\\d\\-+]+\\s*=\\s*[\\d\\-+]+)', 'i') }; /** * Cache LRU pour les résultats de vérification */ static verificationCache = new LRUCache(100); /** * Cache LRU pour les résultats de calcul */ static calculationCache = new LRUCache(50); /** * Constructeur du service de vérification * * @param toolIntegrator L'intégrateur d'outils pour les vérifications externes * @param metricsCalculator Le calculateur de métriques pour évaluer la fiabilité * @param verificationMemory La mémoire de vérification pour la persistance */ constructor(toolIntegrator, metricsCalculator, verificationMemory) { this.toolIntegrator = toolIntegrator; this.metricsCalculator = metricsCalculator; this.verificationMemory = verificationMemory; } /** * Effectue une vérification préliminaire d'une pensée pour détecter des calculs * Version optimisée utilisant le cache et une détection plus efficace * * @param content Le contenu de la pensée à vérifier * @param explicitlyRequested Si la vérification est explicitement demandée * @returns Résultat de la vérification préliminaire */ async performPreliminaryVerification(content, explicitlyRequested = false) { let verifiedCalculations = undefined; let initialVerification = false; let verificationInProgress = false; let preverifiedThought = content; // Détection optimisée des calculs en utilisant l'expression régulière précompilée const hasCalculations = VerificationService.REGEX_CACHE.CALCULATIONS.test(content); if (explicitlyRequested || hasCalculations) { console.error('Smart-Thinking: Détection de calculs, recherche d\'outils de vérification externe...'); verificationInProgress = true; // Générer une clé de cache basée sur le contenu const cacheKey = `prelim_${this.hashString(content)}`; // Vérifier si le résultat est dans le cache const cachedResults = VerificationService.calculationCache.get(cacheKey); if (cachedResults) { console.error('Smart-Thinking: Utilisation des résultats préliminaires en cache'); verifiedCalculations = cachedResults; initialVerification = true; if (verifiedCalculations && verifiedCalculations.length > 0) { preverifiedThought = this.annotateThoughtWithVerifications(content, verifiedCalculations); } return { verifiedCalculations, initialVerification, verificationInProgress, preverifiedThought }; } // Vérifier s'il existe des outils de vérification adaptés const calculationTools = this.toolIntegrator.suggestVerificationTools(content) .filter(tool => tool.name.toLowerCase().includes('calc') || tool.name.toLowerCase().includes('math') || tool.name.toLowerCase().includes('python') || tool.name.toLowerCase().includes('javascript')); if (calculationTools.length > 0) { console.error(`Smart-Thinking: Utilisation de l'outil externe ${calculationTools[0].name} pour vérifier les calculs`); try { // Utiliser executeWithTimeout pour éviter les opérations bloquantes const result = await this.executeWithTimeout(this.toolIntegrator.executeVerificationTool(calculationTools[0].name, content), 5000); if (result && result.verifiedCalculations) { verifiedCalculations = result.verifiedCalculations; initialVerification = true; if (verifiedCalculations && verifiedCalculations.length > 0) { preverifiedThought = this.annotateThoughtWithVerifications(content, verifiedCalculations); console.error(`Smart-Thinking: ${verifiedCalculations.length} calculs vérifiés via outil externe`); // Mettre en cache les résultats VerificationService.calculationCache.put(cacheKey, verifiedCalculations); } return { verifiedCalculations, initialVerification, verificationInProgress, preverifiedThought }; } } catch (error) { console.error(`Smart-Thinking: Erreur lors de l'utilisation de l'outil externe:`, error); } } // Utiliser la vérification interne console.error('Smart-Thinking: Vérification interne des calculs...'); try { verifiedCalculations = await this.detectAndVerifyCalculations(content); initialVerification = verifiedCalculations.length > 0; if (verifiedCalculations.length > 0) { preverifiedThought = this.annotateThoughtWithVerifications(content, verifiedCalculations); console.error(`Smart-Thinking: ${verifiedCalculations.length} calculs détectés et vérifiés`); // Mettre en cache les résultats VerificationService.calculationCache.put(cacheKey, verifiedCalculations); } } catch (error) { console.error('Smart-Thinking: Erreur lors de la vérification préliminaire des calculs:', error); verificationInProgress = true; initialVerification = false; } } return { verifiedCalculations, initialVerification, verificationInProgress, preverifiedThought }; } /** * Vérifie si une pensée similaire a déjà été vérifiée * Version optimisée avec gestion de cache * * @param content Le contenu de la pensée à vérifier * @param sessionId ID de session * @param thoughtType Type de pensée (regular, conclusion, etc.) * @param connectedThoughtIds IDs des pensées connectées * @returns Résultat de la vérification précédente si trouvée */ async checkPreviousVerification(content, sessionId = config_1.SystemConfig.DEFAULT_SESSION_ID, thoughtType = 'regular', connectedThoughtIds = []) { // Générer une clé de cache const cacheKey = `prev_${this.hashString(content)}_${sessionId}`; // Vérifier le cache local pour les vérifications précédentes const cachedResult = VerificationService.verificationCache.get(cacheKey); if (cachedResult) { console.error('Smart-Thinking: Résultat de vérification précédente trouvé dans le cache'); // Construire un résultat à partir du cache return { previousVerification: { id: cacheKey, status: cachedResult.status, confidence: cachedResult.confidence, sources: cachedResult.sources || [], timestamp: new Date(), similarity: 1.0, // Correspondance exacte du cache text: content }, isVerified: cachedResult.status === 'verified' || cachedResult.status === 'partially_verified', verificationStatus: cachedResult.status, certaintySummary: `Information vérifiée précédemment (mise en cache).`, verification: cachedResult }; } // Valeurs par défaut const result = { previousVerification: null, isVerified: false, verificationStatus: 'unverified', certaintySummary: 'Information non vérifiée' }; try { // Seuil de similarité élevé pour éviter les fausses correspondances const similarityThreshold = config_1.VerificationConfig.SIMILARITY.HIGH_SIMILARITY; console.error(`Smart-Thinking: Recherche de vérifications précédentes avec seuil ${similarityThreshold}...`); const previousVerification = await this.verificationMemory.findVerification(content, sessionId, similarityThreshold); if (previousVerification) { console.error(`Smart-Thinking: Vérification précédente trouvée avec similarité: ${previousVerification.similarity}`); // Ne marquer comme vérifié que si le niveau de similarité est vraiment élevé // et si les sources sont valides const isValidSource = previousVerification.sources && previousVerification.sources.length > 0 && !previousVerification.sources.includes("Information non vérifiable"); const isVerified = ['verified', 'partially_verified'].includes(previousVerification.status) && previousVerification.similarity >= config_1.VerificationConfig.SIMILARITY.HIGH_SIMILARITY && isValidSource; // Ajuster le niveau de confiance en fonction de la similarité const adjustedConfidence = Math.min(previousVerification.confidence, previousVerification.similarity); // Construire la réponse avec les informations de vérification précédente const result = { previousVerification, isVerified, verificationStatus: isVerified ? previousVerification.status : 'uncertain', certaintySummary: isVerified ? `Information vérifiée précédemment avec ${Math.round(previousVerification.similarity * 100)}% de similarité. Niveau de confiance: ${Math.round(adjustedConfidence * 100)}%.` : `Information partiellement similaire (${Math.round(previousVerification.similarity * 100)}%) à une vérification précédente, mais nécessite une nouvelle vérification.`, verification: isVerified ? { status: previousVerification.status, confidence: adjustedConfidence, sources: previousVerification.sources || [], verificationSteps: ['Information vérifiée dans une étape précédente du raisonnement'], notes: `Cette information est similaire (${Math.round(previousVerification.similarity * 100)}%) à une information déjà vérifiée.` } : undefined }; // Mettre en cache le résultat si vérifié if (isVerified && result.verification) { VerificationService.verificationCache.put(cacheKey, result.verification); } return result; } // Propagation du statut pour les pensées de type conclusion ou revision else if ((thoughtType === 'conclusion' || thoughtType === 'revision') && connectedThoughtIds.length > 0) { // Chercher les statuts de vérification des pensées connectées const connectedStatuses = await this.getConnectedThoughtsVerificationStatus(connectedThoughtIds); // Si au moins une pensée connectée est vérifiée ou partiellement vérifiée if (connectedStatuses.some(s => s === 'verified' || s === 'partially_verified')) { result.isVerified = true; result.verificationStatus = 'partially_verified'; result.certaintySummary = `${thoughtType === 'conclusion' ? 'Conclusion' : 'Révision'} basée sur des informations partiellement vérifiées.`; // Construire un résultat de vérification simulé result.verification = { status: 'partially_verified', confidence: 0.7, // Valeur par défaut raisonnable sources: ['Propagation depuis pensées connectées'], verificationSteps: [`Héritage du statut de vérification des pensées ${thoughtType === 'conclusion' ? 'précédentes' : 'associées'}`] }; // Mettre en cache ce résultat également VerificationService.verificationCache.put(cacheKey, result.verification); } } else { console.error('Smart-Thinking: Aucune vérification précédente trouvée.'); } } catch (error) { console.error('Smart-Thinking: Erreur lors de la vérification avec la mémoire:', error); } // Aucune vérification précédente n'a été trouvée return result; } /** * Vérification approfondie d'une pensée * Version refactorisée et optimisée * * @param thought La pensée à vérifier * @param containsCalculations Indique si la pensée contient des calculs à vérifier * @param forceVerification Force une nouvelle vérification même si déjà vérifiée * @param sessionId Identifiant de la session de conversation actuelle * @returns Le résultat de la vérification */ async deepVerify(thought, containsCalculations = false, forceVerification = false, sessionId = config_1.SystemConfig.DEFAULT_SESSION_ID) { const content = thought.content; console.error(`Smart-Thinking: Début de la vérification approfondie`); // Vérifier le cache local si la vérification n'est pas forcée if (!forceVerification) { const cacheKey = `verify_${this.hashString(content)}`; const cachedResult = VerificationService.verificationCache.get(cacheKey); if (cachedResult) { console.error('Smart-Thinking: Résultat de vérification trouvé dans le cache'); // Mettre à jour les métadonnées de la pensée thought.metadata.isVerified = cachedResult.status === 'verified' || cachedResult.status === 'partially_verified'; thought.metadata.verificationSource = 'cache'; thought.metadata.verificationTimestamp = new Date(); thought.metadata.verificationSessionId = sessionId; return cachedResult; } } // Étape 1: Vérifier si l'information a déjà été vérifiée const previousVerification = await this.checkForPreviousVerification(thought, forceVerification, sessionId); if (previousVerification) return previousVerification; // Étape 2: Déterminer les besoins de vérification const verificationNeeds = await this.analyzeVerificationNeeds(thought.content); // Étape 3: Sélectionner et exécuter les outils appropriés const verificationResults = await this.executeVerificationTools(thought.content, verificationNeeds); // Étape 4: Vérifier les calculs si nécessaire const verifiedCalculations = containsCalculations ? await this.verifyCalculations(thought.content, verificationResults) : undefined; // Étape 5: Agréger et analyser les résultats return this.analyzeAndAggregateResults(thought, verificationResults, verifiedCalculations, sessionId); } /** * Étape 1: Vérifier si l'information a déjà été vérifiée dans les vérifications précédentes * * @param thought La pensée à vérifier * @param forceVerification Si true, ignore les vérifications précédentes * @param sessionId Identifiant de la session * @returns Le résultat de vérification si trouvé, null sinon */ async checkForPreviousVerification(thought, forceVerification, sessionId) { if (forceVerification) { console.error('Smart-Thinking: Vérification forcée, ignorer les vérifications précédentes'); return null; } const previousCheckResult = await this.checkPreviousVerification(thought.content, sessionId, thought.type, thought.connections.map(c => c.targetId)); if (previousCheckResult.previousVerification && previousCheckResult.isVerified && previousCheckResult.verification) { console.error('Smart-Thinking: Utilisation d\'une vérification précédente trouvée en mémoire'); // Mettre à jour les métadonnées de la pensée thought.metadata.isVerified = previousCheckResult.isVerified; thought.metadata.verificationSource = 'memory'; thought.metadata.verificationTimestamp = previousCheckResult.previousVerification.timestamp; thought.metadata.verificationSessionId = sessionId; thought.metadata.semanticSimilarity = previousCheckResult.previousVerification.similarity; // Retourner la vérification existante return previousCheckResult.verification; } return null; } /** * Étape 2: Analyser les besoins de vérification * * @param content Contenu à analyser * @returns Les besoins de vérification déterminés */ async analyzeVerificationNeeds(content) { console.error('Smart-Thinking: Analyse des besoins de vérification'); // Analyser le contenu en une seule passe (optimisé) const contentCharacteristics = this.analyzeContentCharacteristics(content); // Étiqueter les catégories de contenu détectées const contentCategories = []; if (contentCharacteristics.hasFactualClaims) contentCategories.push('claims'); if (contentCharacteristics.hasCalculations) contentCategories.push('calculations'); if (contentCharacteristics.hasOpinions) contentCategories.push('opinions'); if (contentCharacteristics.hasStatistics) contentCategories.push('statistics'); if (contentCharacteristics.hasExternalRefs) contentCategories.push('references'); console.error(`Smart-Thinking: Catégories de contenu détectées: ${contentCategories.join(', ') || 'aucune spécifique'}`); // Déterminer les besoins de vérification const verificationRequirements = this.metricsCalculator.determineVerificationRequirements(content); return { contentCharacteristics, verificationRequirements }; } /** * Étape 3: Sélectionner et exécuter les outils de vérification * * @param content Contenu à vérifier * @param verificationNeeds Besoins de vérification déterminés * @returns Résultats de vérification */ async executeVerificationTools(content, verificationNeeds) { console.error('Smart-Thinking: Sélection et exécution des outils de vérification'); // Obtenir les outils de vérification recommandés const verificationTools = this.toolIntegrator.suggestVerificationTools(content); if (verificationTools.length === 0) { console.error('Smart-Thinking: Aucun outil de vérification disponible'); return []; } console.error(`Smart-Thinking: ${verificationTools.length} outils de vérification disponibles`); // Calculer le nombre optimal d'outils à utiliser const baseToolCount = Math.min(verificationNeeds.verificationRequirements.requiresMultipleVerifications ? verificationNeeds.verificationRequirements.recommendedVerificationsCount : 1, Math.max(1, verificationTools.length)); // Ajuster le nombre d'outils en fonction de la complexité const contentCategories = Object.values(verificationNeeds.contentCharacteristics) .filter(value => value === true).length; const toolsToUse = Math.min(contentCategories > 2 ? baseToolCount + 1 : baseToolCount, verificationTools.length); console.error(`Smart-Thinking: Utilisation de ${toolsToUse} outil(s) externe(s) pour la vérification`); // Exécuter les vérifications avec Promise.allSettled et timeouts const verificationPromises = verificationTools.slice(0, toolsToUse).map(async (tool) => { return this.executeWithTimeout((async () => { try { console.error(`Smart-Thinking: Utilisation de l'outil de vérification "${tool.name}"...`); const result = await this.toolIntegrator.executeVerificationTool(tool.name, content); // Vérifier si l'outil a retourné un résultat exploitable const isValidResult = result && (result.isValid !== undefined || result.verifiedCalculations || result.sources || result.details); if (isValidResult) { console.error(`Smart-Thinking: Vérification avec "${tool.name}" terminée avec succès`); return { toolName: tool.name, result, confidence: tool.confidence, stage: 'primary' }; } else { console.error(`Smart-Thinking: Résultat de ${tool.name} incomplet ou invalide`); return null; } } catch (error) { console.error(`Smart-Thinking: Erreur lors de la vérification avec l'outil "${tool.name}":`, error); return null; } })(), 10000 // 10 secondes de timeout ); }); // Attendre la résolution de toutes les promesses avec Promise.allSettled const settledResults = await Promise.allSettled(verificationPromises); // Filtrer les résultats réussis const verificationResults = settledResults .filter((result) => result.status === 'fulfilled' && result.value !== null) .map(result => result.value); console.error(`Smart-Thinking: ${verificationResults.length}/${verificationPromises.length} vérifications réussies`); return verificationResults; } /** * Étape 4: Vérifier les calculs si nécessaire * * @param content Contenu à vérifier * @param verificationResults Résultats de vérification existants * @returns Résultats de vérification des calculs */ async verifyCalculations(content, verificationResults) { console.error('Smart-Thinking: Vérification des calculs'); // Vérifier si des calculs ont déjà été vérifiés par les outils externes for (const result of verificationResults) { if (result && result.result && result.result.verifiedCalculations) { console.error(`Smart-Thinking: Calculs vérifiés par l'outil externe "${result.toolName}"`); return result.result.verifiedCalculations; } } console.error('Smart-Thinking: Aucun outil externe n\'a vérifié les calculs, utilisation de la vérification interne'); // Générer une clé de cache pour les calculs const cacheKey = `calc_${this.hashString(content)}`; // Vérifier si les résultats sont dans le cache const cachedResults = VerificationService.calculationCache.get(cacheKey); if (cachedResults) { console.error('Smart-Thinking: Utilisation des résultats de calcul en cache'); return cachedResults; } // Si pas dans le cache, utiliser la détection interne const verifiedCalculations = await this.detectAndVerifyCalculations(content); // Mettre en cache les résultats if (verifiedCalculations.length > 0) { VerificationService.calculationCache.put(cacheKey, verifiedCalculations); } return verifiedCalculations; } /** * Étape 5: Analyser et agréger les résultats * * @param thought Pensée à vérifier * @param verificationResults Résultats de vérification * @param verifiedCalculations Résultats de vérification des calculs * @param sessionId ID de session * @returns Résultat final de vérification */ async analyzeAndAggregateResults(thought, verificationResults, verifiedCalculations, sessionId) { console.error('Smart-Thinking: Analyse et agrégation des résultats'); // Déterminer le statut et le niveau de confiance de manière optimisée const { status, confidence } = this.determineVerificationStatusAndConfidence(verificationResults, thought); console.error(`Smart-Thinking: Statut préliminaire: ${status}, confiance: ${confidence.toFixed(2)}`); // Construire la liste des sources et des étapes const sources = verificationResults.map(r => { const source = r.result.source || `${r.toolName} (source non spécifiée)`; return `${r.toolName}: ${source}`; }); const verificationStages = ['vérification principale']; if (verifiedCalculations && verifiedCalculations.length > 0) { verificationStages.push('vérification des calculs'); } const steps = [ ...verificationStages.map(stage => `Étape de ${stage}`), ...verificationResults.map(r => `Vérifié avec ${r.toolName} (${r.stage})`) ]; // Détecter les contradictions const contradictions = this.detectContradictions(verificationResults); // Générer des notes de vérification const notes = this.generateVerificationNotes(verificationResults, verifiedCalculations); // IMPORTANT: Mettre à jour les métadonnées de la pensée thought.metadata.isVerified = status === 'verified' || status === 'partially_verified'; thought.metadata.verificationTimestamp = new Date(); thought.metadata.verificationSource = verificationResults.length > 0 ? 'tools' : 'internal'; thought.metadata.verificationSessionId = sessionId; thought.metadata.verificationToolsUsed = verificationResults.length; thought.metadata.verificationStages = verificationStages; // Ajustement spécial pour "absence d'information" if (status === 'absence_of_information') { thought.metadata.isVerified = true; // Nous considérons qu'une absence d'information est une information vérifiée } // Construire le résultat final const verificationResult = { status, confidence, sources, verificationSteps: steps, contradictions: contradictions.length > 0 ? contradictions : undefined, notes, verifiedCalculations }; // Stocker le résultat dans le cache const cacheKey = `verify_${this.hashString(thought.content)}`; VerificationService.verificationCache.put(cacheKey, verificationResult); // Stocker le résultat dans la mémoire de vérification await this.storeVerification(thought.content, status, confidence, sources, sessionId); console.error(`Smart-Thinking: Vérification complétée, statut final: ${status}, confiance: ${confidence.toFixed(2)}`); return verificationResult; } /** * Détermine le statut et la confiance de la vérification à partir des résultats * Version optimisée et factorisée * * @param results Résultats de vérification * @param thought Pensée à vérifier * @returns Statut et niveau de confiance */ determineVerificationStatusAndConfidence(results, thought) { // Vérifier si résultats vides if (results.length === 0) { return { status: 'unverified', confidence: Math.min(0.3, thought.metrics?.confidence || 0.3) }; } // Variables pour stocker les compteurs const counts = { verified: results.filter(r => r && r.result && r.result.isValid === true).length, contradicted: results.filter(r => r && r.result && r.result.isValid === false).length, partial: results.filter(r => r && r.result && r.result.isValid === 'partial').length, absence: results.filter(r => r && r.result && (r.result.isValid === 'absence_of_information' || (typeof r.result.isValid === 'string' && r.result.isValid.includes('absence')))).length, uncertain: results.filter(r => r && r.result && (r.result.isValid === null || r.result.isValid === undefined)).length }; // Déterminer l'état en fonction des compteurs if (counts.verified > 0 && counts.contradicted === 0) { // Information vérifiée sans contradiction const averageConfidence = this.calculateAverageConfidence(results.filter(r => r && r.result && r.result.isValid === true)); return { status: 'verified', confidence: Math.min(averageConfidence + (counts.verified * 0.05), 0.95) }; } else if (counts.partial > 0) { // Information partiellement vérifiée const averageConfidence = this.calculateAverageConfidence(results.filter(r => r && r.result && r.result.isValid === 'partial')); return { status: 'partially_verified', confidence: Math.min(averageConfidence, 0.75) }; } else if (counts.verified > 0 && counts.contradicted > 0) { // Information contradictoire return { status: 'contradictory', confidence: 0.4 }; } else if (counts.absence > 0) { // Absence d'information return { status: 'absence_of_information', confidence: Math.min(0.6 + (counts.absence * 0.05), 0.8) }; } else if (counts.uncertain > 0) { // Information incertaine return { status: 'uncertain', confidence: 0.3 }; } else { // Par défaut, non vérifié return { status: 'unverified', confidence: 0.3 }; } } /** * Calcule la confiance moyenne à partir des résultats * * @param results Résultats pour lesquels calculer la moyenne * @returns Confiance moyenne */ calculateAverageConfidence(results) { if (results.length === 0) return 0.5; return results.reduce((sum, r) => sum + (r ? r.confidence : 0), 0) / results.length; } /** * Détecte et vérifie les calculs dans un texte de manière asynchrone * Version optimisée avec mise en cache * * @param content Le texte contenant potentiellement des calculs * @returns Une promesse résolvant vers un tableau de résultats de vérification de calculs */ async detectAndVerifyCalculations(content) { // Générer une clé de cache basée sur le contenu const cacheKey = `calc_${this.hashString(content)}`; // Vérifier si le résultat est dans le cache const cachedResults = VerificationService.calculationCache.get(cacheKey); if (cachedResults) { console.error('Smart-Thinking: Utilisation des résultats de calcul en cache'); return cachedResults; } console.error('Smart-Thinking: Détection et vérification des calculs avec MathEvaluator'); try { const evaluationResults = math_evaluator_1.MathEvaluator.detectAndEvaluate(content); console.error(`Smart-Thinking: ${evaluationResults.length} calcul(s) détecté(s)`); // Filtrer les évaluations vides ou les notations de fonctions const filteredResults = evaluationResults.filter((result) => !isNaN(result.result) || (result.context === "notation_fonction")); // Convertir les résultats au format CalculationVerificationResult const results = math_evaluator_1.MathEvaluator.convertToVerificationResults(filteredResults); // Mettre en cache les résultats VerificationService.calculationCache.put(cacheKey, results); return results; } catch (error) { console.error('Smart-Thinking: Erreur lors de la détection des calculs:', error); return []; } } /** * Annote une pensée avec les résultats de vérification des calculs * * @param content Le texte de la pensée à annoter * @param verifications Les résultats de vérification des calculs * @returns Le texte annoté avec les résultats de vérification */ annotateThoughtWithVerifications(content, verifications) { let annotatedThought = content; // Extraire les notations de fonctions pour les traiter différemment const notationVerifications = verifications.filter(v => v.verified.includes("Notation de fonction")); // Extraire les calculs standards const calcVerifications = verifications.filter(v => !v.verified.includes("Notation de fonction")); // Parcourir les vérifications de calculs dans l'ordre inverse pour ne pas perturber les indices for (let i = calcVerifications.length - 1; i >= 0; i--) { const verification = calcVerifications[i]; const original = verification.original; // Créer une annotation selon que le calcul est correct ou non if (verification.isCorrect) { annotatedThought = annotatedThought.replace(original, `${original} [✓ Vérifié]`); } else if (verification.verified.includes("vérifier") || verification.verified.includes("Vérification")) { annotatedThought = annotatedThought.replace(original, `${original} [⏳ Vérification en cours...]`); } else { // Même si le calcul est incorrect, il a été vérifié annotatedThought = annotatedThought.replace(original, `${original} [✗ Incorrect: ${verification.verified}]`); } } return annotatedThought; } /** * Version optimisée de la détection des contradictions * * @param results Résultats à analyser * @returns Tableau des contradictions détectées */ detectContradictions(results) { if (results.length < 2) return []; // Structure de données pour stocker les contradictions const contradictions = []; const validResults = results.filter(r => r && r.result && r.result.isValid !== undefined); // Tableau d'assertions positives et négatives const positiveResults = validResults.filter(r => r.result.isValid === true); const negativeResults = validResults.filter(r => r.result.isValid === false); // Si pas de contradiction, retourner tableau vide if (positiveResults.length === 0 || negativeResults.length === 0) { return []; } // Génération des contradictions for (const pos of positiveResults) { for (const neg of negativeResults) { contradictions.push(`Contradiction entre ${pos.toolName} (confirme) et ${neg.toolName} (contredit)`); } } // Limiter le nombre de contradictions rapportées return contradictions.slice(0, 5); } /** * Version optimisée et plus informative de la génération des notes de vérification * * @param results Résultats de vérification * @param calculations Résultats de vérification des calculs * @returns Notes de vérification */ generateVerificationNotes(results, calculations) { if (results.length === 0 && (!calculations || calculations.length === 0)) { return "Aucune vérification n'a été effectuée."; } const notes = []; // Ajouter informations sur les outils externes if (results.length > 0) { const toolsUsed = Array.from(new Set(results.map(r => r.toolName))).join(', '); notes.push(`Vérification effectuée avec les outils externes suivants: ${toolsUsed}.`); // Ajouter statistiques sur les résultats const confirmedCount = results.filter(r => r.result?.isValid === true).length; const contradictedCount = results.filter(r => r.result?.isValid === false).length; const uncertainCount = results.filter(r => r.result?.isValid !== true && r.result?.isValid !== false).length; if (confirmedCount > 0) { notes.push(`${confirmedCount} source(s) a(ont) confirmé l'information.`); } if (contradictedCount > 0) { notes.push(`${contradictedCount} source(s) a(ont) contredit l'information.`); } if (uncertainCount > 0) { notes.push(`${uncertainCount} source(s) n'a(ont) pas pu se prononcer.`); } } // Ajouter informations sur les calculs vérifiés if (calculations && calculations.length > 0) { const correctCount = calculations.filter(c => c.isCorrect).length; const incorrectCount = calculations.length - correctCount; notes.push(`${calculations.length} calcul(s) mathématique(s) vérifié(s), dont ${correctCount} correct(s) et ${incorrectCount} incorrect(s).`); } return notes.join(' '); } /** * Stocke une vérification dans la mémoire * * @param content Le contenu vérifié * @param status Le statut de vérification * @param confidence Le niveau de confiance * @param sources Les sources utilisées * @param sessionId L'identifiant de la session * @returns L'identifiant de la vérification stockée */ async storeVerification(content, status, confidence, sources = [], sessionId = config_1.SystemConfig.DEFAULT_SESSION_ID) { return this.verificationMemory.addVerification(content, status, confidence, sources, sessionId); } /** * Récupère les statuts de vérification des pensées connectées * * @param thoughtIds IDs des pensées connectées à vérifier * @returns Tableau des statuts de vérification */ async getConnectedThoughtsVerificationStatus(thoughtIds) { // Ici, il faudrait implémenter la logique pour récupérer les statuts // Dans une implémentation réelle, nous interrogerions le graphe de pensées // Pour le moment, on utilise une valeur par défaut pour démontrer le principe return thoughtIds.map(_ => 'partially_verified'); } /** * Analyse les caractéristiques du contenu en une seule passe * * @param content Contenu à analyser * @returns Caractéristiques détectées */ analyzeContentCharacteristics(content) { return { hasFactualClaims: VerificationService.REGEX_CACHE.FACTUAL_CLAIMS.test(content), hasOpinions: VerificationService.REGEX_CACHE.OPINIONS.test(content), hasStatistics: VerificationService.REGEX_CACHE.STATISTICS.test(content), hasExternalRefs: VerificationService.REGEX_CACHE.EXTERNAL_REFS.test(content), hasCalculations: VerificationService.REGEX_CACHE.CALCULATIONS.test(content) }; } /** * Exécute une promesse avec un timeout pour éviter les opérations bloquantes * * @param promise Promesse à exécuter * @param timeoutMs Délai d'expiration en millisecondes * @returns Résultat de la promesse ou null en cas de timeout */ async executeWithTimeout(promise, timeoutMs = 5000) { let timeoutHandle; const timeoutPromise = new Promise(resolve => { timeoutHandle = setTimeout(() => resolve(null), timeoutMs); }); try { const result = await Promise.race([promise, timeoutPromise]); clearTimeout(timeoutHandle); return result; } catch (error) { clearTimeout(timeoutHandle); console.error('Smart-Thinking: Erreur ou timeout lors de l\'exécution:', error); return null; } } /** * Génère un hash simple pour une chaîne (utilisé pour les clés de cache) * * @param str Chaîne à hacher * @returns Hash sous forme de chaîne */ hashString(str) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32bit integer } return hash.toString(36); } } exports.VerificationService = VerificationService; //# sourceMappingURL=verification-service.js.map