@soulcraft/brainy 3.20.1 โ 3.20.3
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/CHANGELOG.md +19 -0
- package/bin/brainy-interactive.js +2 -2
- package/dist/brainy.d.ts +1 -1
- package/dist/mcp/brainyMCPAdapter.d.ts +1 -1
- package/dist/mcp/brainyMCPService.d.ts +1 -1
- package/dist/neural/embeddedPatterns.d.ts +1 -1
- package/dist/neural/embeddedPatterns.js +1 -1
- package/dist/shared/default-augmentations.d.ts +1 -1
- package/dist/types/{brainyDataInterface.js โ brainyInterface.js} +1 -1
- package/dist/vfs/VirtualFileSystem.d.ts +1 -0
- package/dist/vfs/VirtualFileSystem.js +108 -69
- package/package.json +1 -1
- package/dist/augmentationFactory.d.ts +0 -86
- package/dist/augmentationFactory.js +0 -342
- package/dist/augmentationRegistry.d.ts +0 -38
- package/dist/augmentationRegistry.js +0 -54
- package/dist/augmentationRegistryLoader.d.ts +0 -146
- package/dist/augmentationRegistryLoader.js +0 -213
- package/dist/augmentations/KnowledgeAugmentation.d.ts +0 -40
- package/dist/augmentations/KnowledgeAugmentation.js +0 -251
- package/dist/augmentations/intelligentVerbScoring.d.ts +0 -158
- package/dist/augmentations/intelligentVerbScoring.js +0 -377
- package/dist/augmentations/marketplace/AugmentationMarketplace.d.ts +0 -168
- package/dist/augmentations/marketplace/AugmentationMarketplace.js +0 -329
- package/dist/augmentations/marketplace/cli.d.ts +0 -47
- package/dist/augmentations/marketplace/cli.js +0 -265
- package/dist/augmentations/memoryAugmentations.d.ts +0 -72
- package/dist/augmentations/memoryAugmentations.js +0 -280
- package/dist/augmentations/serverSearchAugmentations.d.ts +0 -190
- package/dist/augmentations/serverSearchAugmentations.js +0 -586
- package/dist/brainy-unified.d.ts +0 -106
- package/dist/brainy-unified.js +0 -327
- package/dist/brainyData.d.ts +0 -1832
- package/dist/brainyData.js +0 -6443
- package/dist/brainyDataV3.d.ts +0 -186
- package/dist/brainyDataV3.js +0 -337
- package/dist/config/distributedPresets-new.d.ts +0 -118
- package/dist/config/distributedPresets-new.js +0 -318
- package/dist/config/modelPrecisionManager.d.ts +0 -42
- package/dist/config/modelPrecisionManager.js +0 -98
- package/dist/connectors/interfaces/IConnector.d.ts +0 -143
- package/dist/connectors/interfaces/IConnector.js +0 -8
- package/dist/demo.d.ts +0 -106
- package/dist/demo.js +0 -201
- package/dist/embeddings/SingletonModelManager.d.ts +0 -95
- package/dist/embeddings/SingletonModelManager.js +0 -220
- package/dist/embeddings/lightweight-embedder.d.ts +0 -22
- package/dist/embeddings/lightweight-embedder.js +0 -128
- package/dist/embeddings/model-manager.d.ts +0 -39
- package/dist/embeddings/model-manager.js +0 -245
- package/dist/embeddings/universal-memory-manager.d.ts +0 -38
- package/dist/embeddings/universal-memory-manager.js +0 -166
- package/dist/embeddings/worker-embedding.d.ts +0 -7
- package/dist/embeddings/worker-embedding.js +0 -73
- package/dist/embeddings/worker-manager.d.ts +0 -28
- package/dist/embeddings/worker-manager.js +0 -162
- package/dist/examples/basicUsage.d.ts +0 -4
- package/dist/examples/basicUsage.js +0 -121
- package/dist/indices/fieldIndex.d.ts +0 -76
- package/dist/indices/fieldIndex.js +0 -357
- package/dist/mcp/brainyMCPBroadcast.d.ts +0 -82
- package/dist/mcp/brainyMCPBroadcast.js +0 -303
- package/dist/mcp/brainyMCPClient.d.ts +0 -92
- package/dist/mcp/brainyMCPClient.js +0 -258
- package/dist/scripts/precomputePatternEmbeddings.d.ts +0 -19
- package/dist/scripts/precomputePatternEmbeddings.js +0 -100
- package/dist/utils/cacheAutoConfig.d.ts +0 -63
- package/dist/utils/cacheAutoConfig.js +0 -261
- package/dist/utils/hybridModelManager.d.ts +0 -64
- package/dist/utils/hybridModelManager.js +0 -95
- package/dist/utils/statistics.d.ts +0 -28
- package/dist/utils/statistics.js +0 -25
- package/dist/vfs/ConceptSystem.d.ts +0 -203
- package/dist/vfs/ConceptSystem.js +0 -545
- package/dist/vfs/EntityManager.d.ts +0 -75
- package/dist/vfs/EntityManager.js +0 -216
- package/dist/vfs/EventRecorder.d.ts +0 -84
- package/dist/vfs/EventRecorder.js +0 -269
- package/dist/vfs/GitBridge.d.ts +0 -167
- package/dist/vfs/GitBridge.js +0 -537
- package/dist/vfs/KnowledgeAugmentation.d.ts +0 -104
- package/dist/vfs/KnowledgeAugmentation.js +0 -146
- package/dist/vfs/KnowledgeLayer.d.ts +0 -35
- package/dist/vfs/KnowledgeLayer.js +0 -443
- package/dist/vfs/PersistentEntitySystem.d.ts +0 -165
- package/dist/vfs/PersistentEntitySystem.js +0 -503
- package/dist/vfs/SemanticVersioning.d.ts +0 -105
- package/dist/vfs/SemanticVersioning.js +0 -309
- package/dist/vfs/VFSHealthCheck.d.ts +0 -78
- package/dist/vfs/VFSHealthCheck.js +0 -299
- /package/dist/types/{brainyDataInterface.d.ts โ brainyInterface.d.ts} +0 -0
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lightweight Embedding Alternative
|
|
3
|
-
*
|
|
4
|
-
* Uses pre-computed embeddings for common terms
|
|
5
|
-
* Falls back to ONNX for unknown terms
|
|
6
|
-
*
|
|
7
|
-
* This reduces memory usage by 90% for typical queries
|
|
8
|
-
*/
|
|
9
|
-
import { singletonModelManager } from './SingletonModelManager.js';
|
|
10
|
-
// Pre-computed embeddings for top 10,000 common terms
|
|
11
|
-
// In production, this would be loaded from a file
|
|
12
|
-
const PRECOMPUTED_EMBEDDINGS = {
|
|
13
|
-
// Programming languages
|
|
14
|
-
'javascript': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.1)),
|
|
15
|
-
'python': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.1)),
|
|
16
|
-
'typescript': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.15)),
|
|
17
|
-
'java': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.15)),
|
|
18
|
-
'rust': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.2)),
|
|
19
|
-
'go': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.2)),
|
|
20
|
-
// Frameworks
|
|
21
|
-
'react': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.25)),
|
|
22
|
-
'vue': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.25)),
|
|
23
|
-
'angular': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.3)),
|
|
24
|
-
'svelte': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.3)),
|
|
25
|
-
// Databases
|
|
26
|
-
'postgresql': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.35)),
|
|
27
|
-
'mysql': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.35)),
|
|
28
|
-
'mongodb': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.4)),
|
|
29
|
-
'redis': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.4)),
|
|
30
|
-
// Common terms
|
|
31
|
-
'database': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.45)),
|
|
32
|
-
'api': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.45)),
|
|
33
|
-
'server': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.5)),
|
|
34
|
-
'client': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.5)),
|
|
35
|
-
'frontend': new Array(384).fill(0).map((_, i) => Math.sin(i * 0.55)),
|
|
36
|
-
'backend': new Array(384).fill(0).map((_, i) => Math.cos(i * 0.55)),
|
|
37
|
-
// Add more pre-computed embeddings here...
|
|
38
|
-
};
|
|
39
|
-
// Simple word similarity using character n-grams
|
|
40
|
-
function computeSimpleEmbedding(text) {
|
|
41
|
-
const normalized = text.toLowerCase().trim();
|
|
42
|
-
const vector = new Array(384).fill(0);
|
|
43
|
-
// Character trigrams for simple semantic similarity
|
|
44
|
-
for (let i = 0; i < normalized.length - 2; i++) {
|
|
45
|
-
const trigram = normalized.slice(i, i + 3);
|
|
46
|
-
const hash = trigram.charCodeAt(0) * 31 +
|
|
47
|
-
trigram.charCodeAt(1) * 7 +
|
|
48
|
-
trigram.charCodeAt(2);
|
|
49
|
-
const index = Math.abs(hash) % 384;
|
|
50
|
-
vector[index] += 1 / (normalized.length - 2);
|
|
51
|
-
}
|
|
52
|
-
// Normalize vector
|
|
53
|
-
const magnitude = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
|
|
54
|
-
if (magnitude > 0) {
|
|
55
|
-
for (let i = 0; i < vector.length; i++) {
|
|
56
|
-
vector[i] /= magnitude;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return vector;
|
|
60
|
-
}
|
|
61
|
-
export class LightweightEmbedder {
|
|
62
|
-
constructor() {
|
|
63
|
-
this.stats = {
|
|
64
|
-
precomputedHits: 0,
|
|
65
|
-
simpleComputes: 0,
|
|
66
|
-
onnxComputes: 0
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
async embed(text) {
|
|
70
|
-
if (Array.isArray(text)) {
|
|
71
|
-
return Promise.all(text.map(t => this.embedSingle(t)));
|
|
72
|
-
}
|
|
73
|
-
return this.embedSingle(text);
|
|
74
|
-
}
|
|
75
|
-
async embedSingle(text) {
|
|
76
|
-
const normalized = text.toLowerCase().trim();
|
|
77
|
-
// 1. Check pre-computed embeddings (instant, zero memory)
|
|
78
|
-
if (PRECOMPUTED_EMBEDDINGS[normalized]) {
|
|
79
|
-
this.stats.precomputedHits++;
|
|
80
|
-
return PRECOMPUTED_EMBEDDINGS[normalized];
|
|
81
|
-
}
|
|
82
|
-
// 2. Check for close matches in pre-computed
|
|
83
|
-
for (const [term, embedding] of Object.entries(PRECOMPUTED_EMBEDDINGS)) {
|
|
84
|
-
if (normalized.includes(term) || term.includes(normalized)) {
|
|
85
|
-
this.stats.precomputedHits++;
|
|
86
|
-
// Return slightly modified version to maintain uniqueness
|
|
87
|
-
return embedding.map(v => v * 0.95);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// 3. For short text, use simple embedding (fast, low memory)
|
|
91
|
-
if (normalized.length < 50) {
|
|
92
|
-
this.stats.simpleComputes++;
|
|
93
|
-
return computeSimpleEmbedding(normalized);
|
|
94
|
-
}
|
|
95
|
-
// 4. Last resort: Use SingletonModelManager for complex text
|
|
96
|
-
console.log('โ ๏ธ Using singleton model for complex text...');
|
|
97
|
-
this.stats.onnxComputes++;
|
|
98
|
-
return await singletonModelManager.embed(text);
|
|
99
|
-
}
|
|
100
|
-
getStats() {
|
|
101
|
-
return {
|
|
102
|
-
...this.stats,
|
|
103
|
-
totalEmbeddings: this.stats.precomputedHits +
|
|
104
|
-
this.stats.simpleComputes +
|
|
105
|
-
this.stats.onnxComputes,
|
|
106
|
-
cacheHitRate: this.stats.precomputedHits /
|
|
107
|
-
(this.stats.precomputedHits +
|
|
108
|
-
this.stats.simpleComputes +
|
|
109
|
-
this.stats.onnxComputes)
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
// Pre-load common embeddings from file
|
|
113
|
-
async loadPrecomputed(filePath) {
|
|
114
|
-
if (!filePath)
|
|
115
|
-
return;
|
|
116
|
-
try {
|
|
117
|
-
const fs = await import('fs/promises');
|
|
118
|
-
const data = await fs.readFile(filePath, 'utf-8');
|
|
119
|
-
const embeddings = JSON.parse(data);
|
|
120
|
-
Object.assign(PRECOMPUTED_EMBEDDINGS, embeddings);
|
|
121
|
-
console.log(`โ
Loaded ${Object.keys(embeddings).length} pre-computed embeddings`);
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
console.warn('Could not load pre-computed embeddings:', error);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
//# sourceMappingURL=lightweight-embedder.js.map
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model Manager - Ensures transformer models are available at runtime
|
|
3
|
-
*
|
|
4
|
-
* Strategy (in order):
|
|
5
|
-
* 1. Check local cache first (instant)
|
|
6
|
-
* 2. Try Soulcraft CDN (fastest when available)
|
|
7
|
-
* 3. Try GitHub release tar.gz with extraction (reliable backup)
|
|
8
|
-
* 4. Fall back to Hugging Face (always works)
|
|
9
|
-
*
|
|
10
|
-
* NO USER CONFIGURATION REQUIRED - Everything is automatic!
|
|
11
|
-
*/
|
|
12
|
-
export declare class ModelManager {
|
|
13
|
-
private static instance;
|
|
14
|
-
private modelsPath;
|
|
15
|
-
private isInitialized;
|
|
16
|
-
private constructor();
|
|
17
|
-
static getInstance(): ModelManager;
|
|
18
|
-
private getModelsPath;
|
|
19
|
-
ensureModels(modelName?: string): Promise<boolean>;
|
|
20
|
-
private verifyModelFiles;
|
|
21
|
-
/**
|
|
22
|
-
* Check which model variants are available locally
|
|
23
|
-
*/
|
|
24
|
-
getAvailableModels(modelName?: string): {
|
|
25
|
-
fp32: boolean;
|
|
26
|
-
q8: boolean;
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Get the best available model variant based on preference and availability
|
|
30
|
-
*/
|
|
31
|
-
getBestAvailableModel(preferredType?: 'fp32' | 'q8', modelName?: string): 'fp32' | 'q8' | null;
|
|
32
|
-
private tryModelSource;
|
|
33
|
-
private downloadAndExtractFromGitHub;
|
|
34
|
-
/**
|
|
35
|
-
* Pre-download models for deployment
|
|
36
|
-
* This is what npm run download-models calls
|
|
37
|
-
*/
|
|
38
|
-
static predownload(): Promise<void>;
|
|
39
|
-
}
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model Manager - Ensures transformer models are available at runtime
|
|
3
|
-
*
|
|
4
|
-
* Strategy (in order):
|
|
5
|
-
* 1. Check local cache first (instant)
|
|
6
|
-
* 2. Try Soulcraft CDN (fastest when available)
|
|
7
|
-
* 3. Try GitHub release tar.gz with extraction (reliable backup)
|
|
8
|
-
* 4. Fall back to Hugging Face (always works)
|
|
9
|
-
*
|
|
10
|
-
* NO USER CONFIGURATION REQUIRED - Everything is automatic!
|
|
11
|
-
*/
|
|
12
|
-
import { existsSync } from 'fs';
|
|
13
|
-
import { mkdir, writeFile } from 'fs/promises';
|
|
14
|
-
import { join } from 'path';
|
|
15
|
-
import { env } from '@huggingface/transformers';
|
|
16
|
-
// Model sources in order of preference
|
|
17
|
-
const MODEL_SOURCES = {
|
|
18
|
-
// CDN - Fastest when available (currently active)
|
|
19
|
-
cdn: {
|
|
20
|
-
host: 'https://models.soulcraft.com/models',
|
|
21
|
-
pathTemplate: '{model}/', // e.g., Xenova/all-MiniLM-L6-v2/
|
|
22
|
-
testFile: 'config.json' // File to test availability
|
|
23
|
-
},
|
|
24
|
-
// GitHub Release - tar.gz fallback (already exists and works)
|
|
25
|
-
githubRelease: {
|
|
26
|
-
tarUrl: 'https://github.com/soulcraftlabs/brainy/releases/download/models-v1/all-MiniLM-L6-v2.tar.gz'
|
|
27
|
-
},
|
|
28
|
-
// Original Hugging Face - final fallback (always works)
|
|
29
|
-
huggingface: {
|
|
30
|
-
host: 'https://huggingface.co',
|
|
31
|
-
pathTemplate: '{model}/resolve/{revision}/' // Default transformers.js pattern
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
// Model verification files - BOTH fp32 and q8 variants
|
|
35
|
-
const REQUIRED_FILES = [
|
|
36
|
-
'config.json',
|
|
37
|
-
'tokenizer.json',
|
|
38
|
-
'tokenizer_config.json'
|
|
39
|
-
];
|
|
40
|
-
const MODEL_VARIANTS = {
|
|
41
|
-
fp32: 'onnx/model.onnx',
|
|
42
|
-
q8: 'onnx/model_quantized.onnx'
|
|
43
|
-
};
|
|
44
|
-
export class ModelManager {
|
|
45
|
-
constructor() {
|
|
46
|
-
this.isInitialized = false;
|
|
47
|
-
// Determine models path
|
|
48
|
-
this.modelsPath = this.getModelsPath();
|
|
49
|
-
}
|
|
50
|
-
static getInstance() {
|
|
51
|
-
if (!ModelManager.instance) {
|
|
52
|
-
ModelManager.instance = new ModelManager();
|
|
53
|
-
}
|
|
54
|
-
return ModelManager.instance;
|
|
55
|
-
}
|
|
56
|
-
getModelsPath() {
|
|
57
|
-
// Check various possible locations
|
|
58
|
-
const paths = [
|
|
59
|
-
process.env.BRAINY_MODELS_PATH,
|
|
60
|
-
'./models',
|
|
61
|
-
join(process.cwd(), 'models'),
|
|
62
|
-
join(process.env.HOME || '', '.brainy', 'models'),
|
|
63
|
-
env.cacheDir
|
|
64
|
-
];
|
|
65
|
-
// Find first existing path or use default
|
|
66
|
-
for (const path of paths) {
|
|
67
|
-
if (path && existsSync(path)) {
|
|
68
|
-
return path;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// Default to local models directory
|
|
72
|
-
return join(process.cwd(), 'models');
|
|
73
|
-
}
|
|
74
|
-
async ensureModels(modelName = 'Xenova/all-MiniLM-L6-v2') {
|
|
75
|
-
if (this.isInitialized) {
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
// Configure transformers.js environment
|
|
79
|
-
env.cacheDir = this.modelsPath;
|
|
80
|
-
env.allowLocalModels = true;
|
|
81
|
-
env.useFSCache = true;
|
|
82
|
-
// Check if model already exists locally
|
|
83
|
-
const modelPath = join(this.modelsPath, ...modelName.split('/'));
|
|
84
|
-
if (await this.verifyModelFiles(modelPath)) {
|
|
85
|
-
console.log('โ
Models found in cache:', modelPath);
|
|
86
|
-
env.allowRemoteModels = false; // Use local only
|
|
87
|
-
this.isInitialized = true;
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
// Try to download from our sources
|
|
91
|
-
console.log('๐ฅ Downloading transformer models...');
|
|
92
|
-
// Try CDN first (fastest when available)
|
|
93
|
-
if (await this.tryModelSource('Soulcraft CDN', MODEL_SOURCES.cdn, modelName)) {
|
|
94
|
-
this.isInitialized = true;
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
// Try GitHub release with tar.gz extraction (reliable backup)
|
|
98
|
-
if (await this.downloadAndExtractFromGitHub(modelName)) {
|
|
99
|
-
this.isInitialized = true;
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
// Fall back to Hugging Face (always works)
|
|
103
|
-
console.log('โ ๏ธ Using Hugging Face fallback for models');
|
|
104
|
-
env.remoteHost = MODEL_SOURCES.huggingface.host;
|
|
105
|
-
env.remotePathTemplate = MODEL_SOURCES.huggingface.pathTemplate;
|
|
106
|
-
env.allowRemoteModels = true;
|
|
107
|
-
this.isInitialized = true;
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
async verifyModelFiles(modelPath) {
|
|
111
|
-
// Check if essential files exist
|
|
112
|
-
for (const file of REQUIRED_FILES) {
|
|
113
|
-
const fullPath = join(modelPath, file);
|
|
114
|
-
if (!existsSync(fullPath)) {
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
// At least one model variant must exist (fp32 or q8)
|
|
119
|
-
const fp32Exists = existsSync(join(modelPath, MODEL_VARIANTS.fp32));
|
|
120
|
-
const q8Exists = existsSync(join(modelPath, MODEL_VARIANTS.q8));
|
|
121
|
-
return fp32Exists || q8Exists;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Check which model variants are available locally
|
|
125
|
-
*/
|
|
126
|
-
getAvailableModels(modelName = 'Xenova/all-MiniLM-L6-v2') {
|
|
127
|
-
const modelPath = join(this.modelsPath, modelName);
|
|
128
|
-
return {
|
|
129
|
-
fp32: existsSync(join(modelPath, MODEL_VARIANTS.fp32)),
|
|
130
|
-
q8: existsSync(join(modelPath, MODEL_VARIANTS.q8))
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Get the best available model variant based on preference and availability
|
|
135
|
-
*/
|
|
136
|
-
getBestAvailableModel(preferredType = 'fp32', modelName = 'Xenova/all-MiniLM-L6-v2') {
|
|
137
|
-
const available = this.getAvailableModels(modelName);
|
|
138
|
-
// If preferred type is available, use it
|
|
139
|
-
if (available[preferredType]) {
|
|
140
|
-
return preferredType;
|
|
141
|
-
}
|
|
142
|
-
// Otherwise fall back to what's available
|
|
143
|
-
if (preferredType === 'q8' && available.fp32) {
|
|
144
|
-
console.warn('โ ๏ธ Q8 model requested but not available, falling back to FP32');
|
|
145
|
-
return 'fp32';
|
|
146
|
-
}
|
|
147
|
-
if (preferredType === 'fp32' && available.q8) {
|
|
148
|
-
console.warn('โ ๏ธ FP32 model requested but not available, falling back to Q8');
|
|
149
|
-
return 'q8';
|
|
150
|
-
}
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
|
-
async tryModelSource(name, source, modelName) {
|
|
154
|
-
try {
|
|
155
|
-
console.log(`๐ฅ Trying ${name}...`);
|
|
156
|
-
// Test if the source is accessible by trying to fetch a test file
|
|
157
|
-
const testFile = source.testFile || 'config.json';
|
|
158
|
-
const modelPath = source.pathTemplate.replace('{model}', modelName).replace('{revision}', 'main');
|
|
159
|
-
const testUrl = `${source.host}/${modelPath}${testFile}`;
|
|
160
|
-
const response = await fetch(testUrl).catch(() => null);
|
|
161
|
-
if (response && response.ok) {
|
|
162
|
-
console.log(`โ
${name} is available`);
|
|
163
|
-
// Configure transformers.js to use this source
|
|
164
|
-
env.remoteHost = source.host;
|
|
165
|
-
env.remotePathTemplate = source.pathTemplate;
|
|
166
|
-
env.allowRemoteModels = true;
|
|
167
|
-
// The model will be downloaded automatically by transformers.js when needed
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
console.log(`โ ๏ธ ${name} not available (${response?.status || 'unreachable'})`);
|
|
172
|
-
return false;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
catch (error) {
|
|
176
|
-
console.log(`โ ๏ธ ${name} check failed:`, error.message);
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
async downloadAndExtractFromGitHub(modelName) {
|
|
181
|
-
try {
|
|
182
|
-
console.log('๐ฅ Trying GitHub Release (tar.gz)...');
|
|
183
|
-
// Download tar.gz file
|
|
184
|
-
const response = await fetch(MODEL_SOURCES.githubRelease.tarUrl);
|
|
185
|
-
if (!response.ok) {
|
|
186
|
-
console.log(`โ ๏ธ GitHub Release not available (${response.status})`);
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
// Since we can't use tar-stream, we'll use Node's built-in child_process
|
|
190
|
-
// to extract using system tar command (available on all Unix systems)
|
|
191
|
-
const buffer = await response.arrayBuffer();
|
|
192
|
-
const modelPath = join(this.modelsPath, ...modelName.split('/'));
|
|
193
|
-
// Create model directory
|
|
194
|
-
await mkdir(modelPath, { recursive: true });
|
|
195
|
-
// Write tar.gz to temp file and extract
|
|
196
|
-
const tempFile = join(this.modelsPath, 'temp-model.tar.gz');
|
|
197
|
-
await writeFile(tempFile, Buffer.from(buffer));
|
|
198
|
-
// Extract using system tar command
|
|
199
|
-
const { exec } = await import('child_process');
|
|
200
|
-
const { promisify } = await import('util');
|
|
201
|
-
const execAsync = promisify(exec);
|
|
202
|
-
try {
|
|
203
|
-
// Extract and strip the first directory component
|
|
204
|
-
await execAsync(`tar -xzf ${tempFile} -C ${modelPath} --strip-components=1`, {
|
|
205
|
-
cwd: this.modelsPath
|
|
206
|
-
});
|
|
207
|
-
// Clean up temp file
|
|
208
|
-
const { unlink } = await import('fs/promises');
|
|
209
|
-
await unlink(tempFile);
|
|
210
|
-
console.log('โ
GitHub Release models extracted and cached locally');
|
|
211
|
-
// Configure to use local models now
|
|
212
|
-
env.allowRemoteModels = false;
|
|
213
|
-
return true;
|
|
214
|
-
}
|
|
215
|
-
catch (extractError) {
|
|
216
|
-
console.log('โ ๏ธ Tar extraction failed, trying alternative method');
|
|
217
|
-
return false;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
catch (error) {
|
|
221
|
-
console.log('โ ๏ธ GitHub Release download failed:', error.message);
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Pre-download models for deployment
|
|
227
|
-
* This is what npm run download-models calls
|
|
228
|
-
*/
|
|
229
|
-
static async predownload() {
|
|
230
|
-
const manager = ModelManager.getInstance();
|
|
231
|
-
const success = await manager.ensureModels();
|
|
232
|
-
if (!success) {
|
|
233
|
-
throw new Error('Failed to download models');
|
|
234
|
-
}
|
|
235
|
-
console.log('โ
Models downloaded successfully');
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
// Auto-initialize on import in production
|
|
239
|
-
if (process.env.NODE_ENV === 'production' && process.env.SKIP_MODEL_CHECK !== 'true') {
|
|
240
|
-
ModelManager.getInstance().ensureModels().catch(error => {
|
|
241
|
-
console.error('โ ๏ธ Model initialization failed:', error);
|
|
242
|
-
// Don't throw - allow app to start and try downloading on first use
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
//# sourceMappingURL=model-manager.js.map
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Universal Memory Manager for Embeddings
|
|
3
|
-
*
|
|
4
|
-
* Works in ALL environments: Node.js, browsers, serverless, workers
|
|
5
|
-
* Solves transformers.js memory leak with environment-specific strategies
|
|
6
|
-
*/
|
|
7
|
-
import { Vector, EmbeddingFunction } from '../coreTypes.js';
|
|
8
|
-
interface MemoryStats {
|
|
9
|
-
embeddings: number;
|
|
10
|
-
memoryUsage: string;
|
|
11
|
-
restarts: number;
|
|
12
|
-
strategy: string;
|
|
13
|
-
}
|
|
14
|
-
export declare class UniversalMemoryManager {
|
|
15
|
-
private embeddingFunction;
|
|
16
|
-
private embedCount;
|
|
17
|
-
private restartCount;
|
|
18
|
-
private lastRestart;
|
|
19
|
-
private strategy;
|
|
20
|
-
private maxEmbeddings;
|
|
21
|
-
constructor();
|
|
22
|
-
getEmbeddingFunction(): Promise<EmbeddingFunction>;
|
|
23
|
-
embed(data: string | string[]): Promise<Vector>;
|
|
24
|
-
private checkMemoryLimits;
|
|
25
|
-
private ensureEmbeddingFunction;
|
|
26
|
-
private initNodeDirect;
|
|
27
|
-
private initServerless;
|
|
28
|
-
private initBrowser;
|
|
29
|
-
private initFallback;
|
|
30
|
-
private initDirect;
|
|
31
|
-
private cleanup;
|
|
32
|
-
getMemoryStats(): MemoryStats;
|
|
33
|
-
dispose(): Promise<void>;
|
|
34
|
-
}
|
|
35
|
-
export declare const universalMemoryManager: UniversalMemoryManager;
|
|
36
|
-
export declare function getUniversalEmbeddingFunction(): Promise<EmbeddingFunction>;
|
|
37
|
-
export declare function getEmbeddingMemoryStats(): MemoryStats;
|
|
38
|
-
export {};
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Universal Memory Manager for Embeddings
|
|
3
|
-
*
|
|
4
|
-
* Works in ALL environments: Node.js, browsers, serverless, workers
|
|
5
|
-
* Solves transformers.js memory leak with environment-specific strategies
|
|
6
|
-
*/
|
|
7
|
-
import { getModelPrecision } from '../config/modelPrecisionManager.js';
|
|
8
|
-
// Environment detection
|
|
9
|
-
const isNode = typeof process !== 'undefined' && process.versions?.node;
|
|
10
|
-
const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
11
|
-
const isServerless = typeof process !== 'undefined' && (process.env.VERCEL ||
|
|
12
|
-
process.env.NETLIFY ||
|
|
13
|
-
process.env.AWS_LAMBDA_FUNCTION_NAME ||
|
|
14
|
-
process.env.FUNCTIONS_WORKER_RUNTIME);
|
|
15
|
-
export class UniversalMemoryManager {
|
|
16
|
-
constructor() {
|
|
17
|
-
// CRITICAL FIX: Never use worker threads with ONNX Runtime
|
|
18
|
-
// Worker threads cause HandleScope V8 API errors due to isolate issues
|
|
19
|
-
// Always use direct embedding on main thread for ONNX compatibility
|
|
20
|
-
this.embeddingFunction = null;
|
|
21
|
-
this.embedCount = 0;
|
|
22
|
-
this.restartCount = 0;
|
|
23
|
-
this.lastRestart = 0;
|
|
24
|
-
if (isServerless) {
|
|
25
|
-
this.strategy = 'serverless-restart';
|
|
26
|
-
this.maxEmbeddings = 50; // Restart frequently in serverless
|
|
27
|
-
}
|
|
28
|
-
else if (isNode && !isBrowser) {
|
|
29
|
-
// CHANGED: Use direct strategy instead of node-worker to avoid V8 isolate issues
|
|
30
|
-
this.strategy = 'node-direct';
|
|
31
|
-
this.maxEmbeddings = 200; // Main thread can handle more with single model instance
|
|
32
|
-
}
|
|
33
|
-
else if (isBrowser) {
|
|
34
|
-
this.strategy = 'browser-dispose';
|
|
35
|
-
this.maxEmbeddings = 25; // Browser memory is limited
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
this.strategy = 'fallback-dispose';
|
|
39
|
-
this.maxEmbeddings = 75;
|
|
40
|
-
}
|
|
41
|
-
console.log(`๐ง Universal Memory Manager: Using ${this.strategy} strategy`);
|
|
42
|
-
console.log('โ
UNIVERSAL: Memory-safe embedding system initialized');
|
|
43
|
-
}
|
|
44
|
-
async getEmbeddingFunction() {
|
|
45
|
-
return async (data) => {
|
|
46
|
-
return this.embed(data);
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
async embed(data) {
|
|
50
|
-
// Check if we need to restart/cleanup
|
|
51
|
-
await this.checkMemoryLimits();
|
|
52
|
-
// Ensure embedding function is available
|
|
53
|
-
await this.ensureEmbeddingFunction();
|
|
54
|
-
// Perform embedding
|
|
55
|
-
const result = await this.embeddingFunction.embed(data);
|
|
56
|
-
this.embedCount++;
|
|
57
|
-
return result;
|
|
58
|
-
}
|
|
59
|
-
async checkMemoryLimits() {
|
|
60
|
-
if (this.embedCount >= this.maxEmbeddings) {
|
|
61
|
-
console.log(`๐ Memory cleanup: ${this.embedCount} embeddings processed`);
|
|
62
|
-
await this.cleanup();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
async ensureEmbeddingFunction() {
|
|
66
|
-
if (this.embeddingFunction) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
switch (this.strategy) {
|
|
70
|
-
case 'node-direct':
|
|
71
|
-
await this.initNodeDirect();
|
|
72
|
-
break;
|
|
73
|
-
case 'serverless-restart':
|
|
74
|
-
await this.initServerless();
|
|
75
|
-
break;
|
|
76
|
-
case 'browser-dispose':
|
|
77
|
-
await this.initBrowser();
|
|
78
|
-
break;
|
|
79
|
-
default:
|
|
80
|
-
await this.initFallback();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async initNodeDirect() {
|
|
84
|
-
if (isNode) {
|
|
85
|
-
// CRITICAL: Use direct embedding to avoid worker thread V8 isolate issues
|
|
86
|
-
// This prevents HandleScope errors and ensures single model instance
|
|
87
|
-
console.log('โ
Using Node.js direct embedding (main thread - ONNX compatible)');
|
|
88
|
-
await this.initDirect();
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
async initServerless() {
|
|
92
|
-
// In serverless, use direct embedding but restart more aggressively
|
|
93
|
-
await this.initDirect();
|
|
94
|
-
console.log('โ
Using serverless strategy with aggressive cleanup');
|
|
95
|
-
}
|
|
96
|
-
async initBrowser() {
|
|
97
|
-
// In browser, use direct embedding with disposal
|
|
98
|
-
await this.initDirect();
|
|
99
|
-
console.log('โ
Using browser strategy with disposal');
|
|
100
|
-
}
|
|
101
|
-
async initFallback() {
|
|
102
|
-
await this.initDirect();
|
|
103
|
-
console.log('โ
Using fallback direct embedding strategy');
|
|
104
|
-
}
|
|
105
|
-
async initDirect() {
|
|
106
|
-
try {
|
|
107
|
-
// Dynamic import to handle different environments
|
|
108
|
-
const { TransformerEmbedding } = await import('../utils/embedding.js');
|
|
109
|
-
this.embeddingFunction = new TransformerEmbedding({
|
|
110
|
-
verbose: false,
|
|
111
|
-
precision: getModelPrecision(), // Use centrally managed precision
|
|
112
|
-
localFilesOnly: process.env.BRAINY_ALLOW_REMOTE_MODELS !== 'true'
|
|
113
|
-
});
|
|
114
|
-
await this.embeddingFunction.init();
|
|
115
|
-
console.log('โ
Direct embedding function initialized');
|
|
116
|
-
}
|
|
117
|
-
catch (error) {
|
|
118
|
-
throw new Error(`Failed to initialize embedding function: ${error instanceof Error ? error.message : String(error)}`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
async cleanup() {
|
|
122
|
-
const startTime = Date.now();
|
|
123
|
-
// SingletonModelManager persists - we just reset our counters
|
|
124
|
-
// The singleton model stays alive for consistency across all operations
|
|
125
|
-
// Reset counters
|
|
126
|
-
this.embedCount = 0;
|
|
127
|
-
this.restartCount++;
|
|
128
|
-
this.lastRestart = Date.now();
|
|
129
|
-
const cleanupTime = Date.now() - startTime;
|
|
130
|
-
console.log(`๐งน Memory counters reset in ${cleanupTime}ms (strategy: ${this.strategy})`);
|
|
131
|
-
console.log('โน๏ธ Singleton model persists for consistency across all operations');
|
|
132
|
-
}
|
|
133
|
-
getMemoryStats() {
|
|
134
|
-
let memoryUsage = 'unknown';
|
|
135
|
-
// Get memory stats based on environment
|
|
136
|
-
if (isNode && typeof process !== 'undefined') {
|
|
137
|
-
const mem = process.memoryUsage();
|
|
138
|
-
memoryUsage = `${(mem.heapUsed / 1024 / 1024).toFixed(2)} MB`;
|
|
139
|
-
}
|
|
140
|
-
else if (isBrowser && performance.memory) {
|
|
141
|
-
const mem = performance.memory;
|
|
142
|
-
memoryUsage = `${(mem.usedJSHeapSize / 1024 / 1024).toFixed(2)} MB`;
|
|
143
|
-
}
|
|
144
|
-
return {
|
|
145
|
-
embeddings: this.embedCount,
|
|
146
|
-
memoryUsage,
|
|
147
|
-
restarts: this.restartCount,
|
|
148
|
-
strategy: this.strategy
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
async dispose() {
|
|
152
|
-
// SingletonModelManager persists - nothing to dispose
|
|
153
|
-
console.log('โน๏ธ Universal Memory Manager: Singleton model persists');
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// Export singleton instance
|
|
157
|
-
export const universalMemoryManager = new UniversalMemoryManager();
|
|
158
|
-
// Export convenience function
|
|
159
|
-
export async function getUniversalEmbeddingFunction() {
|
|
160
|
-
return universalMemoryManager.getEmbeddingFunction();
|
|
161
|
-
}
|
|
162
|
-
// Export memory stats function
|
|
163
|
-
export function getEmbeddingMemoryStats() {
|
|
164
|
-
return universalMemoryManager.getMemoryStats();
|
|
165
|
-
}
|
|
166
|
-
//# sourceMappingURL=universal-memory-manager.js.map
|