File size: 916 Bytes
eb46abf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import type { EmbeddedChunk, ScoredChunk } from "../types";

/**
 * Cosine similarity between two vectors.
 */
export function cosineSimilarity(a: Float32Array, b: Float32Array): number {
  let dot = 0;
  let normA = 0;
  let normB = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    normA += a[i] * a[i];
    normB += b[i] * b[i];
  }
  return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}

/**
 * Search embedded chunks by cosine similarity to query embedding.
 * Returns the top-K results sorted by descending similarity score.
 */
export function vectorSearch(
  queryEmbedding: Float32Array,
  chunks: EmbeddedChunk[],
  topK: number = 20,
): ScoredChunk[] {
  const scored = chunks.map((chunk) => ({
    chunk,
    score: cosineSimilarity(queryEmbedding, chunk.embedding),
    source: "vector" as const,
  }));
  scored.sort((a, b) => b.score - a.score);
  return scored.slice(0, topK);
}