303 lines
9.1 KiB
JavaScript
303 lines
9.1 KiB
JavaScript
/**
|
|
* WASM Acceleration for Intelligence Layer
|
|
*
|
|
* Provides WASM-accelerated components for the intelligence stack:
|
|
* - HNSW vector indexing (150x faster pattern search)
|
|
* - Semantic matching (intelligent agent routing)
|
|
*
|
|
* Uses @ruvector/edge for browser/edge compatibility.
|
|
* Falls back to pure JS when WASM unavailable.
|
|
*/
|
|
import { initRuVectorWasm, isWasmInitialized, RuVectorHnswIndex, RuVectorSemanticMatcher, } from '../wasm/ruvector-edge.js';
|
|
import { logger } from '../utils/logger.js';
|
|
// Default embedding dimension (matches SONA)
|
|
const DEFAULT_DIM = 128;
|
|
/**
|
|
* WASM-accelerated pattern index for fast similarity search
|
|
*/
|
|
export class WasmPatternIndex {
|
|
hnswIndex;
|
|
patterns = new Map();
|
|
indexToId = new Map();
|
|
dimensions;
|
|
constructor(dimensions = DEFAULT_DIM) {
|
|
this.dimensions = dimensions;
|
|
this.hnswIndex = new RuVectorHnswIndex(dimensions, 16, 200);
|
|
}
|
|
/**
|
|
* Initialize WASM (call once at startup)
|
|
*/
|
|
static async init() {
|
|
return await initRuVectorWasm();
|
|
}
|
|
/**
|
|
* Add pattern to index
|
|
*/
|
|
addPattern(id, embedding, metadata = {}) {
|
|
const vec = embedding instanceof Float32Array
|
|
? embedding
|
|
: new Float32Array(embedding);
|
|
const entry = {
|
|
id,
|
|
embedding: vec,
|
|
metadata,
|
|
accessCount: 0,
|
|
lastAccessed: Date.now(),
|
|
};
|
|
this.patterns.set(id, entry);
|
|
const idx = this.hnswIndex.add(vec);
|
|
this.indexToId.set(idx, id);
|
|
}
|
|
/**
|
|
* Search for similar patterns
|
|
*/
|
|
searchSimilar(queryEmbedding, k = 10, minScore = 0) {
|
|
const vec = queryEmbedding instanceof Float32Array
|
|
? queryEmbedding
|
|
: new Float32Array(queryEmbedding);
|
|
const results = this.hnswIndex.search(vec, k);
|
|
const output = [];
|
|
for (const result of results) {
|
|
const id = this.indexToId.get(result.index);
|
|
if (id) {
|
|
const pattern = this.patterns.get(id);
|
|
if (pattern) {
|
|
// Convert distance to similarity score (1 / (1 + distance))
|
|
const score = 1 / (1 + result.distance);
|
|
if (score >= minScore) {
|
|
// Update access stats
|
|
pattern.accessCount++;
|
|
pattern.lastAccessed = Date.now();
|
|
output.push({
|
|
pattern,
|
|
distance: result.distance,
|
|
score,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
/**
|
|
* Get pattern by ID
|
|
*/
|
|
getPattern(id) {
|
|
return this.patterns.get(id);
|
|
}
|
|
/**
|
|
* Get all patterns (for persistence)
|
|
*/
|
|
getAllPatterns() {
|
|
return Array.from(this.patterns.values());
|
|
}
|
|
/**
|
|
* Get index size
|
|
*/
|
|
size() {
|
|
return this.patterns.size;
|
|
}
|
|
/**
|
|
* Check if WASM acceleration is active
|
|
*/
|
|
isWasmAccelerated() {
|
|
return this.hnswIndex.isWasmAccelerated();
|
|
}
|
|
/**
|
|
* Get performance stats
|
|
*/
|
|
getStats() {
|
|
let totalAccesses = 0;
|
|
for (const pattern of this.patterns.values()) {
|
|
totalAccesses += pattern.accessCount;
|
|
}
|
|
return {
|
|
patternCount: this.patterns.size,
|
|
wasmAccelerated: this.isWasmAccelerated(),
|
|
dimensions: this.dimensions,
|
|
totalAccesses,
|
|
};
|
|
}
|
|
}
|
|
/**
|
|
* WASM-accelerated agent router for intelligent task routing
|
|
*/
|
|
export class WasmAgentRouter {
|
|
semanticMatcher;
|
|
agents = new Map();
|
|
dimensions;
|
|
constructor(dimensions = DEFAULT_DIM) {
|
|
this.dimensions = dimensions;
|
|
this.semanticMatcher = new RuVectorSemanticMatcher();
|
|
}
|
|
/**
|
|
* Initialize WASM (call once at startup)
|
|
*/
|
|
static async init() {
|
|
return await initRuVectorWasm();
|
|
}
|
|
/**
|
|
* Register agent for routing
|
|
*/
|
|
registerAgent(profile) {
|
|
this.agents.set(profile.agentId, profile);
|
|
this.semanticMatcher.registerAgent(profile.agentId, profile.embedding, profile.capabilities);
|
|
}
|
|
/**
|
|
* Update agent metrics (success rate, latency)
|
|
*/
|
|
updateAgentMetrics(agentId, successRate, avgLatency) {
|
|
const agent = this.agents.get(agentId);
|
|
if (agent) {
|
|
agent.successRate = successRate;
|
|
agent.avgLatency = avgLatency;
|
|
}
|
|
}
|
|
/**
|
|
* Route task to best agent(s)
|
|
*/
|
|
routeTask(taskEmbedding, options = {}) {
|
|
const { requiredCapabilities = [], minSuccessRate = 0, maxLatency = Infinity, topK = 3, } = options;
|
|
const vec = taskEmbedding instanceof Float32Array
|
|
? taskEmbedding
|
|
: new Float32Array(taskEmbedding);
|
|
// Get semantic matches
|
|
const matches = this.semanticMatcher.matchTask(vec, topK * 2);
|
|
// Filter and enrich with metrics
|
|
const results = matches
|
|
.map(m => {
|
|
const agent = this.agents.get(m.agent);
|
|
return {
|
|
agentId: m.agent,
|
|
score: m.score,
|
|
capabilities: m.capabilities,
|
|
successRate: agent?.successRate ?? 0,
|
|
avgLatency: agent?.avgLatency ?? 0,
|
|
};
|
|
})
|
|
.filter(r => {
|
|
// Filter by required capabilities
|
|
if (requiredCapabilities.length > 0) {
|
|
const hasAll = requiredCapabilities.every(cap => r.capabilities.includes(cap));
|
|
if (!hasAll)
|
|
return false;
|
|
}
|
|
// Filter by success rate
|
|
if (r.successRate < minSuccessRate)
|
|
return false;
|
|
// Filter by latency
|
|
if (r.avgLatency > maxLatency)
|
|
return false;
|
|
return true;
|
|
})
|
|
.slice(0, topK);
|
|
return results;
|
|
}
|
|
/**
|
|
* Get agent profile
|
|
*/
|
|
getAgent(agentId) {
|
|
return this.agents.get(agentId);
|
|
}
|
|
/**
|
|
* Get all registered agents
|
|
*/
|
|
getAllAgents() {
|
|
return Array.from(this.agents.values());
|
|
}
|
|
/**
|
|
* Check if WASM acceleration is active
|
|
*/
|
|
isWasmAccelerated() {
|
|
return this.semanticMatcher.isWasmAccelerated();
|
|
}
|
|
/**
|
|
* Get router stats
|
|
*/
|
|
getStats() {
|
|
let totalSuccess = 0;
|
|
let totalLatency = 0;
|
|
let count = 0;
|
|
for (const agent of this.agents.values()) {
|
|
totalSuccess += agent.successRate;
|
|
totalLatency += agent.avgLatency;
|
|
count++;
|
|
}
|
|
return {
|
|
agentCount: this.agents.size,
|
|
wasmAccelerated: this.isWasmAccelerated(),
|
|
dimensions: this.dimensions,
|
|
avgSuccessRate: count > 0 ? totalSuccess / count : 0,
|
|
avgLatency: count > 0 ? totalLatency / count : 0,
|
|
};
|
|
}
|
|
}
|
|
//=============================================================================
|
|
// Factory Functions
|
|
//=============================================================================
|
|
let patternIndexInstance = null;
|
|
let agentRouterInstance = null;
|
|
/**
|
|
* Get or create singleton pattern index
|
|
*/
|
|
export function getWasmPatternIndex(dimensions = DEFAULT_DIM) {
|
|
if (!patternIndexInstance) {
|
|
patternIndexInstance = new WasmPatternIndex(dimensions);
|
|
logger.info('Created WASM pattern index', {
|
|
dimensions,
|
|
wasmAccelerated: patternIndexInstance.isWasmAccelerated(),
|
|
});
|
|
}
|
|
return patternIndexInstance;
|
|
}
|
|
/**
|
|
* Get or create singleton agent router
|
|
*/
|
|
export function getWasmAgentRouter(dimensions = DEFAULT_DIM) {
|
|
if (!agentRouterInstance) {
|
|
agentRouterInstance = new WasmAgentRouter(dimensions);
|
|
logger.info('Created WASM agent router', {
|
|
dimensions,
|
|
wasmAccelerated: agentRouterInstance.isWasmAccelerated(),
|
|
});
|
|
}
|
|
return agentRouterInstance;
|
|
}
|
|
/**
|
|
* Initialize WASM acceleration for intelligence layer
|
|
*/
|
|
export async function initWasmAcceleration() {
|
|
const initialized = await initRuVectorWasm();
|
|
const patternIndex = getWasmPatternIndex();
|
|
const agentRouter = getWasmAgentRouter();
|
|
logger.info('WASM acceleration initialized for intelligence layer', {
|
|
wasmAvailable: initialized,
|
|
patternIndexAccelerated: patternIndex.isWasmAccelerated(),
|
|
agentRouterAccelerated: agentRouter.isWasmAccelerated(),
|
|
});
|
|
return {
|
|
initialized,
|
|
patternIndex,
|
|
agentRouter,
|
|
};
|
|
}
|
|
/**
|
|
* Get WASM acceleration status
|
|
*/
|
|
export function getWasmAccelerationStatus() {
|
|
return {
|
|
initialized: isWasmInitialized(),
|
|
patternIndex: patternIndexInstance?.isWasmAccelerated() ?? false,
|
|
agentRouter: agentRouterInstance?.isWasmAccelerated() ?? false,
|
|
speedup: isWasmInitialized() ? '150x vs brute-force' : 'JS fallback',
|
|
};
|
|
}
|
|
export default {
|
|
WasmPatternIndex,
|
|
WasmAgentRouter,
|
|
getWasmPatternIndex,
|
|
getWasmAgentRouter,
|
|
initWasmAcceleration,
|
|
getWasmAccelerationStatus,
|
|
};
|
|
//# sourceMappingURL=wasm-acceleration.js.map
|