UNPKG

thoughtmcp

Version:

AI that thinks more like humans do - MCP server with human-like cognitive architecture for enhanced reasoning, memory, and self-monitoring

538 lines 21.7 kB
/** * System 1 (Intuitive) Processor - Fast, automatic, pattern-based thinking * Implements Kahneman's System 1 thinking with pattern matching and heuristics */ import { ProcessingMode, ReasoningType, } from "../types/core.js"; export class IntuitiveProcessor { initialized = false; patternCache = new Map(); heuristicRules = new Map(); lastActivity = 0; config = {}; async initialize(config) { this.config = { pattern_threshold: 0.3, confidence_decay: 0.1, max_patterns: 50, heuristic_weight: 0.8, ...config, }; this.initializeHeuristics(); this.initialized = true; } initializeHeuristics() { // Availability heuristic - judge by ease of recall this.heuristicRules.set("availability", (_input, patterns) => { const recentPatterns = patterns.filter((p) => p.salience > 0.7); return { name: "availability", type: "availability", confidence: recentPatterns.length > 0 ? 0.8 : 0.3, result: `Based on ${recentPatterns.length} easily recalled patterns`, processing_time: 1, }; }); // Representativeness heuristic - judge by similarity to prototypes this.heuristicRules.set("representativeness", (_input, patterns) => { const prototypeMatches = patterns.filter((p) => p.type === "prototype" && p.confidence > 0.6); return { name: "representativeness", type: "representativeness", confidence: prototypeMatches.length > 0 ? 0.7 : 0.4, result: `Matches ${prototypeMatches.length} known prototypes`, processing_time: 2, }; }); // Anchoring heuristic - influenced by initial information this.heuristicRules.set("anchoring", (_input, patterns) => { const firstPattern = patterns[0]; return { name: "anchoring", type: "anchoring", confidence: firstPattern ? firstPattern.confidence * 0.9 : 0.2, result: `Anchored on first impression: ${firstPattern?.content.join(" ") || "none"}`, processing_time: 1, }; }); // Affect heuristic - "how do I feel about it?" this.heuristicRules.set("affect", (_input, patterns) => { const emotionalPatterns = patterns.filter((p) => p.type === "emotional"); const avgSalience = emotionalPatterns.reduce((sum, p) => sum + p.salience, 0) / emotionalPatterns.length || 0; return { name: "affect", type: "affect", confidence: avgSalience > 0.5 ? 0.8 : 0.3, result: `Emotional response strength: ${avgSalience.toFixed(2)}`, processing_time: 1, }; }); } async processIntuitive(input) { const startTime = Date.now(); this.lastActivity = startTime; try { // Step 1: Pattern matching const patterns = this.matchPatterns(input.input); // Step 2: Apply heuristics const heuristicResults = this.applyHeuristics(input.input, patterns); // Step 3: Generate intuitive response const response = this.generateIntuitiveResponse(input.input, patterns, heuristicResults); // Step 4: Assess confidence const confidence = this.getConfidence(response); // Step 5: Create reasoning path const reasoningPath = this.createReasoningPath(patterns, heuristicResults, response); const processingTime = Date.now() - startTime; return { content: response.content, confidence: confidence, reasoning_path: reasoningPath, emotional_context: this.assessEmotionalContext(input.input, patterns), metadata: { processing_time_ms: processingTime, components_used: ["IntuitiveProcessor"], memory_retrievals: patterns.length, system_mode: ProcessingMode.INTUITIVE, temperature: input.configuration.temperature, }, }; } catch (error) { throw new Error(`Intuitive processing failed: ${error.message}`); } } matchPatterns(input) { // Check cache first if (this.patternCache.has(input)) { return this.patternCache.get(input); } const patterns = []; const tokens = input.toLowerCase().split(/\s+/); // Simple pattern matching based on common structures patterns.push(...this.detectQuestionPatterns(tokens)); patterns.push(...this.detectEmotionalPatterns(tokens)); patterns.push(...this.detectCausalPatterns(tokens)); patterns.push(...this.detectComparisonPatterns(tokens)); patterns.push(...this.detectNegationPatterns(tokens)); // Cache results if (patterns.length > 0) { this.patternCache.set(input, patterns); // Limit cache size if (this.patternCache.size > (this.config.max_patterns ?? 50)) { const firstKey = this.patternCache.keys().next().value; if (firstKey) { this.patternCache.delete(firstKey); } } } return patterns; } detectQuestionPatterns(tokens) { const questionWords = [ "what", "how", "why", "when", "where", "who", "which", ]; const patterns = []; for (const qWord of questionWords) { if (tokens.includes(qWord)) { patterns.push({ type: "question", content: [ qWord, ...tokens.slice(tokens.indexOf(qWord), tokens.indexOf(qWord) + 3), ], confidence: 0.9, salience: 0.8, }); } } return patterns; } detectEmotionalPatterns(tokens) { const emotionalWords = { positive: [ "good", "great", "excellent", "happy", "love", "amazing", "wonderful", ], negative: [ "bad", "terrible", "hate", "awful", "horrible", "sad", "angry", ], neutral: ["okay", "fine", "normal", "average"], }; const patterns = []; for (const [valence, words] of Object.entries(emotionalWords)) { for (const word of words) { if (tokens.includes(word)) { patterns.push({ type: "emotional", content: [word], confidence: 0.7, salience: valence === "neutral" ? 0.4 : 0.8, }); } } } return patterns; } detectCausalPatterns(tokens) { const causalIndicators = [ "because", "since", "due to", "caused by", "results in", "leads to", ]; const patterns = []; for (const indicator of causalIndicators) { const indicatorTokens = indicator.split(" "); if (this.containsSequence(tokens, indicatorTokens)) { patterns.push({ type: "causal", content: indicatorTokens, confidence: 0.8, salience: 0.7, }); } } return patterns; } detectComparisonPatterns(tokens) { const comparisonWords = [ "better", "worse", "more", "less", "than", "compared to", "versus", ]; const patterns = []; for (const word of comparisonWords) { if (tokens.includes(word)) { patterns.push({ type: "comparison", content: [word], confidence: 0.6, salience: 0.6, }); } } return patterns; } detectNegationPatterns(tokens) { const negationWords = ["not", "no", "never", "nothing", "none", "neither"]; const patterns = []; for (const word of negationWords) { if (tokens.includes(word)) { patterns.push({ type: "negation", content: [word], confidence: 0.8, salience: 0.7, }); } } return patterns; } containsSequence(tokens, sequence) { for (let i = 0; i <= tokens.length - sequence.length; i++) { if (sequence.every((token, j) => tokens[i + j] === token)) { return true; } } return false; } applyHeuristics(input, patterns) { const results = {}; for (const [name, heuristic] of this.heuristicRules) { try { const result = heuristic(input, patterns); // Ensure the result has the correct type property results[name] = { ...result, type: name, // Add the type property that tests expect }; } catch (error) { results[name] = { name: name, type: name, // Add the type property confidence: 0.1, result: `Heuristic failed: ${error.message}`, processing_time: 0, }; } } return results; } generateIntuitiveResponse(input, patterns, heuristicResults) { // Combine patterns and heuristics to generate a quick response const dominantPattern = patterns.reduce((max, p) => (p.salience > max.salience ? p : max), patterns[0]); const heuristicValues = Object.values(heuristicResults); const dominantHeuristic = heuristicValues.length > 0 ? heuristicValues.reduce((max, h) => (h.confidence > max.confidence ? h : max), heuristicValues[0]) : null; let content = ""; let responseType = "general"; if (dominantPattern) { switch (dominantPattern.type) { case "question": content = this.generateQuestionResponse(input, dominantPattern); responseType = "question_response"; break; case "emotional": content = this.generateEmotionalResponse(input, dominantPattern); responseType = "emotional_response"; break; case "causal": content = this.generateCausalResponse(input, dominantPattern); responseType = "causal_response"; break; default: content = this.generateGeneralResponse(input, dominantPattern); } } else { const heuristicType = dominantHeuristic && typeof dominantHeuristic === "object" && "type" in dominantHeuristic ? dominantHeuristic.type : "general reasoning"; const heuristicReasoning = dominantHeuristic && typeof dominantHeuristic === "object" && "reasoning" in dominantHeuristic ? dominantHeuristic.reasoning : "standard approach"; // Include the input content in the response to ensure uniqueness content = `Regarding "${input}", I sense this relates to ${heuristicType}. My initial impression suggests a ${heuristicReasoning}.`; } return { content, confidence: dominantPattern?.confidence ?? 0.5, type: responseType, }; } generateQuestionResponse(input, pattern) { const questionWord = pattern.content[0]; switch (questionWord) { case "what": return `Based on the patterns I recognize in "${input}", this appears to be asking for identification or definition.`; case "how": return `This seems to be asking about a process or method regarding "${input}". My intuition suggests looking at the steps involved.`; case "why": return `This is asking for reasons or causes about "${input}". I sense there are underlying factors to consider.`; case "when": return `This is about timing regarding "${input}". My initial sense is that temporal context is important here.`; case "where": return `This is about location or context for "${input}". The spatial or situational aspect seems relevant.`; default: return `This appears to be an information-seeking question about "${input}" that requires careful consideration.`; } } generateEmotionalResponse(input, pattern) { return `I detect emotional content in "${input}". The tone suggests ${pattern.content[0]} feelings, which influences how I initially perceive the situation.`; } generateCausalResponse(input, pattern) { return `I notice causal relationships in "${input}" indicated by "${pattern.content.join(" ")}". This suggests cause-and-effect thinking is needed.`; } generateGeneralResponse(input, pattern) { // Extract key terms from input for more specific responses const inputWords = input.toLowerCase().split(/\s+/); const keyTerms = inputWords .filter((word) => word.length > 3 && ![ "what", "how", "why", "when", "where", "which", "that", "this", "with", "from", "they", "have", "been", "will", "would", "could", "should", ].includes(word)) .slice(0, 3); // Add some variability based on input hash const inputHash = input.split("").reduce((a, b) => { a = (a << 5) - a + b.charCodeAt(0); return a & a; }, 0); const variations = [ `I sense this relates to ${pattern.type}. My initial analysis of "${keyTerms.join(", ")}" suggests ${pattern.type}-based reasoning would be most effective.`, `My intuitive response recognizes a ${pattern.type} pattern here. The key elements "${keyTerms.join(", ")}" indicate this requires ${pattern.type} thinking.`, `This immediately strikes me as a ${pattern.type} situation. Based on "${keyTerms.join(", ")}", I'd approach this with ${pattern.type} reasoning.`, `I'm getting a strong ${pattern.type} impression from this. The terms "${keyTerms.join(", ")}" suggest ${pattern.type} analysis is needed.`, `My first instinct identifies this as ${pattern.type}. Looking at "${keyTerms.join(", ")}", ${pattern.type} reasoning seems most appropriate.`, ]; const selectedVariation = variations[Math.abs(inputHash) % variations.length]; return selectedVariation; } getConfidence(result) { // If result has a confidence property, use it if (typeof result === "object" && result !== null && "confidence" in result) { return Math.min(Math.max(result.confidence, 0.1), 0.9); } // Default confidence for System 1 return 0.6; } createReasoningPath(patterns, heuristicResults, response) { const steps = []; // Pattern recognition step if (patterns.length > 0) { steps.push({ type: ReasoningType.PATTERN_MATCH, content: `Recognized ${patterns.length} patterns: ${patterns .map((p) => p.type) .join(", ")}`, confidence: patterns.reduce((sum, p) => sum + p.confidence, 0) / patterns.length, alternatives: patterns.slice(1, 4).map((p) => ({ content: `Alternative pattern: ${p.type}`, confidence: p.confidence, reasoning: `Pattern salience: ${p.salience}`, })), }); } // Heuristic application step - use different types based on heuristic const heuristicNames = Object.keys(heuristicResults); if (heuristicNames.length > 0) { const avgConfidence = Object.values(heuristicResults).reduce((sum, h) => sum + h.confidence, 0) / heuristicNames.length; // Use HEURISTIC type for heuristic-based reasoning steps.push({ type: ReasoningType.HEURISTIC, content: `Applied heuristics: ${heuristicNames.join(", ")}`, confidence: avgConfidence, alternatives: Object.entries(heuristicResults) .slice(0, 3) .map(([name, result]) => ({ content: `${name}: ${result.result}`, confidence: result.confidence, reasoning: `Heuristic application`, })), }); // Add specific reasoning types based on heuristics used if (heuristicNames.includes("availability")) { steps.push({ type: ReasoningType.PROBABILISTIC, content: `Availability heuristic suggests high probability based on ease of recall`, confidence: heuristicResults.availability?.confidence || 0.5, alternatives: [], }); } if (heuristicNames.includes("representativeness")) { steps.push({ type: ReasoningType.ANALOGICAL, content: `Representativeness suggests similarity to known prototypes`, confidence: heuristicResults.representativeness?.confidence || 0.5, alternatives: [], }); } } // Contextual assessment step steps.push({ type: ReasoningType.CONTEXTUAL, content: `Contextual assessment based on immediate impressions and situational cues`, confidence: 0.7, alternatives: [], }); // Intuitive conclusion step - use INDUCTIVE for intuitive leaps steps.push({ type: ReasoningType.INDUCTIVE, content: `Intuitive response: ${response.content}`, confidence: this.getConfidence(response), alternatives: [], }); return steps; } assessEmotionalContext(_input, patterns) { const emotionalPatterns = patterns.filter((p) => p.type === "emotional"); let valence = 0; let arousal = 0.3; // Base arousal for System 1 const dominance = 0.7; // System 1 tends to be confident if (emotionalPatterns.length > 0) { // Simple emotional assessment based on detected patterns const positiveWords = [ "good", "great", "excellent", "happy", "love", "amazing", "wonderful", ]; const negativeWords = [ "bad", "terrible", "hate", "awful", "horrible", "sad", "angry", ]; for (const pattern of emotionalPatterns) { const word = pattern.content[0]; if (positiveWords.includes(word)) { valence += 0.3; arousal += 0.2; } else if (negativeWords.includes(word)) { valence -= 0.3; arousal += 0.3; } } } return { valence: Math.max(-1, Math.min(1, valence)), arousal: Math.max(0, Math.min(1, arousal)), dominance: Math.max(0, Math.min(1, dominance)), specific_emotions: new Map([ ["confidence", dominance], ["curiosity", arousal * 0.8], ["uncertainty", 1 - dominance], ]), }; } process(input) { return this.processIntuitive(input); } reset() { this.patternCache.clear(); this.lastActivity = 0; } getStatus() { return { name: "IntuitiveProcessor", initialized: this.initialized, active: Date.now() - this.lastActivity < 30000, // Active if used in last 30 seconds last_activity: this.lastActivity, error: "", }; } } //# sourceMappingURL=IntuitiveProcessor.js.map