@soulcraft/brainy 6.5.0 → 6.6.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.
Files changed (37) hide show
  1. package/assets/models/all-MiniLM-L6-v2-q8/config.json +25 -0
  2. package/assets/models/all-MiniLM-L6-v2-q8/model.onnx +0 -0
  3. package/assets/models/all-MiniLM-L6-v2-q8/tokenizer.json +30686 -0
  4. package/assets/models/all-MiniLM-L6-v2-q8/vocab.json +1 -0
  5. package/dist/brainy.js +0 -6
  6. package/dist/config/index.d.ts +1 -3
  7. package/dist/config/index.js +2 -4
  8. package/dist/config/modelAutoConfig.d.ts +10 -17
  9. package/dist/config/modelAutoConfig.js +15 -88
  10. package/dist/config/sharedConfigManager.d.ts +1 -2
  11. package/dist/config/zeroConfig.d.ts +2 -13
  12. package/dist/config/zeroConfig.js +7 -15
  13. package/dist/critical/model-guardian.d.ts +5 -22
  14. package/dist/critical/model-guardian.js +38 -210
  15. package/dist/embeddings/EmbeddingManager.d.ts +7 -17
  16. package/dist/embeddings/EmbeddingManager.js +28 -136
  17. package/dist/embeddings/wasm/AssetLoader.d.ts +67 -0
  18. package/dist/embeddings/wasm/AssetLoader.js +238 -0
  19. package/dist/embeddings/wasm/EmbeddingPostProcessor.d.ts +60 -0
  20. package/dist/embeddings/wasm/EmbeddingPostProcessor.js +123 -0
  21. package/dist/embeddings/wasm/ONNXInferenceEngine.d.ts +55 -0
  22. package/dist/embeddings/wasm/ONNXInferenceEngine.js +154 -0
  23. package/dist/embeddings/wasm/WASMEmbeddingEngine.d.ts +82 -0
  24. package/dist/embeddings/wasm/WASMEmbeddingEngine.js +231 -0
  25. package/dist/embeddings/wasm/WordPieceTokenizer.d.ts +71 -0
  26. package/dist/embeddings/wasm/WordPieceTokenizer.js +264 -0
  27. package/dist/embeddings/wasm/index.d.ts +13 -0
  28. package/dist/embeddings/wasm/index.js +15 -0
  29. package/dist/embeddings/wasm/types.d.ts +114 -0
  30. package/dist/embeddings/wasm/types.js +25 -0
  31. package/dist/setup.d.ts +11 -11
  32. package/dist/setup.js +17 -31
  33. package/dist/types/brainy.types.d.ts +0 -5
  34. package/dist/utils/embedding.d.ts +45 -62
  35. package/dist/utils/embedding.js +61 -440
  36. package/package.json +10 -3
  37. package/scripts/download-model.cjs +175 -0
@@ -1,227 +1,23 @@
1
1
  /**
2
- * Embedding functions for converting data to vectors using Transformers.js
3
- * Complete rewrite to eliminate TensorFlow.js and use ONNX-based models
2
+ * Embedding functions for converting data to vectors
3
+ *
4
+ * Uses direct ONNX WASM for universal compatibility.
5
+ * No transformers.js dependency - clean, production-grade implementation.
4
6
  */
5
- import { isBrowser } from './environment.js';
6
- // @ts-ignore - Transformers.js is now the primary embedding library
7
- import { pipeline, env } from '@huggingface/transformers';
8
- // CRITICAL: Disable ONNX memory arena to prevent 4-8GB allocation
9
- // This is needed for BOTH production and testing - reduces memory by 50-75%
10
- if (typeof process !== 'undefined' && process.env) {
11
- process.env.ORT_DISABLE_MEMORY_ARENA = '1';
12
- process.env.ORT_DISABLE_MEMORY_PATTERN = '1';
13
- // Force single-threaded operation for maximum stability (Node.js 22 LTS)
14
- process.env.ORT_INTRA_OP_NUM_THREADS = '1'; // Single thread for operators
15
- process.env.ORT_INTER_OP_NUM_THREADS = '1'; // Single thread for sessions
16
- process.env.ORT_NUM_THREADS = '1'; // Additional safety override
17
- }
18
- /**
19
- * Detect the best available GPU device for the current environment
20
- */
21
- export async function detectBestDevice() {
22
- // Browser environment - check for WebGPU support
23
- if (isBrowser()) {
24
- if (typeof navigator !== 'undefined' && 'gpu' in navigator) {
25
- try {
26
- const adapter = await navigator.gpu?.requestAdapter();
27
- if (adapter) {
28
- return 'webgpu';
29
- }
30
- }
31
- catch (error) {
32
- // WebGPU not available or failed to initialize
33
- }
34
- }
35
- return 'cpu';
36
- }
37
- // Node.js environment - check for CUDA support
38
- try {
39
- // Check if ONNX Runtime GPU packages are available
40
- // This is a simple heuristic - in production you might want more sophisticated detection
41
- const hasGpu = process.env.CUDA_VISIBLE_DEVICES !== undefined ||
42
- process.env.ONNXRUNTIME_GPU_ENABLED === 'true';
43
- return hasGpu ? 'cuda' : 'cpu';
44
- }
45
- catch (error) {
46
- return 'cpu';
47
- }
48
- }
7
+ import { embeddingManager } from '../embeddings/EmbeddingManager.js';
49
8
  /**
50
- * Resolve device string to actual device configuration
9
+ * TransformerEmbedding - Sentence embeddings using WASM ONNX
10
+ *
11
+ * This class delegates all work to EmbeddingManager which uses
12
+ * the direct ONNX WASM engine. Kept for backward compatibility.
51
13
  */
52
- export async function resolveDevice(device = 'auto') {
53
- if (device === 'auto') {
54
- return await detectBestDevice();
55
- }
56
- // Map 'gpu' to appropriate GPU type for current environment
57
- if (device === 'gpu') {
58
- const detected = await detectBestDevice();
59
- return detected === 'cpu' ? 'cpu' : detected;
60
- }
61
- return device;
62
- }
63
14
  export class TransformerEmbedding {
64
- /**
65
- * Create a new TransformerEmbedding instance
66
- */
67
15
  constructor(options = {}) {
68
- this.extractor = null;
69
16
  this.initialized = false;
70
- this.verbose = true;
71
17
  this.verbose = options.verbose !== undefined ? options.verbose : true;
72
- // PRODUCTION-READY MODEL CONFIGURATION
73
- // Priority order: explicit option > environment variable > smart default
74
- let localFilesOnly;
75
- if (options.localFilesOnly !== undefined) {
76
- // 1. Explicit option takes highest priority
77
- localFilesOnly = options.localFilesOnly;
78
- }
79
- else if (process.env.BRAINY_ALLOW_REMOTE_MODELS === 'false') {
80
- // 2. Environment variable explicitly disables remote models (legacy support)
81
- localFilesOnly = true;
82
- }
83
- else if (process.env.NODE_ENV === 'development') {
84
- // 3. Development mode allows remote models
85
- localFilesOnly = false;
86
- }
87
- else if (isBrowser()) {
88
- // 4. Browser defaults to allowing remote models
89
- localFilesOnly = false;
90
- }
91
- else {
92
- // 5. Node.js production: try local first, but allow remote as fallback
93
- // This is the NEW production-friendly default
94
- localFilesOnly = false;
95
- }
96
- this.options = {
97
- model: options.model || 'Xenova/all-MiniLM-L6-v2',
98
- verbose: this.verbose,
99
- cacheDir: options.cacheDir || './models',
100
- localFilesOnly: localFilesOnly,
101
- precision: options.precision || 'fp32', // Clean and clear!
102
- device: options.device || 'auto'
103
- };
104
- // ULTRA-CAREFUL: Runtime warnings for q8 usage
105
- if (this.options.precision === 'q8') {
106
- const confirmed = process.env.BRAINY_Q8_CONFIRMED === 'true';
107
- if (!confirmed && this.verbose) {
108
- console.warn('🚨 Q8 MODEL WARNING:');
109
- console.warn(' • Q8 creates different embeddings than fp32');
110
- console.warn(' • Q8 is incompatible with existing fp32 data');
111
- console.warn(' • Only use q8 for new projects or when explicitly migrating');
112
- console.warn(' • Set BRAINY_Q8_CONFIRMED=true to silence this warning');
113
- console.warn(' • Q8 model is 75% smaller but may have slightly reduced accuracy');
114
- }
115
- }
116
18
  if (this.verbose) {
117
- this.logger('log', `Embedding config: precision=${this.options.precision}, localFilesOnly=${localFilesOnly}, model=${this.options.model}`);
118
- }
119
- // Configure transformers.js environment
120
- if (!isBrowser()) {
121
- // Set cache directory for Node.js
122
- env.cacheDir = this.options.cacheDir;
123
- // Prioritize local models for offline operation
124
- env.allowRemoteModels = !this.options.localFilesOnly;
125
- env.allowLocalModels = true;
126
- }
127
- else {
128
- // Browser configuration
129
- // Allow both local and remote models, but prefer local if available
130
- env.allowLocalModels = true;
131
- env.allowRemoteModels = true;
132
- // Force the configuration to ensure it's applied
133
- if (this.verbose) {
134
- this.logger('log', `Browser env config - allowLocalModels: ${env.allowLocalModels}, allowRemoteModels: ${env.allowRemoteModels}, localFilesOnly: ${this.options.localFilesOnly}`);
135
- }
136
- }
137
- }
138
- /**
139
- * Get the default cache directory for models
140
- */
141
- async getDefaultCacheDir() {
142
- if (isBrowser()) {
143
- return './models'; // Browser default
144
- }
145
- // Check for bundled models in the package
146
- const possiblePaths = [
147
- // In the installed package
148
- './node_modules/@soulcraft/brainy/models',
149
- // In development/source
150
- './models',
151
- './dist/../models',
152
- // Alternative locations
153
- '../models',
154
- '../../models'
155
- ];
156
- // Check if we're in Node.js and try to find the bundled models
157
- if (typeof process !== 'undefined' && process.versions?.node) {
158
- try {
159
- // Use dynamic import instead of require for ES modules compatibility
160
- const { createRequire } = await import('module');
161
- const require = createRequire(import.meta.url);
162
- const path = require('node:path');
163
- const fs = require('node:fs');
164
- // Try to resolve the package location
165
- try {
166
- const brainyPackagePath = require.resolve('@soulcraft/brainy/package.json');
167
- const brainyPackageDir = path.dirname(brainyPackagePath);
168
- const bundledModelsPath = path.join(brainyPackageDir, 'models');
169
- if (fs.existsSync(bundledModelsPath)) {
170
- this.logger('log', `Using bundled models from package: ${bundledModelsPath}`);
171
- return bundledModelsPath;
172
- }
173
- }
174
- catch (e) {
175
- // Not installed as package, continue
176
- }
177
- // Try relative paths from current location
178
- for (const relativePath of possiblePaths) {
179
- const fullPath = path.resolve(relativePath);
180
- if (fs.existsSync(fullPath)) {
181
- this.logger('log', `Using bundled models from: ${fullPath}`);
182
- return fullPath;
183
- }
184
- }
185
- }
186
- catch (error) {
187
- // Silently fall back to default path if module detection fails
188
- }
189
- }
190
- // Fallback to default cache directory
191
- return './models';
192
- }
193
- /**
194
- * Check if we're running in a test environment
195
- */
196
- isTestEnvironment() {
197
- // Always use real implementation - no more mocking
198
- return false;
199
- }
200
- /**
201
- * Log message only if verbose mode is enabled
202
- */
203
- logger(level, message, ...args) {
204
- if (level === 'error' || this.verbose) {
205
- console[level](`[TransformerEmbedding] ${message}`, ...args);
206
- }
207
- }
208
- /**
209
- * Generate mock embeddings for unit tests
210
- */
211
- getMockEmbedding(data) {
212
- // Use the same mock logic as setup-unit.ts for consistency
213
- const input = Array.isArray(data) ? data.join(' ') : data;
214
- const str = typeof input === 'string' ? input : JSON.stringify(input);
215
- const vector = new Array(384).fill(0);
216
- // Create semi-realistic embeddings based on text content
217
- for (let i = 0; i < Math.min(str.length, 384); i++) {
218
- vector[i] = (str.charCodeAt(i % str.length) % 256) / 256;
19
+ console.log('[TransformerEmbedding] Using WASM ONNX backend (delegating to EmbeddingManager)');
219
20
  }
220
- // Add position-based variation
221
- for (let i = 0; i < 384; i++) {
222
- vector[i] += Math.sin(i * 0.1 + str.length) * 0.1;
223
- }
224
- return vector;
225
21
  }
226
22
  /**
227
23
  * Initialize the embedding model
@@ -230,272 +26,97 @@ export class TransformerEmbedding {
230
26
  if (this.initialized) {
231
27
  return;
232
28
  }
233
- // In unit test mode, skip real model initialization to prevent ONNX conflicts
234
- if (process.env.BRAINY_UNIT_TEST === 'true' || globalThis.__BRAINY_UNIT_TEST__) {
235
- this.initialized = true;
236
- this.logger('log', '🧪 Using mocked embeddings for unit tests');
237
- return;
238
- }
239
29
  try {
240
- // Resolve device configuration and cache directory
241
- const device = await resolveDevice(this.options.device);
242
- const cacheDir = this.options.cacheDir === './models'
243
- ? await this.getDefaultCacheDir()
244
- : this.options.cacheDir;
245
- this.logger('log', `Loading Transformer model: ${this.options.model} on device: ${device}`);
246
- const startTime = Date.now();
247
- // Use the configured precision from EmbeddingManager
248
- const { embeddingManager } = await import('../embeddings/EmbeddingManager.js');
249
- let actualType = embeddingManager.getPrecision();
250
- // CRITICAL: Control which model precision transformers.js uses
251
- // Q8 models use quantized int8 weights for 75% size reduction
252
- // Always use Q8 for optimal balance
253
- actualType = 'q8'; // Always Q8
254
- this.logger('log', '🎯 Using Q8 quantized model (75% smaller, 99% accuracy)');
255
- // Load the feature extraction pipeline with memory optimizations
256
- const pipelineOptions = {
257
- cache_dir: cacheDir,
258
- local_files_only: isBrowser() ? false : this.options.localFilesOnly,
259
- // CRITICAL: Specify dtype for model precision
260
- dtype: 'q8',
261
- // CRITICAL: For Q8, explicitly use quantized model
262
- quantized: true,
263
- // CRITICAL: ONNX memory optimizations
264
- session_options: {
265
- enableCpuMemArena: false, // Disable pre-allocated memory arena
266
- enableMemPattern: false, // Disable memory pattern optimization
267
- interOpNumThreads: 1, // Force single thread for V8 stability
268
- intraOpNumThreads: 1, // Force single thread for V8 stability
269
- graphOptimizationLevel: 'disabled' // Disable threading optimizations
270
- }
271
- };
272
- // Add device configuration for GPU acceleration
273
- if (device !== 'cpu') {
274
- pipelineOptions.device = device;
275
- this.logger('log', `🚀 GPU acceleration enabled: ${device}`);
276
- }
30
+ await embeddingManager.init();
31
+ this.initialized = true;
277
32
  if (this.verbose) {
278
- this.logger('log', `Pipeline options: ${JSON.stringify(pipelineOptions)}`);
33
+ console.log('[TransformerEmbedding] Initialized via EmbeddingManager (WASM)');
279
34
  }
280
- try {
281
- // For Q8 models, we need to explicitly specify the model file
282
- if (actualType === 'q8' && !isBrowser()) {
283
- try {
284
- // Check if quantized model exists (Node.js only)
285
- const { join } = await import('node:path');
286
- const { existsSync } = await import('node:fs');
287
- const modelPath = join(cacheDir, this.options.model, 'onnx', 'model_quantized.onnx');
288
- if (existsSync(modelPath)) {
289
- this.logger('log', '✅ Q8 model found locally');
290
- }
291
- else {
292
- this.logger('warn', '⚠️ Q8 model not found');
293
- actualType = 'q8'; // Always Q8
294
- }
295
- }
296
- catch (error) {
297
- // Skip model path check in browser or if imports fail
298
- this.logger('log', '🌐 Skipping local model check in browser environment');
299
- }
300
- }
301
- this.extractor = await pipeline('feature-extraction', this.options.model, pipelineOptions);
302
- }
303
- catch (gpuError) {
304
- // Fallback to CPU if GPU initialization fails
305
- if (device !== 'cpu') {
306
- this.logger('warn', `GPU initialization failed, falling back to CPU: ${gpuError?.message || gpuError}`);
307
- const cpuOptions = { ...pipelineOptions };
308
- delete cpuOptions.device;
309
- this.extractor = await pipeline('feature-extraction', this.options.model, cpuOptions);
310
- }
311
- else {
312
- // PRODUCTION-READY ERROR HANDLING
313
- // If local_files_only is true and models are missing, try enabling remote downloads
314
- if (pipelineOptions.local_files_only && gpuError?.message?.includes('local_files_only')) {
315
- this.logger('warn', 'Local models not found, attempting remote download as fallback...');
316
- try {
317
- const remoteOptions = { ...pipelineOptions, local_files_only: false };
318
- this.extractor = await pipeline('feature-extraction', this.options.model, remoteOptions);
319
- this.logger('log', '✅ Successfully downloaded and loaded model from remote');
320
- // Update the configuration to reflect what actually worked
321
- this.options.localFilesOnly = false;
322
- }
323
- catch (remoteError) {
324
- // Both local and remote failed - throw comprehensive error
325
- const errorMsg = `Failed to load embedding model "${this.options.model}". ` +
326
- `Local models not found and remote download failed. ` +
327
- `To fix: 1) Run "npm run download-models", ` +
328
- `2) Check your internet connection, or ` +
329
- `3) Use a custom embedding function.`;
330
- throw new Error(errorMsg);
331
- }
332
- }
333
- else {
334
- throw gpuError;
335
- }
336
- }
337
- }
338
- const loadTime = Date.now() - startTime;
339
- this.logger('log', `✅ Model loaded successfully in ${loadTime}ms`);
340
- this.initialized = true;
341
35
  }
342
36
  catch (error) {
343
- this.logger('error', 'Failed to initialize Transformer embedding model:', error);
344
- throw new Error(`Transformer embedding initialization failed: ${error}`);
37
+ console.error('[TransformerEmbedding] Failed to initialize:', error);
38
+ throw new Error(`TransformerEmbedding initialization failed: ${error}`);
345
39
  }
346
40
  }
347
41
  /**
348
42
  * Generate embeddings for text data
349
43
  */
350
44
  async embed(data) {
351
- // In unit test mode, return mock embeddings
352
- if (process.env.BRAINY_UNIT_TEST === 'true' || globalThis.__BRAINY_UNIT_TEST__) {
353
- return this.getMockEmbedding(data);
354
- }
355
45
  if (!this.initialized) {
356
46
  await this.init();
357
47
  }
358
- try {
359
- // Handle different input types
360
- let textToEmbed;
361
- if (typeof data === 'string') {
362
- // Handle empty string case
363
- if (data.trim() === '') {
364
- // Return a zero vector of 384 dimensions (all-MiniLM-L6-v2 standard)
365
- return new Array(384).fill(0);
366
- }
367
- textToEmbed = [data];
368
- }
369
- else if (Array.isArray(data) && data.every((item) => typeof item === 'string')) {
370
- // Handle empty array or array with empty strings
371
- if (data.length === 0 || data.every((item) => item.trim() === '')) {
372
- return new Array(384).fill(0);
373
- }
374
- // Filter out empty strings
375
- textToEmbed = data.filter((item) => item.trim() !== '');
376
- if (textToEmbed.length === 0) {
377
- return new Array(384).fill(0);
378
- }
379
- }
380
- else {
381
- throw new Error('TransformerEmbedding only supports string or string[] data');
382
- }
383
- // Ensure the extractor is available
384
- if (!this.extractor) {
385
- throw new Error('Transformer embedding model is not available');
386
- }
387
- // Generate embeddings with mean pooling and normalization
388
- const result = await this.extractor(textToEmbed, {
389
- pooling: 'mean',
390
- normalize: true
391
- });
392
- // Extract the embedding data
393
- let embedding;
394
- if (textToEmbed.length === 1) {
395
- // Single text input - return first embedding
396
- embedding = Array.from(result.data.slice(0, 384));
397
- }
398
- else {
399
- // Multiple texts - return first embedding (maintain compatibility)
400
- embedding = Array.from(result.data.slice(0, 384));
401
- }
402
- // Validate embedding dimensions
403
- if (embedding.length !== 384) {
404
- this.logger('warn', `Unexpected embedding dimension: ${embedding.length}, expected 384`);
405
- // Pad or truncate to 384 dimensions
406
- if (embedding.length < 384) {
407
- embedding = [...embedding, ...new Array(384 - embedding.length).fill(0)];
408
- }
409
- else {
410
- embedding = embedding.slice(0, 384);
411
- }
412
- }
413
- return embedding;
414
- }
415
- catch (error) {
416
- this.logger('error', 'Error generating embeddings:', error);
417
- throw new Error(`Failed to generate embeddings: ${error}`);
418
- }
48
+ // Delegate to EmbeddingManager
49
+ return embeddingManager.embed(data);
419
50
  }
420
51
  /**
421
- * Dispose of the model and free resources
52
+ * Get the embedding function
422
53
  */
423
- async dispose() {
424
- if (this.extractor && typeof this.extractor.dispose === 'function') {
425
- await this.extractor.dispose();
426
- }
427
- this.extractor = null;
428
- this.initialized = false;
54
+ getEmbeddingFunction() {
55
+ return async (data) => {
56
+ return this.embed(data);
57
+ };
429
58
  }
430
59
  /**
431
- * Get the dimension of embeddings produced by this model
60
+ * Check if initialized
432
61
  */
433
- getDimension() {
434
- return 384;
62
+ isInitialized() {
63
+ return this.initialized;
435
64
  }
436
65
  /**
437
- * Check if the model is initialized
66
+ * Dispose resources (no-op for WASM engine)
438
67
  */
439
- isInitialized() {
440
- return this.initialized;
68
+ async dispose() {
69
+ this.initialized = false;
441
70
  }
442
71
  }
443
- // Legacy alias for backward compatibility
444
- export const UniversalSentenceEncoder = TransformerEmbedding;
445
72
  /**
446
- * Create a new embedding model instance
73
+ * Create a simple embedding function using the default TransformerEmbedding
74
+ * This is the recommended way to create an embedding function for Brainy
447
75
  */
448
- export function createEmbeddingModel(options) {
76
+ export function createEmbeddingFunction(options = {}) {
77
+ return embeddingManager.getEmbeddingFunction();
78
+ }
79
+ /**
80
+ * Create a TransformerEmbedding instance (backward compatibility)
81
+ */
82
+ export function createTransformerEmbedding(options = {}) {
449
83
  return new TransformerEmbedding(options);
450
84
  }
451
85
  /**
452
- * Default embedding function using the unified EmbeddingManager
453
- * Simple, clean, reliable - no more layers of indirection
86
+ * Convenience function to detect best device (always returns 'wasm')
454
87
  */
455
- export const defaultEmbeddingFunction = async (data) => {
456
- const { embed } = await import('../embeddings/EmbeddingManager.js');
457
- return await embed(data);
458
- };
88
+ export async function detectBestDevice() {
89
+ return 'wasm';
90
+ }
459
91
  /**
460
- * Create an embedding function with custom options
461
- * NOTE: Options are validated but the singleton EmbeddingManager is always used
92
+ * Resolve device string (always returns 'wasm')
462
93
  */
463
- export function createEmbeddingFunction(options = {}) {
464
- return async (data) => {
465
- const { embeddingManager } = await import('../embeddings/EmbeddingManager.js');
466
- // Validate precision if specified
467
- // Precision is always Q8 now
468
- return await embeddingManager.embed(data);
469
- };
94
+ export async function resolveDevice(_device = 'auto') {
95
+ return 'wasm';
470
96
  }
471
97
  /**
472
- * Batch embedding function for processing multiple texts efficiently
98
+ * Default embedding function (backward compatibility)
473
99
  */
474
- export async function batchEmbed(texts, options = {}) {
475
- const embedder = new TransformerEmbedding(options);
476
- await embedder.init();
477
- const embeddings = [];
478
- // Process in batches for memory efficiency
479
- const batchSize = 32;
480
- for (let i = 0; i < texts.length; i += batchSize) {
481
- const batch = texts.slice(i, i + batchSize);
482
- for (const text of batch) {
483
- const embedding = await embedder.embed(text);
484
- embeddings.push(embedding);
485
- }
100
+ export const defaultEmbeddingFunction = embeddingManager.getEmbeddingFunction();
101
+ /**
102
+ * UniversalSentenceEncoder alias (backward compatibility)
103
+ */
104
+ export const UniversalSentenceEncoder = TransformerEmbedding;
105
+ /**
106
+ * Batch embed function (backward compatibility)
107
+ */
108
+ export async function batchEmbed(texts) {
109
+ const results = [];
110
+ for (const text of texts) {
111
+ results.push(await embeddingManager.embed(text));
486
112
  }
487
- await embedder.dispose();
488
- return embeddings;
113
+ return results;
489
114
  }
490
115
  /**
491
- * Embedding functions for specific model types
116
+ * Embedding functions registry (backward compatibility)
492
117
  */
493
118
  export const embeddingFunctions = {
494
- /** Default lightweight model (all-MiniLM-L6-v2, 384 dimensions) */
495
- default: defaultEmbeddingFunction,
496
- /** Create custom embedding function */
497
- create: createEmbeddingFunction,
498
- /** Batch processing */
499
- batch: batchEmbed
119
+ transformer: createEmbeddingFunction,
120
+ default: createEmbeddingFunction,
500
121
  };
501
122
  //# sourceMappingURL=embedding.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "6.5.0",
3
+ "version": "6.6.1",
4
4
  "description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. Stage 3 CANONICAL: 42 nouns × 127 verbs covering 96-97% of all human knowledge.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -64,7 +64,8 @@
64
64
  "./dist/cortex/backupRestore.js": false
65
65
  },
66
66
  "engines": {
67
- "node": "22.x"
67
+ "node": "22.x",
68
+ "bun": ">=1.0.0"
68
69
  },
69
70
  "scripts": {
70
71
  "build": "npm run build:types:if-needed && npm run build:patterns:if-needed && npm run build:keywords:if-needed && tsc && tsc -p tsconfig.cli.json",
@@ -90,6 +91,10 @@
90
91
  "test:ci-unit": "CI=true vitest run --config tests/configs/vitest.unit.config.ts",
91
92
  "test:ci-integration": "NODE_OPTIONS='--max-old-space-size=16384' CI=true vitest run --config tests/configs/vitest.integration.config.ts",
92
93
  "test:ci": "npm run test:ci-unit",
94
+ "test:bun": "bun tests/integration/bun-compile-test.ts",
95
+ "test:bun:compile": "bun build tests/integration/bun-compile-test.ts --compile --outfile /tmp/brainy-bun-test && /tmp/brainy-bun-test",
96
+ "test:wasm": "npx vitest run tests/integration/wasm-embeddings.test.ts",
97
+ "download-model": "node scripts/download-model.cjs",
93
98
  "download-models": "node scripts/download-models.cjs",
94
99
  "download-models:q8": "node scripts/download-models.cjs",
95
100
  "models:verify": "node scripts/ensure-models.js",
@@ -142,7 +147,9 @@
142
147
  "dist/**/*.js",
143
148
  "dist/**/*.d.ts",
144
149
  "bin/",
150
+ "assets/models/**/*",
145
151
  "scripts/download-models.cjs",
152
+ "scripts/download-model.cjs",
146
153
  "scripts/ensure-models.js",
147
154
  "scripts/prepare-models.js",
148
155
  "brainy.png",
@@ -180,7 +187,7 @@
180
187
  "@azure/identity": "^4.0.0",
181
188
  "@azure/storage-blob": "^12.17.0",
182
189
  "@google-cloud/storage": "^7.14.0",
183
- "@huggingface/transformers": "^3.7.2",
190
+ "onnxruntime-web": "^1.22.0",
184
191
  "@msgpack/msgpack": "^3.1.2",
185
192
  "@types/js-yaml": "^4.0.9",
186
193
  "boxen": "^8.0.1",