/** * Pure vector helpers: float32 <-> SQLite BLOB and cosine similarity. * * No DB or network imports, so this is safe to unit-test directly and to * import from anywhere. (de)serialization is endian- and alignment-safe so * a vector survives a round trip through better-sqlite3. */ export function serializeEmbedding(v: Float32Array): Buffer { const buf = Buffer.allocUnsafe(v.length * 4); for (let i = 0; i < v.length; i++) buf.writeFloatLE(v[i], i * 4); return buf; } export function deserializeEmbedding(buf: Buffer): Float32Array { const n = Math.floor(buf.byteLength / 4); const out = new Float32Array(n); for (let i = 0; i < n; i++) out[i] = buf.readFloatLE(i * 4); return out; } export function cosineSimilarity(a: Float32Array, b: Float32Array): number { if (a.length !== b.length || a.length === 0) return 0; let dot = 0; let na = 0; let nb = 0; for (let i = 0; i < a.length; i++) { dot += a[i] * b[i]; na += a[i] * a[i]; nb += b[i] * b[i]; } const denom = Math.sqrt(na) * Math.sqrt(nb); return denom === 0 ? 0 : dot / denom; }