@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
JavaScript
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;
}
}