Spaces:
Sleeping
Sleeping
| // ---------------------------------------------------------------------------- | |
| // 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; | |
| } | |