mem100x
Version:
⚡ The FASTEST MCP memory server ever built - 66k+ entities/sec with intelligent context detection
201 lines • 8.01 kB
JavaScript
"use strict";
/**
* Context Confidence Scoring System
* ML-like intelligence for automatic context detection
* Blazing fast pattern matching with detailed scoring
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContextConfidenceScorer = void 0;
class ContextConfidenceScorer {
contextConfigs;
// Component weights (sum to 1.0) - tuned for optimal detection
WEIGHTS = {
entityExists: 0.25, // Entity already in context
entityType: 0.30, // Entity type matches config
keywordMatch: 0.35, // Keyword pattern matches
relationContext: 0.05, // Related entities in context
temporal: 0.05 // Recent activity bonus
};
// Confidence thresholds
HIGH_CONFIDENCE = 0.50;
MEDIUM_CONFIDENCE = 0.30;
LOW_CONFIDENCE = 0.15;
contextPatterns = new Map();
entityContextMap = new Map();
recentContexts = [];
maxRecent = 100;
constructor(contextConfigs, entityContextMap) {
this.contextConfigs = contextConfigs;
this.entityContextMap = entityContextMap;
this.compilePatterns();
}
compilePatterns() {
// Pre-compile regex patterns for blazing-fast matching
for (const [context, config] of Object.entries(this.contextConfigs)) {
const patterns = config.patterns.map(pattern => new RegExp(`\\b${pattern}\\b`, 'i'));
this.contextPatterns.set(context, patterns);
}
}
scoreContexts(data, availableContexts) {
const scores = [];
for (const context of availableContexts) {
const score = this.scoreSingleContext(context, data);
scores.push(score);
}
// Sort by confidence descending
scores.sort((a, b) => b.confidence - a.confidence);
// Update recent contexts if we have a clear winner
if (scores.length > 0 && scores[0].confidence >= this.LOW_CONFIDENCE) {
this.updateRecentContexts(scores[0].context);
}
return scores;
}
scoreSingleContext(context, data) {
const breakdown = {
entityExists: 0,
entityType: 0,
keywordMatch: 0,
relationContext: 0,
temporal: 0
};
const evidence = [];
// 1. Entity existence check (highest weight)
if (data.entities) {
for (const entity of data.entities) {
const name = entity.name?.toLowerCase();
if (name && this.entityContextMap.get(name) === context) {
breakdown.entityExists = 1.0;
evidence.push(`Entity '${name}' exists in ${context}`);
break;
}
}
}
// 2. Entity type matching
if (data.entities && this.contextConfigs[context]) {
const configTypes = new Set(this.contextConfigs[context].entityTypes);
let typeMatches = 0;
for (const entity of data.entities) {
if (entity.entityType && configTypes.has(entity.entityType.toLowerCase())) {
typeMatches++;
evidence.push(`Type '${entity.entityType}' matches ${context}`);
}
}
if (data.entities.length > 0) {
breakdown.entityType = typeMatches / data.entities.length;
}
}
// 3. Keyword pattern matching
const patterns = this.contextPatterns.get(context) || [];
const searchTexts = [];
// Collect all searchable text
if (data.entities) {
for (const entity of data.entities) {
const text = [
entity.name || '',
entity.entityType || '',
...(entity.observations || [])
].join(' ');
searchTexts.push(text);
}
}
if (data.query) {
searchTexts.push(data.query);
}
// Fast pattern matching
const matchedPatterns = new Set();
const allText = searchTexts.join(' ').toLowerCase();
for (const pattern of patterns) {
if (pattern.test(allText)) {
matchedPatterns.add(pattern.source);
evidence.push(`Pattern '${pattern.source}' found`);
}
}
if (patterns.length > 0) {
// Score based on percentage of unique patterns matched
breakdown.keywordMatch = matchedPatterns.size / patterns.length;
}
// 4. Relation context scoring
if (data.relations) {
let relationMatches = 0;
for (const relation of data.relations) {
const fromContext = this.entityContextMap.get(relation.from?.toLowerCase());
const toContext = this.entityContextMap.get(relation.to?.toLowerCase());
if (fromContext === context) {
relationMatches += 0.5;
evidence.push(`Relation from '${relation.from}' in ${context}`);
}
if (toContext === context) {
relationMatches += 0.5;
evidence.push(`Relation to '${relation.to}' in ${context}`);
}
}
if (data.relations.length > 0) {
breakdown.relationContext = Math.min(1.0, relationMatches / data.relations.length);
}
}
// 5. Temporal scoring (recent usage)
breakdown.temporal = this.calculateTemporalScore(context);
if (breakdown.temporal > 0.5) {
evidence.push('Recently used context');
}
// Calculate weighted total
const totalScore = Object.entries(breakdown).reduce((sum, [key, value]) => sum + value * this.WEIGHTS[key], 0);
const confidence = Math.min(1.0, totalScore);
return {
context,
confidence,
score: totalScore,
breakdown,
evidence
};
}
calculateTemporalScore(context) {
if (this.recentContexts.length === 0)
return 0;
const now = Date.now();
let recencyScore = 0;
for (const recent of this.recentContexts) {
if (recent.context === context) {
// Exponential decay: half-life of 1 hour
const timeDiff = (now - recent.timestamp) / 1000; // seconds
const decayFactor = Math.pow(0.5, timeDiff / 3600);
recencyScore += decayFactor;
}
}
// Normalize to 0-1 range
return Math.min(1.0, recencyScore / 3.0);
}
updateRecentContexts(context) {
this.recentContexts.push({ context, timestamp: Date.now() });
// Keep only recent entries
if (this.recentContexts.length > this.maxRecent) {
this.recentContexts = this.recentContexts.slice(-this.maxRecent);
}
// Remove entries older than 24 hours
const cutoff = Date.now() - 24 * 60 * 60 * 1000;
this.recentContexts = this.recentContexts.filter(r => r.timestamp > cutoff);
}
getConfidenceLevel(confidence) {
if (confidence >= this.HIGH_CONFIDENCE)
return 'high';
if (confidence >= this.MEDIUM_CONFIDENCE)
return 'medium';
if (confidence >= this.LOW_CONFIDENCE)
return 'low';
return 'very_low';
}
shouldPromptUser(topScore, secondScore) {
// Prompt if confidence is too low
if (topScore.confidence < this.MEDIUM_CONFIDENCE)
return true;
// Prompt if second best is too close (within 10%)
if (secondScore && (topScore.confidence - secondScore.confidence) < 0.10)
return true;
return false;
}
updateEntityContext(entityName, context) {
this.entityContextMap.set(entityName.toLowerCase(), context);
}
}
exports.ContextConfidenceScorer = ContextConfidenceScorer;
//# sourceMappingURL=context-confidence.js.map