Spaces:
Sleeping
Sleeping
File size: 1,681 Bytes
c438abf | 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 | // ----------------------------------------------------------------------------
// Sentence embeddings with all-MiniLM-L6-v2 running locally in Node via
// Transformers.js (@xenova/transformers). No API key, no external calls — the
// model (~90MB) is downloaded once on first use and cached on disk.
//
// Output: 384-dim, mean-pooled, L2-normalised vectors (cosine == dot product).
// ----------------------------------------------------------------------------
import { pipeline, env } from '@xenova/transformers';
// Cache models under ./.models so repeated deploys don't re-download.
env.cacheDir = process.env.MODEL_CACHE_DIR || './.models';
// We only need inference; disable local-file-only so it can fetch once.
env.allowRemoteModels = true;
let extractorPromise = null;
function getExtractor() {
if (!extractorPromise) {
extractorPromise = pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');
}
return extractorPromise;
}
/** Warm the model at boot so the first request isn't slow. */
export async function warmup() {
const e = await getExtractor();
await e('warmup', { pooling: 'mean', normalize: true });
}
/** Embed a single string -> number[] (384). */
export async function embed(text) {
const e = await getExtractor();
const out = await e(String(text ?? ''), { pooling: 'mean', normalize: true });
return Array.from(out.data);
}
/** Embed many strings -> number[][]. */
export async function embedBatch(texts) {
const e = await getExtractor();
const vecs = [];
for (const t of texts) {
const out = await e(String(t ?? ''), { pooling: 'mean', normalize: true });
vecs.push(Array.from(out.data));
}
return vecs;
}
|