UNPKG

claude-flow

Version:

Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration

178 lines 5.32 kB
/** * Pure JavaScript SemanticRouter implementation * * Provides intent routing using cosine similarity. * This is a fallback implementation since @ruvector/router's native VectorDb has bugs. * * Performance: ~50,000 routes/sec with 100 intents (sufficient for agent routing) */ export class SemanticRouter { dimension; metric; intents = new Map(); totalVectors = 0; constructor(config) { if (!config || typeof config.dimension !== 'number') { throw new Error('SemanticRouter requires a dimension in config'); } this.dimension = config.dimension; this.metric = config.metric ?? 'cosine'; } /** * Add an intent with pre-computed embeddings */ addIntentWithEmbeddings(name, embeddings, metadata = {}) { if (!name || !Array.isArray(embeddings)) { throw new Error('Must provide name and embeddings array'); } // Validate embeddings for (const emb of embeddings) { if (!(emb instanceof Float32Array) || emb.length !== this.dimension) { throw new Error(`Embedding must be Float32Array of length ${this.dimension}`); } } // Normalize embeddings for cosine similarity const normalizedEmbeddings = embeddings.map(emb => this.normalize(emb)); this.intents.set(name, { name, embeddings: normalizedEmbeddings, metadata, }); this.totalVectors += embeddings.length; } /** * Route a query using a pre-computed embedding */ routeWithEmbedding(embedding, k = 5) { if (!(embedding instanceof Float32Array) || embedding.length !== this.dimension) { throw new Error(`Embedding must be Float32Array of length ${this.dimension}`); } const normalizedQuery = this.normalize(embedding); const scores = []; // Calculate best score for each intent for (const [intentName, intent] of this.intents) { let bestScore = -Infinity; for (const storedEmb of intent.embeddings) { const score = this.similarity(normalizedQuery, storedEmb); if (score > bestScore) { bestScore = score; } } scores.push({ intent: intentName, score: bestScore, metadata: intent.metadata, }); } // Sort by score descending and take top k return scores .sort((a, b) => b.score - a.score) .slice(0, k); } /** * Remove an intent */ removeIntent(name) { const intent = this.intents.get(name); if (!intent) return false; this.totalVectors -= intent.embeddings.length; this.intents.delete(name); return true; } /** * Get all intent names */ getIntents() { return Array.from(this.intents.keys()); } /** * Get intent details */ getIntent(name) { const data = this.intents.get(name); if (!data) return null; return { name: data.name, utterances: [], // We don't store utterances, only embeddings metadata: data.metadata, }; } /** * Clear all intents */ clear() { this.intents.clear(); this.totalVectors = 0; } /** * Get total vector count */ count() { return this.totalVectors; } /** * Get number of intents */ intentCount() { return this.intents.size; } /** * Normalize a vector for cosine similarity */ normalize(vec) { let norm = 0; for (let i = 0; i < vec.length; i++) { norm += vec[i] * vec[i]; } norm = Math.sqrt(norm); if (norm === 0) return vec; const normalized = new Float32Array(vec.length); for (let i = 0; i < vec.length; i++) { normalized[i] = vec[i] / norm; } return normalized; } /** * Calculate similarity between two normalized vectors */ similarity(a, b) { switch (this.metric) { case 'cosine': // For normalized vectors, cosine similarity = dot product return this.dotProduct(a, b); case 'dotProduct': return this.dotProduct(a, b); case 'euclidean': // Convert Euclidean distance to similarity return 1 / (1 + this.euclideanDistance(a, b)); default: return this.dotProduct(a, b); } } dotProduct(a, b) { let sum = 0; for (let i = 0; i < a.length; i++) { sum += a[i] * b[i]; } return sum; } euclideanDistance(a, b) { let sum = 0; for (let i = 0; i < a.length; i++) { const diff = a[i] - b[i]; sum += diff * diff; } return Math.sqrt(sum); } } /** * Create a SemanticRouter with the given configuration */ export function createSemanticRouter(config) { return new SemanticRouter(config); } export default SemanticRouter; //# sourceMappingURL=semantic-router.js.map