const MODEL_NAME = "Xenova/all-MiniLM-L6-v2"; const MODEL_DTYPE = "q8"; let pipelinePromise: Promise | undefined; async function getPipeline() { if (!pipelinePromise) { pipelinePromise = (async () => { const { pipeline } = await import("@huggingface/transformers"); return pipeline("feature-extraction", MODEL_NAME, { dtype: MODEL_DTYPE, }); })(); } return pipelinePromise; } export async function generateEmbedding(text: string): Promise { const pipe = await getPipeline(); const output = await pipe(text, { pooling: "mean", normalize: true }); return Array.from(output.data as Float32Array) as number[]; } export function cosineSimilarity(a: number[], b: number[]): number { if (a.length !== b.length) { throw new Error( `Embedding dimension mismatch: ${a.length} vs ${b.length}`, ); } let dotProduct = 0; let normA = 0; let normB = 0; for (let i = 0; i < a.length; i++) { const ai = a[i]!; const bi = b[i]!; dotProduct += ai * bi; normA += ai * ai; normB += bi * bi; } const denominator = Math.sqrt(normA) * Math.sqrt(normB); if (denominator === 0) return 0; return dotProduct / denominator; }