cozo-memory 1.0.9 → 1.1.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.
@@ -0,0 +1,402 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ require("dotenv/config");
37
+ const embedding_service_1 = require("./embedding-service");
38
+ const path = __importStar(require("path"));
39
+ const fs = __importStar(require("fs"));
40
+ // Test data - verschiedene Szenarien
41
+ const TEST_QUERIES = [
42
+ "What is machine learning?",
43
+ "How do neural networks work?",
44
+ "Explain quantum computing",
45
+ "What are the benefits of TypeScript?",
46
+ "How to optimize database queries?",
47
+ "Best practices for API design",
48
+ "Understanding distributed systems",
49
+ "Introduction to graph databases",
50
+ "Microservices architecture patterns",
51
+ "Cloud computing fundamentals"
52
+ ];
53
+ const TEST_DOCUMENTS = [
54
+ "Machine learning is a subset of artificial intelligence that enables systems to learn and improve from experience without being explicitly programmed.",
55
+ "Neural networks are computing systems inspired by biological neural networks that constitute animal brains. They consist of interconnected nodes or neurons.",
56
+ "Quantum computing uses quantum-mechanical phenomena such as superposition and entanglement to perform operations on data.",
57
+ "TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.",
58
+ "Database query optimization involves analyzing and improving query performance through indexing, query rewriting, and execution plan analysis.",
59
+ "API design best practices include using RESTful principles, proper versioning, clear documentation, and consistent error handling.",
60
+ "Distributed systems are computing systems whose components are located on different networked computers, which communicate and coordinate their actions.",
61
+ "Graph databases use graph structures with nodes, edges, and properties to represent and store data, ideal for connected data.",
62
+ "Microservices architecture is an approach to developing a single application as a suite of small services, each running in its own process.",
63
+ "Cloud computing delivers computing services including servers, storage, databases, networking, software, analytics, and intelligence over the Internet."
64
+ ];
65
+ // Cosine similarity berechnen
66
+ function cosineSimilarity(a, b) {
67
+ let dotProduct = 0;
68
+ let normA = 0;
69
+ let normB = 0;
70
+ for (let i = 0; i < a.length; i++) {
71
+ dotProduct += a[i] * b[i];
72
+ normA += a[i] * a[i];
73
+ normB += b[i] * b[i];
74
+ }
75
+ return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
76
+ }
77
+ // Test 1: Embedding-Geschwindigkeit
78
+ async function testEmbeddingSpeed(service, modelName) {
79
+ console.log(`\n${'='.repeat(70)}`);
80
+ console.log(`TEST 1: Embedding-Geschwindigkeit - ${modelName}`);
81
+ console.log('='.repeat(70));
82
+ const times = [];
83
+ // Warmup
84
+ await service.embed("warmup");
85
+ // Single embeddings
86
+ for (const query of TEST_QUERIES) {
87
+ const start = performance.now();
88
+ await service.embed(query);
89
+ const end = performance.now();
90
+ times.push(end - start);
91
+ }
92
+ const avgTime = times.reduce((a, b) => a + b, 0) / times.length;
93
+ const minTime = Math.min(...times);
94
+ const maxTime = Math.max(...times);
95
+ console.log(`\nSingle Embedding Performance:`);
96
+ console.log(` Average: ${avgTime.toFixed(2)} ms`);
97
+ console.log(` Min: ${minTime.toFixed(2)} ms`);
98
+ console.log(` Max: ${maxTime.toFixed(2)} ms`);
99
+ return { avgTime, minTime, maxTime };
100
+ }
101
+ // Test 2: Batch-Performance
102
+ async function testBatchPerformance(service, modelName) {
103
+ console.log(`\n${'='.repeat(70)}`);
104
+ console.log(`TEST 2: Batch-Performance - ${modelName}`);
105
+ console.log('='.repeat(70));
106
+ const start = performance.now();
107
+ await service.embedBatch(TEST_DOCUMENTS);
108
+ const end = performance.now();
109
+ const totalTime = end - start;
110
+ const avgPerDoc = totalTime / TEST_DOCUMENTS.length;
111
+ console.log(`\nBatch Embedding (${TEST_DOCUMENTS.length} documents):`);
112
+ console.log(` Total time: ${totalTime.toFixed(2)} ms`);
113
+ console.log(` Avg per doc: ${avgPerDoc.toFixed(2)} ms`);
114
+ console.log(` Throughput: ${(1000 / avgPerDoc).toFixed(2)} docs/sec`);
115
+ return { totalTime, avgPerDoc };
116
+ }
117
+ // Test 3: Semantic Similarity Quality
118
+ async function testSemanticSimilarity(service, modelName) {
119
+ console.log(`\n${'='.repeat(70)}`);
120
+ console.log(`TEST 3: Semantic Similarity Quality - ${modelName}`);
121
+ console.log('='.repeat(70));
122
+ // Embed queries and documents
123
+ const queryEmbeddings = await service.embedBatch(TEST_QUERIES);
124
+ const docEmbeddings = await service.embedBatch(TEST_DOCUMENTS);
125
+ // Expected matches (query index -> document index)
126
+ const expectedMatches = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
127
+ let correctMatches = 0;
128
+ const similarities = [];
129
+ console.log(`\nTop Match for each Query:`);
130
+ for (let i = 0; i < TEST_QUERIES.length; i++) {
131
+ const queryEmb = queryEmbeddings[i];
132
+ // Calculate similarities with all documents
133
+ const sims = docEmbeddings.map((docEmb, idx) => ({
134
+ idx,
135
+ similarity: cosineSimilarity(queryEmb, docEmb)
136
+ }));
137
+ // Sort by similarity
138
+ sims.sort((a, b) => b.similarity - a.similarity);
139
+ const topMatch = sims[0];
140
+ const isCorrect = topMatch.idx === expectedMatches[i];
141
+ if (isCorrect)
142
+ correctMatches++;
143
+ similarities.push(topMatch.similarity);
144
+ console.log(` Q${i}: "${TEST_QUERIES[i].substring(0, 40)}..."`);
145
+ console.log(` → Doc ${topMatch.idx} (sim: ${topMatch.similarity.toFixed(4)}) ${isCorrect ? '✓' : '✗'}`);
146
+ }
147
+ const accuracy = (correctMatches / TEST_QUERIES.length) * 100;
148
+ const avgSimilarity = similarities.reduce((a, b) => a + b, 0) / similarities.length;
149
+ console.log(`\nResults:`);
150
+ console.log(` Accuracy: ${accuracy.toFixed(1)}% (${correctMatches}/${TEST_QUERIES.length})`);
151
+ console.log(` Avg Similarity: ${avgSimilarity.toFixed(4)}`);
152
+ return { accuracy, avgSimilarity, correctMatches };
153
+ }
154
+ // Test 4: Long Context Handling
155
+ async function testLongContext(service, modelName) {
156
+ console.log(`\n${'='.repeat(70)}`);
157
+ console.log(`TEST 4: Long Context Handling - ${modelName}`);
158
+ console.log('='.repeat(70));
159
+ const shortText = "Machine learning is AI.";
160
+ const mediumText = TEST_DOCUMENTS[0]; // ~150 chars
161
+ const longText = TEST_DOCUMENTS.join(" "); // ~1000 chars
162
+ const veryLongText = longText.repeat(5); // ~5000 chars
163
+ const tests = [
164
+ { name: "Short (~20 chars)", text: shortText },
165
+ { name: "Medium (~150 chars)", text: mediumText },
166
+ { name: "Long (~1000 chars)", text: longText },
167
+ { name: "Very Long (~5000 chars)", text: veryLongText }
168
+ ];
169
+ console.log(`\nContext Length Performance:`);
170
+ const results = [];
171
+ for (const test of tests) {
172
+ const start = performance.now();
173
+ await service.embed(test.text);
174
+ const end = performance.now();
175
+ const time = end - start;
176
+ console.log(` ${test.name.padEnd(25)} ${time.toFixed(2)} ms`);
177
+ results.push({ name: test.name, time });
178
+ }
179
+ return results;
180
+ }
181
+ // Test 5: Cache Performance
182
+ async function testCachePerformance(service, modelName) {
183
+ console.log(`\n${'='.repeat(70)}`);
184
+ console.log(`TEST 5: Cache Performance - ${modelName}`);
185
+ console.log('='.repeat(70));
186
+ const testText = "Test cache performance";
187
+ // First call (cold)
188
+ const start1 = performance.now();
189
+ await service.embed(testText);
190
+ const end1 = performance.now();
191
+ const coldTime = end1 - start1;
192
+ // Second call (cached)
193
+ const start2 = performance.now();
194
+ await service.embed(testText);
195
+ const end2 = performance.now();
196
+ const cachedTime = end2 - start2;
197
+ const speedup = coldTime / cachedTime;
198
+ console.log(`\nCache Hit Performance:`);
199
+ console.log(` Cold (first call): ${coldTime.toFixed(2)} ms`);
200
+ console.log(` Cached (second): ${cachedTime.toFixed(2)} ms`);
201
+ console.log(` Speedup: ${speedup.toFixed(1)}x faster`);
202
+ const stats = service.getCacheStats();
203
+ console.log(`\nCache Statistics:`);
204
+ console.log(` Size: ${stats.size}/${stats.maxSize}`);
205
+ console.log(` Model: ${stats.model}`);
206
+ console.log(` Dims: ${stats.dimensions}`);
207
+ return { coldTime, cachedTime, speedup };
208
+ }
209
+ // Test 6: Memory Usage
210
+ async function testMemoryUsage(service, modelName) {
211
+ console.log(`\n${'='.repeat(70)}`);
212
+ console.log(`TEST 6: Memory Usage - ${modelName}`);
213
+ console.log('='.repeat(70));
214
+ const memBefore = process.memoryUsage();
215
+ // Embed a batch
216
+ await service.embedBatch(TEST_DOCUMENTS);
217
+ const memAfter = process.memoryUsage();
218
+ const heapUsedMB = (memAfter.heapUsed - memBefore.heapUsed) / 1024 / 1024;
219
+ const rssMB = (memAfter.rss - memBefore.rss) / 1024 / 1024;
220
+ console.log(`\nMemory Usage (after batch embedding):`);
221
+ console.log(` Heap Used: ${heapUsedMB.toFixed(2)} MB`);
222
+ console.log(` RSS: ${rssMB.toFixed(2)} MB`);
223
+ console.log(` Total Heap: ${(memAfter.heapTotal / 1024 / 1024).toFixed(2)} MB`);
224
+ return { heapUsedMB, rssMB };
225
+ }
226
+ // Main comparison function
227
+ async function runSingleModelTest(modelId) {
228
+ console.log('\n' + '█'.repeat(70));
229
+ console.log(`TESTING MODEL: ${modelId}`);
230
+ console.log('█'.repeat(70));
231
+ const service = new embedding_service_1.EmbeddingService();
232
+ const results = {
233
+ model: modelId,
234
+ timestamp: new Date().toISOString()
235
+ };
236
+ // Run tests
237
+ results.speed = await testEmbeddingSpeed(service, modelId);
238
+ results.batch = await testBatchPerformance(service, modelId);
239
+ results.similarity = await testSemanticSimilarity(service, modelId);
240
+ results.longContext = await testLongContext(service, modelId);
241
+ results.cache = await testCachePerformance(service, modelId);
242
+ results.memory = await testMemoryUsage(service, modelId);
243
+ // Save results
244
+ const resultsPath = path.join(__dirname, '..', `embedding-results-${modelId.replace(/\//g, '-')}.json`);
245
+ fs.writeFileSync(resultsPath, JSON.stringify(results, null, 2));
246
+ console.log(`\n✓ Results saved to: ${resultsPath}`);
247
+ return results;
248
+ }
249
+ async function compareResults() {
250
+ console.log('\n' + '█'.repeat(70));
251
+ console.log('LOADING AND COMPARING RESULTS');
252
+ console.log('█'.repeat(70));
253
+ const bgeFile = path.join(__dirname, '..', 'embedding-results-Xenova-bge-m3.json');
254
+ const pplxFile = path.join(__dirname, '..', 'embedding-results-perplexity-ai-pplx-embed-v1-0.6b.json');
255
+ if (!fs.existsSync(bgeFile)) {
256
+ console.error('\n✗ BGE-M3 results not found!');
257
+ console.log('Please run: EMBEDDING_MODEL=Xenova/bge-m3 npm run compare-embeddings');
258
+ return;
259
+ }
260
+ if (!fs.existsSync(pplxFile)) {
261
+ console.error('\n✗ pplx-embed results not found!');
262
+ console.log('Please run: EMBEDDING_MODEL=perplexity-ai/pplx-embed-v1-0.6b npm run compare-embeddings');
263
+ return;
264
+ }
265
+ const bge = JSON.parse(fs.readFileSync(bgeFile, 'utf-8'));
266
+ const pplx = JSON.parse(fs.readFileSync(pplxFile, 'utf-8'));
267
+ // Print comparison summary
268
+ console.log(`\n\n${'█'.repeat(70)}`);
269
+ console.log('COMPARISON SUMMARY');
270
+ console.log('█'.repeat(70));
271
+ console.log(`\n1. EMBEDDING SPEED (lower is better)`);
272
+ console.log(` BGE-M3: ${bge.speed.avgTime.toFixed(2)} ms`);
273
+ console.log(` pplx-embed: ${pplx.speed.avgTime.toFixed(2)} ms`);
274
+ const speedDiff = ((pplx.speed.avgTime - bge.speed.avgTime) / bge.speed.avgTime * 100);
275
+ console.log(` Winner: ${bge.speed.avgTime < pplx.speed.avgTime ? 'BGE-M3' : 'pplx-embed'} (${Math.abs(speedDiff).toFixed(1)}% ${speedDiff > 0 ? 'slower' : 'faster'})`);
276
+ console.log(`\n2. BATCH THROUGHPUT (higher is better)`);
277
+ const bgeThroughput = 1000 / bge.batch.avgPerDoc;
278
+ const pplxThroughput = 1000 / pplx.batch.avgPerDoc;
279
+ console.log(` BGE-M3: ${bgeThroughput.toFixed(2)} docs/sec`);
280
+ console.log(` pplx-embed: ${pplxThroughput.toFixed(2)} docs/sec`);
281
+ console.log(` Winner: ${bgeThroughput > pplxThroughput ? 'BGE-M3' : 'pplx-embed'}`);
282
+ console.log(`\n3. SEMANTIC SIMILARITY ACCURACY (higher is better)`);
283
+ console.log(` BGE-M3: ${bge.similarity.accuracy.toFixed(1)}% (${bge.similarity.correctMatches}/${TEST_QUERIES.length})`);
284
+ console.log(` pplx-embed: ${pplx.similarity.accuracy.toFixed(1)}% (${pplx.similarity.correctMatches}/${TEST_QUERIES.length})`);
285
+ console.log(` Winner: ${bge.similarity.accuracy > pplx.similarity.accuracy ? 'BGE-M3' : 'pplx-embed'} ${pplx.similarity.accuracy > bge.similarity.accuracy ? '🏆' : ''}`);
286
+ console.log(`\n4. AVERAGE SIMILARITY SCORE (higher is better)`);
287
+ console.log(` BGE-M3: ${bge.similarity.avgSimilarity.toFixed(4)}`);
288
+ console.log(` pplx-embed: ${pplx.similarity.avgSimilarity.toFixed(4)}`);
289
+ const simDiff = ((pplx.similarity.avgSimilarity - bge.similarity.avgSimilarity) / bge.similarity.avgSimilarity * 100);
290
+ console.log(` Winner: ${bge.similarity.avgSimilarity > pplx.similarity.avgSimilarity ? 'BGE-M3' : 'pplx-embed'} (${Math.abs(simDiff).toFixed(1)}% ${simDiff > 0 ? 'higher' : 'lower'})`);
291
+ console.log(`\n5. CACHE SPEEDUP (higher is better)`);
292
+ console.log(` BGE-M3: ${bge.cache.speedup.toFixed(1)}x`);
293
+ console.log(` pplx-embed: ${pplx.cache.speedup.toFixed(1)}x`);
294
+ console.log(`\n6. MEMORY USAGE (lower is better)`);
295
+ console.log(` BGE-M3: ${bge.memory.heapUsedMB.toFixed(2)} MB heap`);
296
+ console.log(` pplx-embed: ${pplx.memory.heapUsedMB.toFixed(2)} MB heap`);
297
+ console.log(` Winner: ${bge.memory.heapUsedMB < pplx.memory.heapUsedMB ? 'BGE-M3' : 'pplx-embed'}`);
298
+ // Score calculation
299
+ let bgeScore = 0;
300
+ let pplxScore = 0;
301
+ if (bge.speed.avgTime < pplx.speed.avgTime)
302
+ bgeScore++;
303
+ else
304
+ pplxScore++;
305
+ if (bgeThroughput > pplxThroughput)
306
+ bgeScore++;
307
+ else
308
+ pplxScore++;
309
+ if (bge.similarity.accuracy > pplx.similarity.accuracy)
310
+ bgeScore++;
311
+ else
312
+ pplxScore++;
313
+ if (bge.similarity.avgSimilarity > pplx.similarity.avgSimilarity)
314
+ bgeScore++;
315
+ else
316
+ pplxScore++;
317
+ if (bge.memory.heapUsedMB < pplx.memory.heapUsedMB)
318
+ bgeScore++;
319
+ else
320
+ pplxScore++;
321
+ // Overall winner
322
+ console.log(`\n${'='.repeat(70)}`);
323
+ console.log('OVERALL SCORE');
324
+ console.log('='.repeat(70));
325
+ console.log(`\n BGE-M3: ${bgeScore}/5 wins`);
326
+ console.log(` pplx-embed: ${pplxScore}/5 wins`);
327
+ console.log(`\n${'='.repeat(70)}`);
328
+ console.log('RECOMMENDATION');
329
+ console.log('='.repeat(70));
330
+ if (pplxScore > bgeScore) {
331
+ console.log(`\n✓ pplx-embed-v1-0.6b is RECOMMENDED 🏆`);
332
+ console.log(` Reasons:`);
333
+ if (pplx.similarity.accuracy > bge.similarity.accuracy) {
334
+ console.log(` ✓ Better semantic similarity accuracy (+${(pplx.similarity.accuracy - bge.similarity.accuracy).toFixed(1)}%)`);
335
+ }
336
+ if (pplx.similarity.avgSimilarity > bge.similarity.avgSimilarity) {
337
+ console.log(` ✓ Higher quality embeddings (+${(simDiff).toFixed(1)}%)`);
338
+ }
339
+ console.log(` ✓ 32K context length (vs 8K for BGE-M3)`);
340
+ console.log(` ✓ Better MTEB benchmark scores`);
341
+ }
342
+ else if (bgeScore > pplxScore) {
343
+ console.log(`\n✓ BGE-M3 is RECOMMENDED 🏆`);
344
+ console.log(` Reasons:`);
345
+ if (bge.speed.avgTime < pplx.speed.avgTime) {
346
+ console.log(` ✓ Faster embedding speed (-${Math.abs(speedDiff).toFixed(1)}%)`);
347
+ }
348
+ if (bge.memory.heapUsedMB < pplx.memory.heapUsedMB) {
349
+ console.log(` ✓ Lower memory usage`);
350
+ }
351
+ console.log(` ✓ Automatic download (no manual setup)`);
352
+ console.log(` ✓ Proven stability`);
353
+ }
354
+ else {
355
+ console.log(`\n⚖ BOTH MODELS ARE EQUALLY COMPETITIVE`);
356
+ console.log(` Choose based on your priorities:`);
357
+ console.log(` - pplx-embed: Better quality, longer context (32K)`);
358
+ console.log(` - BGE-M3: Faster, easier setup, automatic download`);
359
+ }
360
+ console.log('\n' + '█'.repeat(70));
361
+ console.log('COMPARISON COMPLETE');
362
+ console.log('█'.repeat(70) + '\n');
363
+ }
364
+ // Main entry point
365
+ async function main() {
366
+ const currentModel = process.env.EMBEDDING_MODEL || "Xenova/bge-m3";
367
+ // Check if we should compare existing results
368
+ const args = process.argv.slice(2);
369
+ if (args.includes('--compare')) {
370
+ await compareResults();
371
+ return;
372
+ }
373
+ console.log('\n' + '█'.repeat(70));
374
+ console.log('EMBEDDING MODEL BENCHMARK');
375
+ console.log('█'.repeat(70));
376
+ console.log(`\nCurrent model: ${currentModel}`);
377
+ console.log('\nThis will run a comprehensive test suite including:');
378
+ console.log(' 1. Embedding speed');
379
+ console.log(' 2. Batch performance');
380
+ console.log(' 3. Semantic similarity quality');
381
+ console.log(' 4. Long context handling');
382
+ console.log(' 5. Cache performance');
383
+ console.log(' 6. Memory usage');
384
+ console.log('\nEstimated time: 2-3 minutes\n');
385
+ await runSingleModelTest(currentModel);
386
+ console.log('\n' + '='.repeat(70));
387
+ console.log('NEXT STEPS');
388
+ console.log('='.repeat(70));
389
+ if (currentModel === 'Xenova/bge-m3') {
390
+ console.log('\nTo test pplx-embed, run:');
391
+ console.log(' EMBEDDING_MODEL=perplexity-ai/pplx-embed-v1-0.6b npm run compare-embeddings');
392
+ }
393
+ else if (currentModel === 'perplexity-ai/pplx-embed-v1-0.6b') {
394
+ console.log('\nTo test BGE-M3, run:');
395
+ console.log(' EMBEDDING_MODEL=Xenova/bge-m3 npm run compare-embeddings');
396
+ }
397
+ console.log('\nTo compare both results, run:');
398
+ console.log(' npm run compare-embeddings -- --compare');
399
+ console.log();
400
+ }
401
+ // Run
402
+ main().catch(console.error);
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ require("dotenv/config");
37
+ const https = __importStar(require("https"));
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const transformers_1 = require("@xenova/transformers");
41
+ // Configure cache path
42
+ const CACHE_DIR = path.resolve('./.cache');
43
+ transformers_1.env.cacheDir = CACHE_DIR;
44
+ const MODEL_ID = "perplexity-ai/pplx-embed-v1-0.6b";
45
+ const BASE_URL = `https://huggingface.co/${MODEL_ID}/resolve/main/onnx`;
46
+ // Model variant to download (quantized is recommended for smaller size)
47
+ const USE_QUANTIZED = true; // Set to false for FP32 full precision
48
+ // Files to download based on variant
49
+ const FILES = USE_QUANTIZED ? [
50
+ { name: 'model_quantized.onnx', size: '614 KB' },
51
+ { name: 'model_quantized.onnx_data', size: '706 MB' }
52
+ ] : [
53
+ { name: 'model.onnx', size: '520 KB' },
54
+ { name: 'model.onnx_data', size: '2.09 GB' },
55
+ { name: 'model.onnx_data_1', size: '306 MB' }
56
+ ];
57
+ // Target directory
58
+ const targetDir = path.join(CACHE_DIR, 'perplexity-ai', 'pplx-embed-v1-0.6b', 'onnx');
59
+ function downloadFile(url, dest) {
60
+ return new Promise((resolve, reject) => {
61
+ const file = fs.createWriteStream(dest);
62
+ https.get(url, (response) => {
63
+ if (response.statusCode === 302 || response.statusCode === 301) {
64
+ // Follow redirect
65
+ const redirectUrl = response.headers.location;
66
+ if (redirectUrl) {
67
+ file.close();
68
+ fs.unlinkSync(dest);
69
+ return downloadFile(redirectUrl, dest).then(resolve).catch(reject);
70
+ }
71
+ }
72
+ const totalSize = parseInt(response.headers['content-length'] || '0', 10);
73
+ let downloadedSize = 0;
74
+ response.on('data', (chunk) => {
75
+ downloadedSize += chunk.length;
76
+ const progress = ((downloadedSize / totalSize) * 100).toFixed(2);
77
+ process.stdout.write(`\r Progress: ${progress}% (${(downloadedSize / 1024 / 1024).toFixed(2)} MB / ${(totalSize / 1024 / 1024).toFixed(2)} MB)`);
78
+ });
79
+ response.pipe(file);
80
+ file.on('finish', () => {
81
+ file.close();
82
+ console.log('\n ✓ Download complete');
83
+ resolve();
84
+ });
85
+ }).on('error', (err) => {
86
+ fs.unlinkSync(dest);
87
+ reject(err);
88
+ });
89
+ });
90
+ }
91
+ async function downloadPplxEmbed() {
92
+ console.log('='.repeat(70));
93
+ console.log('Downloading Perplexity pplx-embed-v1-0.6b ONNX files');
94
+ console.log(`Variant: ${USE_QUANTIZED ? 'INT8 Quantized (Recommended)' : 'FP32 Full Precision'}`);
95
+ console.log('='.repeat(70));
96
+ console.log();
97
+ // Create target directory
98
+ if (!fs.existsSync(targetDir)) {
99
+ fs.mkdirSync(targetDir, { recursive: true });
100
+ console.log(`✓ Created directory: ${targetDir}`);
101
+ }
102
+ console.log();
103
+ console.log('Files to download:');
104
+ FILES.forEach(f => console.log(` - ${f.name} (${f.size})`));
105
+ console.log();
106
+ console.log(`Total size: ${USE_QUANTIZED ? '~706 MB' : '~2.5 GB'}`);
107
+ console.log(`This may take ${USE_QUANTIZED ? '3-10' : '10-30'} minutes depending on your internet connection.`);
108
+ console.log();
109
+ if (USE_QUANTIZED) {
110
+ console.log('ℹ Using INT8 quantized model (recommended):');
111
+ console.log(' ✓ 3x smaller than FP32 (~706 MB vs ~2.4 GB)');
112
+ console.log(' ✓ Minimal quality loss (~1.5% MTEB drop)');
113
+ console.log(' ✓ Faster inference');
114
+ console.log();
115
+ console.log(' To use FP32 instead, edit src/download-pplx-embed.ts');
116
+ console.log(' and set USE_QUANTIZED = false');
117
+ console.log();
118
+ }
119
+ // Download each file
120
+ for (const file of FILES) {
121
+ const filePath = path.join(targetDir, file.name);
122
+ // Skip if already exists
123
+ if (fs.existsSync(filePath)) {
124
+ console.log(`⊘ Skipping ${file.name} (already exists)`);
125
+ continue;
126
+ }
127
+ console.log(`⬇ Downloading ${file.name} (${file.size})...`);
128
+ const url = `${BASE_URL}/${file.name}`;
129
+ try {
130
+ await downloadFile(url, filePath);
131
+ }
132
+ catch (error) {
133
+ console.error(`✗ Failed to download ${file.name}:`, error.message);
134
+ console.error(' Please download manually from:');
135
+ console.error(` ${url}`);
136
+ process.exit(1);
137
+ }
138
+ }
139
+ console.log();
140
+ console.log('='.repeat(70));
141
+ console.log('✓ All files downloaded successfully!');
142
+ console.log('='.repeat(70));
143
+ console.log();
144
+ console.log('You can now use the model by setting in .env:');
145
+ console.log(' EMBEDDING_MODEL=perplexity-ai/pplx-embed-v1-0.6b');
146
+ console.log();
147
+ console.log('Then start the server with:');
148
+ console.log(' npm run start');
149
+ console.log();
150
+ }
151
+ downloadPplxEmbed().catch(console.error);