@soulcraft/brainy 1.2.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.
@@ -0,0 +1,77 @@
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
+ import { EmbeddingFunction } from '../coreTypes.js';
12
+ /**
13
+ * Global singleton model manager
14
+ * CRITICAL: This prevents multiple model loads which cause:
15
+ * - Test timeouts
16
+ * - Memory bloat
17
+ * - Performance degradation
18
+ * - ONNX runtime conflicts
19
+ */
20
+ declare class ModelManager {
21
+ private static instance;
22
+ private primaryModel;
23
+ private modelPromise;
24
+ private isInitialized;
25
+ private constructor();
26
+ static getInstance(): ModelManager;
27
+ /**
28
+ * Get the primary embedding model - LOADS ONCE, REUSES FOREVER
29
+ */
30
+ getPrimaryModel(): Promise<TransformerEmbedding>;
31
+ /**
32
+ * Initialize the primary model ONCE - WORKS IN ALL ENVIRONMENTS
33
+ */
34
+ private initializePrimaryModel;
35
+ /**
36
+ * Get embedding function that reuses the singleton model
37
+ */
38
+ getEmbeddingFunction(): Promise<EmbeddingFunction>;
39
+ /**
40
+ * Check if model is ready (loaded and initialized)
41
+ */
42
+ isModelReady(): boolean;
43
+ /**
44
+ * Force model reload (for testing or recovery)
45
+ */
46
+ reloadModel(): Promise<void>;
47
+ /**
48
+ * Get model status for debugging
49
+ */
50
+ getModelStatus(): {
51
+ loaded: boolean;
52
+ ready: boolean;
53
+ modelType: string;
54
+ };
55
+ /**
56
+ * Cleanup method for testing
57
+ */
58
+ cleanup(): void;
59
+ }
60
+ export declare const modelManager: ModelManager;
61
+ /**
62
+ * Get the singleton embedding function - USE THIS EVERYWHERE!
63
+ */
64
+ export declare function getSingletonEmbeddingFunction(): Promise<EmbeddingFunction>;
65
+ /**
66
+ * Optimized default embedding function that reuses singleton model
67
+ */
68
+ export declare const optimizedDefaultEmbeddingFunction: EmbeddingFunction;
69
+ /**
70
+ * Preload model for tests or production - CALL THIS ONCE AT START
71
+ */
72
+ export declare function preloadModel(): Promise<void>;
73
+ /**
74
+ * Get model readiness status
75
+ */
76
+ export declare function isModelReady(): boolean;
77
+ export {};
@@ -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.2.0",
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",
@@ -142,7 +142,10 @@
142
142
  "_workflow:major": "node scripts/release-workflow.js major",
143
143
  "_workflow:dry-run": "npm run build && npm test && npm run _release:dry-run",
144
144
  "_dry-run": "npm pack --dry-run",
145
- "download-models": "node scripts/download-models.cjs"
145
+ "download-models": "node scripts/download-models.cjs",
146
+ "prepare-models": "node scripts/prepare-models.js",
147
+ "models:verify": "node scripts/ensure-models.js",
148
+ "models:download": "BRAINY_ALLOW_REMOTE_MODELS=true node scripts/download-models.cjs"
146
149
  },
147
150
  "keywords": [
148
151
  "vector-database",