UNPKG

contaigents

Version:

Modular AI Content Ecosystem with Audio Generation

246 lines (245 loc) 9.86 kB
import { LocalKnowledgeBase } from './LocalKnowledgeBase.js'; /** * Learning engine for continuous improvement and pattern recognition */ export class LearningEngine { constructor() { this.learningHistory = new Map(); this.knowledgeBase = new LocalKnowledgeBase(); } /** * Learn from successful tool execution */ async learnFromToolSuccess(toolName, parameters, result, context) { const pattern = { tool: toolName, parameters, context: { projectType: context.metadata.type, fileCount: context.fileTree.length }, outcome: 'success', timestamp: Date.now() }; await this.knowledgeBase.storeKnowledge('pattern', `Successful ${toolName} usage: ${JSON.stringify(pattern)}`, 'tool_execution', 0.8); this.recordLearningEvent('tool_success', pattern); } /** * Learn from tool failures */ async learnFromToolFailure(toolName, parameters, error, context) { const antiPattern = { tool: toolName, parameters, context: { projectType: context.metadata.type, fileCount: context.fileTree.length }, error, timestamp: Date.now() }; await this.knowledgeBase.storeKnowledge('rule', `Avoid ${toolName} with these parameters: ${JSON.stringify(antiPattern)}`, 'tool_failure', 0.7); this.recordLearningEvent('tool_failure', antiPattern); } /** * Learn from conversation patterns */ async learnFromConversation(conversation) { const userMessages = conversation.messages.filter(m => m.role === 'user'); const assistantMessages = conversation.messages.filter(m => m.role === 'assistant'); // Learn from successful conversation patterns if (conversation.status === 'completed' && userMessages.length > 1) { const conversationPattern = { projectType: conversation.context.metadata.type, messageCount: conversation.messages.length, duration: conversation.updatedAt - conversation.createdAt, topics: this.extractTopics(userMessages.map(m => m.content)), successful: true }; await this.knowledgeBase.storeKnowledge('pattern', `Successful conversation pattern: ${JSON.stringify(conversationPattern)}`, 'conversation', 0.6); } // Learn user preferences await this.learnUserPreferences(userMessages, conversation.context); } /** * Learn user preferences from messages */ async learnUserPreferences(userMessages, context) { const preferences = this.extractPreferences(userMessages.map(m => m.content)); for (const preference of preferences) { await this.knowledgeBase.storeKnowledge('preference', `User prefers ${preference} in ${context.metadata.type} projects`, 'user_interaction', 0.5); } } /** * Get recommendations based on learning */ async getRecommendations(context, currentAction) { const relevantKnowledge = await this.knowledgeBase.getRelevantKnowledge(context, 10); const recommendations = []; // Generate recommendations from patterns const patterns = relevantKnowledge.filter(k => k.type === 'pattern'); for (const pattern of patterns.slice(0, 3)) { try { const patternData = JSON.parse(pattern.content); if (patternData.tool && currentAction !== patternData.tool) { recommendations.push(`Consider using ${patternData.tool} - it has worked well in similar contexts`); } } catch (error) { // Skip malformed patterns } } // Generate recommendations from rules const rules = relevantKnowledge.filter(k => k.type === 'rule'); for (const rule of rules.slice(0, 2)) { recommendations.push(`Recommendation: ${rule.content}`); } return recommendations; } /** * Predict success probability for an action */ async predictSuccess(toolName, parameters, context) { const relevantKnowledge = await this.knowledgeBase.getRelevantKnowledge(context); let successCount = 0; let failureCount = 0; let totalRelevance = 0; for (const knowledge of relevantKnowledge) { try { const data = JSON.parse(knowledge.content); if (data.tool === toolName) { const relevance = this.calculateParameterSimilarity(parameters, data.parameters || {}); totalRelevance += relevance; if (data.outcome === 'success' || knowledge.type === 'pattern') { successCount += relevance; } else if (data.error || knowledge.type === 'rule') { failureCount += relevance; } } } catch (error) { // Skip malformed knowledge } } const total = successCount + failureCount; const probability = total > 0 ? successCount / total : 0.5; // Default to neutral if no data const confidence = Math.min(1, totalRelevance / 3); // Confidence based on amount of relevant data const reasoning = total > 0 ? `Based on ${Math.round(total)} similar past executions` : 'No historical data available for this action'; return { probability, confidence, reasoning }; } /** * Optimize parameters based on learning */ async optimizeParameters(toolName, baseParameters, context) { const relevantKnowledge = await this.knowledgeBase.getRelevantKnowledge(context); const improvements = []; const optimizedParameters = { ...baseParameters }; // Find successful patterns for this tool const successfulPatterns = relevantKnowledge .filter(k => k.type === 'pattern') .map(k => { try { return JSON.parse(k.content); } catch { return null; } }) .filter(data => data && data.tool === toolName && data.outcome === 'success'); // Optimize based on successful patterns for (const pattern of successfulPatterns) { if (pattern.parameters) { for (const [key, value] of Object.entries(pattern.parameters)) { if (key in baseParameters && baseParameters[key] !== value) { optimizedParameters[key] = value; improvements.push(`Changed ${key} to ${value} based on successful pattern`); } } } } return { optimizedParameters, improvements }; } /** * Generate learning insights */ async generateInsights() { const stats = await this.knowledgeBase.getKnowledgeStats(); const topPatterns = stats.mostUsed.map(k => k.content.substring(0, 100) + '...'); const recommendations = [ `You have ${stats.total} learnings with ${(stats.averageConfidence * 100).toFixed(1)}% average confidence`, 'Most successful patterns involve consistent tool usage', 'Consider reviewing and cleaning up low-confidence learnings' ]; const improvementAreas = [ 'Increase tool usage consistency', 'Provide more feedback on results', 'Explore new tool combinations' ]; return { totalLearnings: stats.total, topPatterns, recommendations, improvementAreas }; } /** * Helper methods */ recordLearningEvent(type, data) { if (!this.learningHistory.has(type)) { this.learningHistory.set(type, []); } const events = this.learningHistory.get(type); events.push(data); // Keep only recent events if (events.length > 100) { events.splice(0, events.length - 100); } } extractTopics(messages) { const topics = new Set(); const topicKeywords = ['file', 'analyze', 'write', 'read', 'summarize', 'classify', 'project', 'documentation']; for (const message of messages) { const words = message.toLowerCase().split(/\s+/); for (const keyword of topicKeywords) { if (words.includes(keyword)) { topics.add(keyword); } } } return Array.from(topics); } extractPreferences(messages) { const preferences = []; const preferencePatterns = [ /prefer\s+(\w+)/gi, /like\s+(\w+)/gi, /want\s+(\w+)/gi, /need\s+(\w+)/gi ]; for (const message of messages) { for (const pattern of preferencePatterns) { const matches = message.match(pattern); if (matches) { preferences.push(...matches); } } } return preferences.slice(0, 5); // Limit to top 5 preferences } calculateParameterSimilarity(params1, params2) { const keys1 = Object.keys(params1); const keys2 = Object.keys(params2); const allKeys = new Set([...keys1, ...keys2]); let matches = 0; for (const key of allKeys) { if (params1[key] === params2[key]) { matches++; } } return allKeys.size > 0 ? matches / allKeys.size : 0; } }