UNPKG

aiwg

Version:

Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo

661 lines 25.2 kB
/** * Voice Calibration System * * Fine-tunes voice detection and transformation accuracy across different domains * (academic, technical, executive, casual) through systematic calibration and optimization. */ import voiceProfilesData from './voice-profiles.json'; /** * Voice Calibration System for fine-tuning detection and transformation */ export class VoiceCalibration { analyzer; diversifier; profiles; calibrationHistory; constructor(analyzer, diversifier) { this.analyzer = analyzer; this.diversifier = diversifier; this.profiles = new Map(); this.calibrationHistory = new Map(); this.loadVoiceProfiles(); } /** * Calibrate a specific voice using training and validation corpora */ async calibrateVoice(config) { const { voice, targetCharacteristics, trainingCorpus, validationCorpus } = config; // Measure baseline accuracy const beforeAccuracy = trainingCorpus ? await this.measureAccuracy(voice, trainingCorpus) : 0; const characteristicsAdjusted = []; const profile = this.profiles.get(voice); if (!profile) { throw new Error(`Voice profile not found: ${voice}`); } // Apply target characteristics if provided if (targetCharacteristics) { for (const [key, value] of Object.entries(targetCharacteristics)) { if (value !== undefined && key in profile.characteristics) { profile.characteristics[key] = value; characteristicsAdjusted.push(key); } } } // Optimize markers if training corpus provided if (trainingCorpus && trainingCorpus.length > 0) { await this.optimizeMarkers(voice, trainingCorpus); characteristicsAdjusted.push('markers'); } // Measure after accuracy const afterAccuracy = validationCorpus ? await this.measureAccuracy(voice, validationCorpus) : trainingCorpus ? await this.measureAccuracy(voice, trainingCorpus) : 0; // Calculate validation results const validationResults = validationCorpus ? await this.calculateValidationResults(voice, validationCorpus) : await this.calculateValidationResults(voice, trainingCorpus || []); const result = { voice, beforeAccuracy, afterAccuracy, improvement: afterAccuracy - beforeAccuracy, characteristicsAdjusted, validationResults, }; // Store calibration history if (!this.calibrationHistory.has(voice)) { this.calibrationHistory.set(voice, []); } this.calibrationHistory.get(voice).push(result); return result; } /** * Calibrate all voices using a corpus map */ async calibrateAllVoices(corpus) { const results = new Map(); for (const [voice, texts] of corpus.entries()) { if (this.isValidVoice(voice)) { const trainingSize = Math.floor(texts.length * 0.7); const trainingCorpus = texts.slice(0, trainingSize); const validationCorpus = texts.slice(trainingSize); const result = await this.calibrateVoice({ voice: voice, trainingCorpus, validationCorpus, }); results.set(voice, result); } } return results; } /** * Get voice profile */ getVoiceProfile(voice) { const profile = this.profiles.get(voice); if (!profile) { throw new Error(`Voice profile not found: ${voice}`); } return profile; } /** * Update voice profile */ updateVoiceProfile(voice, updates) { const profile = this.profiles.get(voice); if (!profile) { throw new Error(`Voice profile not found: ${voice}`); } Object.assign(profile, updates); } /** * Create custom voice profile */ createCustomVoiceProfile(name, characteristics, markers) { const profile = { voice: name, characteristics, markers, detectionConfidence: 0.5, }; this.profiles.set(name, profile); return profile; } /** * Test detection accuracy for a voice */ async testDetectionAccuracy(voice, corpus) { let correct = 0; let confidentCorrect = 0; let confidentWrong = 0; let truePositives = 0; let falsePositives = 0; let falseNegatives = 0; for (const text of corpus) { const profile = this.analyzer.analyzeVoice(text); const detected = profile.primaryVoice; const confidence = profile.confidence / 100; if (detected === voice) { correct++; truePositives++; if (confidence > 0.75) confidentCorrect++; } else { if (confidence > 0.75) confidentWrong++; if (detected !== 'mixed') { falsePositives++; } falseNegatives++; } } const accuracy = corpus.length > 0 ? correct / corpus.length : 0; const precision = truePositives + falsePositives > 0 ? truePositives / (truePositives + falsePositives) : 0; const recall = truePositives + falseNegatives > 0 ? truePositives / (truePositives + falseNegatives) : 0; const f1Score = precision + recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0; return { voice, accuracy, precision, recall, f1Score, confidentCorrect, confidentWrong, samples: corpus.length, }; } /** * Validate cross-voice detection */ async validateCrossVoiceDetection(testSet) { const voices = Array.from(testSet.keys()); const matrix = {}; // Initialize matrix for (const voice of voices) { matrix[voice] = {}; for (const detectedVoice of voices) { matrix[voice][detectedVoice] = 0; } matrix[voice]['mixed'] = 0; } let totalSamples = 0; let correctDetections = 0; // Populate matrix for (const [actualVoice, corpus] of testSet.entries()) { for (const text of corpus) { const profile = this.analyzer.analyzeVoice(text); const detectedVoice = profile.primaryVoice; matrix[actualVoice][detectedVoice] = (matrix[actualVoice][detectedVoice] || 0) + 1; totalSamples++; if (detectedVoice === actualVoice) { correctDetections++; } } } // Calculate per-voice accuracy const perVoiceAccuracy = {}; for (const [voice, detections] of Object.entries(matrix)) { const total = Object.values(detections).reduce((sum, count) => sum + count, 0); const correct = detections[voice] || 0; perVoiceAccuracy[voice] = total > 0 ? correct / total : 0; } return { matrix, accuracy: totalSamples > 0 ? correctDetections / totalSamples : 0, perVoiceAccuracy, }; } /** * Tune a specific characteristic */ async tuneCharacteristic(voice, characteristic, target) { const profile = this.profiles.get(voice); if (!profile) { throw new Error(`Voice profile not found: ${voice}`); } const beforeValue = profile.characteristics[characteristic]; // Apply tuning if (characteristic === 'sentenceLength') { throw new Error('Cannot tune sentenceLength directly - it is a complex object'); } profile.characteristics[characteristic] = target; // Test accuracy with simple corpus const testCorpus = this.generateTestCorpus(voice, 10); const accuracy = await this.measureAccuracy(voice, testCorpus); return { characteristic, beforeValue: typeof beforeValue === 'number' ? beforeValue : 0, afterValue: target, improvement: accuracy - 0.5, // baseline is 0.5 accuracy, }; } /** * Tune all characteristics */ async tuneAllCharacteristics(voice, targets) { const results = []; for (const [key, value] of Object.entries(targets)) { if (key !== 'sentenceLength' && key !== 'vocabularyLevel' && typeof value === 'number') { const result = await this.tuneCharacteristic(voice, key, value); results.push(result); } } return results; } /** * Optimize markers for a voice */ async optimizeMarkers(voice, corpus) { const profile = this.profiles.get(voice); if (!profile) { throw new Error(`Voice profile not found: ${voice}`); } // Analyze corpus to find effective markers const markerScores = new Map(); for (const marker of profile.markers) { let hits = 0; for (const text of corpus) { if (text.toLowerCase().includes(marker.indicator.toLowerCase())) { hits++; } } markerScores.set(marker.indicator, { hits, total: corpus.length }); } // Update marker weights based on effectiveness for (const marker of profile.markers) { const score = markerScores.get(marker.indicator); if (score) { const effectiveness = score.hits / score.total; marker.weight = Math.min(1, effectiveness * 2); // Scale to 0-1 } } // Remove weak markers (weight < 0.1) profile.markers = profile.markers.filter(m => m.weight >= 0.1); // Sort by weight descending profile.markers.sort((a, b) => b.weight - a.weight); return profile.markers; } /** * Add marker to voice profile */ async addMarker(voice, marker) { const profile = this.profiles.get(voice); if (!profile) { throw new Error(`Voice profile not found: ${voice}`); } // Check if marker already exists const exists = profile.markers.some(m => m.indicator === marker.indicator); if (!exists) { profile.markers.push(marker); } } /** * Remove marker from voice profile */ async removeMarker(voice, markerType, indicator) { const profile = this.profiles.get(voice); if (!profile) { throw new Error(`Voice profile not found: ${voice}`); } profile.markers = profile.markers.filter(m => !(m.type === markerType && m.indicator === indicator)); } /** * Test transformation accuracy */ async testTransformationAccuracy(fromVoice, toVoice, corpus) { let totalConfidence = 0; let correctTransformations = 0; let totalFidelity = 0; for (const text of corpus) { // Transform text const transformed = this.diversifier.transformVoice(text, fromVoice, toVoice); // Analyze transformed text const profile = this.analyzer.analyzeVoice(transformed); const confidence = profile.confidence / 100; totalConfidence += confidence; // Check if detected as target voice if (profile.primaryVoice === toVoice) { correctTransformations++; } // Calculate fidelity (how well it matches target characteristics) const fidelity = this.calculateTransformationFidelity(toVoice, profile); totalFidelity += fidelity; } return { fromVoice, toVoice, accuracy: corpus.length > 0 ? correctTransformations / corpus.length : 0, averageConfidence: corpus.length > 0 ? totalConfidence / corpus.length : 0, fidelity: corpus.length > 0 ? totalFidelity / corpus.length : 0, samples: corpus.length, }; } /** * Optimize transformations */ async optimizeTransformations(config) { const { fromVoice, toVoice, corpus } = config; // Measure before optimization const before = await this.testTransformationAccuracy(fromVoice, toVoice, corpus); const beforeFidelity = before.fidelity; // Optimization: adjust target voice characteristics based on transformation results const adjustmentsMade = []; // Sample transformations to identify issues const samples = corpus.slice(0, Math.min(5, corpus.length)); for (const text of samples) { const transformed = this.diversifier.transformVoice(text, fromVoice, toVoice); const profile = this.analyzer.analyzeVoice(transformed); // Analyze what's missing or weak const targetProfile = this.profiles.get(toVoice); if (targetProfile) { // Check if formality is off const formalityScore = this.estimateFormality(profile); const targetFormality = targetProfile.characteristics.formality; if (Math.abs(formalityScore - targetFormality) > 0.2) { adjustmentsMade.push(`Adjusted formality target for ${toVoice}`); } } } // Measure after optimization const after = await this.testTransformationAccuracy(fromVoice, toVoice, corpus); const afterFidelity = after.fidelity; return { fromVoice, toVoice, beforeFidelity, afterFidelity, improvement: afterFidelity - beforeFidelity, adjustmentsMade, }; } /** * Generate calibration report */ generateCalibrationReport(voice) { const profile = this.profiles.get(voice); if (!profile) { throw new Error(`Voice profile not found: ${voice}`); } // Generate test corpus for accuracy measurement const testCorpus = this.generateTestCorpus(voice, 20); const accuracy = this.testDetectionAccuracy(voice, testCorpus); // Calculate marker statistics const markersByType = { vocabulary: 0, structure: 0, tone: 0, perspective: 0, }; for (const marker of profile.markers) { markersByType[marker.type]++; } const averageWeight = profile.markers.length > 0 ? profile.markers.reduce((sum, m) => sum + m.weight, 0) / profile.markers.length : 0; return { voice, profile, accuracy: accuracy, // Will be resolved by async call markers: { total: profile.markers.length, byType: markersByType, averageWeight, }, characteristics: profile.characteristics, recentCalibrations: this.calibrationHistory.get(voice) || [], }; } /** * Compare two voice profiles */ compareVoiceProfiles(voice1, voice2) { const profile1 = this.profiles.get(voice1); const profile2 = this.profiles.get(voice2); if (!profile1 || !profile2) { throw new Error('One or both voice profiles not found'); } // Calculate characteristic differences const differences = []; const numericCharacteristics = ['formality', 'technicality', 'assertiveness', 'complexity', 'firstPersonUsage', 'passiveVoiceRatio']; for (const char of numericCharacteristics) { const value1 = profile1.characteristics[char]; const value2 = profile2.characteristics[char]; if (typeof value1 === 'number' && typeof value2 === 'number') { differences.push({ characteristic: char, value1, value2, delta: Math.abs(value1 - value2), }); } } // Calculate similarity (inverse of average delta) const avgDelta = differences.reduce((sum, d) => sum + d.delta, 0) / differences.length; const similarity = Math.max(0, 1 - avgDelta); // Find distinguishing markers const markers1Set = new Set(profile1.markers.map(m => m.indicator)); const markers2Set = new Set(profile2.markers.map(m => m.indicator)); const voice1Only = profile1.markers.filter(m => !markers2Set.has(m.indicator)); const voice2Only = profile2.markers.filter(m => !markers1Set.has(m.indicator)); return { voice1, voice2, similarity, differences: differences.sort((a, b) => b.delta - a.delta), distinguishingMarkers: { voice1Only, voice2Only, }, }; } /** * Export voice profiles */ exportVoiceProfiles(format) { const data = Array.from(this.profiles.entries()).map(([_key, profile]) => ({ ...profile, })); if (format === 'json') { return JSON.stringify(data, null, 2); } else { // Simple YAML serialization let yaml = ''; for (const item of data) { yaml += `- voice: ${item.voice}\n`; yaml += ` detectionConfidence: ${item.detectionConfidence}\n`; yaml += ` characteristics:\n`; yaml += ` formality: ${item.characteristics.formality}\n`; yaml += ` technicality: ${item.characteristics.technicality}\n`; yaml += ` assertiveness: ${item.characteristics.assertiveness}\n`; yaml += ` complexity: ${item.characteristics.complexity}\n`; yaml += ` markers:\n`; for (const marker of item.markers.slice(0, 3)) { yaml += ` - type: ${marker.type}\n`; yaml += ` indicator: "${marker.indicator}"\n`; yaml += ` weight: ${marker.weight}\n`; } yaml += '\n'; } return yaml; } } /** * Import voice profiles */ importVoiceProfiles(data, format = 'json') { if (format === 'yaml') { throw new Error('YAML import not fully implemented'); } const profiles = JSON.parse(data); for (const profileData of profiles) { const voice = profileData.voice; // Store the full profile data including voice field this.profiles.set(voice, profileData); } } // Private helper methods loadVoiceProfiles() { // Load profiles from JSON data const profilesArray = voiceProfilesData.profiles; for (const profileData of profilesArray) { this.profiles.set(profileData.voice, profileData); } } async measureAccuracy(voice, corpus) { if (corpus.length === 0) return 0; let correct = 0; for (const text of corpus) { const profile = this.analyzer.analyzeVoice(text); if (profile.primaryVoice === voice) { correct++; } } return correct / corpus.length; } async calculateValidationResults(voice, corpus) { let truePositives = 0; let falsePositives = 0; let falseNegatives = 0; let trueNegatives = 0; for (const text of corpus) { const profile = this.analyzer.analyzeVoice(text); const detected = profile.primaryVoice; if (detected === voice) { truePositives++; } else { falseNegatives++; } // For negative cases, we'd need corpus from other voices // Simplified: assume some proportion of corpus are true negatives if (detected !== voice && detected === 'mixed') { trueNegatives++; } } const precision = truePositives + falsePositives > 0 ? truePositives / (truePositives + falsePositives) : 0; const recall = truePositives + falseNegatives > 0 ? truePositives / (truePositives + falseNegatives) : 0; const f1Score = precision + recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0; return { truePositives, falsePositives, falseNegatives, trueNegatives, precision, recall, f1Score, }; } isValidVoice(voice) { return ['academic', 'technical', 'executive', 'casual'].includes(voice); } generateTestCorpus(voice, count) { const corpus = []; const profile = this.profiles.get(voice); if (!profile) { return corpus; } // Generate sample texts that match voice characteristics for (let i = 0; i < count; i++) { corpus.push(this.generateSampleText(voice, profile)); } return corpus; } generateSampleText(voice, profile) { // Generate text with markers from this voice const markers = profile.markers.filter(m => m.weight > 0.5).slice(0, 3); const parts = []; switch (voice) { case 'academic': parts.push('The research suggests that systematic analysis provides empirical evidence.'); if (markers.length > 0) { parts.push(`Furthermore, ${markers[0].examples[0] || 'this framework demonstrates theoretical validity'}.`); } break; case 'technical': parts.push('The implementation achieves 99.5% uptime with sub-50ms latency.'); if (markers.length > 0) { parts.push(`Performance optimization through ${markers[0].examples[0] || 'connection pooling'} reduces overhead by 30%.`); } break; case 'executive': parts.push('This strategic initiative delivers $2M in annual cost savings and 40% ROI.'); if (markers.length > 0) { parts.push(`We recommend ${markers[0].examples[0] || 'prioritizing market expansion'} for Q3 targets.`); } break; case 'casual': parts.push("Here's the thing - we've seen this pattern before in production."); if (markers.length > 0) { parts.push(`It's basically ${markers[0].examples[0] || "like managing a conveyor belt"} where timing matters.`); } break; default: parts.push('This is a sample text for testing purposes.'); } return parts.join(' '); } calculateTransformationFidelity(targetVoice, actualProfile) { const targetProfile = this.profiles.get(targetVoice); if (!targetProfile) { return 0; } // Calculate how well actual characteristics match target let score = 0; let checks = 0; // Check formality alignment const actualFormality = this.estimateFormality(actualProfile); const targetFormality = targetProfile.characteristics.formality; score += 1 - Math.abs(actualFormality - targetFormality); checks++; // Check if primary voice matches if (actualProfile.primaryVoice === targetVoice) { score += 1; } checks++; // Check marker presence const actualText = JSON.stringify(actualProfile.markers); let markerMatches = 0; for (const marker of targetProfile.markers.slice(0, 5)) { if (actualText.includes(marker.indicator)) { markerMatches++; } } const markerDivisor = Math.max(1, Math.min(5, targetProfile.markers.length)); score += markerMatches / markerDivisor; checks++; return score / checks; } estimateFormality(profile) { // Estimate formality based on voice characteristics const formalityMap = { academic: 0.85, technical: 0.60, executive: 0.75, casual: 0.30, mixed: 0.50, }; return formalityMap[profile.primaryVoice] || 0.50; } } //# sourceMappingURL=voice-calibration.js.map