UNPKG

mcp-prompt-optimizer-local

Version:

Advanced cross-platform prompt optimization with MCP integration and 120+ optimization rules

265 lines (233 loc) 11 kB
/** * Goal Alignment Calculator - Core optimization goal scoring system * Implements weighted goal matching with partial credit scoring * Matches Python implementation from ai_aware_optimization_rules.py */ // Goal importance weights based on frequency of user requests const GOAL_WEIGHTS = { 'clarity': 1.0, // Most commonly requested 'actionability': 1.0, // Very common in user requests 'structure': 0.9, // Frequently requested 'comprehensiveness': 0.8, // Often requested for complex tasks 'quality-enhancement': 0.7, // Common for content creation 'specificity': 0.7, // Important for detailed requests 'creative-enhancement': 0.6, // For creative tasks 'technical-precision': 0.6, // For technical contexts 'analytical-depth': 0.5, // For analysis tasks 'educational-value': 0.5, // For learning-focused requests 'professionalism': 0.4, // Less commonly explicit 'safety': 0.4, // Important but implicit 'conciseness': 0.3, // Sometimes requested 'token-efficiency': 0.2, // Rarely explicit 'parameter-preservation': 0.2, // Context-specific 'persuasiveness': 0.6, // For marketing/sales content 'context-specificity': 0.5, // For contextual requests 'outcome-specification': 0.5, // For specific outcomes 'confidence': 0.4, // For decisive language 'directness': 0.4, // For clear communication }; // Goal relationships for partial credit scoring const GOAL_RELATIONSHIPS = { 'clarity': ['comprehensiveness', 'structure', 'educational-value', 'specificity'], 'actionability': ['structure', 'specificity', 'technical-precision', 'clarity'], 'structure': ['clarity', 'comprehensiveness', 'actionability', 'specificity'], 'comprehensiveness': ['clarity', 'analytical-depth', 'quality-enhancement', 'educational-value'], 'technical-precision': ['actionability', 'safety', 'quality-enhancement', 'specificity'], 'quality-enhancement': ['comprehensiveness', 'technical-precision', 'professionalism', 'creative-enhancement'], 'creative-enhancement': ['quality-enhancement', 'comprehensiveness', 'specificity'], 'analytical-depth': ['comprehensiveness', 'structure', 'educational-value'], 'specificity': ['clarity', 'actionability', 'technical-precision', 'structure'], 'persuasiveness': ['quality-enhancement', 'structure', 'professionalism'], 'educational-value': ['clarity', 'comprehensiveness', 'structure', 'analytical-depth'], 'professionalism': ['quality-enhancement', 'structure', 'clarity'], 'safety': ['technical-precision', 'quality-enhancement'], 'conciseness': ['clarity', 'token-efficiency'], 'token-efficiency': ['conciseness', 'directness'], 'parameter-preservation': ['technical-precision', 'safety'], 'context-specificity': ['clarity', 'actionability', 'specificity'], 'outcome-specification': ['specificity', 'actionability', 'structure'], 'confidence': ['directness', 'clarity'], 'directness': ['clarity', 'confidence', 'conciseness'] }; class GoalAlignmentCalculator { constructor(logger = null) { this.logger = logger; this.ruleMetrics = new Map(); } /** * Calculate goal alignment score for a rule against user goals * @param {string} ruleName - Name of the optimization rule * @param {Array<string>} userGoals - List of user optimization goals * @param {Array<string>} ruleGoals - Goals that the rule addresses * @returns {number} - Alignment score between 0.0 and 1.0 */ calculateScore(ruleName, userGoals, ruleGoals) { if (!ruleGoals || ruleGoals.length === 0) { // Foundation/universal rules get high baseline score if (ruleName.includes('foundation') || ruleName.includes('universal')) { return 0.8; } this._logWarning(ruleName, `Rule missing target goals; using default score 0.4`); this._trackMisconfigured(ruleName); return 0.4; } const directMatches = new Set(userGoals.filter(goal => ruleGoals.includes(goal))); if (directMatches.size === 0) { // Check for related goal matches (partial credit) let relatedScore = 0; for (const userGoal of userGoals) { const relatedGoals = GOAL_RELATIONSHIPS[userGoal] || []; const relatedMatches = relatedGoals.filter(goal => ruleGoals.includes(goal)); if (relatedMatches.length > 0) { // Give 40% credit for related goals const relatedWeight = relatedMatches.reduce( (sum, goal) => sum + (GOAL_WEIGHTS[goal] || 0.5), 0 ); relatedScore += relatedWeight * 0.4; } } if (relatedScore > 0) { // Normalize related score and ensure minimum threshold const totalTargetWeight = ruleGoals.reduce( (sum, goal) => sum + (GOAL_WEIGHTS[goal] || 0.5), 0 ); const finalScore = Math.min(relatedScore / totalTargetWeight, 0.5); const result = Math.max(finalScore, 0.1); // Minimum for related matches this._logDebug(ruleName, `Related goal alignment: ${result.toFixed(2)} (0 direct, related matches found)`); return result; } else { return 0.0; } } // Calculate weighted match score for direct matches const totalMatchWeight = Array.from(directMatches).reduce( (sum, goal) => sum + (GOAL_WEIGHTS[goal] || 0.5), 0 ); const totalTargetWeight = ruleGoals.reduce( (sum, goal) => sum + (GOAL_WEIGHTS[goal] || 0.5), 0 ); const weightedScore = totalMatchWeight / totalTargetWeight; // Bonus for covering multiple user goals const coverageBonus = userGoals.length > 0 ? (directMatches.size / userGoals.length) * 0.2 : 0; // Additional related goal bonus let relatedBonus = 0; for (const userGoal of userGoals) { if (!directMatches.has(userGoal)) { const relatedGoals = GOAL_RELATIONSHIPS[userGoal] || []; const relatedMatches = relatedGoals.filter(goal => ruleGoals.includes(goal)); if (relatedMatches.length > 0) { relatedBonus += 0.1; // Small bonus for related goals } } } // Combine scores let finalScore = weightedScore + coverageBonus + Math.min(relatedBonus, 0.3); // Minimum score for any direct match (prevents complete exclusion) finalScore = Math.max(finalScore, 0.15); this._logDebug(ruleName, `Weighted goal alignment: ${finalScore.toFixed(2)} (matched ${directMatches.size}/${ruleGoals.length} goals, coverage: ${coverageBonus.toFixed(2)})`); return Math.min(finalScore, 1.0); } /** * Get dynamic threshold based on rule characteristics * @param {Object} rule - Optimization rule object * @param {string} context - AI context type * @param {number} sophistication - Sophistication score * @returns {number} - Dynamic threshold value */ getDynamicThreshold(rule, context, sophistication) { // Foundation rules have very low threshold if (rule.universalApplicability || rule.name.includes('foundation')) { return 0.01; } // High-priority rules get lower threshold if (rule.priority >= 10) { return 0.05; } // Rules with many goals get lower threshold (they're harder to match) const numGoals = rule.goals ? rule.goals.length : 0; if (numGoals >= 5) { return 0.06; // Very low for complex rules } else if (numGoals >= 4) { return 0.08; } else if (numGoals >= 3) { return 0.10; } else { return 0.12; // Higher threshold for simple rules } // Context-specific thresholds if (rule.contexts && rule.contexts.includes(context)) { return 0.08; // Lower threshold for context-matched rules } // Hotfix rules get special treatment if (rule.name.includes('hotfix')) { return 0.05; } return 0.08; // Default fallback threshold } /** * Get rule performance metrics * @returns {Object} - Performance metrics by rule */ getRuleMetrics() { const metrics = {}; for (const [ruleName, data] of this.ruleMetrics.entries()) { metrics[ruleName] = { ...data }; } return metrics; } /** * Clear rule metrics */ clearRuleMetrics() { this.ruleMetrics.clear(); this._logDebug('goal-alignment', 'Rule metrics cleared'); } /** * Get performance summary * @returns {Object} - Summary of rule performance */ getRulePerformanceSummary() { const totalApplied = Array.from(this.ruleMetrics.values()) .reduce((sum, metrics) => sum + (metrics.applied || 0), 0); const totalAttempts = Array.from(this.ruleMetrics.values()) .reduce((sum, metrics) => sum + (metrics.applied || 0) + (metrics.skipped || 0) + (metrics.failed || 0), 0); const rulesWithIssues = []; const topPerforming = []; for (const [name, metrics] of this.ruleMetrics.entries()) { if (metrics.misconfigured > 0 || (metrics.applied > 0 && metrics.failed > metrics.applied)) { rulesWithIssues.push(name); } topPerforming.push([name, metrics.applied || 0]); } topPerforming.sort((a, b) => b[1] - a[1]); return { totalRuleAttempts: totalAttempts, totalRulesApplied: totalApplied, applicationRate: totalAttempts > 0 ? totalApplied / totalAttempts : 0, rulesWithIssues, topPerformingRules: topPerforming.slice(0, 5) }; } // Private helper methods _logDebug(ruleName, message) { if (this.logger && this.logger.debug) { this.logger.debug(`Rule ${ruleName}: ${message}`); } } _logWarning(ruleName, message) { if (this.logger && this.logger.warning) { this.logger.warning(`Rule ${ruleName}: ${message}`); } } _trackMisconfigured(ruleName) { if (!this.ruleMetrics.has(ruleName)) { this.ruleMetrics.set(ruleName, { applied: 0, skipped: 0, failed: 0, misconfigured: 0 }); } this.ruleMetrics.get(ruleName).misconfigured++; } } module.exports = { GoalAlignmentCalculator, GOAL_WEIGHTS, GOAL_RELATIONSHIPS };