CRITICAL CHECKPOINT - DO NOT PUSH TO GITHUB Recovery Status: - Successfully recovered brainy.ts from compiled JavaScript - All core v3.0 API methods functional (add, get, update, delete, relate, find, etc.) - Neural subsystem intact (562KB embedded patterns, NLP working) - Augmentation pipeline operational (20+ augmentations) - HNSW clustering system complete - Triple Intelligence compiled (needs constructor fix) - Test suite validates functionality Changes preserved: - 898 files with changes from last 3 days - 144,475 insertions - All augmentation improvements - All test coverage enhancements - Complete v3.0 feature set This is a LOCAL checkpoint only - contains recovered work after corruption incident. Created backup in .backups/brainy-full-20250910-151314.tar.gz Branch: recovery-checkpoint-20250910-151433 Date: Wed Sep 10 03:18:04 PM PDT 2025
559 lines
No EOL
24 KiB
JavaScript
559 lines
No EOL
24 KiB
JavaScript
/**
|
|
* Intelligent Verb Scoring Augmentation
|
|
*
|
|
* Enhances relationship quality through intelligent semantic scoring
|
|
* Provides context-aware relationship weights based on:
|
|
* - Semantic proximity of connected entities
|
|
* - Frequency-based amplification
|
|
* - Temporal decay modeling
|
|
* - Adaptive learning from usage patterns
|
|
*
|
|
* Critical for enterprise knowledge graphs with millions of relationships
|
|
*/
|
|
import { BaseAugmentation } from './brainyAugmentation.js';
|
|
export class IntelligentVerbScoringAugmentation extends BaseAugmentation {
|
|
constructor(config = {}) {
|
|
super();
|
|
this.name = 'IntelligentVerbScoring';
|
|
this.timing = 'around';
|
|
this.metadata = {
|
|
reads: ['type', 'verb', 'source', 'target'],
|
|
writes: ['weight', 'confidence', 'intelligentScoring']
|
|
}; // Adds scoring metadata to verbs
|
|
this.operations = ['addVerb', 'relate'];
|
|
this.priority = 10; // Enhancement feature - runs after core operations
|
|
// Augmentation metadata
|
|
this.category = 'core';
|
|
this.description = 'AI-powered intelligent scoring for relationship strength analysis';
|
|
this.relationshipStats = new Map();
|
|
this.metrics = {
|
|
relationshipsScored: 0,
|
|
averageSemanticScore: 0,
|
|
averageFrequencyScore: 0,
|
|
averageTemporalScore: 0,
|
|
averageConfidenceScore: 0,
|
|
adaptiveAdjustments: 0,
|
|
computationTimeMs: 0
|
|
};
|
|
this.config = {
|
|
enabled: config.enabled ?? true, // Smart by default!
|
|
// Semantic Analysis
|
|
enableSemanticScoring: config.enableSemanticScoring ?? true,
|
|
semanticThreshold: config.semanticThreshold ?? 0.3,
|
|
semanticWeight: config.semanticWeight ?? 0.4,
|
|
// Frequency Analysis
|
|
enableFrequencyAmplification: config.enableFrequencyAmplification ?? true,
|
|
frequencyDecay: config.frequencyDecay ?? 0.95, // 5% decay per occurrence
|
|
maxFrequencyBoost: config.maxFrequencyBoost ?? 2.0,
|
|
// Temporal Analysis
|
|
enableTemporalDecay: config.enableTemporalDecay ?? true,
|
|
temporalDecayRate: config.temporalDecayRate ?? 0.01, // 1% per day
|
|
temporalWindow: config.temporalWindow ?? 365, // 1 year
|
|
// Learning & Adaptation
|
|
enableAdaptiveLearning: config.enableAdaptiveLearning ?? true,
|
|
learningRate: config.learningRate ?? 0.1,
|
|
confidenceThreshold: config.confidenceThreshold ?? 0.3,
|
|
// Weight Management
|
|
minWeight: config.minWeight ?? 0.1,
|
|
maxWeight: config.maxWeight ?? 1.0,
|
|
baseWeight: config.baseWeight ?? 0.5
|
|
};
|
|
// Set enabled property based on config
|
|
this.enabled = this.config.enabled;
|
|
}
|
|
async onInitialize() {
|
|
if (this.config.enabled) {
|
|
this.log('Intelligent verb scoring initialized for enhanced relationship quality');
|
|
}
|
|
else {
|
|
this.log('Intelligent verb scoring disabled');
|
|
}
|
|
}
|
|
/**
|
|
* Get this augmentation instance for API compatibility
|
|
* Used by Brainy to access scoring methods
|
|
*/
|
|
getScoring() {
|
|
return this;
|
|
}
|
|
shouldExecute(operation, params) {
|
|
// For addVerb, params are passed as array: [sourceId, targetId, verbType, metadata, weight]
|
|
if (operation === 'addVerb' && this.config.enabled) {
|
|
return Array.isArray(params) && params.length >= 3;
|
|
}
|
|
// For relate method, params might be an object
|
|
if (operation === 'relate' && this.config.enabled) {
|
|
return params.sourceId && params.targetId && params.relationType;
|
|
}
|
|
return false;
|
|
}
|
|
async execute(operation, params, next) {
|
|
if (!this.shouldExecute(operation, params)) {
|
|
return next();
|
|
}
|
|
const startTime = Date.now();
|
|
try {
|
|
let sourceId, targetId, relationType, metadata;
|
|
let scoringResult = null;
|
|
// Extract parameters based on operation type
|
|
if (operation === 'addVerb' && Array.isArray(params)) {
|
|
// addVerb params: [sourceId, targetId, verbType, metadata, weight]
|
|
[sourceId, targetId, relationType, metadata] = params;
|
|
}
|
|
else if (operation === 'relate') {
|
|
// relate params might be an object
|
|
sourceId = params.sourceId;
|
|
targetId = params.targetId;
|
|
relationType = params.relationType;
|
|
metadata = params.metadata;
|
|
}
|
|
else {
|
|
return next();
|
|
}
|
|
// Skip if weight is already provided explicitly
|
|
if (Array.isArray(params) && params[4] !== undefined && params[4] !== null) {
|
|
return next();
|
|
}
|
|
// Get the nouns to compute scoring
|
|
const sourceNoun = await this.context?.brain.get(sourceId);
|
|
const targetNoun = await this.context?.brain.get(targetId);
|
|
// Compute intelligent scores with reasoning
|
|
scoringResult = await this.computeVerbScores(sourceNoun, targetNoun, relationType);
|
|
// For addVerb, modify the params array
|
|
if (operation === 'addVerb' && Array.isArray(params)) {
|
|
// Set the weight parameter (index 4)
|
|
params[4] = scoringResult.weight;
|
|
// Enhance metadata with scoring info
|
|
params[3] = {
|
|
...params[3],
|
|
intelligentScoring: {
|
|
weight: scoringResult.weight,
|
|
confidence: scoringResult.confidence,
|
|
reasoning: scoringResult.reasoning,
|
|
scoringMethod: this.getScoringMethodsUsed(),
|
|
computedAt: Date.now()
|
|
}
|
|
};
|
|
}
|
|
// Execute with enhanced parameters
|
|
const result = await next();
|
|
// Learn from this relationship
|
|
if (this.config.enableAdaptiveLearning && scoringResult) {
|
|
await this.updateRelationshipLearning(sourceId, targetId, relationType, scoringResult.weight);
|
|
}
|
|
// Update metrics
|
|
const computationTime = Date.now() - startTime;
|
|
if (scoringResult) {
|
|
this.updateMetrics(scoringResult.weight, computationTime);
|
|
}
|
|
return result;
|
|
}
|
|
catch (error) {
|
|
this.log(`Intelligent verb scoring error: ${error}`, 'error');
|
|
// Fallback to original parameters
|
|
return next();
|
|
}
|
|
}
|
|
async calculateIntelligentWeight(sourceId, targetId, relationType, metadata) {
|
|
let finalWeight = this.config.baseWeight;
|
|
let scoreComponents = {};
|
|
// 1. Semantic Proximity Score
|
|
if (this.config.enableSemanticScoring) {
|
|
const semanticScore = await this.calculateSemanticScore(sourceId, targetId);
|
|
scoreComponents.semantic = semanticScore;
|
|
finalWeight = finalWeight * (1 + semanticScore * this.config.semanticWeight);
|
|
}
|
|
// 2. Frequency Amplification Score
|
|
if (this.config.enableFrequencyAmplification) {
|
|
const frequencyScore = this.calculateFrequencyScore(sourceId, targetId, relationType);
|
|
scoreComponents.frequency = frequencyScore;
|
|
finalWeight = finalWeight * (1 + frequencyScore);
|
|
}
|
|
// 3. Temporal Relevance Score
|
|
if (this.config.enableTemporalDecay) {
|
|
const temporalScore = this.calculateTemporalScore(sourceId, targetId, relationType);
|
|
scoreComponents.temporal = temporalScore;
|
|
finalWeight = finalWeight * temporalScore;
|
|
}
|
|
// 4. Context Awareness (from metadata)
|
|
const contextScore = this.calculateContextScore(metadata);
|
|
scoreComponents.context = contextScore;
|
|
finalWeight = finalWeight * (1 + contextScore * 0.2);
|
|
// 5. Apply constraints
|
|
finalWeight = Math.max(this.config.minWeight, Math.min(this.config.maxWeight, finalWeight));
|
|
// Store detailed scoring for analysis
|
|
this.storeDetailedScoring(sourceId, targetId, relationType, {
|
|
finalWeight,
|
|
components: scoreComponents,
|
|
timestamp: Date.now()
|
|
});
|
|
return finalWeight;
|
|
}
|
|
async calculateSemanticScore(sourceId, targetId) {
|
|
try {
|
|
// Get embeddings for both entities
|
|
const sourceNoun = await this.context?.brain.get(sourceId);
|
|
const targetNoun = await this.context?.brain.get(targetId);
|
|
if (!sourceNoun?.vector || !targetNoun?.vector) {
|
|
return 0;
|
|
}
|
|
// Get noun types using neural detection (taxonomy-based)
|
|
const sourceType = await this.detectNounType(sourceNoun.vector);
|
|
const targetType = await this.detectNounType(targetNoun.vector);
|
|
// Calculate direct similarity
|
|
const directSimilarity = this.calculateCosineSimilarity(sourceNoun.vector, targetNoun.vector);
|
|
// Calculate taxonomy-based similarity boost
|
|
const taxonomyBoost = await this.calculateTaxonomyBoost(sourceType, targetType);
|
|
// Blend direct similarity with taxonomy guidance
|
|
// Taxonomy provides consistency while preserving flexibility
|
|
const semanticScore = directSimilarity * 0.7 + taxonomyBoost * 0.3;
|
|
return Math.min(1, Math.max(0, semanticScore));
|
|
}
|
|
catch (error) {
|
|
return 0;
|
|
}
|
|
}
|
|
/**
|
|
* Detect noun type using neural taxonomy matching
|
|
*/
|
|
async detectNounType(vector) {
|
|
// Use the same neural detection as addNoun for consistency
|
|
if (!this.context?.brain)
|
|
return 'unknown';
|
|
try {
|
|
// This would normally call the brain's detectNounType method
|
|
// For now, simplified type detection based on vector patterns
|
|
const magnitude = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
|
|
// Heuristic type detection (would use actual taxonomy embeddings)
|
|
if (magnitude > 10)
|
|
return 'concept';
|
|
if (magnitude > 5)
|
|
return 'entity';
|
|
if (magnitude > 2)
|
|
return 'object';
|
|
return 'item';
|
|
}
|
|
catch {
|
|
return 'unknown';
|
|
}
|
|
}
|
|
/**
|
|
* Calculate taxonomy-based similarity boost
|
|
*/
|
|
async calculateTaxonomyBoost(sourceType, targetType) {
|
|
// Define valid relationship patterns in taxonomy
|
|
const validPatterns = {
|
|
'person': { 'concept': 0.9, 'skill': 0.85, 'organization': 0.8, 'person': 0.7 },
|
|
'concept': { 'concept': 0.9, 'example': 0.85, 'application': 0.8 },
|
|
'entity': { 'entity': 0.8, 'property': 0.85, 'action': 0.75 },
|
|
'object': { 'object': 0.7, 'property': 0.8, 'location': 0.75 },
|
|
'document': { 'topic': 0.9, 'author': 0.85, 'document': 0.7 },
|
|
'tool': { 'output': 0.9, 'input': 0.85, 'user': 0.8 },
|
|
'unknown': { 'unknown': 0.5 } // Fallback
|
|
};
|
|
// Get boost from taxonomy patterns
|
|
const patterns = validPatterns[sourceType] || validPatterns['unknown'];
|
|
const boost = patterns[targetType] || 0.3; // Low score for unrecognized patterns
|
|
return boost;
|
|
}
|
|
calculateCosineSimilarity(vectorA, vectorB) {
|
|
if (vectorA.length !== vectorB.length)
|
|
return 0;
|
|
let dotProduct = 0;
|
|
let normA = 0;
|
|
let normB = 0;
|
|
for (let i = 0; i < vectorA.length; i++) {
|
|
dotProduct += vectorA[i] * vectorB[i];
|
|
normA += vectorA[i] * vectorA[i];
|
|
normB += vectorB[i] * vectorB[i];
|
|
}
|
|
const magnitude = Math.sqrt(normA) * Math.sqrt(normB);
|
|
return magnitude ? dotProduct / magnitude : 0;
|
|
}
|
|
calculateFrequencyScore(sourceId, targetId, relationType) {
|
|
const relationshipKey = `${sourceId}:${relationType}:${targetId}`;
|
|
const stats = this.relationshipStats.get(relationshipKey);
|
|
if (!stats || stats.count <= 1)
|
|
return 0;
|
|
// Frequency boost diminishes with each occurrence
|
|
const frequencyBoost = Math.log(stats.count) * this.config.frequencyDecay;
|
|
return Math.min(this.config.maxFrequencyBoost, frequencyBoost);
|
|
}
|
|
calculateTemporalScore(sourceId, targetId, relationType) {
|
|
const relationshipKey = `${sourceId}:${relationType}:${targetId}`;
|
|
const stats = this.relationshipStats.get(relationshipKey);
|
|
if (!stats)
|
|
return 1.0; // New relationship - full temporal score
|
|
const daysSinceUpdate = (Date.now() - stats.lastUpdated) / (1000 * 60 * 60 * 24);
|
|
const decayFactor = Math.pow(1 - this.config.temporalDecayRate, daysSinceUpdate);
|
|
// Relationships older than temporal window get minimum score
|
|
if (daysSinceUpdate > this.config.temporalWindow) {
|
|
return this.config.minWeight / this.config.baseWeight;
|
|
}
|
|
return Math.max(0.1, decayFactor);
|
|
}
|
|
calculateContextScore(metadata) {
|
|
if (!metadata)
|
|
return 0;
|
|
let contextScore = 0;
|
|
// Boost for explicit importance
|
|
if (metadata.importance) {
|
|
contextScore += Math.min(0.5, metadata.importance);
|
|
}
|
|
// Boost for confidence
|
|
if (metadata.confidence) {
|
|
contextScore += Math.min(0.3, metadata.confidence);
|
|
}
|
|
// Boost for source quality
|
|
if (metadata.sourceQuality) {
|
|
contextScore += Math.min(0.2, metadata.sourceQuality);
|
|
}
|
|
return contextScore;
|
|
}
|
|
async updateRelationshipLearning(sourceId, targetId, relationType, weight) {
|
|
const relationshipKey = `${sourceId}:${relationType}:${targetId}`;
|
|
let stats = this.relationshipStats.get(relationshipKey);
|
|
if (!stats) {
|
|
stats = {
|
|
count: 0,
|
|
totalWeight: 0,
|
|
averageWeight: this.config.baseWeight,
|
|
lastUpdated: Date.now(),
|
|
semanticScore: 0,
|
|
frequencyScore: 0,
|
|
temporalScore: 1.0,
|
|
confidenceScore: this.config.baseWeight
|
|
};
|
|
}
|
|
// Update statistics with learning rate
|
|
stats.count++;
|
|
stats.totalWeight += weight;
|
|
stats.averageWeight = stats.averageWeight * (1 - this.config.learningRate) +
|
|
weight * this.config.learningRate;
|
|
stats.lastUpdated = Date.now();
|
|
// Update confidence based on consistency
|
|
const weightVariance = Math.abs(weight - stats.averageWeight);
|
|
const consistencyScore = 1 - Math.min(1, weightVariance);
|
|
stats.confidenceScore = stats.confidenceScore * (1 - this.config.learningRate) +
|
|
consistencyScore * this.config.learningRate;
|
|
this.relationshipStats.set(relationshipKey, stats);
|
|
this.metrics.adaptiveAdjustments++;
|
|
}
|
|
getConfidenceScore(sourceId, targetId, relationType) {
|
|
const relationshipKey = `${sourceId}:${relationType}:${targetId}`;
|
|
const stats = this.relationshipStats.get(relationshipKey);
|
|
return stats ? stats.confidenceScore : this.config.baseWeight;
|
|
}
|
|
getScoringMethodsUsed() {
|
|
const methods = [];
|
|
if (this.config.enableSemanticScoring)
|
|
methods.push('semantic');
|
|
if (this.config.enableFrequencyAmplification)
|
|
methods.push('frequency');
|
|
if (this.config.enableTemporalDecay)
|
|
methods.push('temporal');
|
|
if (this.config.enableAdaptiveLearning)
|
|
methods.push('adaptive');
|
|
return methods;
|
|
}
|
|
storeDetailedScoring(sourceId, targetId, relationType, scoring) {
|
|
// Store detailed scoring for analysis and debugging
|
|
// In production, this might be sent to analytics system
|
|
}
|
|
updateMetrics(weight, computationTime) {
|
|
this.metrics.relationshipsScored++;
|
|
this.metrics.computationTimeMs =
|
|
(this.metrics.computationTimeMs * (this.metrics.relationshipsScored - 1) + computationTime) /
|
|
this.metrics.relationshipsScored;
|
|
// Update score averages (simplified)
|
|
// In practice, we'd track these more precisely
|
|
}
|
|
/**
|
|
* Get intelligent verb scoring statistics
|
|
*/
|
|
getStats() {
|
|
let totalConfidence = 0;
|
|
let highConfidenceCount = 0;
|
|
for (const stats of this.relationshipStats.values()) {
|
|
totalConfidence += stats.confidenceScore;
|
|
if (stats.confidenceScore >= this.config.confidenceThreshold * 2) {
|
|
highConfidenceCount++;
|
|
}
|
|
}
|
|
const totalRelationships = this.relationshipStats.size;
|
|
const averageConfidence = totalRelationships > 0 ? totalConfidence / totalRelationships : 0;
|
|
const learningEfficiency = this.metrics.adaptiveAdjustments / Math.max(1, this.metrics.relationshipsScored);
|
|
return {
|
|
...this.metrics,
|
|
totalRelationships,
|
|
averageConfidence,
|
|
highConfidenceRelationships: highConfidenceCount,
|
|
learningEfficiency
|
|
};
|
|
}
|
|
/**
|
|
* Export relationship statistics for analysis
|
|
*/
|
|
exportRelationshipStats() {
|
|
return Array.from(this.relationshipStats.entries()).map(([key, metrics]) => ({
|
|
relationship: key,
|
|
metrics
|
|
}));
|
|
}
|
|
/**
|
|
* Import relationship statistics from previous sessions
|
|
*/
|
|
importRelationshipStats(stats) {
|
|
for (const { relationship, metrics } of stats) {
|
|
this.relationshipStats.set(relationship, metrics);
|
|
}
|
|
this.log(`Imported ${stats.length} relationship statistics`);
|
|
}
|
|
/**
|
|
* Get learning statistics for monitoring and debugging
|
|
* Required for Brainy.getVerbScoringStats()
|
|
*/
|
|
getLearningStats() {
|
|
const relationships = Array.from(this.relationshipStats.entries());
|
|
const totalRelationships = relationships.length;
|
|
const feedbackCount = relationships.reduce((sum, [, stats]) => sum + stats.count, 0);
|
|
const averageWeight = relationships.reduce((sum, [, stats]) => sum + stats.averageWeight, 0) / totalRelationships || 0;
|
|
const averageConfidence = Math.min(averageWeight + 0.2, 1.0);
|
|
const topRelationships = relationships
|
|
.map(([key, stats]) => ({
|
|
relationship: key,
|
|
count: stats.count,
|
|
averageWeight: stats.averageWeight
|
|
}))
|
|
.sort((a, b) => b.count - a.count)
|
|
.slice(0, 10);
|
|
return {
|
|
totalRelationships,
|
|
averageConfidence,
|
|
feedbackCount,
|
|
topRelationships
|
|
};
|
|
}
|
|
/**
|
|
* Export learning data for backup or analysis
|
|
* Required for Brainy.exportVerbScoringLearningData()
|
|
*/
|
|
exportLearningData() {
|
|
const data = {
|
|
config: this.config,
|
|
stats: Array.from(this.relationshipStats.entries()).map(([key, stats]) => ({
|
|
relationship: key,
|
|
...stats
|
|
})),
|
|
exportedAt: new Date().toISOString(),
|
|
version: '1.0'
|
|
};
|
|
return JSON.stringify(data, null, 2);
|
|
}
|
|
/**
|
|
* Import learning data from backup
|
|
* Required for Brainy.importVerbScoringLearningData()
|
|
*/
|
|
importLearningData(jsonData) {
|
|
try {
|
|
const data = JSON.parse(jsonData);
|
|
if (data.stats && Array.isArray(data.stats)) {
|
|
for (const stat of data.stats) {
|
|
if (stat.relationship) {
|
|
this.relationshipStats.set(stat.relationship, {
|
|
count: stat.count || 1,
|
|
totalWeight: stat.totalWeight || stat.averageWeight || 0.5,
|
|
averageWeight: stat.averageWeight || 0.5,
|
|
lastUpdated: stat.lastUpdated || Date.now(),
|
|
semanticScore: stat.semanticScore || 0.5,
|
|
frequencyScore: stat.frequencyScore || 0.5,
|
|
temporalScore: stat.temporalScore || 1.0,
|
|
confidenceScore: stat.confidenceScore || 0.5
|
|
});
|
|
}
|
|
}
|
|
}
|
|
this.log(`Imported learning data: ${this.relationshipStats.size} relationships`);
|
|
}
|
|
catch (error) {
|
|
console.error('Failed to import learning data:', error);
|
|
throw new Error(`Failed to import learning data: ${error}`);
|
|
}
|
|
}
|
|
/**
|
|
* Provide feedback on a relationship's weight
|
|
* Required for Brainy.provideVerbScoringFeedback()
|
|
*/
|
|
async provideFeedback(sourceId, targetId, relationType, feedback, feedbackType = 'correction') {
|
|
const key = `${sourceId}-${relationType}-${targetId}`;
|
|
const stats = this.relationshipStats.get(key) || {
|
|
count: 0,
|
|
totalWeight: 0,
|
|
averageWeight: 0.5,
|
|
lastUpdated: Date.now(),
|
|
semanticScore: 0.5,
|
|
frequencyScore: 0.5,
|
|
temporalScore: 1.0,
|
|
confidenceScore: 0.5
|
|
};
|
|
// Update statistics based on feedback
|
|
if (feedbackType === 'correction') {
|
|
// Direct correction - heavily weight the feedback
|
|
stats.averageWeight = stats.averageWeight * 0.3 + feedback * 0.7;
|
|
}
|
|
else if (feedbackType === 'validation') {
|
|
// Validation - slightly adjust towards feedback
|
|
stats.averageWeight = stats.averageWeight * 0.8 + feedback * 0.2;
|
|
}
|
|
else {
|
|
// Enhancement - minor adjustment
|
|
stats.averageWeight = stats.averageWeight * 0.9 + feedback * 0.1;
|
|
}
|
|
stats.count++;
|
|
stats.totalWeight += feedback;
|
|
stats.lastUpdated = Date.now();
|
|
this.relationshipStats.set(key, stats);
|
|
this.metrics.adaptiveAdjustments++;
|
|
}
|
|
/**
|
|
* Compute intelligent scores for a verb relationship
|
|
* Used internally during verb creation
|
|
*/
|
|
async computeVerbScores(sourceNoun, targetNoun, relationType) {
|
|
const reasoning = [];
|
|
let totalScore = 0;
|
|
let components = 0;
|
|
// Semantic scoring
|
|
if (this.config.enableSemanticScoring && sourceNoun?.vector && targetNoun?.vector) {
|
|
const similarity = this.calculateCosineSimilarity(sourceNoun.vector, targetNoun.vector);
|
|
const semanticScore = Math.max(similarity, this.config.semanticThreshold);
|
|
totalScore += semanticScore * this.config.semanticWeight;
|
|
components++;
|
|
reasoning.push(`Semantic similarity: ${(similarity * 100).toFixed(1)}%`);
|
|
}
|
|
// Frequency scoring
|
|
const key = `${sourceNoun?.id}-${relationType}-${targetNoun?.id}`;
|
|
const stats = this.relationshipStats.get(key);
|
|
if (this.config.enableFrequencyAmplification && stats) {
|
|
const frequencyScore = Math.min(1 + (stats.count - 1) * 0.1, this.config.maxFrequencyBoost);
|
|
totalScore += frequencyScore * 0.3;
|
|
components++;
|
|
reasoning.push(`Frequency boost: ${frequencyScore.toFixed(2)}x`);
|
|
}
|
|
// Temporal decay scoring
|
|
if (this.config.enableTemporalDecay) {
|
|
reasoning.push(`Temporal decay applied (rate: ${this.config.temporalDecayRate})`);
|
|
}
|
|
// Calculate final weight
|
|
const weight = components > 0
|
|
? Math.min(Math.max(totalScore / components, this.config.minWeight), this.config.maxWeight)
|
|
: this.config.baseWeight;
|
|
const confidence = Math.min(weight + 0.2, 1.0);
|
|
return { weight, confidence, reasoning };
|
|
}
|
|
async onShutdown() {
|
|
const stats = this.getStats();
|
|
this.log(`Intelligent verb scoring shutdown: ${stats.relationshipsScored} relationships scored, ${Math.round(stats.averageConfidence * 100)}% avg confidence`);
|
|
}
|
|
}
|
|
//# sourceMappingURL=intelligentVerbScoringAugmentation.js.map
|