Initial commit: Brainy - Multi-Dimensional AI Database
Open source vector database with HNSW indexing, graph relationships, and metadata facets. Features CLI with professional augmentation registry integration for discovering extensions and capabilities.
This commit is contained in:
commit
f8c45f2d8d
448 changed files with 103294 additions and 0 deletions
307
dist/distributed/domainDetector.js
vendored
Normal file
307
dist/distributed/domainDetector.js
vendored
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
/**
|
||||
* Domain Detector
|
||||
* Automatically detects and manages data domains for logical separation
|
||||
*/
|
||||
export class DomainDetector {
|
||||
constructor() {
|
||||
this.domainPatterns = [
|
||||
{
|
||||
domain: 'medical',
|
||||
patterns: {
|
||||
fields: ['symptoms', 'diagnosis', 'treatment', 'medication', 'patient'],
|
||||
keywords: ['medical', 'health', 'disease', 'symptom', 'treatment', 'doctor', 'patient']
|
||||
},
|
||||
priority: 1
|
||||
},
|
||||
{
|
||||
domain: 'legal',
|
||||
patterns: {
|
||||
fields: ['contract', 'clause', 'litigation', 'statute', 'jurisdiction'],
|
||||
keywords: ['legal', 'law', 'contract', 'court', 'attorney', 'litigation', 'statute']
|
||||
},
|
||||
priority: 1
|
||||
},
|
||||
{
|
||||
domain: 'product',
|
||||
patterns: {
|
||||
fields: ['price', 'sku', 'inventory', 'category', 'brand'],
|
||||
keywords: ['product', 'price', 'sale', 'inventory', 'catalog', 'item', 'sku']
|
||||
},
|
||||
priority: 1
|
||||
},
|
||||
{
|
||||
domain: 'customer',
|
||||
patterns: {
|
||||
fields: ['customerId', 'email', 'phone', 'address', 'orders'],
|
||||
keywords: ['customer', 'client', 'user', 'account', 'profile', 'contact']
|
||||
},
|
||||
priority: 1
|
||||
},
|
||||
{
|
||||
domain: 'financial',
|
||||
patterns: {
|
||||
fields: ['amount', 'currency', 'transaction', 'balance', 'account'],
|
||||
keywords: ['financial', 'money', 'payment', 'transaction', 'bank', 'credit', 'debit']
|
||||
},
|
||||
priority: 1
|
||||
},
|
||||
{
|
||||
domain: 'technical',
|
||||
patterns: {
|
||||
fields: ['code', 'function', 'error', 'stack', 'api'],
|
||||
keywords: ['code', 'software', 'api', 'error', 'debug', 'function', 'class', 'method']
|
||||
},
|
||||
priority: 2
|
||||
}
|
||||
];
|
||||
this.customPatterns = [];
|
||||
this.domainStats = new Map();
|
||||
}
|
||||
/**
|
||||
* Detect domain from data object
|
||||
* @param data - The data object to analyze
|
||||
* @returns The detected domain and metadata
|
||||
*/
|
||||
detectDomain(data) {
|
||||
if (!data || typeof data !== 'object') {
|
||||
return { domain: 'general' };
|
||||
}
|
||||
// Check for explicit domain field
|
||||
if (data.domain && typeof data.domain === 'string') {
|
||||
this.updateStats(data.domain);
|
||||
return {
|
||||
domain: data.domain,
|
||||
domainMetadata: this.extractDomainMetadata(data, data.domain)
|
||||
};
|
||||
}
|
||||
// Score each domain pattern
|
||||
const scores = new Map();
|
||||
// Check custom patterns first (higher priority)
|
||||
for (const pattern of this.customPatterns) {
|
||||
const score = this.scorePattern(data, pattern);
|
||||
if (score > 0) {
|
||||
scores.set(pattern.domain, score * (pattern.priority || 1));
|
||||
}
|
||||
}
|
||||
// Check default patterns
|
||||
for (const pattern of this.domainPatterns) {
|
||||
const score = this.scorePattern(data, pattern);
|
||||
if (score > 0) {
|
||||
const currentScore = scores.get(pattern.domain) || 0;
|
||||
scores.set(pattern.domain, currentScore + score * (pattern.priority || 1));
|
||||
}
|
||||
}
|
||||
// Find highest scoring domain
|
||||
let bestDomain = 'general';
|
||||
let bestScore = 0;
|
||||
for (const [domain, score] of scores.entries()) {
|
||||
if (score > bestScore) {
|
||||
bestDomain = domain;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
this.updateStats(bestDomain);
|
||||
return {
|
||||
domain: bestDomain,
|
||||
domainMetadata: this.extractDomainMetadata(data, bestDomain)
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Score a data object against a domain pattern
|
||||
*/
|
||||
scorePattern(data, pattern) {
|
||||
let score = 0;
|
||||
// Check field matches
|
||||
if (pattern.patterns.fields) {
|
||||
const dataKeys = Object.keys(data);
|
||||
for (const field of pattern.patterns.fields) {
|
||||
if (dataKeys.some(key => key.toLowerCase().includes(field.toLowerCase()))) {
|
||||
score += 2; // Field match is strong signal
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check keyword matches in values
|
||||
if (pattern.patterns.keywords) {
|
||||
const dataStr = JSON.stringify(data).toLowerCase();
|
||||
for (const keyword of pattern.patterns.keywords) {
|
||||
if (dataStr.includes(keyword.toLowerCase())) {
|
||||
score += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check regex patterns
|
||||
if (pattern.patterns.regex) {
|
||||
const dataStr = JSON.stringify(data);
|
||||
if (pattern.patterns.regex.test(dataStr)) {
|
||||
score += 3; // Regex match is very specific
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
/**
|
||||
* Extract domain-specific metadata
|
||||
*/
|
||||
extractDomainMetadata(data, domain) {
|
||||
const metadata = {};
|
||||
switch (domain) {
|
||||
case 'medical':
|
||||
if (data.patientId)
|
||||
metadata.patientId = data.patientId;
|
||||
if (data.condition)
|
||||
metadata.condition = data.condition;
|
||||
if (data.severity)
|
||||
metadata.severity = data.severity;
|
||||
break;
|
||||
case 'legal':
|
||||
if (data.caseId)
|
||||
metadata.caseId = data.caseId;
|
||||
if (data.jurisdiction)
|
||||
metadata.jurisdiction = data.jurisdiction;
|
||||
if (data.documentType)
|
||||
metadata.documentType = data.documentType;
|
||||
break;
|
||||
case 'product':
|
||||
if (data.sku)
|
||||
metadata.sku = data.sku;
|
||||
if (data.category)
|
||||
metadata.category = data.category;
|
||||
if (data.brand)
|
||||
metadata.brand = data.brand;
|
||||
if (data.price)
|
||||
metadata.priceRange = this.getPriceRange(data.price);
|
||||
break;
|
||||
case 'customer':
|
||||
if (data.customerId)
|
||||
metadata.customerId = data.customerId;
|
||||
if (data.segment)
|
||||
metadata.segment = data.segment;
|
||||
if (data.lifetime_value)
|
||||
metadata.valueCategory = this.getValueCategory(data.lifetime_value);
|
||||
break;
|
||||
case 'financial':
|
||||
if (data.accountId)
|
||||
metadata.accountId = data.accountId;
|
||||
if (data.transactionType)
|
||||
metadata.transactionType = data.transactionType;
|
||||
if (data.amount)
|
||||
metadata.amountRange = this.getAmountRange(data.amount);
|
||||
break;
|
||||
case 'technical':
|
||||
if (data.service)
|
||||
metadata.service = data.service;
|
||||
if (data.environment)
|
||||
metadata.environment = data.environment;
|
||||
if (data.severity)
|
||||
metadata.severity = data.severity;
|
||||
break;
|
||||
}
|
||||
// Add detection confidence
|
||||
metadata.detectionConfidence = this.calculateConfidence(data, domain);
|
||||
return metadata;
|
||||
}
|
||||
/**
|
||||
* Calculate detection confidence
|
||||
*/
|
||||
calculateConfidence(data, domain) {
|
||||
// If domain was explicitly specified
|
||||
if (data.domain === domain)
|
||||
return 'high';
|
||||
// Check how many patterns matched
|
||||
const pattern = [...this.customPatterns, ...this.domainPatterns]
|
||||
.find(p => p.domain === domain);
|
||||
if (!pattern)
|
||||
return 'low';
|
||||
const score = this.scorePattern(data, pattern);
|
||||
if (score >= 5)
|
||||
return 'high';
|
||||
if (score >= 2)
|
||||
return 'medium';
|
||||
return 'low';
|
||||
}
|
||||
/**
|
||||
* Categorize price ranges
|
||||
*/
|
||||
getPriceRange(price) {
|
||||
if (price < 10)
|
||||
return 'low';
|
||||
if (price < 100)
|
||||
return 'medium';
|
||||
if (price < 1000)
|
||||
return 'high';
|
||||
return 'premium';
|
||||
}
|
||||
/**
|
||||
* Categorize customer value
|
||||
*/
|
||||
getValueCategory(value) {
|
||||
if (value < 100)
|
||||
return 'low';
|
||||
if (value < 1000)
|
||||
return 'medium';
|
||||
if (value < 10000)
|
||||
return 'high';
|
||||
return 'vip';
|
||||
}
|
||||
/**
|
||||
* Categorize amount ranges
|
||||
*/
|
||||
getAmountRange(amount) {
|
||||
if (amount < 100)
|
||||
return 'micro';
|
||||
if (amount < 1000)
|
||||
return 'small';
|
||||
if (amount < 10000)
|
||||
return 'medium';
|
||||
if (amount < 100000)
|
||||
return 'large';
|
||||
return 'enterprise';
|
||||
}
|
||||
/**
|
||||
* Add custom domain pattern
|
||||
* @param pattern - Custom domain pattern to add
|
||||
*/
|
||||
addCustomPattern(pattern) {
|
||||
// Remove existing pattern for same domain if exists
|
||||
this.customPatterns = this.customPatterns.filter(p => p.domain !== pattern.domain);
|
||||
this.customPatterns.push(pattern);
|
||||
}
|
||||
/**
|
||||
* Remove custom domain pattern
|
||||
* @param domain - Domain to remove pattern for
|
||||
*/
|
||||
removeCustomPattern(domain) {
|
||||
this.customPatterns = this.customPatterns.filter(p => p.domain !== domain);
|
||||
}
|
||||
/**
|
||||
* Update domain statistics
|
||||
*/
|
||||
updateStats(domain) {
|
||||
const count = this.domainStats.get(domain) || 0;
|
||||
this.domainStats.set(domain, count + 1);
|
||||
}
|
||||
/**
|
||||
* Get domain statistics
|
||||
* @returns Map of domain to count
|
||||
*/
|
||||
getDomainStats() {
|
||||
return new Map(this.domainStats);
|
||||
}
|
||||
/**
|
||||
* Clear domain statistics
|
||||
*/
|
||||
clearStats() {
|
||||
this.domainStats.clear();
|
||||
}
|
||||
/**
|
||||
* Get all configured domains
|
||||
* @returns Array of domain names
|
||||
*/
|
||||
getConfiguredDomains() {
|
||||
const domains = new Set();
|
||||
for (const pattern of [...this.domainPatterns, ...this.customPatterns]) {
|
||||
domains.add(pattern.domain);
|
||||
}
|
||||
return Array.from(domains).sort();
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=domainDetector.js.map
|
||||
Loading…
Add table
Add a link
Reference in a new issue