@soulcraft/brainy 0.12.0 → 0.14.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/README.demo.md +1 -1
- package/README.md +7 -22
- package/dist/brainyData.d.ts +12 -0
- package/dist/storage/fileSystemStorage.d.ts.map +1 -1
- package/dist/unified.js +145 -59
- package/dist/unified.min.js +747 -747
- package/dist/utils/embedding.d.ts +45 -3
- package/dist/utils/embedding.d.ts.map +1 -1
- package/dist/utils/version.d.ts +1 -1
- package/package.json +3 -3
- package/dist/brainy.js +0 -87814
- package/dist/brainy.min.js +0 -12511
package/README.demo.md
CHANGED
|
@@ -35,7 +35,7 @@ npx http-server
|
|
|
35
35
|
If you see the error "Could not load Brainy library. Please ensure the project is built and served over HTTP", check the
|
|
36
36
|
following:
|
|
37
37
|
|
|
38
|
-
1. Make sure you've built the project with `npm run build:
|
|
38
|
+
1. Make sure you've built the project with `npm run build && npm run build:browser`
|
|
39
39
|
2. Ensure you're accessing the demo through HTTP (not by opening the file directly)
|
|
40
40
|
3. Check your browser's console for additional error messages
|
|
41
41
|
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://nodejs.org/)
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
[](CONTRIBUTING.md)
|
|
9
|
-
[](https://www.npmjs.com/package/@soulcraft/brainy)
|
|
10
10
|
|
|
11
11
|
[//]: # ([](https://github.com/sodal-project/cartographer))
|
|
12
12
|
|
|
@@ -62,12 +62,7 @@ GitHub Pages that showcases Brainy's main features.
|
|
|
62
62
|
npm install @soulcraft/brainy
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
TensorFlow.js packages are included as
|
|
66
|
-
dependency conflicts, you may need to use the `--legacy-peer-deps` flag:
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
npm install @soulcraft/brainy --legacy-peer-deps
|
|
70
|
-
```
|
|
65
|
+
TensorFlow.js packages are included as bundled dependencies and will be automatically installed without any additional configuration.
|
|
71
66
|
|
|
72
67
|
## 🏁 Quick Start
|
|
73
68
|
|
|
@@ -110,14 +105,9 @@ import { BrainyData } from '@soulcraft/brainy'
|
|
|
110
105
|
|
|
111
106
|
// Minified version for production
|
|
112
107
|
import { BrainyData } from '@soulcraft/brainy/min'
|
|
113
|
-
|
|
114
|
-
// CLI functionality (only imported when needed)
|
|
115
|
-
import '@soulcraft/brainy/cli'
|
|
116
108
|
```
|
|
117
109
|
|
|
118
|
-
> **Note**: The CLI functionality
|
|
119
|
-
> Node.js applications. The CLI is only built and loaded when explicitly imported or when using the command-line
|
|
120
|
-
> interface.
|
|
110
|
+
> **Note**: The CLI functionality is available as a separate package `@soulcraft/brainy-cli` to reduce the bundle size of the main package. Install it globally with `npm install -g @soulcraft/brainy-cli` to use the command-line interface.
|
|
121
111
|
|
|
122
112
|
### Browser Usage
|
|
123
113
|
|
|
@@ -417,18 +407,13 @@ brainy visualize --root <id> --depth 3
|
|
|
417
407
|
|
|
418
408
|
### Using the CLI in Your Code
|
|
419
409
|
|
|
420
|
-
If you need
|
|
410
|
+
The CLI functionality is available as a separate package `@soulcraft/brainy-cli`. If you need CLI functionality in your application, install the CLI package:
|
|
421
411
|
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
import '@soulcraft/brainy/cli'
|
|
425
|
-
|
|
426
|
-
// Now you can use the CLI programmatically
|
|
427
|
-
// ...
|
|
412
|
+
```bash
|
|
413
|
+
npm install @soulcraft/brainy-cli
|
|
428
414
|
```
|
|
429
415
|
|
|
430
|
-
|
|
431
|
-
the CLI.
|
|
416
|
+
Then you can use the CLI commands programmatically or through the command line interface.
|
|
432
417
|
|
|
433
418
|
### Available Commands
|
|
434
419
|
|
package/dist/brainyData.d.ts
CHANGED
|
@@ -89,6 +89,17 @@ export interface BrainyDataConfig {
|
|
|
89
89
|
*/
|
|
90
90
|
autoConnect?: boolean;
|
|
91
91
|
};
|
|
92
|
+
/**
|
|
93
|
+
* Logging configuration
|
|
94
|
+
*/
|
|
95
|
+
logging?: {
|
|
96
|
+
/**
|
|
97
|
+
* Whether to enable verbose logging
|
|
98
|
+
* When false, suppresses non-essential log messages like model loading progress
|
|
99
|
+
* Default: true
|
|
100
|
+
*/
|
|
101
|
+
verbose?: boolean;
|
|
102
|
+
};
|
|
92
103
|
}
|
|
93
104
|
export declare class BrainyData<T = any> implements BrainyDataInterface<T> {
|
|
94
105
|
private index;
|
|
@@ -102,6 +113,7 @@ export declare class BrainyData<T = any> implements BrainyDataInterface<T> {
|
|
|
102
113
|
private storageConfig;
|
|
103
114
|
private useOptimizedIndex;
|
|
104
115
|
private _dimensions;
|
|
116
|
+
private loggingConfig;
|
|
105
117
|
private remoteServerConfig;
|
|
106
118
|
private serverSearchConduit;
|
|
107
119
|
private serverConnection;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileSystemStorage.d.ts","sourceRoot":"","sources":["../../src/storage/fileSystemStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AA4DrE;;GAEG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,aAAa,CAAQ;gBAEjB,aAAa,CAAC,EAAE,MAAM;IAelC;;OAEG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"fileSystemStorage.d.ts","sourceRoot":"","sources":["../../src/storage/fileSystemStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AA4DrE;;GAEG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,aAAa,CAAQ;gBAEjB,aAAa,CAAC,EAAE,MAAM;IAelC;;OAEG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YA2DpB,qBAAqB;IAWnC,OAAO,CAAC,WAAW;IA6BN,QAAQ,CACnB,IAAI,EAAE,QAAQ,GAAG;QAAE,QAAQ,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAChD,OAAO,CAAC,IAAI,CAAC;IAQH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAyB7C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBrC,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IA+B/C;;;;OAIG;IACU,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IA8CzD,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrD;;;;OAIG;IACU,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAc9C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMrE;;;;OAIG;IACU,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMrE;;;;OAIG;IACU,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMlD,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAoBnC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAalD;;;;OAIG;IACU,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnE;;;;OAIG;IACU,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAc5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA4DtB,gBAAgB,IAAI,OAAO,CAAC;QACvC,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAC9B,CAAC;CAyCH"}
|
package/dist/unified.js
CHANGED
|
@@ -3553,12 +3553,18 @@ function cleanupWorkerPools() {
|
|
|
3553
3553
|
* falling back to CPU processing for compatibility across all environments.
|
|
3554
3554
|
*/
|
|
3555
3555
|
let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
3556
|
-
|
|
3556
|
+
/**
|
|
3557
|
+
* Create a new UniversalSentenceEncoder instance
|
|
3558
|
+
* @param options Configuration options
|
|
3559
|
+
*/
|
|
3560
|
+
constructor(options = {}) {
|
|
3557
3561
|
this.model = null;
|
|
3558
3562
|
this.initialized = false;
|
|
3559
3563
|
this.tf = null;
|
|
3560
3564
|
this.use = null;
|
|
3561
3565
|
this.backend = 'cpu'; // Default to CPU
|
|
3566
|
+
this.verbose = true; // Whether to log non-essential messages
|
|
3567
|
+
this.verbose = options.verbose !== undefined ? options.verbose : true;
|
|
3562
3568
|
}
|
|
3563
3569
|
/**
|
|
3564
3570
|
* Add polyfills and patches for TensorFlow.js compatibility
|
|
@@ -3624,10 +3630,12 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3624
3630
|
process.argv.some((arg) => arg.includes('vitest')));
|
|
3625
3631
|
}
|
|
3626
3632
|
/**
|
|
3627
|
-
* Log message only if
|
|
3633
|
+
* Log message only if verbose mode is enabled or if it's an error
|
|
3634
|
+
* This helps suppress non-essential log messages
|
|
3628
3635
|
*/
|
|
3629
|
-
|
|
3630
|
-
if
|
|
3636
|
+
logger(level, message, ...args) {
|
|
3637
|
+
// Always log errors, but only log other messages if verbose mode is enabled
|
|
3638
|
+
if (level === 'error' || this.verbose) {
|
|
3631
3639
|
console[level](message, ...args);
|
|
3632
3640
|
}
|
|
3633
3641
|
}
|
|
@@ -3642,12 +3650,12 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3642
3650
|
let lastError = null;
|
|
3643
3651
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
3644
3652
|
try {
|
|
3645
|
-
this.
|
|
3653
|
+
this.logger('log', attempt === 0
|
|
3646
3654
|
? 'Loading Universal Sentence Encoder model...'
|
|
3647
3655
|
: `Retrying Universal Sentence Encoder model loading (attempt ${attempt + 1}/${maxRetries + 1})...`);
|
|
3648
3656
|
const model = await loadFunction();
|
|
3649
3657
|
if (attempt > 0) {
|
|
3650
|
-
this.
|
|
3658
|
+
this.logger('log', 'Universal Sentence Encoder model loaded successfully after retry');
|
|
3651
3659
|
}
|
|
3652
3660
|
return model;
|
|
3653
3661
|
}
|
|
@@ -3665,16 +3673,16 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3665
3673
|
errorMessage.includes('model.json');
|
|
3666
3674
|
if (attempt < maxRetries && isRetryableError) {
|
|
3667
3675
|
const delay = baseDelay * Math.pow(2, attempt); // Exponential backoff
|
|
3668
|
-
this.
|
|
3676
|
+
this.logger('warn', `Universal Sentence Encoder model loading failed (attempt ${attempt + 1}): ${errorMessage}. Retrying in ${delay}ms...`);
|
|
3669
3677
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
3670
3678
|
}
|
|
3671
3679
|
else {
|
|
3672
3680
|
// Either we've exhausted retries or this is not a retryable error
|
|
3673
3681
|
if (attempt >= maxRetries) {
|
|
3674
|
-
this.
|
|
3682
|
+
this.logger('error', `Universal Sentence Encoder model loading failed after ${maxRetries + 1} attempts. Last error: ${errorMessage}`);
|
|
3675
3683
|
}
|
|
3676
3684
|
else {
|
|
3677
|
-
this.
|
|
3685
|
+
this.logger('error', `Universal Sentence Encoder model loading failed with non-retryable error: ${errorMessage}`);
|
|
3678
3686
|
}
|
|
3679
3687
|
throw lastError;
|
|
3680
3688
|
}
|
|
@@ -3718,7 +3726,9 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3718
3726
|
if (globalObj) {
|
|
3719
3727
|
// Try to use Node.js util module if available (Node.js environments)
|
|
3720
3728
|
try {
|
|
3721
|
-
if (typeof process !== 'undefined' &&
|
|
3729
|
+
if (typeof process !== 'undefined' &&
|
|
3730
|
+
process.versions &&
|
|
3731
|
+
process.versions.node) {
|
|
3722
3732
|
const util = await Promise.resolve().then(function () { return _utilShim$1; });
|
|
3723
3733
|
if (!globalObj.TextEncoder) {
|
|
3724
3734
|
globalObj.TextEncoder = util.TextEncoder;
|
|
@@ -3774,15 +3784,14 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3774
3784
|
this.use = await Promise.resolve().then(function () { return universalSentenceEncoder_esm; });
|
|
3775
3785
|
}
|
|
3776
3786
|
catch (error) {
|
|
3777
|
-
this.
|
|
3787
|
+
this.logger('error', 'Failed to initialize TensorFlow.js:', error);
|
|
3778
3788
|
throw error;
|
|
3779
3789
|
}
|
|
3780
3790
|
// Set the backend
|
|
3781
3791
|
if (this.tf.setBackend) {
|
|
3782
3792
|
await this.tf.setBackend(this.backend);
|
|
3783
3793
|
}
|
|
3784
|
-
//
|
|
3785
|
-
console.log('Universal Sentence Encoder module structure in main thread:', Object.keys(this.use), this.use.default ? Object.keys(this.use.default) : 'No default export');
|
|
3794
|
+
// Module structure available for debugging if needed
|
|
3786
3795
|
// Try to find the load function in different possible module structures
|
|
3787
3796
|
const loadFunction = findUSELoadFunction(this.use);
|
|
3788
3797
|
if (!loadFunction) {
|
|
@@ -3795,7 +3804,7 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3795
3804
|
console.warn = originalWarn;
|
|
3796
3805
|
}
|
|
3797
3806
|
catch (error) {
|
|
3798
|
-
this.
|
|
3807
|
+
this.logger('error', 'Failed to initialize Universal Sentence Encoder:', error);
|
|
3799
3808
|
throw new Error(`Failed to initialize Universal Sentence Encoder: ${error}`);
|
|
3800
3809
|
}
|
|
3801
3810
|
}
|
|
@@ -3842,7 +3851,7 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3842
3851
|
return embeddingArray[0];
|
|
3843
3852
|
}
|
|
3844
3853
|
catch (error) {
|
|
3845
|
-
this.
|
|
3854
|
+
this.logger('error', 'Failed to embed text with Universal Sentence Encoder:', error);
|
|
3846
3855
|
throw new Error(`Failed to embed text with Universal Sentence Encoder: ${error}`);
|
|
3847
3856
|
}
|
|
3848
3857
|
}
|
|
@@ -3891,7 +3900,7 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3891
3900
|
return results;
|
|
3892
3901
|
}
|
|
3893
3902
|
catch (error) {
|
|
3894
|
-
this.
|
|
3903
|
+
this.logger('error', 'Failed to batch embed text with Universal Sentence Encoder:', error);
|
|
3895
3904
|
throw new Error(`Failed to batch embed text with Universal Sentence Encoder: ${error}`);
|
|
3896
3905
|
}
|
|
3897
3906
|
}
|
|
@@ -3907,7 +3916,7 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3907
3916
|
this.initialized = false;
|
|
3908
3917
|
}
|
|
3909
3918
|
catch (error) {
|
|
3910
|
-
this.
|
|
3919
|
+
this.logger('error', 'Failed to dispose Universal Sentence Encoder:', error);
|
|
3911
3920
|
}
|
|
3912
3921
|
}
|
|
3913
3922
|
return Promise.resolve();
|
|
@@ -3920,47 +3929,38 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
|
|
|
3920
3929
|
* @returns The load function or null if not found
|
|
3921
3930
|
*/
|
|
3922
3931
|
function findUSELoadFunction(sentenceEncoderModule) {
|
|
3923
|
-
//
|
|
3924
|
-
console.log('Universal Sentence Encoder module structure:', Object.keys(sentenceEncoderModule), sentenceEncoderModule.default
|
|
3925
|
-
? Object.keys(sentenceEncoderModule.default)
|
|
3926
|
-
: 'No default export');
|
|
3932
|
+
// Module structure available for debugging if needed
|
|
3927
3933
|
let loadFunction = null;
|
|
3928
3934
|
// Try sentenceEncoderModule.load first (direct export)
|
|
3929
3935
|
if (sentenceEncoderModule.load &&
|
|
3930
3936
|
typeof sentenceEncoderModule.load === 'function') {
|
|
3931
3937
|
loadFunction = sentenceEncoderModule.load;
|
|
3932
|
-
console.log('Using sentenceEncoderModule.load');
|
|
3933
3938
|
}
|
|
3934
3939
|
// Then try sentenceEncoderModule.default.load (default export)
|
|
3935
3940
|
else if (sentenceEncoderModule.default &&
|
|
3936
3941
|
sentenceEncoderModule.default.load &&
|
|
3937
3942
|
typeof sentenceEncoderModule.default.load === 'function') {
|
|
3938
3943
|
loadFunction = sentenceEncoderModule.default.load;
|
|
3939
|
-
console.log('Using sentenceEncoderModule.default.load');
|
|
3940
3944
|
}
|
|
3941
3945
|
// Try sentenceEncoderModule.default directly if it's a function
|
|
3942
3946
|
else if (sentenceEncoderModule.default &&
|
|
3943
3947
|
typeof sentenceEncoderModule.default === 'function') {
|
|
3944
3948
|
loadFunction = sentenceEncoderModule.default;
|
|
3945
|
-
console.log('Using sentenceEncoderModule.default as function');
|
|
3946
3949
|
}
|
|
3947
3950
|
// Try sentenceEncoderModule directly if it's a function
|
|
3948
3951
|
else if (typeof sentenceEncoderModule === 'function') {
|
|
3949
3952
|
loadFunction = sentenceEncoderModule;
|
|
3950
|
-
console.log('Using sentenceEncoderModule as function');
|
|
3951
3953
|
}
|
|
3952
3954
|
// Try additional common patterns
|
|
3953
3955
|
else if (sentenceEncoderModule.UniversalSentenceEncoder &&
|
|
3954
3956
|
typeof sentenceEncoderModule.UniversalSentenceEncoder.load === 'function') {
|
|
3955
3957
|
loadFunction = sentenceEncoderModule.UniversalSentenceEncoder.load;
|
|
3956
|
-
console.log('Using sentenceEncoderModule.UniversalSentenceEncoder.load');
|
|
3957
3958
|
}
|
|
3958
3959
|
else if (sentenceEncoderModule.default &&
|
|
3959
3960
|
sentenceEncoderModule.default.UniversalSentenceEncoder &&
|
|
3960
3961
|
typeof sentenceEncoderModule.default.UniversalSentenceEncoder.load ===
|
|
3961
3962
|
'function') {
|
|
3962
3963
|
loadFunction = sentenceEncoderModule.default.UniversalSentenceEncoder.load;
|
|
3963
|
-
console.log('Using sentenceEncoderModule.default.UniversalSentenceEncoder.load');
|
|
3964
3964
|
}
|
|
3965
3965
|
// Try to find the load function in the module's properties
|
|
3966
3966
|
else {
|
|
@@ -3971,7 +3971,6 @@ function findUSELoadFunction(sentenceEncoderModule) {
|
|
|
3971
3971
|
const fnName = sentenceEncoderModule[key].name || key;
|
|
3972
3972
|
if (fnName.toLowerCase().includes('load')) {
|
|
3973
3973
|
loadFunction = sentenceEncoderModule[key];
|
|
3974
|
-
console.log(`Using sentenceEncoderModule.${key} as load function`);
|
|
3975
3974
|
break;
|
|
3976
3975
|
}
|
|
3977
3976
|
}
|
|
@@ -3983,7 +3982,6 @@ function findUSELoadFunction(sentenceEncoderModule) {
|
|
|
3983
3982
|
const fnName = sentenceEncoderModule[key][nestedKey].name || nestedKey;
|
|
3984
3983
|
if (fnName.toLowerCase().includes('load')) {
|
|
3985
3984
|
loadFunction = sentenceEncoderModule[key][nestedKey];
|
|
3986
|
-
console.log(`Using sentenceEncoderModule.${key}.${nestedKey} as load function`);
|
|
3987
3985
|
break;
|
|
3988
3986
|
}
|
|
3989
3987
|
}
|
|
@@ -4008,9 +4006,14 @@ function isTestEnvironment() {
|
|
|
4008
4006
|
process.argv.some((arg) => arg.includes('vitest')));
|
|
4009
4007
|
}
|
|
4010
4008
|
/**
|
|
4011
|
-
* Log message only if not in test environment (standalone version)
|
|
4009
|
+
* Log message only if not in test environment and verbose mode is enabled (standalone version)
|
|
4010
|
+
* @param level Log level ('log', 'warn', 'error')
|
|
4011
|
+
* @param message Message to log
|
|
4012
|
+
* @param args Additional arguments to log
|
|
4013
|
+
* @param verbose Whether to log non-essential messages (default: true)
|
|
4012
4014
|
*/
|
|
4013
|
-
function logIfNotTest(level, message,
|
|
4015
|
+
function logIfNotTest(level, message, args = [], verbose = true) {
|
|
4016
|
+
// Always log errors, but only log other messages if verbose mode is enabled
|
|
4014
4017
|
if (!isTestEnvironment()) {
|
|
4015
4018
|
console[level](message, ...args);
|
|
4016
4019
|
}
|
|
@@ -4032,11 +4035,22 @@ function createEmbeddingFunction(model) {
|
|
|
4032
4035
|
* Creates a TensorFlow-based Universal Sentence Encoder embedding function
|
|
4033
4036
|
* This is the required embedding function for all text embeddings
|
|
4034
4037
|
* Uses a shared model instance for better performance across multiple calls
|
|
4038
|
+
* @param options Configuration options
|
|
4039
|
+
* @param options.verbose Whether to log non-essential messages (default: true)
|
|
4035
4040
|
*/
|
|
4036
4041
|
// Create a single shared instance of the model that persists across all embedding calls
|
|
4037
|
-
|
|
4042
|
+
let sharedModel = null;
|
|
4038
4043
|
let sharedModelInitialized = false;
|
|
4039
|
-
|
|
4044
|
+
let sharedModelVerbose = true;
|
|
4045
|
+
function createTensorFlowEmbeddingFunction(options = {}) {
|
|
4046
|
+
// Update verbose setting if provided
|
|
4047
|
+
if (options.verbose !== undefined) {
|
|
4048
|
+
sharedModelVerbose = options.verbose;
|
|
4049
|
+
}
|
|
4050
|
+
// Create the shared model if it doesn't exist yet
|
|
4051
|
+
if (!sharedModel) {
|
|
4052
|
+
sharedModel = new UniversalSentenceEncoder$1({ verbose: sharedModelVerbose });
|
|
4053
|
+
}
|
|
4040
4054
|
return async (data) => {
|
|
4041
4055
|
try {
|
|
4042
4056
|
// Initialize the model if it hasn't been initialized yet
|
|
@@ -4054,7 +4068,7 @@ function createTensorFlowEmbeddingFunction() {
|
|
|
4054
4068
|
return await sharedModel.embed(data);
|
|
4055
4069
|
}
|
|
4056
4070
|
catch (error) {
|
|
4057
|
-
logIfNotTest('error', 'Failed to use TensorFlow embedding:', error);
|
|
4071
|
+
logIfNotTest('error', 'Failed to use TensorFlow embedding:', [error], sharedModelVerbose);
|
|
4058
4072
|
throw new Error(`Universal Sentence Encoder is required but failed: ${error}`);
|
|
4059
4073
|
}
|
|
4060
4074
|
};
|
|
@@ -4064,32 +4078,73 @@ function createTensorFlowEmbeddingFunction() {
|
|
|
4064
4078
|
* Uses UniversalSentenceEncoder for all text embeddings
|
|
4065
4079
|
* TensorFlow.js is required for this to work
|
|
4066
4080
|
* Uses CPU for compatibility
|
|
4081
|
+
* @param options Configuration options
|
|
4082
|
+
* @param options.verbose Whether to log non-essential messages (default: true)
|
|
4067
4083
|
*/
|
|
4068
|
-
|
|
4084
|
+
function getDefaultEmbeddingFunction(options = {}) {
|
|
4085
|
+
return createTensorFlowEmbeddingFunction(options);
|
|
4086
|
+
}
|
|
4069
4087
|
/**
|
|
4070
|
-
* Default
|
|
4088
|
+
* Default embedding function with default options
|
|
4071
4089
|
* Uses UniversalSentenceEncoder for all text embeddings
|
|
4072
4090
|
* TensorFlow.js is required for this to work
|
|
4091
|
+
* Uses CPU for compatibility
|
|
4092
|
+
*/
|
|
4093
|
+
const defaultEmbeddingFunction = getDefaultEmbeddingFunction();
|
|
4094
|
+
/**
|
|
4095
|
+
* Creates a batch embedding function that uses UniversalSentenceEncoder
|
|
4096
|
+
* TensorFlow.js is required for this to work
|
|
4073
4097
|
* Processes all items in a single batch operation
|
|
4074
4098
|
* Uses a shared model instance for better performance across multiple calls
|
|
4099
|
+
* @param options Configuration options
|
|
4100
|
+
* @param options.verbose Whether to log non-essential messages (default: true)
|
|
4075
4101
|
*/
|
|
4076
4102
|
// Create a single shared instance of the model that persists across function calls
|
|
4077
|
-
|
|
4103
|
+
let sharedBatchModel = null;
|
|
4078
4104
|
let sharedBatchModelInitialized = false;
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
sharedBatchModelInitialized = true;
|
|
4085
|
-
}
|
|
4086
|
-
return await sharedBatchModel.embedBatch(dataArray);
|
|
4105
|
+
let sharedBatchModelVerbose = true;
|
|
4106
|
+
function createBatchEmbeddingFunction(options = {}) {
|
|
4107
|
+
// Update verbose setting if provided
|
|
4108
|
+
if (options.verbose !== undefined) {
|
|
4109
|
+
sharedBatchModelVerbose = options.verbose;
|
|
4087
4110
|
}
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4111
|
+
// Create the shared model if it doesn't exist yet
|
|
4112
|
+
if (!sharedBatchModel) {
|
|
4113
|
+
sharedBatchModel = new UniversalSentenceEncoder$1({ verbose: sharedBatchModelVerbose });
|
|
4091
4114
|
}
|
|
4092
|
-
|
|
4115
|
+
return async (dataArray) => {
|
|
4116
|
+
try {
|
|
4117
|
+
// Initialize the model if it hasn't been initialized yet
|
|
4118
|
+
if (!sharedBatchModelInitialized) {
|
|
4119
|
+
await sharedBatchModel.init();
|
|
4120
|
+
sharedBatchModelInitialized = true;
|
|
4121
|
+
}
|
|
4122
|
+
return await sharedBatchModel.embedBatch(dataArray);
|
|
4123
|
+
}
|
|
4124
|
+
catch (error) {
|
|
4125
|
+
logIfNotTest('error', 'Failed to use TensorFlow batch embedding:', [error], sharedBatchModelVerbose);
|
|
4126
|
+
throw new Error(`Universal Sentence Encoder batch embedding failed: ${error}`);
|
|
4127
|
+
}
|
|
4128
|
+
};
|
|
4129
|
+
}
|
|
4130
|
+
/**
|
|
4131
|
+
* Get a batch embedding function with custom options
|
|
4132
|
+
* Uses UniversalSentenceEncoder for all text embeddings
|
|
4133
|
+
* TensorFlow.js is required for this to work
|
|
4134
|
+
* Processes all items in a single batch operation
|
|
4135
|
+
* @param options Configuration options
|
|
4136
|
+
* @param options.verbose Whether to log non-essential messages (default: true)
|
|
4137
|
+
*/
|
|
4138
|
+
function getDefaultBatchEmbeddingFunction(options = {}) {
|
|
4139
|
+
return createBatchEmbeddingFunction(options);
|
|
4140
|
+
}
|
|
4141
|
+
/**
|
|
4142
|
+
* Default batch embedding function with default options
|
|
4143
|
+
* Uses UniversalSentenceEncoder for all text embeddings
|
|
4144
|
+
* TensorFlow.js is required for this to work
|
|
4145
|
+
* Processes all items in a single batch operation
|
|
4146
|
+
*/
|
|
4147
|
+
const defaultBatchEmbeddingFunction = getDefaultBatchEmbeddingFunction();
|
|
4093
4148
|
/**
|
|
4094
4149
|
* Creates an embedding function that runs in a separate thread
|
|
4095
4150
|
* This is a wrapper around createEmbeddingFunction that uses executeInThread
|
|
@@ -4108,11 +4163,14 @@ function createThreadedEmbeddingFunction(model) {
|
|
|
4108
4163
|
var embedding = /*#__PURE__*/Object.freeze({
|
|
4109
4164
|
__proto__: null,
|
|
4110
4165
|
UniversalSentenceEncoder: UniversalSentenceEncoder$1,
|
|
4166
|
+
createBatchEmbeddingFunction: createBatchEmbeddingFunction,
|
|
4111
4167
|
createEmbeddingFunction: createEmbeddingFunction,
|
|
4112
4168
|
createTensorFlowEmbeddingFunction: createTensorFlowEmbeddingFunction,
|
|
4113
4169
|
createThreadedEmbeddingFunction: createThreadedEmbeddingFunction,
|
|
4114
4170
|
defaultBatchEmbeddingFunction: defaultBatchEmbeddingFunction,
|
|
4115
|
-
defaultEmbeddingFunction: defaultEmbeddingFunction
|
|
4171
|
+
defaultEmbeddingFunction: defaultEmbeddingFunction,
|
|
4172
|
+
getDefaultBatchEmbeddingFunction: getDefaultBatchEmbeddingFunction,
|
|
4173
|
+
getDefaultEmbeddingFunction: getDefaultEmbeddingFunction
|
|
4116
4174
|
});
|
|
4117
4175
|
|
|
4118
4176
|
/**
|
|
@@ -8492,6 +8550,7 @@ class BrainyData {
|
|
|
8492
8550
|
this.isInitializing = false;
|
|
8493
8551
|
this.storageConfig = {};
|
|
8494
8552
|
this.useOptimizedIndex = false;
|
|
8553
|
+
this.loggingConfig = { verbose: true };
|
|
8495
8554
|
// Remote server properties
|
|
8496
8555
|
this.remoteServerConfig = null;
|
|
8497
8556
|
this.serverSearchConduit = null;
|
|
@@ -8516,9 +8575,22 @@ class BrainyData {
|
|
|
8516
8575
|
}
|
|
8517
8576
|
// Set storage if provided, otherwise it will be initialized in init()
|
|
8518
8577
|
this.storage = config.storageAdapter || null;
|
|
8519
|
-
//
|
|
8520
|
-
|
|
8521
|
-
|
|
8578
|
+
// Store logging configuration
|
|
8579
|
+
if (config.logging !== undefined) {
|
|
8580
|
+
this.loggingConfig = {
|
|
8581
|
+
...this.loggingConfig,
|
|
8582
|
+
...config.logging
|
|
8583
|
+
};
|
|
8584
|
+
}
|
|
8585
|
+
// Set embedding function if provided, otherwise create one with the appropriate verbose setting
|
|
8586
|
+
if (config.embeddingFunction) {
|
|
8587
|
+
this.embeddingFunction = config.embeddingFunction;
|
|
8588
|
+
}
|
|
8589
|
+
else {
|
|
8590
|
+
this.embeddingFunction = getDefaultEmbeddingFunction({
|
|
8591
|
+
verbose: this.loggingConfig?.verbose
|
|
8592
|
+
});
|
|
8593
|
+
}
|
|
8522
8594
|
// Set persistent storage request flag
|
|
8523
8595
|
this.requestPersistentStorage =
|
|
8524
8596
|
config.storage?.requestPersistentStorage || false;
|
|
@@ -8557,15 +8629,15 @@ class BrainyData {
|
|
|
8557
8629
|
// Pre-load the embedding model early to ensure it's always available
|
|
8558
8630
|
// This helps prevent issues with the Universal Sentence Encoder not being loaded
|
|
8559
8631
|
try {
|
|
8560
|
-
|
|
8632
|
+
// Pre-loading Universal Sentence Encoder model
|
|
8561
8633
|
// Call embedding function directly to avoid circular dependency with embed()
|
|
8562
8634
|
await this.embeddingFunction('');
|
|
8563
|
-
|
|
8635
|
+
// Universal Sentence Encoder model loaded successfully
|
|
8564
8636
|
}
|
|
8565
8637
|
catch (embedError) {
|
|
8566
8638
|
console.warn('Failed to pre-load Universal Sentence Encoder:', embedError);
|
|
8567
8639
|
// Try again with a retry mechanism
|
|
8568
|
-
|
|
8640
|
+
// Retrying Universal Sentence Encoder initialization
|
|
8569
8641
|
try {
|
|
8570
8642
|
// Wait a moment before retrying
|
|
8571
8643
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
@@ -8947,7 +9019,11 @@ class BrainyData {
|
|
|
8947
9019
|
if (!noun) {
|
|
8948
9020
|
continue;
|
|
8949
9021
|
}
|
|
8950
|
-
|
|
9022
|
+
let metadata = await this.storage.getMetadata(id);
|
|
9023
|
+
// Initialize metadata to an empty object if it's null
|
|
9024
|
+
if (metadata === null) {
|
|
9025
|
+
metadata = {};
|
|
9026
|
+
}
|
|
8951
9027
|
searchResults.push({
|
|
8952
9028
|
id,
|
|
8953
9029
|
score,
|
|
@@ -8983,7 +9059,11 @@ class BrainyData {
|
|
|
8983
9059
|
if (!noun) {
|
|
8984
9060
|
continue;
|
|
8985
9061
|
}
|
|
8986
|
-
|
|
9062
|
+
let metadata = await this.storage.getMetadata(id);
|
|
9063
|
+
// Initialize metadata to an empty object if it's null
|
|
9064
|
+
if (metadata === null) {
|
|
9065
|
+
metadata = {};
|
|
9066
|
+
}
|
|
8987
9067
|
searchResults.push({
|
|
8988
9068
|
id,
|
|
8989
9069
|
score,
|
|
@@ -10316,7 +10396,13 @@ class FileSystemStorage {
|
|
|
10316
10396
|
try {
|
|
10317
10397
|
// Now set up the directory paths
|
|
10318
10398
|
const rootDir = this.rootDir || process.cwd();
|
|
10319
|
-
|
|
10399
|
+
// Check if rootDir already ends with ROOT_DIR to prevent duplication
|
|
10400
|
+
if (rootDir.endsWith(ROOT_DIR)) {
|
|
10401
|
+
this.rootDir = rootDir;
|
|
10402
|
+
}
|
|
10403
|
+
else {
|
|
10404
|
+
this.rootDir = path.resolve(rootDir, ROOT_DIR);
|
|
10405
|
+
}
|
|
10320
10406
|
this.nounsDir = path.join(this.rootDir, NOUNS_DIR);
|
|
10321
10407
|
this.verbsDir = path.join(this.rootDir, VERBS_DIR);
|
|
10322
10408
|
this.metadataDir = path.join(this.rootDir, METADATA_DIR);
|