UNPKG

@polybiouslabs/polybious

Version:

Polybius is a next-generation intelligent agent framework built for adaptability across diverse domains. It merges contextual awareness, multi-agent collaboration, and predictive reasoning to deliver dynamic, self-optimizing performance.

244 lines (243 loc) 10.6 kB
import { MemorySystem } from './memory'; import { logger } from '../config/logger'; export class PerformancePredictor { memory; model; personality; constructor(memory, personality) { this.memory = memory; this.personality = personality; this.model = { weights: { length: 0.1, hasHashtags: 0.2, hashtagCount: -0.05, hasLinks: 0.15, hasEmojis: 0.1, emojiCount: -0.02, hasQuestion: 0.25, hasExclamation: 0.1, sentiment: 0.3, readabilityScore: 0.2, timeOfDay: 0.1, dayOfWeek: 0.05 }, bias: 0.5, accuracy: 0.0, trainingCount: 0 }; } async predictEngagement(content) { const features = this.extractFeatures(content); const score = this.calculateScore(features); const confidence = Math.min(0.95, this.model.accuracy * (this.model.trainingCount / 100)); // Calculate factor contributions const factors = {}; for (const [feature, value] of Object.entries(features)) { const weight = this.model.weights[feature] || 0; factors[feature] = (typeof value === 'number' ? value : (value ? 1 : 0)) * weight; } const recommendations = this.generateRecommendations(features, factors); return { score, confidence, factors, recommendations }; } async trainModel(contentHistory) { if (contentHistory.length < 10) { logger.warn('Insufficient data for model training', { samples: contentHistory.length }); return; } logger.info('Training performance prediction model', { samples: contentHistory.length }); const trainingData = contentHistory.map(item => ({ features: this.extractFeatures(item.content), target: this.normalizePerformance(item.performance) })); // Simple gradient descent training const learningRate = 0.01; const epochs = 100; for (let epoch = 0; epoch < epochs; epoch++) { let totalError = 0; for (const sample of trainingData) { const predicted = this.calculateScore(sample.features); const error = sample.target - predicted; totalError += error * error; // Update weights for (const [feature, value] of Object.entries(sample.features)) { const featureValue = typeof value === 'number' ? value : (value ? 1 : 0); this.model.weights[feature] += learningRate * error * featureValue; } // Update bias this.model.bias += learningRate * error; } if (epoch % 20 === 0) { logger.debug('Training progress', { epoch, error: Math.sqrt(totalError / trainingData.length) }); } } // Calculate accuracy on training data (in production, use validation set) let correct = 0; for (const sample of trainingData) { const predicted = this.calculateScore(sample.features); const error = Math.abs(predicted - sample.target); if (error < 0.2) correct++; // Within 20% is considered correct } this.model.accuracy = correct / trainingData.length; this.model.trainingCount = trainingData.length; logger.info('Model training completed', { accuracy: this.model.accuracy, trainingCount: this.model.trainingCount }); } async getOptimizationSuggestions(content) { const currentPrediction = await this.predictEngagement(content); const optimizedVersions = []; // Try different optimizations const optimizations = [ { name: 'Add question', apply: (text) => text.includes('?') ? text : text + ' What do you think?', condition: (text) => !text.includes('?') }, { name: 'Add emoji', apply: (text) => text + ' ✨', condition: (text) => !/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]/gu.test(text) }, { name: 'Add hashtag', apply: (text) => text + ' #insight', condition: (text) => !text.includes('#') }, { name: 'Shorten content', apply: (text) => text.length > 100 ? text.substring(0, 100) + '...' : text, condition: (text) => text.length > 150 } ]; for (const opt of optimizations) { if (opt.condition(content)) { const optimized = opt.apply(content); const prediction = await this.predictEngagement(optimized); if (prediction.score > currentPrediction.score) { optimizedVersions.push({ content: optimized, score: prediction.score, changes: [opt.name] }); } } } // Sort by score improvement optimizedVersions.sort((a, b) => b.score - a.score); return { currentScore: currentPrediction.score, optimizedVersions: optimizedVersions.slice(0, 3) }; } extractFeatures(content) { const now = new Date(); return { length: content.length, hasHashtags: content.includes('#'), hashtagCount: (content.match(/#\w+/g) || []).length, hasLinks: /https?:\/\/\S+/.test(content), hasEmojis: /[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]/gu.test(content), emojiCount: (content.match(/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]/gu) || []).length, hasQuestion: content.includes('?'), hasExclamation: content.includes('!'), sentiment: this.calculateSentiment(content), readabilityScore: this.calculateReadability(content), timeOfDay: now.getHours(), dayOfWeek: now.getDay() }; } calculateScore(features) { let score = this.model.bias; for (const [feature, value] of Object.entries(features)) { const weight = this.model.weights[feature] || 0; const featureValue = typeof value === 'number' ? value : (value ? 1 : 0); score += weight * featureValue; } // Normalize to 0-1 range using sigmoid return 1 / (1 + Math.exp(-score)); } normalizePerformance(performance) { // Simple normalization based on engagement rate const engagements = performance.likes + performance.shares * 2 + performance.comments * 3; const rate = engagements / Math.max(1, performance.views); return Math.min(1, rate * 10); // Scale to 0-1 } calculateSentiment(content) { const positiveWords = ['good', 'great', 'amazing', 'love', 'excellent', 'perfect', 'wonderful']; const negativeWords = ['bad', 'terrible', 'hate', 'awful', 'worst', 'horrible']; const words = content.toLowerCase().split(/\s+/); let score = 0; for (const word of words) { if (positiveWords.includes(word)) score += 1; if (negativeWords.includes(word)) score -= 1; } return Math.max(-1, Math.min(1, score / words.length * 10)); } calculateReadability(content) { const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 0); const words = content.split(/\s+/).filter(w => w.length > 0); if (sentences.length === 0 || words.length === 0) return 0; const avgWordsPerSentence = words.length / sentences.length; const avgSyllablesPerWord = words.reduce((sum, word) => sum + this.countSyllables(word), 0) / words.length; // Simplified Flesch Reading Ease const score = 206.835 - (1.015 * avgWordsPerSentence) - (84.6 * avgSyllablesPerWord); return Math.max(0, Math.min(100, score)) / 100; // Normalize to 0-1 } countSyllables(word) { word = word.toLowerCase(); if (word.length <= 3) return 1; const vowels = 'aeiouy'; let count = 0; let previousWasVowel = false; for (let i = 0; i < word.length; i++) { const isVowel = vowels.includes(word[i]); if (isVowel && !previousWasVowel) { count++; } previousWasVowel = isVowel; } // Handle silent e if (word.endsWith('e')) count--; return Math.max(1, count); } generateRecommendations(features, factors) { const recommendations = []; // Sort factors by impact const sortedFactors = Object.entries(factors) .sort(([, a], [, b]) => Math.abs(b) - Math.abs(a)); for (const [factor, impact] of sortedFactors.slice(0, 3)) { if (Math.abs(impact) < 0.1) continue; if (factor === 'hasQuestion' && !features.hasQuestion && impact > 0) { recommendations.push('Add a question to increase engagement'); } else if (factor === 'sentiment' && features.sentiment < 0 && impact > 0) { recommendations.push('Use more positive language'); } else if (factor === 'hasHashtags' && !features.hasHashtags && impact > 0) { recommendations.push('Consider adding relevant hashtags'); } else if (factor === 'length' && features.length > 200 && impact < 0) { recommendations.push('Try shortening the content for better engagement'); } else if (factor === 'hasEmojis' && !features.hasEmojis && impact > 0) { recommendations.push('Add emojis to make content more engaging'); } } if (recommendations.length === 0) { recommendations.push('Content looks good! Consider A/B testing for optimization.'); } return recommendations; } }