-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathembedder.ts
More file actions
49 lines (39 loc) · 1.59 KB
/
Copy pathembedder.ts
File metadata and controls
49 lines (39 loc) · 1.59 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
/**
* Embedder — local sentence-transformers model via @huggingface/transformers.
*/
const DEFAULT_MODEL_ID = 'onnx-community/bge-small-zh-v1.5-ONNX';
const DEFAULT_DIMENSIONS = 512;
type TransformersPipeline = (texts: string[], options: Record<string, unknown>) => Promise<{ tolist(): number[][] }>;
export class Embedder {
private static pipeline: TransformersPipeline | null = null;
private static pipelinePromise: Promise<TransformersPipeline> | null = null;
readonly dimensions = DEFAULT_DIMENSIONS;
private static async getPipeline(): Promise<TransformersPipeline> {
if (Embedder.pipeline) return Embedder.pipeline;
if (!Embedder.pipelinePromise) {
Embedder.pipelinePromise = (async () => {
const mod = await import('@huggingface/transformers');
const hfEndpoint = process.env.HF_ENDPOINT;
if (hfEndpoint && (mod as any).env) {
(mod as any).env.remoteHost = hfEndpoint;
}
const pipe = await mod.pipeline('feature-extraction', DEFAULT_MODEL_ID) as TransformersPipeline;
Embedder.pipeline = pipe;
return Embedder.pipeline;
})().catch((err) => {
Embedder.pipeline = null;
Embedder.pipelinePromise = null;
throw err;
});
}
return Embedder.pipelinePromise;
}
async embed(text: string): Promise<number[]> {
return (await this.embedBatch([text]))[0];
}
async embedBatch(texts: string[]): Promise<number[][]> {
const pipe = await Embedder.getPipeline();
const outputs = await pipe(texts, { pooling: 'mean', normalize: true });
return outputs.tolist();
}
}