-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathembedder.ts
More file actions
55 lines (49 loc) · 1.93 KB
/
Copy pathembedder.ts
File metadata and controls
55 lines (49 loc) · 1.93 KB
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* Embedder — pluggable interface for text → vector conversion.
*
* Ships with a transformers.js implementation (pure-WASM, zero native deps).
* A faster fastembed-js impl can slot in later behind the same interface;
* the factory will try it first and fall back on init failure.
*/
/** Name of the default local model. 384-dim, ~50MB, BGE-small quality. */
export const DEFAULT_EMBEDDING_MODEL = "Xenova/bge-small-en-v1.5";
export interface Embedder {
readonly modelName: string;
readonly dimensions: number;
/** Load the model. Safe to call multiple times; only the first init does work. */
init(): Promise<void>;
/** Compute embeddings for a batch of strings. Returned vectors are L2-normalized. */
embed(texts: string[]): Promise<Float32Array[]>;
/** Free model resources. */
close(): Promise<void>;
}
export interface EmbedderConfig {
/** HuggingFace model ID (default: Xenova/bge-small-en-v1.5). */
model?: string;
/** Cache dir for model weights (default: ~/.codeoid/models). */
cacheDir?: string;
}
/** Factory — returns a ready-to-init Embedder. */
export async function createEmbedder(config: EmbedderConfig = {}): Promise<Embedder> {
const { TransformersJsEmbedder } = await import("./embedder-transformersjs.js");
return new TransformersJsEmbedder(
config.model ?? DEFAULT_EMBEDDING_MODEL,
config.cacheDir,
);
}
/** L2-normalize a vector in place. */
export function normalize(v: Float32Array): Float32Array {
let sum = 0;
for (let i = 0; i < v.length; i++) sum += v[i]! * v[i]!;
const norm = Math.sqrt(sum);
if (norm === 0) return v;
for (let i = 0; i < v.length; i++) v[i] = v[i]! / norm;
return v;
}
/** Cosine similarity — assumes both vectors are L2-normalized (returns dot product). */
export function cosine(a: Float32Array, b: Float32Array): number {
if (a.length !== b.length) return 0;
let sum = 0;
for (let i = 0; i < a.length; i++) sum += a[i]! * b[i]!;
return sum;
}