@soulcraft/brainy 3.35.0 → 3.36.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.
- package/CHANGELOG.md +62 -0
- package/README.md +32 -12
- package/dist/hnsw/hnswIndex.d.ts +104 -1
- package/dist/hnsw/hnswIndex.js +282 -25
- package/dist/hnsw/hnswIndexOptimized.d.ts +1 -2
- package/dist/hnsw/hnswIndexOptimized.js +3 -5
- package/dist/hnsw/partitionedHNSWIndex.js +1 -1
- package/dist/interfaces/IIndex.d.ts +14 -5
- package/dist/storage/adapters/gcsStorage.js +15 -5
- package/dist/utils/memoryDetection.d.ts +119 -0
- package/dist/utils/memoryDetection.js +321 -0
- package/dist/utils/unifiedCache.d.ts +75 -1
- package/dist/utils/unifiedCache.js +123 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,68 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [3.36.1](https://github.com/soulcraftlabs/brainy/compare/v3.36.0...v3.36.1) (2025-10-10)
|
|
6
|
+
|
|
7
|
+
- fix: resolve critical GCS storage bugs preventing production use (3cd0b9a)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### [3.36.0](https://github.com/soulcraftlabs/brainy/compare/v3.35.0...v3.36.0) (2025-10-10)
|
|
11
|
+
|
|
12
|
+
#### 🚀 Always-Adaptive Caching with Enhanced Monitoring
|
|
13
|
+
|
|
14
|
+
**Zero Breaking Changes** - Internal optimizations with automatic performance improvements
|
|
15
|
+
|
|
16
|
+
#### What's New
|
|
17
|
+
|
|
18
|
+
- **Renamed API**: `getLazyModeStats()` → `getCacheStats()` (backward compatible)
|
|
19
|
+
- **Enhanced Metrics**: Changed `lazyModeEnabled: boolean` → `cachingStrategy: 'preloaded' | 'on-demand'`
|
|
20
|
+
- **Improved Thresholds**: Updated preloading threshold from 30% to 80% for better cache utilization
|
|
21
|
+
- **Better Terminology**: Eliminated "lazy mode" concept in favor of "adaptive caching strategy"
|
|
22
|
+
- **Production Monitoring**: Comprehensive diagnostics for capacity planning and tuning
|
|
23
|
+
|
|
24
|
+
#### Benefits
|
|
25
|
+
|
|
26
|
+
- ✅ **Clearer Semantics**: "preloaded" vs "on-demand" instead of confusing "lazy mode enabled/disabled"
|
|
27
|
+
- ✅ **Better Cache Utilization**: 80% threshold maximizes memory usage before switching to on-demand
|
|
28
|
+
- ✅ **Enhanced Monitoring**: `getCacheStats()` provides actionable insights for production deployments
|
|
29
|
+
- ✅ **Backward Compatible**: Deprecated `lazy` option still accepted (ignored, always adaptive)
|
|
30
|
+
- ✅ **Zero Config**: System automatically chooses optimal strategy based on dataset size and available memory
|
|
31
|
+
|
|
32
|
+
#### API Changes
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// New API (recommended)
|
|
36
|
+
const stats = brain.hnsw.getCacheStats()
|
|
37
|
+
console.log(`Strategy: ${stats.cachingStrategy}`) // 'preloaded' or 'on-demand'
|
|
38
|
+
console.log(`Hit Rate: ${stats.unifiedCache.hitRatePercent}%`)
|
|
39
|
+
console.log(`Recommendations: ${stats.recommendations.join(', ')}`)
|
|
40
|
+
|
|
41
|
+
// Old API (deprecated but still works)
|
|
42
|
+
const oldStats = brain.hnsw.getLazyModeStats() // Returns same data
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### Documentation Updates
|
|
46
|
+
|
|
47
|
+
- Added comprehensive migration guide: `docs/guides/migration-3.36.0.md`
|
|
48
|
+
- Added operations guide: `docs/operations/capacity-planning.md`
|
|
49
|
+
- Updated architecture docs with new terminology
|
|
50
|
+
- Renamed example: `monitor-lazy-mode.ts` → `monitor-cache-performance.ts`
|
|
51
|
+
|
|
52
|
+
#### Files Changed
|
|
53
|
+
|
|
54
|
+
- `src/hnsw/hnswIndex.ts`: Core adaptive caching improvements
|
|
55
|
+
- `src/interfaces/IIndex.ts`: Updated interface documentation
|
|
56
|
+
- `docs/guides/migration-3.36.0.md`: Complete migration guide
|
|
57
|
+
- `docs/operations/capacity-planning.md`: Enterprise operations guide
|
|
58
|
+
- `examples/monitor-cache-performance.ts`: Production monitoring example
|
|
59
|
+
- All documentation updated to reflect new terminology
|
|
60
|
+
|
|
61
|
+
#### Migration
|
|
62
|
+
|
|
63
|
+
**No action required!** All changes are backward compatible. Update your code to use `getCacheStats()` when convenient.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
5
67
|
### [3.35.0](https://github.com/soulcraftlabs/brainy/compare/v3.34.0...v3.35.0) (2025-10-10)
|
|
6
68
|
|
|
7
69
|
- feat: implement HNSW index rebuild and unified index interface (6a4d1ae)
|
package/README.md
CHANGED
|
@@ -19,6 +19,32 @@
|
|
|
19
19
|
|
|
20
20
|
## 🎉 Key Features
|
|
21
21
|
|
|
22
|
+
### ⚡ **NEW in 3.36.0: Production-Scale Memory & Performance**
|
|
23
|
+
|
|
24
|
+
**Enterprise-grade adaptive sizing and zero-overhead optimizations:**
|
|
25
|
+
|
|
26
|
+
- **🎯 Adaptive Memory Sizing**: Auto-scales from 2GB to 128GB+ based on available system resources
|
|
27
|
+
- Container-aware (Docker/K8s cgroups v1/v2 detection)
|
|
28
|
+
- Environment-smart (development 25%, container 40%, production 50% allocation)
|
|
29
|
+
- Model memory accounting (150MB Q8, 250MB FP32 reserved before cache)
|
|
30
|
+
|
|
31
|
+
- **⚡ Sync Fast Path**: Zero async overhead when vectors are cached
|
|
32
|
+
- Intelligent sync/async branching - synchronous when data is in memory
|
|
33
|
+
- Falls back to async only when loading from storage
|
|
34
|
+
- Massive performance win for hot paths (vector search, distance calculations)
|
|
35
|
+
|
|
36
|
+
- **📊 Production Monitoring**: Comprehensive diagnostics
|
|
37
|
+
- `getCacheStats()` - UnifiedCache hit rates, fairness metrics, memory pressure
|
|
38
|
+
- Actionable recommendations for tuning
|
|
39
|
+
- Tracks model memory, cache efficiency, and competition across indexes
|
|
40
|
+
|
|
41
|
+
- **🛡️ Zero Breaking Changes**: All optimizations are internal - your code stays the same
|
|
42
|
+
- Public API unchanged
|
|
43
|
+
- Automatic memory detection and allocation
|
|
44
|
+
- Progressive enhancement for existing applications
|
|
45
|
+
|
|
46
|
+
**[📖 Operations Guide →](docs/operations/capacity-planning.md)** | **[🎯 Migration Guide →](docs/guides/migration-3.36.0.md)**
|
|
47
|
+
|
|
22
48
|
### 🚀 **NEW in 3.21.0: Enhanced Import & Neural Processing**
|
|
23
49
|
|
|
24
50
|
- **📊 Progress Tracking**: Unified progress reporting with automatic time estimation
|
|
@@ -38,7 +64,7 @@
|
|
|
38
64
|
|
|
39
65
|
- **Modern Syntax**: `brain.add()`, `brain.find()`, `brain.relate()`
|
|
40
66
|
- **Type Safety**: Full TypeScript integration
|
|
41
|
-
- **Zero Config**: Works out of the box with
|
|
67
|
+
- **Zero Config**: Works out of the box with intelligent storage auto-detection
|
|
42
68
|
- **Consistent Parameters**: Clean, predictable API surface
|
|
43
69
|
|
|
44
70
|
### ⚡ **Performance & Reliability**
|
|
@@ -352,7 +378,7 @@ const brain = new Brainy()
|
|
|
352
378
|
|
|
353
379
|
// 2. Custom configuration
|
|
354
380
|
const brain = new Brainy({
|
|
355
|
-
storage: { type: '
|
|
381
|
+
storage: { type: 'filesystem', path: './brainy-data' },
|
|
356
382
|
embeddings: { model: 'all-MiniLM-L6-v2' },
|
|
357
383
|
cache: { enabled: true, maxSize: 1000 }
|
|
358
384
|
})
|
|
@@ -368,7 +394,7 @@ const customBrain = new Brainy({
|
|
|
368
394
|
|
|
369
395
|
**What's Auto-Detected:**
|
|
370
396
|
|
|
371
|
-
- **Storage**: S3/GCS/R2 → Filesystem
|
|
397
|
+
- **Storage**: S3/GCS/R2 → Filesystem (priority order)
|
|
372
398
|
- **Models**: Always Q8 for optimal balance
|
|
373
399
|
- **Features**: Minimal → Default → Full based on environment
|
|
374
400
|
- **Memory**: Optimal cache sizes and batching
|
|
@@ -390,13 +416,12 @@ Most users **never need this** - zero-config handles everything. For advanced us
|
|
|
390
416
|
const brain = new Brainy() // Uses Q8 automatically
|
|
391
417
|
|
|
392
418
|
// Storage control (auto-detected by default)
|
|
393
|
-
const
|
|
394
|
-
const diskBrain = new Brainy({storage: 'disk'}) // Local filesystem
|
|
419
|
+
const diskBrain = new Brainy({storage: 'disk'}) // Local filesystem
|
|
395
420
|
const cloudBrain = new Brainy({storage: 'cloud'}) // S3/GCS/R2
|
|
396
421
|
|
|
397
422
|
// Legacy full config (still supported)
|
|
398
423
|
const legacyBrain = new Brainy({
|
|
399
|
-
storage: {
|
|
424
|
+
storage: {type: 'filesystem', path: './data'}
|
|
400
425
|
})
|
|
401
426
|
```
|
|
402
427
|
|
|
@@ -665,12 +690,7 @@ const context = await brain.find({
|
|
|
665
690
|
Brainy supports multiple storage backends:
|
|
666
691
|
|
|
667
692
|
```javascript
|
|
668
|
-
//
|
|
669
|
-
const brain = new Brainy({
|
|
670
|
-
storage: {type: 'memory'}
|
|
671
|
-
})
|
|
672
|
-
|
|
673
|
-
// FileSystem (Node.js)
|
|
693
|
+
// FileSystem (Node.js - recommended for development)
|
|
674
694
|
const brain = new Brainy({
|
|
675
695
|
storage: {
|
|
676
696
|
type: 'filesystem',
|
package/dist/hnsw/hnswIndex.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare class HNSWIndex {
|
|
|
15
15
|
private dimension;
|
|
16
16
|
private useParallelization;
|
|
17
17
|
private storage;
|
|
18
|
+
private unifiedCache;
|
|
18
19
|
constructor(config?: Partial<HNSWConfig>, distanceFunction?: DistanceFunction, options?: {
|
|
19
20
|
useParallelization?: boolean;
|
|
20
21
|
storage?: BaseStorage;
|
|
@@ -48,7 +49,7 @@ export declare class HNSWIndex {
|
|
|
48
49
|
/**
|
|
49
50
|
* Remove an item from the index
|
|
50
51
|
*/
|
|
51
|
-
removeItem(id: string): boolean
|
|
52
|
+
removeItem(id: string): Promise<boolean>;
|
|
52
53
|
/**
|
|
53
54
|
* Get all nouns in the index
|
|
54
55
|
* @deprecated Use getNounsPaginated() instead for better scalability
|
|
@@ -96,6 +97,60 @@ export declare class HNSWIndex {
|
|
|
96
97
|
* Get the configuration
|
|
97
98
|
*/
|
|
98
99
|
getConfig(): HNSWConfig;
|
|
100
|
+
/**
|
|
101
|
+
* Get vector safely (always uses adaptive caching via UnifiedCache)
|
|
102
|
+
*
|
|
103
|
+
* Production-grade adaptive caching (v3.36.0+):
|
|
104
|
+
* - Vector already loaded: Returns immediately (O(1))
|
|
105
|
+
* - Vector in cache: Loads from UnifiedCache (O(1) hash lookup)
|
|
106
|
+
* - Vector on disk: Loads from storage → UnifiedCache (O(disk))
|
|
107
|
+
* - Cost-aware caching: UnifiedCache manages memory competition
|
|
108
|
+
*
|
|
109
|
+
* @param noun The HNSW noun (may have empty vector if not yet loaded)
|
|
110
|
+
* @returns Promise<Vector> The vector (loaded on-demand if needed)
|
|
111
|
+
*/
|
|
112
|
+
private getVectorSafe;
|
|
113
|
+
/**
|
|
114
|
+
* Get vector synchronously if available in memory (v3.36.0+)
|
|
115
|
+
*
|
|
116
|
+
* Sync fast path optimization:
|
|
117
|
+
* - Vector in memory: Returns immediately (zero overhead)
|
|
118
|
+
* - Vector in cache: Returns from UnifiedCache synchronously
|
|
119
|
+
* - Returns null if vector not available (caller must handle async path)
|
|
120
|
+
*
|
|
121
|
+
* Use for sync fast path in distance calculations - eliminates async overhead
|
|
122
|
+
* when vectors are already cached.
|
|
123
|
+
*
|
|
124
|
+
* @param noun The HNSW noun
|
|
125
|
+
* @returns Vector | null - vector if in memory/cache, null if needs async load
|
|
126
|
+
*/
|
|
127
|
+
private getVectorSync;
|
|
128
|
+
/**
|
|
129
|
+
* Preload multiple vectors in parallel via UnifiedCache
|
|
130
|
+
*
|
|
131
|
+
* Optimization for search operations:
|
|
132
|
+
* - Loads all candidate vectors before distance calculations
|
|
133
|
+
* - Reduces serial disk I/O (parallel loads are faster)
|
|
134
|
+
* - Uses UnifiedCache's request coalescing to prevent stampede
|
|
135
|
+
* - Always active (no "mode" check) for optimal performance
|
|
136
|
+
*
|
|
137
|
+
* @param nodeIds Array of node IDs to preload
|
|
138
|
+
*/
|
|
139
|
+
private preloadVectors;
|
|
140
|
+
/**
|
|
141
|
+
* Calculate distance with sync fast path (v3.36.0+)
|
|
142
|
+
*
|
|
143
|
+
* Eliminates async overhead when vectors are in memory:
|
|
144
|
+
* - Sync path: Vector in memory → returns number (zero overhead)
|
|
145
|
+
* - Async path: Vector needs loading → returns Promise<number>
|
|
146
|
+
*
|
|
147
|
+
* Callers must handle union type: `const dist = await Promise.resolve(distance)`
|
|
148
|
+
*
|
|
149
|
+
* @param queryVector The query vector
|
|
150
|
+
* @param noun The target noun (may have empty vector in lazy mode)
|
|
151
|
+
* @returns number | Promise<number> - sync when cached, async when needs load
|
|
152
|
+
*/
|
|
153
|
+
private distanceSafe;
|
|
99
154
|
/**
|
|
100
155
|
* Get all nodes at a specific level for clustering
|
|
101
156
|
* This enables O(n) clustering using HNSW's natural hierarchy
|
|
@@ -139,6 +194,54 @@ export declare class HNSWIndex {
|
|
|
139
194
|
maxLayer: number;
|
|
140
195
|
totalNodes: number;
|
|
141
196
|
};
|
|
197
|
+
/**
|
|
198
|
+
* Get cache performance statistics for monitoring and diagnostics (v3.36.0+)
|
|
199
|
+
*
|
|
200
|
+
* Production-grade monitoring:
|
|
201
|
+
* - Adaptive caching strategy (preloading vs on-demand)
|
|
202
|
+
* - UnifiedCache performance (hits, misses, evictions)
|
|
203
|
+
* - HNSW-specific cache statistics
|
|
204
|
+
* - Fair competition metrics across all indexes
|
|
205
|
+
* - Actionable recommendations for tuning
|
|
206
|
+
*
|
|
207
|
+
* Use this to:
|
|
208
|
+
* - Diagnose performance issues (low hit rate = increase cache)
|
|
209
|
+
* - Monitor memory competition (fairness violations = adjust costs)
|
|
210
|
+
* - Verify adaptive caching decisions (memory estimates vs actual)
|
|
211
|
+
* - Track cache efficiency over time
|
|
212
|
+
*
|
|
213
|
+
* @returns Comprehensive caching and performance statistics
|
|
214
|
+
*/
|
|
215
|
+
getCacheStats(): {
|
|
216
|
+
cachingStrategy: 'preloaded' | 'on-demand';
|
|
217
|
+
autoDetection: {
|
|
218
|
+
entityCount: number;
|
|
219
|
+
estimatedVectorMemoryMB: number;
|
|
220
|
+
availableCacheMB: number;
|
|
221
|
+
threshold: number;
|
|
222
|
+
rationale: string;
|
|
223
|
+
};
|
|
224
|
+
unifiedCache: {
|
|
225
|
+
totalSize: number;
|
|
226
|
+
maxSize: number;
|
|
227
|
+
utilizationPercent: number;
|
|
228
|
+
itemCount: number;
|
|
229
|
+
hitRatePercent: number;
|
|
230
|
+
totalAccessCount: number;
|
|
231
|
+
};
|
|
232
|
+
hnswCache: {
|
|
233
|
+
vectorsInCache: number;
|
|
234
|
+
cacheKeyPrefix: string;
|
|
235
|
+
estimatedMemoryMB: number;
|
|
236
|
+
};
|
|
237
|
+
fairness: {
|
|
238
|
+
hnswAccessCount: number;
|
|
239
|
+
hnswAccessPercent: number;
|
|
240
|
+
totalAccessCount: number;
|
|
241
|
+
fairnessViolation: boolean;
|
|
242
|
+
};
|
|
243
|
+
recommendations: string[];
|
|
244
|
+
};
|
|
142
245
|
/**
|
|
143
246
|
* Search within a specific layer
|
|
144
247
|
* Returns a map of noun IDs to distances, sorted by distance
|