@soulcraft/brainy 1.3.0 โ 1.4.0
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/brainyData.js +34 -9
- package/dist/critical/model-guardian.js +6 -6
- package/dist/intelligence/neuralEngine.d.ts +207 -0
- package/dist/intelligence/neuralEngine.js +706 -0
- package/dist/utils/embedding.d.ts +2 -1
- package/dist/utils/embedding.js +5 -3
- package/dist/utils/hybridModelManager.d.ts +73 -0
- package/dist/utils/hybridModelManager.js +254 -0
- package/dist/utils/modelLoader.d.ts +32 -0
- package/dist/utils/modelLoader.js +219 -0
- package/dist/utils/modelManager.d.ts +77 -0
- package/dist/utils/modelManager.js +219 -0
- package/package.json +1 -1
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model Manager - CRITICAL SINGLETON for preventing multiple model loads
|
|
3
|
+
*
|
|
4
|
+
* This ensures that ONNX/Transformer models are loaded ONCE and reused across:
|
|
5
|
+
* - All BrainyData instances
|
|
6
|
+
* - All test cases
|
|
7
|
+
* - All embedding operations
|
|
8
|
+
* - Neural intelligence operations
|
|
9
|
+
*/
|
|
10
|
+
import { TransformerEmbedding } from './embedding.js';
|
|
11
|
+
/**
|
|
12
|
+
* Global singleton model manager
|
|
13
|
+
* CRITICAL: This prevents multiple model loads which cause:
|
|
14
|
+
* - Test timeouts
|
|
15
|
+
* - Memory bloat
|
|
16
|
+
* - Performance degradation
|
|
17
|
+
* - ONNX runtime conflicts
|
|
18
|
+
*/
|
|
19
|
+
class ModelManager {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.primaryModel = null;
|
|
22
|
+
this.modelPromise = null;
|
|
23
|
+
this.isInitialized = false;
|
|
24
|
+
}
|
|
25
|
+
static getInstance() {
|
|
26
|
+
if (!ModelManager.instance) {
|
|
27
|
+
ModelManager.instance = new ModelManager();
|
|
28
|
+
}
|
|
29
|
+
return ModelManager.instance;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the primary embedding model - LOADS ONCE, REUSES FOREVER
|
|
33
|
+
*/
|
|
34
|
+
async getPrimaryModel() {
|
|
35
|
+
// If already initialized, return immediately
|
|
36
|
+
if (this.primaryModel && this.isInitialized) {
|
|
37
|
+
return this.primaryModel;
|
|
38
|
+
}
|
|
39
|
+
// If initialization is in progress, wait for it
|
|
40
|
+
if (this.modelPromise) {
|
|
41
|
+
return await this.modelPromise;
|
|
42
|
+
}
|
|
43
|
+
// Start initialization
|
|
44
|
+
this.modelPromise = this.initializePrimaryModel();
|
|
45
|
+
return await this.modelPromise;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Initialize the primary model ONCE - WORKS IN ALL ENVIRONMENTS
|
|
49
|
+
*/
|
|
50
|
+
async initializePrimaryModel() {
|
|
51
|
+
try {
|
|
52
|
+
// Environment detection for optimal configuration
|
|
53
|
+
const isTest = globalThis.__BRAINY_TEST_ENV__ || process.env.NODE_ENV === 'test';
|
|
54
|
+
const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
55
|
+
const isServerless = typeof process !== 'undefined' && (process.env.VERCEL ||
|
|
56
|
+
process.env.NETLIFY ||
|
|
57
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME ||
|
|
58
|
+
process.env.FUNCTIONS_WORKER_RUNTIME);
|
|
59
|
+
const isDocker = typeof process !== 'undefined' && (process.env.DOCKER_CONTAINER ||
|
|
60
|
+
process.env.KUBERNETES_SERVICE_HOST);
|
|
61
|
+
// Smart configuration based on environment
|
|
62
|
+
let options = {
|
|
63
|
+
verbose: !isTest && !isServerless, // Quiet in tests and serverless
|
|
64
|
+
dtype: 'q8', // Balanced performance/size
|
|
65
|
+
device: 'cpu' // Most compatible across all environments
|
|
66
|
+
};
|
|
67
|
+
// Environment-specific optimizations
|
|
68
|
+
if (isBrowser) {
|
|
69
|
+
// Browser: Prioritize compatibility and size
|
|
70
|
+
options = {
|
|
71
|
+
...options,
|
|
72
|
+
localFilesOnly: false, // Allow CDN downloads
|
|
73
|
+
dtype: 'q8', // Smaller models for bandwidth
|
|
74
|
+
device: 'cpu', // WebGPU support varies widely
|
|
75
|
+
verbose: false // Never verbose in browser
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
else if (isServerless) {
|
|
79
|
+
// Serverless: Prioritize cold start performance
|
|
80
|
+
options = {
|
|
81
|
+
...options,
|
|
82
|
+
localFilesOnly: true, // Assume models are pre-deployed
|
|
83
|
+
dtype: 'q8', // Faster loading
|
|
84
|
+
device: 'cpu', // Consistent across platforms
|
|
85
|
+
verbose: false // No console noise in serverless
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
else if (isDocker) {
|
|
89
|
+
// Docker: Assume models are in container
|
|
90
|
+
options = {
|
|
91
|
+
...options,
|
|
92
|
+
localFilesOnly: true, // Models should be baked in
|
|
93
|
+
dtype: 'fp32', // Use full precision if available
|
|
94
|
+
device: 'auto', // Let it detect GPU in container
|
|
95
|
+
verbose: false // Quiet for container logs
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
else if (isTest) {
|
|
99
|
+
// Test: Optimize for reliability and speed
|
|
100
|
+
options = {
|
|
101
|
+
...options,
|
|
102
|
+
localFilesOnly: false, // Allow downloads in development
|
|
103
|
+
dtype: 'q8', // Faster test execution
|
|
104
|
+
device: 'cpu', // Consistent test results
|
|
105
|
+
verbose: false // Clean test output
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// Development/Production Node.js: Full features
|
|
110
|
+
options = {
|
|
111
|
+
...options,
|
|
112
|
+
localFilesOnly: false, // Allow downloads
|
|
113
|
+
dtype: 'q8', // Good balance
|
|
114
|
+
device: 'auto', // Use best available
|
|
115
|
+
verbose: true // Helpful for development
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// Graceful logging based on environment
|
|
119
|
+
const environmentName = isBrowser ? 'browser' :
|
|
120
|
+
isServerless ? 'serverless' :
|
|
121
|
+
isDocker ? 'container' :
|
|
122
|
+
isTest ? 'test' : 'node';
|
|
123
|
+
if (options.verbose) {
|
|
124
|
+
console.log(`๐ง Loading embedding model (${environmentName} mode)...`);
|
|
125
|
+
}
|
|
126
|
+
this.primaryModel = new TransformerEmbedding(options);
|
|
127
|
+
await this.primaryModel.init();
|
|
128
|
+
this.isInitialized = true;
|
|
129
|
+
this.modelPromise = null; // Clear the promise
|
|
130
|
+
if (options.verbose) {
|
|
131
|
+
console.log(`โ
Embedding model loaded successfully in ${environmentName} environment`);
|
|
132
|
+
}
|
|
133
|
+
return this.primaryModel;
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
this.modelPromise = null; // Clear failed promise
|
|
137
|
+
// Enhanced error reporting with environment context
|
|
138
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
139
|
+
const environmentInfo = typeof window !== 'undefined' ? 'browser' :
|
|
140
|
+
typeof process !== 'undefined' ? `node (${process.version})` : 'unknown';
|
|
141
|
+
throw new Error(`Failed to initialize embedding model in ${environmentInfo} environment: ${errorMessage}. ` +
|
|
142
|
+
`This is critical for all Brainy operations. Please check model availability and network connectivity.`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get embedding function that reuses the singleton model
|
|
147
|
+
*/
|
|
148
|
+
async getEmbeddingFunction() {
|
|
149
|
+
const model = await this.getPrimaryModel();
|
|
150
|
+
return async (data) => {
|
|
151
|
+
return await model.embed(data);
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Check if model is ready (loaded and initialized)
|
|
156
|
+
*/
|
|
157
|
+
isModelReady() {
|
|
158
|
+
return this.isInitialized && this.primaryModel !== null;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Force model reload (for testing or recovery)
|
|
162
|
+
*/
|
|
163
|
+
async reloadModel() {
|
|
164
|
+
this.primaryModel = null;
|
|
165
|
+
this.isInitialized = false;
|
|
166
|
+
this.modelPromise = null;
|
|
167
|
+
await this.getPrimaryModel();
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get model status for debugging
|
|
171
|
+
*/
|
|
172
|
+
getModelStatus() {
|
|
173
|
+
return {
|
|
174
|
+
loaded: this.primaryModel !== null,
|
|
175
|
+
ready: this.isInitialized,
|
|
176
|
+
modelType: 'TransformerEmbedding (ONNX)'
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Cleanup method for testing
|
|
181
|
+
*/
|
|
182
|
+
cleanup() {
|
|
183
|
+
// Note: We don't actually destroy the model in cleanup
|
|
184
|
+
// because other parts of the system might still be using it
|
|
185
|
+
// This is mainly for status reset
|
|
186
|
+
console.log('๐งน Model manager cleanup requested (model remains loaded)');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
ModelManager.instance = null;
|
|
190
|
+
// Export singleton instance
|
|
191
|
+
export const modelManager = ModelManager.getInstance();
|
|
192
|
+
/**
|
|
193
|
+
* Get the singleton embedding function - USE THIS EVERYWHERE!
|
|
194
|
+
*/
|
|
195
|
+
export async function getSingletonEmbeddingFunction() {
|
|
196
|
+
return await modelManager.getEmbeddingFunction();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Optimized default embedding function that reuses singleton model
|
|
200
|
+
*/
|
|
201
|
+
export const optimizedDefaultEmbeddingFunction = async (data) => {
|
|
202
|
+
const embeddingFn = await getSingletonEmbeddingFunction();
|
|
203
|
+
return await embeddingFn(data);
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* Preload model for tests or production - CALL THIS ONCE AT START
|
|
207
|
+
*/
|
|
208
|
+
export async function preloadModel() {
|
|
209
|
+
console.log('๐ Preloading embedding model...');
|
|
210
|
+
await modelManager.getPrimaryModel();
|
|
211
|
+
console.log('โ
Model preloaded and ready!');
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get model readiness status
|
|
215
|
+
*/
|
|
216
|
+
export function isModelReady() {
|
|
217
|
+
return modelManager.isModelReady();
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=modelManager.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soulcraft/brainy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Multi-Dimensional AI Database - Vector similarity, graph relationships, metadata facets with HNSW indexing and OPFS storage",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|