vecbox 0.1.0 → 0.2.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/README.md +100 -46
- package/dist/index.cjs +164 -204
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -36
- package/dist/index.d.ts +26 -36
- package/dist/index.js +171 -205
- package/dist/index.js.map +1 -1
- package/dist/llama_embedding-EC3MWSUZ.node +0 -0
- package/native/README.md +67 -0
- package/native/binding.gyp +65 -0
- package/native/index.js +39 -0
- package/native/llama_embedding.cpp +179 -0
- package/native/llama_embedding_simple.cpp +111 -0
- package/native/package-lock.json +1277 -0
- package/native/package.json +26 -0
- package/package.json +7 -6
- package/src/factory/EmbeddingFactory.ts +0 -4
- package/src/images/vecbox.png +0 -0
- package/src/providers/gemini.ts +2 -2
- package/src/providers/llamacpp.ts +84 -6
- package/src/types/index.ts +0 -2
- package/src/images/embed-kit.png +0 -0
- package/src/providers/claude.ts +0 -78
- package/src/providers/deepseek.ts +0 -115
- package/src/types/deepseek.d.ts +0 -15
- package/src/types/index.d.ts +0 -43
- package/src/types/transformers.d.ts +0 -7
package/dist/index.js
CHANGED
|
@@ -1,6 +1,75 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
|
|
1
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
11
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
12
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// native/build/Release/llama_embedding.node
|
|
16
|
+
var llama_embedding_default;
|
|
17
|
+
var init_llama_embedding = __esm({
|
|
18
|
+
"native/build/Release/llama_embedding.node"() {
|
|
19
|
+
llama_embedding_default = "./llama_embedding-EC3MWSUZ.node";
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// node-file:/home/inky/Development/vecbox/native/build/Release/llama_embedding.node
|
|
24
|
+
var require_llama_embedding = __commonJS({
|
|
25
|
+
"node-file:/home/inky/Development/vecbox/native/build/Release/llama_embedding.node"(exports, module) {
|
|
26
|
+
"use strict";
|
|
27
|
+
init_llama_embedding();
|
|
28
|
+
try {
|
|
29
|
+
module.exports = __require(llama_embedding_default);
|
|
30
|
+
} catch {
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// native/index.js
|
|
36
|
+
var require_native = __commonJS({
|
|
37
|
+
"native/index.js"(exports, module) {
|
|
38
|
+
"use strict";
|
|
39
|
+
var binding = require_llama_embedding();
|
|
40
|
+
var LlamaEmbedding = class {
|
|
41
|
+
constructor(modelPath) {
|
|
42
|
+
this.modelPtr = binding.createModel(modelPath);
|
|
43
|
+
if (!this.modelPtr) {
|
|
44
|
+
throw new Error("Failed to load model");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
embed(text) {
|
|
48
|
+
if (typeof text !== "string") {
|
|
49
|
+
throw new Error("Text must be a string");
|
|
50
|
+
}
|
|
51
|
+
const embedding = binding.getEmbedding(this.modelPtr, text);
|
|
52
|
+
if (!embedding) {
|
|
53
|
+
throw new Error("Failed to generate embedding");
|
|
54
|
+
}
|
|
55
|
+
return embedding;
|
|
56
|
+
}
|
|
57
|
+
close() {
|
|
58
|
+
if (this.modelPtr) {
|
|
59
|
+
binding.destroyModel(this.modelPtr);
|
|
60
|
+
this.modelPtr = null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
function create(modelPath) {
|
|
65
|
+
return new LlamaEmbedding(modelPath);
|
|
66
|
+
}
|
|
67
|
+
module.exports = {
|
|
68
|
+
create,
|
|
69
|
+
LlamaEmbedding
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
});
|
|
4
73
|
|
|
5
74
|
// main.ts
|
|
6
75
|
import * as dotenv from "dotenv";
|
|
@@ -11,7 +80,6 @@ import OpenAI from "openai";
|
|
|
11
80
|
// src/providers/base/EmbeddingProvider.ts
|
|
12
81
|
var EmbeddingProvider = class {
|
|
13
82
|
constructor(config2) {
|
|
14
|
-
__publicField(this, "config");
|
|
15
83
|
this.config = config2;
|
|
16
84
|
}
|
|
17
85
|
getModel() {
|
|
@@ -32,8 +100,6 @@ var EmbeddingProvider = class {
|
|
|
32
100
|
// src/util/logger.ts
|
|
33
101
|
var _Logger = class _Logger {
|
|
34
102
|
constructor(moduleName = "embedbox", level = 1 /* INFO */) {
|
|
35
|
-
__publicField(this, "currentLevel");
|
|
36
|
-
__publicField(this, "moduleName");
|
|
37
103
|
this.moduleName = moduleName;
|
|
38
104
|
this.currentLevel = level;
|
|
39
105
|
}
|
|
@@ -78,29 +144,28 @@ var _Logger = class _Logger {
|
|
|
78
144
|
}
|
|
79
145
|
// Static methods for quick access
|
|
80
146
|
static debug(message, moduleName) {
|
|
81
|
-
const
|
|
82
|
-
|
|
147
|
+
const logger7 = new _Logger(moduleName || "embedbox");
|
|
148
|
+
logger7.debug(message);
|
|
83
149
|
}
|
|
84
150
|
static info(message, moduleName) {
|
|
85
|
-
const
|
|
86
|
-
|
|
151
|
+
const logger7 = new _Logger(moduleName || "embedbox");
|
|
152
|
+
logger7.info(message);
|
|
87
153
|
}
|
|
88
154
|
static warn(message, moduleName) {
|
|
89
|
-
const
|
|
90
|
-
|
|
155
|
+
const logger7 = new _Logger(moduleName || "embedbox");
|
|
156
|
+
logger7.warn(message);
|
|
91
157
|
}
|
|
92
158
|
static error(message, moduleName) {
|
|
93
|
-
const
|
|
94
|
-
|
|
159
|
+
const logger7 = new _Logger(moduleName || "embedbox");
|
|
160
|
+
logger7.error(message);
|
|
95
161
|
}
|
|
96
162
|
// Method to create a logger instance for a specific module
|
|
97
163
|
static createModuleLogger(moduleName, level) {
|
|
98
164
|
return new _Logger(`embedbox:${moduleName}`, level);
|
|
99
165
|
}
|
|
100
166
|
};
|
|
101
|
-
__publicField(_Logger, "instance");
|
|
102
167
|
// ANSI color codes - simplified for better readability
|
|
103
|
-
|
|
168
|
+
_Logger.COLORS = {
|
|
104
169
|
RESET: "\x1B[0m",
|
|
105
170
|
DEBUG: "\x1B[36m",
|
|
106
171
|
// Cyan
|
|
@@ -110,13 +175,13 @@ __publicField(_Logger, "COLORS", {
|
|
|
110
175
|
// Yellow
|
|
111
176
|
ERROR: "\x1B[31m"
|
|
112
177
|
// Red
|
|
113
|
-
}
|
|
114
|
-
|
|
178
|
+
};
|
|
179
|
+
_Logger.LEVEL_NAMES = {
|
|
115
180
|
[0 /* DEBUG */]: "DEBUG",
|
|
116
181
|
[1 /* INFO */]: "INFO",
|
|
117
182
|
[2 /* WARN */]: "WARN",
|
|
118
183
|
[3 /* ERROR */]: "ERROR"
|
|
119
|
-
}
|
|
184
|
+
};
|
|
120
185
|
var Logger = _Logger;
|
|
121
186
|
var logger = Logger.getInstance();
|
|
122
187
|
|
|
@@ -125,7 +190,6 @@ var logger2 = Logger.createModuleLogger("openai");
|
|
|
125
190
|
var OpenAIProvider = class extends EmbeddingProvider {
|
|
126
191
|
constructor(config2) {
|
|
127
192
|
super(config2);
|
|
128
|
-
__publicField(this, "client");
|
|
129
193
|
if (!config2.apiKey) {
|
|
130
194
|
throw new Error("OpenAI API key is required");
|
|
131
195
|
}
|
|
@@ -214,7 +278,6 @@ var logger3 = Logger.createModuleLogger("gemini");
|
|
|
214
278
|
var GeminiProvider = class extends EmbeddingProvider {
|
|
215
279
|
constructor(config2) {
|
|
216
280
|
super(config2);
|
|
217
|
-
__publicField(this, "client");
|
|
218
281
|
if (!config2.apiKey) {
|
|
219
282
|
throw new Error("Google API key is required");
|
|
220
283
|
}
|
|
@@ -265,11 +328,11 @@ var GeminiProvider = class extends EmbeddingProvider {
|
|
|
265
328
|
}
|
|
266
329
|
getDimensions() {
|
|
267
330
|
const model = this.getModel();
|
|
268
|
-
if (model.includes("gemini-embedding-001")) return
|
|
331
|
+
if (model.includes("gemini-embedding-001")) return 3072;
|
|
269
332
|
if (model.includes("text-embedding-004")) return 768;
|
|
270
333
|
if (model.includes("embedding-001")) return 768;
|
|
271
334
|
if (model.includes("multimodalembedding")) return 768;
|
|
272
|
-
return
|
|
335
|
+
return 3072;
|
|
273
336
|
}
|
|
274
337
|
getProviderName() {
|
|
275
338
|
return "Google Gemini";
|
|
@@ -291,71 +354,12 @@ var GeminiProvider = class extends EmbeddingProvider {
|
|
|
291
354
|
}
|
|
292
355
|
};
|
|
293
356
|
|
|
294
|
-
// src/providers/claude.ts
|
|
295
|
-
import Anthropic from "@anthropic-ai/sdk";
|
|
296
|
-
var logger4 = Logger.createModuleLogger("claude");
|
|
297
|
-
var ClaudeProvider = class extends EmbeddingProvider {
|
|
298
|
-
constructor(config2) {
|
|
299
|
-
super(config2);
|
|
300
|
-
__publicField(this, "client");
|
|
301
|
-
if (!config2.apiKey) {
|
|
302
|
-
throw new Error("Anthropic API key is required");
|
|
303
|
-
}
|
|
304
|
-
this.client = new Anthropic({
|
|
305
|
-
apiKey: config2.apiKey,
|
|
306
|
-
baseURL: config2.baseUrl,
|
|
307
|
-
timeout: config2.timeout || 3e4
|
|
308
|
-
});
|
|
309
|
-
logger4.info("Claude provider initialized");
|
|
310
|
-
}
|
|
311
|
-
async embed() {
|
|
312
|
-
try {
|
|
313
|
-
logger4.debug(`Embedding text with model: ${this.getModel()}`);
|
|
314
|
-
throw new Error("Claude embeddings API not yet available. Please use another provider.");
|
|
315
|
-
} catch (error) {
|
|
316
|
-
const errorMessage = error instanceof Error ? error instanceof Error ? error.message : String(error) : "Unknown error";
|
|
317
|
-
logger4.error(`Claude embedding failed: ${errorMessage}`);
|
|
318
|
-
throw error;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
async embedBatch() {
|
|
322
|
-
try {
|
|
323
|
-
throw new Error("Claude embeddings API not yet available. Please use another provider.");
|
|
324
|
-
} catch (error) {
|
|
325
|
-
const errorMessage = error instanceof Error ? error instanceof Error ? error.message : String(error) : "Unknown error";
|
|
326
|
-
logger4.error(`Claude batch embedding failed: ${errorMessage}`);
|
|
327
|
-
throw error;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
getDimensions() {
|
|
331
|
-
return 0;
|
|
332
|
-
}
|
|
333
|
-
getProviderName() {
|
|
334
|
-
return "Anthropic Claude";
|
|
335
|
-
}
|
|
336
|
-
async isReady() {
|
|
337
|
-
try {
|
|
338
|
-
await this.client.messages.create({
|
|
339
|
-
model: "claude-3-haiku-20240307",
|
|
340
|
-
max_tokens: 10,
|
|
341
|
-
messages: [{ role: "user", content: "test" }]
|
|
342
|
-
});
|
|
343
|
-
return true;
|
|
344
|
-
} catch (error) {
|
|
345
|
-
const errorMessage = error instanceof Error ? error instanceof Error ? error.message : String(error) : "Unknown error";
|
|
346
|
-
logger4.error(`Claude readiness check failed: ${errorMessage}`);
|
|
347
|
-
return false;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
|
|
352
357
|
// src/providers/mistral.ts
|
|
353
358
|
import { Mistral } from "@mistralai/mistralai";
|
|
354
|
-
var
|
|
359
|
+
var logger4 = Logger.createModuleLogger("mistral");
|
|
355
360
|
var MistralProvider = class extends EmbeddingProvider {
|
|
356
361
|
constructor(config2) {
|
|
357
362
|
super(config2);
|
|
358
|
-
__publicField(this, "client");
|
|
359
363
|
if (!config2.apiKey) {
|
|
360
364
|
throw new Error("Mistral API key is required");
|
|
361
365
|
}
|
|
@@ -364,12 +368,12 @@ var MistralProvider = class extends EmbeddingProvider {
|
|
|
364
368
|
serverURL: config2.baseUrl,
|
|
365
369
|
timeoutMs: config2.timeout || 3e4
|
|
366
370
|
});
|
|
367
|
-
|
|
371
|
+
logger4.info("Mistral provider initialized");
|
|
368
372
|
}
|
|
369
373
|
async embed(input) {
|
|
370
374
|
try {
|
|
371
375
|
const text = await this.readInput(input);
|
|
372
|
-
|
|
376
|
+
logger4.debug(`Embedding text with model: ${this.getModel()}`);
|
|
373
377
|
const response = await this.client.embeddings.create({
|
|
374
378
|
model: this.getModel(),
|
|
375
379
|
inputs: [text]
|
|
@@ -389,14 +393,14 @@ var MistralProvider = class extends EmbeddingProvider {
|
|
|
389
393
|
} : void 0
|
|
390
394
|
};
|
|
391
395
|
} catch (error) {
|
|
392
|
-
|
|
396
|
+
logger4.error(`Mistral embedding failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
393
397
|
throw error;
|
|
394
398
|
}
|
|
395
399
|
}
|
|
396
400
|
async embedBatch(inputs) {
|
|
397
401
|
try {
|
|
398
402
|
const texts = await Promise.all(inputs.map((input) => this.readInput(input)));
|
|
399
|
-
|
|
403
|
+
logger4.debug(`Batch embedding ${texts.length} texts with model: ${this.getModel()}`);
|
|
400
404
|
const response = await this.client.embeddings.create({
|
|
401
405
|
model: this.getModel(),
|
|
402
406
|
inputs: texts
|
|
@@ -416,7 +420,7 @@ var MistralProvider = class extends EmbeddingProvider {
|
|
|
416
420
|
} : void 0
|
|
417
421
|
};
|
|
418
422
|
} catch (error) {
|
|
419
|
-
|
|
423
|
+
logger4.error(`Mistral batch embedding failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
420
424
|
throw error;
|
|
421
425
|
}
|
|
422
426
|
}
|
|
@@ -436,100 +440,7 @@ var MistralProvider = class extends EmbeddingProvider {
|
|
|
436
440
|
});
|
|
437
441
|
return response.data.length > 0;
|
|
438
442
|
} catch (error) {
|
|
439
|
-
|
|
440
|
-
return false;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
};
|
|
444
|
-
|
|
445
|
-
// src/providers/deepseek.ts
|
|
446
|
-
import { DeepSeek } from "deepseek";
|
|
447
|
-
var logger6 = Logger.createModuleLogger("deepseek");
|
|
448
|
-
var DeepSeekProvider = class extends EmbeddingProvider {
|
|
449
|
-
constructor(config2) {
|
|
450
|
-
super(config2);
|
|
451
|
-
__publicField(this, "client");
|
|
452
|
-
if (!config2.apiKey) {
|
|
453
|
-
throw new Error("DeepSeek API key is required");
|
|
454
|
-
}
|
|
455
|
-
const clientOptions = {
|
|
456
|
-
apiKey: config2.apiKey,
|
|
457
|
-
timeout: config2.timeout || 3e4
|
|
458
|
-
};
|
|
459
|
-
if (config2.baseUrl) {
|
|
460
|
-
clientOptions.baseURL = config2.baseUrl;
|
|
461
|
-
}
|
|
462
|
-
this.client = new DeepSeek(clientOptions);
|
|
463
|
-
logger6.info("DeepSeek provider initialized");
|
|
464
|
-
}
|
|
465
|
-
async embed(input) {
|
|
466
|
-
try {
|
|
467
|
-
const text = await this.readInput(input);
|
|
468
|
-
logger6.debug(`Embedding text with model: ${this.getModel()}`);
|
|
469
|
-
const response = await this.client.embeddings.create({
|
|
470
|
-
model: this.getModel(),
|
|
471
|
-
input: text
|
|
472
|
-
});
|
|
473
|
-
const embedding = response.data[0];
|
|
474
|
-
if (!embedding) {
|
|
475
|
-
throw new Error("No embedding returned from DeepSeek API");
|
|
476
|
-
}
|
|
477
|
-
return {
|
|
478
|
-
embedding: embedding.embedding || [],
|
|
479
|
-
dimensions: embedding.embedding?.length || 0,
|
|
480
|
-
model: embedding.model || this.getModel(),
|
|
481
|
-
provider: "deepseek",
|
|
482
|
-
usage: response.usage ? {
|
|
483
|
-
promptTokens: response.usage.prompt_tokens,
|
|
484
|
-
totalTokens: response.usage.total_tokens
|
|
485
|
-
} : void 0
|
|
486
|
-
};
|
|
487
|
-
} catch (error) {
|
|
488
|
-
logger6.error(`DeepSeek embedding failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
489
|
-
throw error;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
async embedBatch(inputs) {
|
|
493
|
-
try {
|
|
494
|
-
const texts = await Promise.all(inputs.map((input) => this.readInput(input)));
|
|
495
|
-
logger6.debug(`Batch embedding ${texts.length} texts with model: ${this.getModel()}`);
|
|
496
|
-
const response = await this.client.embeddings.create({
|
|
497
|
-
model: this.getModel(),
|
|
498
|
-
input: texts
|
|
499
|
-
});
|
|
500
|
-
const embeddings = response.data.map((item) => item.embedding);
|
|
501
|
-
return {
|
|
502
|
-
embeddings,
|
|
503
|
-
dimensions: embeddings[0]?.length || 0,
|
|
504
|
-
model: response.model,
|
|
505
|
-
provider: "deepseek",
|
|
506
|
-
usage: response.usage ? {
|
|
507
|
-
promptTokens: response.usage.prompt_tokens,
|
|
508
|
-
totalTokens: response.usage.total_tokens
|
|
509
|
-
} : void 0
|
|
510
|
-
};
|
|
511
|
-
} catch (error) {
|
|
512
|
-
logger6.error(`DeepSeek batch embedding failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
513
|
-
throw error;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
getDimensions() {
|
|
517
|
-
const model = this.getModel();
|
|
518
|
-
if (model.includes("deepseek-chat")) return 4096;
|
|
519
|
-
return 4096;
|
|
520
|
-
}
|
|
521
|
-
getProviderName() {
|
|
522
|
-
return "DeepSeek";
|
|
523
|
-
}
|
|
524
|
-
async isReady() {
|
|
525
|
-
try {
|
|
526
|
-
await this.client.embeddings.create({
|
|
527
|
-
model: this.getModel(),
|
|
528
|
-
input: "test"
|
|
529
|
-
});
|
|
530
|
-
return true;
|
|
531
|
-
} catch (error) {
|
|
532
|
-
logger6.error(`DeepSeek readiness check failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
443
|
+
logger4.error(`Mistral readiness check failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
533
444
|
return false;
|
|
534
445
|
}
|
|
535
446
|
}
|
|
@@ -539,14 +450,31 @@ var DeepSeekProvider = class extends EmbeddingProvider {
|
|
|
539
450
|
import { access, constants } from "fs/promises";
|
|
540
451
|
import { join, resolve } from "path";
|
|
541
452
|
import * as http from "http";
|
|
453
|
+
var nativeModule = null;
|
|
454
|
+
try {
|
|
455
|
+
nativeModule = require_native();
|
|
456
|
+
logger.info("Using native Llama.cpp module");
|
|
457
|
+
} catch (error) {
|
|
458
|
+
logger.warn("Native module not available, falling back to HTTP");
|
|
459
|
+
}
|
|
542
460
|
var LlamaCppProvider = class extends EmbeddingProvider {
|
|
543
461
|
constructor(config2) {
|
|
544
462
|
super({ ...config2, provider: "llamacpp" });
|
|
545
|
-
|
|
546
|
-
__publicField(this, "modelPath");
|
|
463
|
+
this.nativeModel = null;
|
|
547
464
|
this.modelPath = config2.model || "nomic-embed-text-v1.5.Q4_K_M.gguf";
|
|
548
465
|
this.llamaPath = config2.llamaPath || "./llama.cpp/build/bin/llama-embedding";
|
|
549
|
-
|
|
466
|
+
this.useNative = !!nativeModule;
|
|
467
|
+
if (this.useNative) {
|
|
468
|
+
try {
|
|
469
|
+
this.nativeModel = nativeModule.create(this.modelPath);
|
|
470
|
+
logger.info(`Llama.cpp provider initialized with native module: ${this.modelPath}`);
|
|
471
|
+
} catch (error) {
|
|
472
|
+
logger.error(`Failed to initialize native module: ${error}`);
|
|
473
|
+
this.useNative = false;
|
|
474
|
+
}
|
|
475
|
+
} else {
|
|
476
|
+
logger.info(`Llama.cpp provider initialized with HTTP fallback: ${this.modelPath}`);
|
|
477
|
+
}
|
|
550
478
|
}
|
|
551
479
|
// Public API methods
|
|
552
480
|
getProviderName() {
|
|
@@ -563,6 +491,9 @@ var LlamaCppProvider = class extends EmbeddingProvider {
|
|
|
563
491
|
}
|
|
564
492
|
async isReady() {
|
|
565
493
|
try {
|
|
494
|
+
if (this.useNative && this.nativeModel) {
|
|
495
|
+
return true;
|
|
496
|
+
}
|
|
566
497
|
await access(this.llamaPath, constants.F_OK);
|
|
567
498
|
await access(this.llamaPath, constants.X_OK);
|
|
568
499
|
const modelPath = await this.getModelPath();
|
|
@@ -581,6 +512,15 @@ var LlamaCppProvider = class extends EmbeddingProvider {
|
|
|
581
512
|
if (!text.trim()) {
|
|
582
513
|
throw new Error("Text input cannot be empty");
|
|
583
514
|
}
|
|
515
|
+
if (this.useNative && this.nativeModel) {
|
|
516
|
+
const embedding2 = this.nativeModel.embed(text);
|
|
517
|
+
return {
|
|
518
|
+
embedding: embedding2,
|
|
519
|
+
dimensions: embedding2.length,
|
|
520
|
+
model: this.getModel(),
|
|
521
|
+
provider: "llamacpp"
|
|
522
|
+
};
|
|
523
|
+
}
|
|
584
524
|
const requestBody = {
|
|
585
525
|
input: text,
|
|
586
526
|
model: await this.getModelPath(),
|
|
@@ -603,6 +543,25 @@ var LlamaCppProvider = class extends EmbeddingProvider {
|
|
|
603
543
|
async embedBatch(inputs) {
|
|
604
544
|
try {
|
|
605
545
|
logger.debug(`Batch embedding ${inputs.length} texts with llama.cpp`);
|
|
546
|
+
if (this.useNative && this.nativeModel) {
|
|
547
|
+
const embeddings2 = [];
|
|
548
|
+
for (const input of inputs) {
|
|
549
|
+
const text = await this.readInput(input);
|
|
550
|
+
if (text.trim()) {
|
|
551
|
+
const embedding = this.nativeModel.embed(text);
|
|
552
|
+
embeddings2.push(embedding);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (embeddings2.length === 0) {
|
|
556
|
+
throw new Error("No valid texts to embed");
|
|
557
|
+
}
|
|
558
|
+
return {
|
|
559
|
+
embeddings: embeddings2,
|
|
560
|
+
dimensions: embeddings2[0]?.length || 0,
|
|
561
|
+
model: this.getModel(),
|
|
562
|
+
provider: "llamacpp"
|
|
563
|
+
};
|
|
564
|
+
}
|
|
606
565
|
const texts = [];
|
|
607
566
|
for (const input of inputs) {
|
|
608
567
|
const text = await this.readInput(input);
|
|
@@ -637,6 +596,18 @@ var LlamaCppProvider = class extends EmbeddingProvider {
|
|
|
637
596
|
throw error;
|
|
638
597
|
}
|
|
639
598
|
}
|
|
599
|
+
// Cleanup method
|
|
600
|
+
async cleanup() {
|
|
601
|
+
if (this.useNative && this.nativeModel) {
|
|
602
|
+
try {
|
|
603
|
+
this.nativeModel.close();
|
|
604
|
+
this.nativeModel = null;
|
|
605
|
+
logger.info("Native Llama.cpp model closed");
|
|
606
|
+
} catch (error) {
|
|
607
|
+
logger.error(`Error closing native model: ${error}`);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
640
611
|
// Protected methods
|
|
641
612
|
getModel() {
|
|
642
613
|
return this.modelPath;
|
|
@@ -735,8 +706,8 @@ var LlamaCppProvider = class extends EmbeddingProvider {
|
|
|
735
706
|
}
|
|
736
707
|
throw new Error(`Unexpected format: ${JSON.stringify(Object.keys(response))}`);
|
|
737
708
|
} catch (error) {
|
|
738
|
-
const errorMessage = error instanceof Error ? error
|
|
739
|
-
throw new Error(`Parse failed: ${errorMessage}
|
|
709
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
710
|
+
throw new Error(`Parse failed: ${errorMessage}`);
|
|
740
711
|
}
|
|
741
712
|
}
|
|
742
713
|
parseArrayOutput(output) {
|
|
@@ -754,10 +725,10 @@ var LlamaCppProvider = class extends EmbeddingProvider {
|
|
|
754
725
|
};
|
|
755
726
|
|
|
756
727
|
// src/factory/EmbeddingFactory.ts
|
|
757
|
-
var
|
|
728
|
+
var logger5 = Logger.createModuleLogger("factory");
|
|
758
729
|
var EmbeddingFactory = class {
|
|
759
730
|
static create(config2) {
|
|
760
|
-
|
|
731
|
+
logger5.info(`Creating provider: ${config2.provider}`);
|
|
761
732
|
const ProviderClass = this.providers.get(config2.provider);
|
|
762
733
|
if (!ProviderClass) {
|
|
763
734
|
throw new Error(`Unsupported provider: ${config2.provider}`);
|
|
@@ -768,54 +739,51 @@ var EmbeddingFactory = class {
|
|
|
768
739
|
return Array.from(this.providers.keys());
|
|
769
740
|
}
|
|
770
741
|
};
|
|
771
|
-
|
|
742
|
+
EmbeddingFactory.providers = /* @__PURE__ */ new Map([
|
|
772
743
|
["openai", OpenAIProvider],
|
|
773
744
|
["gemini", GeminiProvider],
|
|
774
|
-
["claude", ClaudeProvider],
|
|
775
745
|
["mistral", MistralProvider],
|
|
776
|
-
["deepseek", DeepSeekProvider],
|
|
777
746
|
["llamacpp", LlamaCppProvider]
|
|
778
747
|
// Local embeddings with llama.cpp
|
|
779
|
-
])
|
|
748
|
+
]);
|
|
780
749
|
|
|
781
750
|
// main.ts
|
|
782
751
|
dotenv.config();
|
|
783
|
-
var
|
|
752
|
+
var logger6 = Logger.createModuleLogger("main");
|
|
784
753
|
async function embed(config2, input) {
|
|
785
754
|
try {
|
|
786
|
-
|
|
755
|
+
logger6.info(`Starting embedding with provider: ${config2.provider}`);
|
|
787
756
|
const provider = EmbeddingFactory.create(config2);
|
|
788
757
|
const isReady = await provider.isReady();
|
|
789
758
|
if (!isReady) {
|
|
790
759
|
throw new Error(`Provider ${config2.provider} is not ready`);
|
|
791
760
|
}
|
|
792
761
|
if (Array.isArray(input)) {
|
|
793
|
-
|
|
762
|
+
logger6.debug(`Processing batch of ${input.length} items`);
|
|
794
763
|
return await provider.embedBatch(input);
|
|
795
764
|
} else {
|
|
796
|
-
|
|
765
|
+
logger6.debug(`Processing single item`);
|
|
797
766
|
return await provider.embed(input);
|
|
798
767
|
}
|
|
799
768
|
} catch (error) {
|
|
800
769
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
801
|
-
|
|
770
|
+
logger6.error(`Embedding failed: ${errorMessage}`);
|
|
802
771
|
throw error;
|
|
803
772
|
}
|
|
804
773
|
}
|
|
805
774
|
async function autoEmbed(input) {
|
|
806
|
-
|
|
775
|
+
logger6.info("Auto-detecting best provider...");
|
|
807
776
|
const providers = [
|
|
808
777
|
{ provider: "llamacpp", model: "nomic-embed-text-v1.5.Q4_K_M.gguf" },
|
|
809
778
|
// Local & free (llama.cpp)
|
|
810
779
|
{ provider: "openai", model: "text-embedding-3-small", apiKey: process.env.OPENAI_API_KEY || void 0 },
|
|
811
780
|
{ provider: "gemini", model: "gemini-embedding-001", apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY || void 0 },
|
|
812
|
-
{ provider: "mistral", model: "mistral-embed", apiKey: process.env.MISTRAL_API_KEY || void 0 }
|
|
813
|
-
{ provider: "deepseek", model: "deepseek-chat", apiKey: process.env.DEEPSEEK_API_KEY || void 0 }
|
|
781
|
+
{ provider: "mistral", model: "mistral-embed", apiKey: process.env.MISTRAL_API_KEY || void 0 }
|
|
814
782
|
];
|
|
815
783
|
for (const config2 of providers) {
|
|
816
784
|
try {
|
|
817
785
|
if (config2.provider === "llamacpp" || config2.apiKey) {
|
|
818
|
-
|
|
786
|
+
logger6.info(`Trying provider: ${config2.provider}`);
|
|
819
787
|
const cleanConfig = {
|
|
820
788
|
provider: config2.provider,
|
|
821
789
|
model: config2.model
|
|
@@ -827,7 +795,7 @@ async function autoEmbed(input) {
|
|
|
827
795
|
}
|
|
828
796
|
} catch (error) {
|
|
829
797
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
830
|
-
|
|
798
|
+
logger6.warn(`Provider ${config2.provider} failed: ${errorMessage}`);
|
|
831
799
|
continue;
|
|
832
800
|
}
|
|
833
801
|
}
|
|
@@ -854,9 +822,7 @@ var LIB_INFO = {
|
|
|
854
822
|
supportedProviders: [
|
|
855
823
|
"openai",
|
|
856
824
|
"gemini",
|
|
857
|
-
"claude",
|
|
858
825
|
"mistral",
|
|
859
|
-
"deepseek",
|
|
860
826
|
"llamacpp"
|
|
861
827
|
]
|
|
862
828
|
};
|