ruvector-fixed / dist /core /attention-fallbacks.js
Archie
Fix dimension/dimensions bug and positional insert/search args
40d7073
"use strict";
/**
* Attention Fallbacks - Safe wrapper around @ruvector/attention with automatic array conversion
*
* This wrapper handles the array type conversion automatically, allowing users
* to pass either regular arrays or Float32Arrays.
*
* @ruvector/attention requires Float32Array inputs.
* This wrapper handles the conversion automatically.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.AdamOptimizer = exports.DotProductAttention = exports.DualSpaceAttention = exports.EdgeFeaturedAttention = exports.GraphRoPeAttention = exports.MoEAttention = exports.LocalGlobalAttention = exports.LinearAttention = exports.HyperbolicAttention = exports.FlashAttention = exports.MultiHeadAttention = void 0;
exports.projectToPoincareBall = projectToPoincareBall;
exports.poincareDistance = poincareDistance;
exports.mobiusAddition = mobiusAddition;
exports.expMap = expMap;
exports.logMap = logMap;
exports.isAttentionAvailable = isAttentionAvailable;
exports.getAttentionVersion = getAttentionVersion;
exports.parallelAttentionCompute = parallelAttentionCompute;
exports.batchAttentionCompute = batchAttentionCompute;
exports.computeFlashAttentionAsync = computeFlashAttentionAsync;
exports.computeHyperbolicAttentionAsync = computeHyperbolicAttentionAsync;
exports.infoNceLoss = infoNceLoss;
exports.mineHardNegatives = mineHardNegatives;
exports.benchmarkAttention = benchmarkAttention;
// Lazy load to avoid import errors if not installed
let attentionModule = null;
let loadError = null;
function getAttentionModule() {
if (attentionModule)
return attentionModule;
if (loadError)
throw loadError;
try {
attentionModule = require('@ruvector/attention');
return attentionModule;
}
catch (e) {
loadError = new Error(`@ruvector/attention is not installed or failed to load: ${e.message}\n` +
`Install with: npm install @ruvector/attention`);
throw loadError;
}
}
/**
* Convert any array-like input to Float32Array
*/
function toFloat32Array(input) {
if (input instanceof Float32Array) {
return input;
}
return new Float32Array(input);
}
/**
* Convert nested arrays to Float32Arrays
*/
function toFloat32Arrays(inputs) {
return inputs.map(arr => toFloat32Array(arr));
}
/**
* Convert Float32Array result back to regular array if needed
*/
function fromFloat32Array(input) {
return Array.from(input);
}
/**
* Multi-head attention mechanism
*
* This wrapper automatically converts array inputs to Float32Array.
*/
class MultiHeadAttention {
/**
* Create a new multi-head attention instance
*
* @param dim - Embedding dimension (must be divisible by numHeads)
* @param numHeads - Number of attention heads
*/
constructor(dim, numHeads) {
const attention = getAttentionModule();
this.inner = new attention.MultiHeadAttention(dim, numHeads);
this.dim = dim;
this.numHeads = numHeads;
}
/**
* Compute multi-head attention
*
* @param query - Query vector
* @param keys - Array of key vectors
* @param values - Array of value vectors
* @returns Attention output
*
* @example
* ```typescript
* const mha = new MultiHeadAttention(64, 4);
*
* // Works with regular arrays
* const result1 = mha.compute([...64 values], [[...64], [...64]], [[...64], [...64]]);
*
* // Also works with Float32Array
* const q = new Float32Array(64);
* const k = [new Float32Array(64)];
* const v = [new Float32Array(64)];
* const result2 = mha.compute(q, k, v);
* ```
*/
compute(query, keys, values) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values));
return {
values: fromFloat32Array(raw),
raw
};
}
/**
* Compute and return raw Float32Array (faster, no conversion)
*/
computeRaw(query, keys, values) {
return this.inner.compute(query, keys, values);
}
get headDim() {
return this.dim / this.numHeads;
}
}
exports.MultiHeadAttention = MultiHeadAttention;
/**
* Flash attention with tiled computation
*/
class FlashAttention {
/**
* Create a new flash attention instance
*
* @param dim - Embedding dimension
* @param blockSize - Block size for tiled computation (default: 512)
*/
constructor(dim, blockSize = 512) {
const attention = getAttentionModule();
this.inner = new attention.FlashAttention(dim, blockSize);
this.dim = dim;
this.blockSize = blockSize;
}
/**
* Compute flash attention
*/
compute(query, keys, values) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values));
return {
values: fromFloat32Array(raw),
raw
};
}
computeRaw(query, keys, values) {
return this.inner.compute(query, keys, values);
}
}
exports.FlashAttention = FlashAttention;
/**
* Hyperbolic attention in Poincare ball model
*/
class HyperbolicAttention {
/**
* Create a new hyperbolic attention instance
*
* @param dim - Embedding dimension
* @param curvature - Hyperbolic curvature (typically 1.0)
*/
constructor(dim, curvature = 1.0) {
const attention = getAttentionModule();
this.inner = new attention.HyperbolicAttention(dim, curvature);
this.dim = dim;
this.curvature = curvature;
}
/**
* Compute hyperbolic attention
*/
compute(query, keys, values) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values));
return {
values: fromFloat32Array(raw),
raw
};
}
computeRaw(query, keys, values) {
return this.inner.compute(query, keys, values);
}
}
exports.HyperbolicAttention = HyperbolicAttention;
/**
* Linear attention (Performer-style) with O(n) complexity
*/
class LinearAttention {
/**
* Create a new linear attention instance
*
* @param dim - Embedding dimension
* @param numFeatures - Number of random features
*/
constructor(dim, numFeatures) {
const attention = getAttentionModule();
this.inner = new attention.LinearAttention(dim, numFeatures);
this.dim = dim;
this.numFeatures = numFeatures;
}
/**
* Compute linear attention
*/
compute(query, keys, values) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values));
return {
values: fromFloat32Array(raw),
raw
};
}
computeRaw(query, keys, values) {
return this.inner.compute(query, keys, values);
}
}
exports.LinearAttention = LinearAttention;
/**
* Local-global attention (Longformer-style)
*/
class LocalGlobalAttention {
/**
* Create a new local-global attention instance
*
* @param dim - Embedding dimension
* @param localWindow - Size of local attention window
* @param globalTokens - Number of global attention tokens
*/
constructor(dim, localWindow, globalTokens) {
const attention = getAttentionModule();
this.inner = new attention.LocalGlobalAttention(dim, localWindow, globalTokens);
this.dim = dim;
this.localWindow = localWindow;
this.globalTokens = globalTokens;
}
/**
* Compute local-global attention
*/
compute(query, keys, values) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values));
return {
values: fromFloat32Array(raw),
raw
};
}
computeRaw(query, keys, values) {
return this.inner.compute(query, keys, values);
}
}
exports.LocalGlobalAttention = LocalGlobalAttention;
/**
* Mixture of Experts attention
*/
class MoEAttention {
/**
* Create a new MoE attention instance
*
* @param config - MoE configuration
*/
constructor(config) {
const attention = getAttentionModule();
this.inner = new attention.MoEAttention({
dim: config.dim,
num_experts: config.numExperts,
top_k: config.topK,
expert_capacity: config.expertCapacity ?? 1.25,
});
this.config = config;
}
/**
* Create with simple parameters
*/
static simple(dim, numExperts, topK) {
return new MoEAttention({ dim, numExperts, topK });
}
/**
* Compute MoE attention
*/
compute(query, keys, values) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values));
return {
values: fromFloat32Array(raw),
raw
};
}
computeRaw(query, keys, values) {
return this.inner.compute(query, keys, values);
}
}
exports.MoEAttention = MoEAttention;
// Hyperbolic math utilities
/**
* Project a vector into the Poincare ball
*/
function projectToPoincareBall(vector, curvature = 1.0) {
const attention = getAttentionModule();
const result = attention.projectToPoincareBall(toFloat32Array(vector), curvature);
return fromFloat32Array(result);
}
/**
* Compute hyperbolic (Poincare) distance between two points
*/
function poincareDistance(a, b, curvature = 1.0) {
const attention = getAttentionModule();
return attention.poincareDistance(toFloat32Array(a), toFloat32Array(b), curvature);
}
/**
* Mobius addition in hyperbolic space
*/
function mobiusAddition(a, b, curvature = 1.0) {
const attention = getAttentionModule();
const result = attention.mobiusAddition(toFloat32Array(a), toFloat32Array(b), curvature);
return fromFloat32Array(result);
}
/**
* Exponential map from tangent space to hyperbolic space
*/
function expMap(base, tangent, curvature = 1.0) {
const attention = getAttentionModule();
const result = attention.expMap(toFloat32Array(base), toFloat32Array(tangent), curvature);
return fromFloat32Array(result);
}
/**
* Logarithmic map from hyperbolic space to tangent space
*/
function logMap(base, point, curvature = 1.0) {
const attention = getAttentionModule();
const result = attention.logMap(toFloat32Array(base), toFloat32Array(point), curvature);
return fromFloat32Array(result);
}
/**
* Check if attention module is available
*/
function isAttentionAvailable() {
try {
getAttentionModule();
return true;
}
catch {
return false;
}
}
/**
* Get attention module version
*/
function getAttentionVersion() {
try {
const attention = getAttentionModule();
return attention.version?.() ?? null;
}
catch {
return null;
}
}
// ============================================================================
// Graph-based Attention (for code structure)
// ============================================================================
/**
* Graph attention with Rotary Position Embeddings
* Excellent for code AST and dependency graphs
*/
class GraphRoPeAttention {
constructor(dim, numHeads = 4, maxSeqLen = 4096) {
const attention = getAttentionModule();
this.inner = new attention.GraphRoPeAttention(dim, numHeads, maxSeqLen);
this.dim = dim;
this.numHeads = numHeads;
this.maxSeqLen = maxSeqLen;
}
compute(query, keys, values, positions) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values), positions ? new Int32Array(positions) : undefined);
return { values: fromFloat32Array(raw), raw };
}
}
exports.GraphRoPeAttention = GraphRoPeAttention;
/**
* Edge-featured attention for graphs with edge attributes
* Useful for weighted dependency graphs
*/
class EdgeFeaturedAttention {
constructor(dim, edgeDim = 16) {
const attention = getAttentionModule();
this.inner = new attention.EdgeFeaturedAttention(dim, edgeDim);
this.dim = dim;
this.edgeDim = edgeDim;
}
compute(query, keys, values, edgeFeatures) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values), edgeFeatures ? toFloat32Arrays(edgeFeatures) : undefined);
return { values: fromFloat32Array(raw), raw };
}
}
exports.EdgeFeaturedAttention = EdgeFeaturedAttention;
/**
* Dual-space attention (Euclidean + Hyperbolic)
* Best of both worlds for hierarchical + semantic similarity
*/
class DualSpaceAttention {
constructor(dim, curvature = 1.0, alpha = 0.5) {
const attention = getAttentionModule();
this.inner = new attention.DualSpaceAttention(dim, curvature, alpha);
this.dim = dim;
this.curvature = curvature;
this.alpha = alpha;
}
compute(query, keys, values) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values));
return { values: fromFloat32Array(raw), raw };
}
}
exports.DualSpaceAttention = DualSpaceAttention;
/**
* Basic dot-product attention
*/
class DotProductAttention {
constructor(dim) {
const attention = getAttentionModule();
this.inner = new attention.DotProductAttention(dim);
this.dim = dim;
}
compute(query, keys, values) {
const raw = this.inner.compute(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values));
return { values: fromFloat32Array(raw), raw };
}
}
exports.DotProductAttention = DotProductAttention;
// ============================================================================
// Parallel/Batch Attention Compute
// ============================================================================
/**
* Compute attention in parallel across multiple queries
*/
async function parallelAttentionCompute(queries, keys, values, attentionType = 'multi-head') {
const attention = getAttentionModule();
const results = await attention.parallelAttentionCompute(toFloat32Arrays(queries), toFloat32Arrays(keys), toFloat32Arrays(values), attentionType);
return results.map((r) => fromFloat32Array(r));
}
/**
* Batch attention compute for multiple query-key-value sets
*/
async function batchAttentionCompute(batches, attentionType = 'multi-head') {
const attention = getAttentionModule();
const nativeBatches = batches.map(b => ({
query: toFloat32Array(b.query),
keys: toFloat32Arrays(b.keys),
values: toFloat32Arrays(b.values),
}));
const results = await attention.batchAttentionCompute(nativeBatches, attentionType);
return results.map((r) => fromFloat32Array(r));
}
/**
* Async flash attention with callback
*/
function computeFlashAttentionAsync(query, keys, values) {
const attention = getAttentionModule();
return new Promise((resolve, reject) => {
attention.computeFlashAttentionAsync(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values), (err, result) => {
if (err)
reject(err);
else
resolve(fromFloat32Array(result));
});
});
}
/**
* Async hyperbolic attention
*/
function computeHyperbolicAttentionAsync(query, keys, values, curvature = 1.0) {
const attention = getAttentionModule();
return new Promise((resolve, reject) => {
attention.computeHyperbolicAttentionAsync(toFloat32Array(query), toFloat32Arrays(keys), toFloat32Arrays(values), curvature, (err, result) => {
if (err)
reject(err);
else
resolve(fromFloat32Array(result));
});
});
}
// ============================================================================
// Training Utilities (for SONA integration)
// ============================================================================
/**
* Adam optimizer for attention training
*/
class AdamOptimizer {
constructor(learningRate = 0.001, beta1 = 0.9, beta2 = 0.999) {
const attention = getAttentionModule();
this.inner = new attention.AdamOptimizer(learningRate, beta1, beta2);
}
step(gradients, params) {
const result = this.inner.step(toFloat32Array(gradients), toFloat32Array(params));
return fromFloat32Array(result);
}
}
exports.AdamOptimizer = AdamOptimizer;
/**
* InfoNCE contrastive loss
*/
function infoNceLoss(anchor, positive, negatives, temperature = 0.07) {
const attention = getAttentionModule();
return attention.InfoNceLoss.compute(toFloat32Array(anchor), toFloat32Array(positive), toFloat32Arrays(negatives), temperature);
}
/**
* Hard negative mining for contrastive learning
*/
function mineHardNegatives(anchor, candidates, topK = 5) {
const attention = getAttentionModule();
const miner = new attention.HardNegativeMiner(topK);
const results = miner.mine(toFloat32Array(anchor), toFloat32Arrays(candidates));
return results.map((r) => fromFloat32Array(r));
}
// ============================================================================
// Benchmarking
// ============================================================================
/**
* Benchmark attention implementations
*/
async function benchmarkAttention(dim, seqLen, iterations = 100) {
const attention = getAttentionModule();
return attention.benchmarkAttention(dim, seqLen, iterations);
}
exports.default = {
// Core attention types
DotProductAttention,
MultiHeadAttention,
FlashAttention,
HyperbolicAttention,
LinearAttention,
LocalGlobalAttention,
MoEAttention,
// Graph attention types
GraphRoPeAttention,
EdgeFeaturedAttention,
DualSpaceAttention,
// Parallel/batch compute
parallelAttentionCompute,
batchAttentionCompute,
computeFlashAttentionAsync,
computeHyperbolicAttentionAsync,
// Training utilities
AdamOptimizer,
infoNceLoss,
mineHardNegatives,
// Hyperbolic math
projectToPoincareBall,
poincareDistance,
mobiusAddition,
expMap,
logMap,
// Utilities
isAttentionAvailable,
getAttentionVersion,
benchmarkAttention,
};