smart-thinking-mcp
Version:
Un serveur MCP avancé pour le raisonnement multi-dimensionnel, adaptatif et collaboratif
312 lines • 14.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.QualityEvaluator = void 0;
const metrics_calculator_1 = require("./metrics-calculator");
const config_1 = require("./config");
const service_container_1 = require("./services/service-container");
const openrouter_client_1 = require("./utils/openrouter-client"); // Corrected import path
/**
* Classe qui évalue la qualité des pensées
* Utilise le service de vérification centralisé pour toutes les fonctionnalités de vérification
* Version optimisée avec mise en cache et structures de données efficaces
*/
class QualityEvaluator {
verificationService; // L'opérateur ! indique que la propriété sera initialisée après la construction
metricsCalculator;
// Caches pour les résultats d'évaluation et les détections de biais
evaluationCache = new Map();
biasCache = new Map();
suggestionCache = new Map();
// Expressions régulières pré-compilées pour la détection de biais (heuristique de repli)
biasPatterns = [
{
regex: /\b(comme je l'ai dit|comme je le pensais|tel que mentionné)\b/i,
type: "confirmation_bias",
score: 0.7,
description: "Tend à confirmer des croyances existantes"
},
{
regex: /\b(récemment|dernièrement|ces derniers temps)\b/i,
type: "recency_bias",
score: 0.6,
description: "Accorde trop d'importance aux événements récents"
},
{
regex: /\b(tous|toujours|jamais|aucun|systématiquement|sans exception)\b/i,
type: "absolutism_bias",
score: 0.65,
description: "Utilise des généralisations absolues"
},
{
regex: /\b(évident|évidemment|clairement|bien sûr|naturellement|sans doute)\b/i,
type: "certainty_bias",
score: 0.6,
description: "Présente comme certain ce qui est discutable"
}
];
// Mappage pour les suggestions d'amélioration (heuristique de repli)
suggestionMappings = [
{
condition: (metrics) => metrics.confidence < config_1.VerificationConfig.CONFIDENCE.LOW_CONFIDENCE,
suggestions: [
'Renforcez l\'argumentation avec des preuves ou des références précises.',
'Évitez les modalisateurs d\'incertitude excessive ("peut-être", "probablement").'
]
},
{
condition: (metrics) => metrics.relevance < config_1.VerificationConfig.CONFIDENCE.LOW_CONFIDENCE,
suggestions: [
'Clarifiez le lien avec le contexte ou le sujet principal.'
]
},
{
condition: (metrics) => metrics.quality < config_1.VerificationConfig.CONFIDENCE.LOW_CONFIDENCE,
suggestions: [
'Améliorez la structure et la clarté de cette pensée.'
]
}
];
// Mappage pour les suggestions spécifiques au type de pensée (heuristique de repli)
typeSuggestionMap = {
'hypothesis': [
{
condition: (thought) => !thought.content.toLowerCase().includes('si'),
suggestion: 'Formulez l\'hypothèse sous forme conditionnelle (si... alors...).'
}
],
'conclusion': [
{
condition: (thought, connectedThoughts) => connectedThoughts.length < 2,
suggestion: 'Une conclusion devrait synthétiser plusieurs pensées précédentes.'
}
],
'revision': [
{
condition: (thought, connectedThoughts) => !connectedThoughts.some(t => thought.connections.some(conn => conn.targetId === t.id &&
['refines', 'contradicts', 'supports'].includes(conn.type))),
suggestion: 'Une révision devrait clairement indiquer ce qu\'elle raffine ou corrige.'
}
]
};
constructor() {
this.metricsCalculator = new metrics_calculator_1.MetricsCalculator();
// L'initialisation du verificationService se fera via setVerificationService
}
/**
* Définit le service de vérification à utiliser
*
* @param verificationService Le service de vérification
*/
setVerificationService(verificationService) {
this.verificationService = verificationService;
}
/**
* Obtient le service de vérification depuis le conteneur si nécessaire
* @returns Le service de vérification
*/
getVerificationService() {
if (!this.verificationService) {
this.verificationService = service_container_1.ServiceContainer.getInstance().getVerificationService();
}
return this.verificationService;
}
/**
* Crée une clé unique pour le cache
*
* @param thoughtId L'identifiant de la pensée
* @param contextId Un identifiant supplémentaire pour le contexte (comme l'ID de graphe)
* @returns Une clé unique pour le cache
*/
createCacheKey(thoughtId, contextId) {
return contextId ? `${thoughtId}:${contextId}` : thoughtId;
}
/**
* Évalue la qualité d'une pensée avec mise en cache pour améliorer les performances
*
* @param thoughtId L'identifiant de la pensée à évaluer
* @param thoughtGraph Le graphe de pensées contenant la pensée
* @returns Les métriques de qualité évaluées
*/
async evaluate(thoughtId, thoughtGraph) {
// Créer une clé de cache unique basée sur l'ID de la pensée
const cacheKey = this.createCacheKey(thoughtId);
// Vérifier si le résultat est déjà en cache
const cachedMetrics = this.evaluationCache.get(cacheKey);
if (cachedMetrics) {
return { ...cachedMetrics }; // Retourner une copie pour éviter la mutation
}
const thought = thoughtGraph.getThought(thoughtId);
if (!thought) {
// Retourner des métriques par défaut si la pensée n'est pas trouvée
return {
confidence: 0.5,
relevance: 0.5,
quality: 0.5
};
}
// Récupérer les pensées connectées pour le contexte
const connectedThoughts = thoughtGraph.getConnectedThoughts(thoughtId);
// Utiliser le calculateur de métriques pour obtenir des valeurs plus précises (maintenant asynchrone)
// Utiliser Promise.all pour exécuter les calculs en parallèle
const [confidence, relevance, quality] = await Promise.all([
this.metricsCalculator.calculateConfidence(thought),
this.metricsCalculator.calculateRelevance(thought, connectedThoughts),
this.metricsCalculator.calculateQuality(thought, connectedThoughts)
]);
const metrics = {
confidence,
relevance,
quality
};
// Mettre en cache le résultat
this.evaluationCache.set(cacheKey, { ...metrics });
return metrics;
}
/**
* Méthode de délégation pour performPreliminaryVerification
*/
async performPreliminaryVerification(thought, explicitlyRequested = false) {
return this.getVerificationService().performPreliminaryVerification(thought, explicitlyRequested);
}
/**
* Méthode de délégation pour checkPreviousVerification
*/
async checkPreviousVerification(thoughtContent, sessionId = config_1.SystemConfig.DEFAULT_SESSION_ID) {
return this.getVerificationService().checkPreviousVerification(thoughtContent, sessionId);
}
/**
* Méthode de délégation pour deepVerify
*/
async deepVerify(thought, containsCalculations = false, // toolIntegrator removed as it's handled within VerificationService
forceVerification = false, sessionId = config_1.SystemConfig.DEFAULT_SESSION_ID) {
return this.getVerificationService().deepVerify(thought, containsCalculations, forceVerification, sessionId);
}
/**
* Méthode de délégation pour detectAndVerifyCalculations
*/
async detectAndVerifyCalculations(content) {
return this.getVerificationService().detectAndVerifyCalculations(content);
}
/**
* Méthode de délégation pour annotateThoughtWithVerifications
*/
annotateThoughtWithVerifications(thought, verifications) {
// Ensure the parameter type matches the interface/implementation
return this.getVerificationService().annotateThoughtWithVerifications(thought, verifications);
}
/**
* Détecte les biais potentiels dans une pensée avec mise en cache des résultats
* et utilisation d'expressions régulières optimisées (maintenant asynchrone)
*
* @param thought La pensée à analyser
* @returns Un tableau de biais détectés, vide si aucun
*/
async detectBiases(thought) {
// Vérifier d'abord le cache
if (this.biasCache.has(thought.id)) {
// Retourner une copie pour éviter la mutation des données en cache
return [...this.biasCache.get(thought.id)];
}
// Utiliser la méthode asynchrone de MetricsCalculator
const biases = await this.metricsCalculator.detectBiases(thought);
// Mettre le résultat en cache
this.biasCache.set(thought.id, [...biases]);
return biases;
}
/**
* Suggère des améliorations pour une pensée avec mise en cache des résultats
* et structure optimisée pour réduire les calculs redondants (maintenant asynchrone)
*
* @param thought La pensée à améliorer
* @param thoughtGraph Le graphe de pensées
* @returns Un tableau de suggestions d'amélioration (basé sur LLM ou heuristique)
*/
async suggestImprovements(thought, thoughtGraph) {
// Créer une clé de cache basée sur l'ID de la pensée
const cacheKey = this.createCacheKey(thought.id);
// Vérifier si les suggestions sont déjà en cache
if (this.suggestionCache.has(cacheKey)) {
return [...this.suggestionCache.get(cacheKey)];
}
// Attempt LLM-based suggestions first
const llmSuggestions = await (0, openrouter_client_1.suggestLlmImprovements)(thought.content);
if (llmSuggestions !== null && llmSuggestions.length > 0) {
this.suggestionCache.set(cacheKey, [...llmSuggestions]);
return llmSuggestions;
}
else if (llmSuggestions === null) {
console.warn(`LLM analysis failed for suggestions on thought ${thought.id}. Falling back to heuristic.`);
}
// If LLM fails or returns no suggestions, fallback to heuristic method
// Obtenir les métriques et les pensées connectées (evaluate est maintenant async)
const metrics = await this.evaluate(thought.id, thoughtGraph); // Await the async evaluate call
const connectedThoughts = thoughtGraph.getConnectedThoughts(thought.id);
const suggestions = [];
// Appliquer les mappages de suggestions basées sur les métriques
for (const mapping of this.suggestionMappings) {
if (mapping.condition(metrics)) {
suggestions.push(...mapping.suggestions);
}
}
// Analyse du contenu pour des suggestions spécifiques
const content = thought.content.toLowerCase();
const wordCount = content.split(/\s+/).length;
if (wordCount < 10) {
suggestions.push('Développez davantage cette pensée, elle est trop courte pour être complète.');
}
else if (wordCount > config_1.SystemConfig.MAX_THOUGHT_LENGTH / 50) { // Assuming MAX_THOUGHT_LENGTH exists in SystemConfig
suggestions.push('Considérez diviser cette pensée en plusieurs parties plus ciblées.');
}
// Vérifier la présence de biais (detectBiases est maintenant async)
const biases = await this.detectBiases(thought); // Await the async detectBiases call
if (biases.length > 0) {
suggestions.push(`Attention aux biais potentiels: ${biases.map(bias => bias.type).join(', ')}.`);
}
// Appliquer les suggestions spécifiques au type de pensée
if (thought.type in this.typeSuggestionMap) {
for (const mapping of this.typeSuggestionMap[thought.type]) {
if (mapping.condition(thought, connectedThoughts)) {
suggestions.push(mapping.suggestion);
}
}
}
// Vérifier les contradictions de manière optimisée
const hasContradictions = connectedThoughts.some(t => thought.connections.some(conn => conn.targetId === t.id && conn.type === 'contradicts'));
if (hasContradictions) {
suggestions.push('Résolvez ou clarifiez les contradictions avec d\'autres pensées.');
}
// Mettre en cache les suggestions (heuristiques)
this.suggestionCache.set(cacheKey, [...suggestions]);
return suggestions; // Return heuristic suggestions if LLM failed
}
/**
* Efface les caches pour forcer une réévaluation complète
* Utile lorsque des pensées sont modifiées
*/
clearCaches() {
this.evaluationCache.clear();
this.biasCache.clear();
this.suggestionCache.clear();
}
/**
* Supprime une entrée spécifique des caches
*
* @param thoughtId L'identifiant de la pensée à supprimer des caches
*/
invalidateCacheForThought(thoughtId) {
// Supprimer toutes les entrées liées à cette pensée
for (const key of this.evaluationCache.keys()) {
if (key.startsWith(thoughtId)) {
this.evaluationCache.delete(key);
}
}
this.biasCache.delete(thoughtId);
for (const key of this.suggestionCache.keys()) {
if (key.startsWith(thoughtId)) {
this.suggestionCache.delete(key);
}
}
}
}
exports.QualityEvaluator = QualityEvaluator;
//# sourceMappingURL=quality-evaluator.js.map