@mastra/fastembed 1.3.4 → 1.3.5-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fastembed.d.ts.map +1 -1
- package/dist/index.cjs +48 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +48 -24
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import fsp from "fs/promises";
|
|
2
2
|
import os from "os";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { AddedToken, Tokenizer } from "@anush008/tokenizers";
|
|
5
4
|
import fs from "fs";
|
|
6
5
|
import { Readable } from "stream";
|
|
7
6
|
import { pipeline } from "stream/promises";
|
|
8
|
-
import
|
|
7
|
+
import { AddedToken, Tokenizer } from "@anush008/tokenizers";
|
|
9
8
|
import { downloadFile } from "@huggingface/hub";
|
|
9
|
+
import * as ort from "onnxruntime-node";
|
|
10
10
|
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/zod/4.6.7/4c9f15c99caaca8b83ba8ab68f247a75121c86fb7e498876ed36daccd0f3d3ce/node_modules/zod/v4/core/util.js
|
|
11
11
|
function getEnumValues(entries) {
|
|
12
12
|
const numericValues = Object.values(entries).filter((v) => typeof v === "number");
|
|
@@ -18387,12 +18387,19 @@ function normalize(v) {
|
|
|
18387
18387
|
const epsilon = 1e-12;
|
|
18388
18388
|
return v.map((val) => val / Math.max(norm, epsilon));
|
|
18389
18389
|
}
|
|
18390
|
-
function getEmbeddings(data, dimensions) {
|
|
18391
|
-
const [
|
|
18392
|
-
return
|
|
18393
|
-
const
|
|
18394
|
-
|
|
18395
|
-
|
|
18390
|
+
function getEmbeddings(data, dimensions, masks) {
|
|
18391
|
+
const [batchSize, sequenceLength, hiddenSize] = dimensions;
|
|
18392
|
+
return Array.from({ length: batchSize }, (_, batchIndex) => {
|
|
18393
|
+
const start = batchIndex * sequenceLength * hiddenSize;
|
|
18394
|
+
if (!masks) return data.slice(start, start + hiddenSize);
|
|
18395
|
+
const embedding = new Array(hiddenSize).fill(0);
|
|
18396
|
+
let tokenCount = 0;
|
|
18397
|
+
for (let tokenIndex = 0; tokenIndex < sequenceLength; tokenIndex++) {
|
|
18398
|
+
if (masks[batchIndex][tokenIndex] === 0n) continue;
|
|
18399
|
+
tokenCount++;
|
|
18400
|
+
for (let dimension = 0; dimension < hiddenSize; dimension++) embedding[dimension] = embedding[dimension] + data[start + tokenIndex * hiddenSize + dimension];
|
|
18401
|
+
}
|
|
18402
|
+
return embedding.map((value) => value / Math.max(tokenCount, 1));
|
|
18396
18403
|
});
|
|
18397
18404
|
}
|
|
18398
18405
|
var Embedding = class {};
|
|
@@ -18409,7 +18416,7 @@ function loadTokenizerFromDir(modelDir, maxLength) {
|
|
|
18409
18416
|
const tokenizerFilePath = path.join(modelDir.toString(), "tokenizer_config.json");
|
|
18410
18417
|
if (!fs.existsSync(tokenizerFilePath)) throw new Error(`Tokenizer config file not found at ${tokenizerFilePath}`);
|
|
18411
18418
|
const tokenizerConfig = JSON.parse(fs.readFileSync(tokenizerFilePath, "utf-8"));
|
|
18412
|
-
maxLength = Math.min(maxLength, tokenizerConfig["model_max_length"]);
|
|
18419
|
+
maxLength = Math.min(maxLength, tokenizerConfig["model_max_length"] ?? maxLength);
|
|
18413
18420
|
const tokensMapPath = path.join(modelDir.toString(), "special_tokens_map.json");
|
|
18414
18421
|
if (!fs.existsSync(tokensMapPath)) throw new Error(`Tokens map file not found at ${tokensMapPath}`);
|
|
18415
18422
|
const tokensMap = JSON.parse(fs.readFileSync(tokensMapPath, "utf-8"));
|
|
@@ -18544,7 +18551,7 @@ var FlagEmbedding = class FlagEmbedding extends Embedding {
|
|
|
18544
18551
|
};
|
|
18545
18552
|
if (this.model === "fast-multilingual-e5-large") delete inputs.token_type_ids;
|
|
18546
18553
|
const lastHiddenState = (await this.session.run(inputs)).last_hidden_state;
|
|
18547
|
-
yield getEmbeddings(lastHiddenState.data, lastHiddenState.dims).map(normalize);
|
|
18554
|
+
yield getEmbeddings(lastHiddenState.data, lastHiddenState.dims, this.model === "fast-all-MiniLM-L6-v2" || this.model === "fast-multilingual-e5-large" ? maskArray : void 0).map(normalize);
|
|
18548
18555
|
}
|
|
18549
18556
|
}
|
|
18550
18557
|
passageEmbed(texts, batchSize = 256) {
|
|
@@ -18619,29 +18626,46 @@ var SparseTextEmbedding = class SparseTextEmbedding extends SparseEmbedding {
|
|
|
18619
18626
|
return { tokenizer: loadTokenizerFromDir(modelDir, maxLength) };
|
|
18620
18627
|
}
|
|
18621
18628
|
static async retrieveModel(model, cacheDir, _showDownloadProgress = true) {
|
|
18622
|
-
if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, {
|
|
18629
|
+
if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, {
|
|
18630
|
+
recursive: true,
|
|
18631
|
+
mode: 493
|
|
18632
|
+
});
|
|
18623
18633
|
const modelDir = path.join(cacheDir.toString(), model.replace("/", "_"));
|
|
18624
18634
|
if (fs.existsSync(modelDir)) return modelDir;
|
|
18625
|
-
|
|
18626
|
-
for (const fileName of [
|
|
18635
|
+
const filesToDownload = [
|
|
18627
18636
|
"onnx/model.onnx",
|
|
18628
18637
|
"tokenizer.json",
|
|
18629
18638
|
"tokenizer_config.json",
|
|
18630
18639
|
"config.json",
|
|
18631
18640
|
"special_tokens_map.json"
|
|
18632
|
-
]
|
|
18633
|
-
|
|
18634
|
-
|
|
18635
|
-
|
|
18641
|
+
];
|
|
18642
|
+
const tmpDir = fs.mkdtempSync(`${modelDir}.tmp-`);
|
|
18643
|
+
try {
|
|
18644
|
+
for (const fileName of filesToDownload) {
|
|
18645
|
+
const outputPath = path.join(tmpDir, fileName);
|
|
18646
|
+
fs.mkdirSync(path.dirname(outputPath), {
|
|
18647
|
+
recursive: true,
|
|
18648
|
+
mode: 493
|
|
18649
|
+
});
|
|
18650
|
+
const downloaded = await downloadFile({
|
|
18651
|
+
repo: model,
|
|
18652
|
+
path: fileName
|
|
18653
|
+
});
|
|
18654
|
+
if (!downloaded) throw new Error(`Model file not found in ${model}: ${fileName}`);
|
|
18655
|
+
await pipeline(Readable.fromWeb(downloaded.stream()), fs.createWriteStream(outputPath));
|
|
18656
|
+
}
|
|
18657
|
+
try {
|
|
18658
|
+
fs.renameSync(tmpDir, modelDir);
|
|
18659
|
+
} catch (error) {
|
|
18660
|
+
const code = error.code;
|
|
18661
|
+
if ((code === "EEXIST" || code === "ENOTEMPTY") && fs.existsSync(modelDir)) return modelDir;
|
|
18662
|
+
throw error;
|
|
18663
|
+
}
|
|
18664
|
+
} finally {
|
|
18665
|
+
fs.rmSync(tmpDir, {
|
|
18636
18666
|
recursive: true,
|
|
18637
|
-
|
|
18638
|
-
});
|
|
18639
|
-
const downloaded = await downloadFile({
|
|
18640
|
-
repo: model,
|
|
18641
|
-
path: fileName
|
|
18667
|
+
force: true
|
|
18642
18668
|
});
|
|
18643
|
-
if (!downloaded) throw new Error(`Model file not found in ${model}: ${fileName}`);
|
|
18644
|
-
await pipeline(Readable.fromWeb(downloaded.stream()), fs.createWriteStream(outputPath));
|
|
18645
18669
|
}
|
|
18646
18670
|
return modelDir;
|
|
18647
18671
|
}
|