- Add comprehensive zero-config preset system (production, development, minimal) - Implement intelligent auto-configuration for models and storage - Add Node.js version enforcement for ONNX Runtime stability - Force single-threaded ONNX operations to prevent V8 HandleScope crashes - Create extensible configuration architecture - Add 14 distributed system presets for enterprise deployments - Include detailed documentation and migration guides BREAKING CHANGE: Now requires Node.js 22.x LTS for optimal stability
493 lines
No EOL
13 KiB
Markdown
493 lines
No EOL
13 KiB
Markdown
# Brainy Zero-Config Initiative
|
|
## Strategic Plan for Configuration Simplification
|
|
|
|
Created: 2025-08-29
|
|
Version: 2.9.0 Released with `precision` parameter fix
|
|
|
|
---
|
|
|
|
## 🚨 Current State: Configuration Overload
|
|
|
|
### Problem Scale
|
|
- **60+ configuration options** across 10+ categories
|
|
- **500+ lines of TypeScript interfaces** just for config
|
|
- **Nested configs up to 5 levels deep**
|
|
- Users overwhelmed with choices that should be automatic
|
|
|
|
### Major Issues Discovered
|
|
|
|
1. **`embeddingOptions` doesn't exist!**
|
|
- Used in explorer but not in actual API
|
|
- Should be via `embeddingFunction` with `createEmbeddingFunction()`
|
|
|
|
2. **Storage Confusion**
|
|
- 7+ different storage configurations
|
|
- Complex nested options for S3/GCS/R2
|
|
- No auto-detection from environment
|
|
|
|
3. **Redundant Mode Flags**
|
|
- `readOnly`, `frozen`, `writeOnly`, `lazyLoadInReadOnlyMode`, `allowDirectReads`
|
|
- Too many overlapping concepts
|
|
|
|
4. **Manual Performance Tuning**
|
|
- Users set `batchSize`, `hotCacheMaxSize`, `efConstruction`
|
|
- Should be automatic based on data size and resources
|
|
|
|
---
|
|
|
|
## ✅ What Brainy Already Auto-Detects
|
|
|
|
### Environment & Resources
|
|
- **Environment Type**: Browser vs Node vs Serverless (✅ Working)
|
|
- **Memory Available**: Via `AutoConfiguration` class (✅ Exists)
|
|
- **CPU Cores**: Detected for thread management (✅ Working)
|
|
- **Threading**: Auto-detects worker thread availability (✅ Working)
|
|
- **Storage Type**: Auto-picks OPFS (browser) or filesystem (Node) (✅ Working)
|
|
|
|
### Model & Embedding Management
|
|
- **Default Embedding**: `defaultEmbeddingFunction` works automatically (✅)
|
|
- **Model Downloads**: Auto-downloads on first use (✅ Fixed in 2.7.x)
|
|
- **Model Manager**: Falls back through multiple sources (✅)
|
|
- **Universal Memory Manager**: Auto-selects embedding strategy (✅)
|
|
|
|
### Performance Optimization
|
|
- **HNSW Defaults**: M=16, efConstruction=200 (✅ Set)
|
|
- **Distance Function**: Defaults to cosine (✅)
|
|
- **Dimensions**: Fixed at 384 for all-MiniLM-L6-v2 (✅)
|
|
- **Cache Auto-tuning**: `CacheAutoConfigurator` adapts to usage (✅)
|
|
- **Batch Processing**: Auto-batches operations (✅)
|
|
- **Cleanup**: Periodic cleanup runs automatically (✅)
|
|
|
|
### Augmentations
|
|
- **Default Set**: Core augmentations load automatically (✅)
|
|
- **WAL**: Write-ahead logging for durability (✅)
|
|
- **Connection Pool**: Manages connections automatically (✅)
|
|
- **Entity Registry**: Fast ID lookups (✅)
|
|
- **Request Deduplication**: Prevents duplicate work (✅)
|
|
|
|
---
|
|
|
|
## 🎯 Zero-Config Vision
|
|
|
|
### True Zero Config (Works Today!)
|
|
```typescript
|
|
const brain = new BrainyData()
|
|
await brain.init()
|
|
// ✅ Everything works!
|
|
```
|
|
|
|
**Current Limitations:**
|
|
- Uses memory storage (not persistent)
|
|
- Uses FP32 models (not Q8)
|
|
- Loads all augmentations (might be heavy)
|
|
|
|
### Ideal Minimal Config (Proposed)
|
|
```typescript
|
|
// Option 1: Preset-based
|
|
const brain = new BrainyData('production') // or 'development', 'minimal'
|
|
|
|
// Option 2: Three key decisions
|
|
const brain = new BrainyData({
|
|
storage: 'disk', // or 'memory', 'cloud', auto-detected
|
|
model: 'small', // or 'fast' (q8 vs fp32)
|
|
features: 'default' // or 'minimal', 'full'
|
|
})
|
|
|
|
// Option 3: Even simpler
|
|
const brain = new BrainyData({ mode: 'production' })
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 Implementation Plan
|
|
|
|
### Phase 1: Add Missing Auto-Detection (v2.10)
|
|
|
|
#### 1.1 Storage Auto-Detection
|
|
```typescript
|
|
function autoDetectStorage(): StorageConfig {
|
|
// Check environment variables
|
|
if (process.env.AWS_BUCKET) return { type: 's3', bucket: process.env.AWS_BUCKET }
|
|
if (process.env.GCS_BUCKET) return { type: 'gcs', bucket: process.env.GCS_BUCKET }
|
|
|
|
// Check environment type
|
|
if (isBrowser()) return { type: 'opfs' }
|
|
if (process.env.VERCEL) return { type: 'memory' } // Serverless
|
|
|
|
// Default to filesystem with smart path
|
|
return {
|
|
type: 'filesystem',
|
|
path: process.env.BRAINY_DATA_PATH || './brainy-data'
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 1.2 Model Precision Auto-Selection
|
|
```typescript
|
|
function autoSelectModelPrecision(): 'fp32' | 'q8' {
|
|
const memoryMB = getAvailableMemory() / 1024 / 1024
|
|
|
|
// Use Q8 for constrained environments
|
|
if (isBrowser()) return 'q8'
|
|
if (memoryMB < 512) return 'q8'
|
|
if (process.env.BRAINY_MODEL === 'small') return 'q8'
|
|
|
|
return 'fp32' // Default to full precision
|
|
}
|
|
```
|
|
|
|
#### 1.3 Feature Level Auto-Configuration
|
|
```typescript
|
|
function autoConfigureFeatures(): FeatureLevel {
|
|
// Minimal for browsers and serverless
|
|
if (isBrowser() || isServerless()) return 'minimal'
|
|
|
|
// Full for development
|
|
if (process.env.NODE_ENV === 'development') return 'full'
|
|
|
|
// Default for production
|
|
return 'default'
|
|
}
|
|
```
|
|
|
|
### Phase 2: Simplify Config Interface (v3.0)
|
|
|
|
#### 2.1 New Simple Config
|
|
```typescript
|
|
export interface BrainyConfig {
|
|
// Just 3-5 top-level options
|
|
mode?: 'development' | 'production' | 'minimal'
|
|
storage?: 'auto' | 'memory' | 'disk' | 'cloud' | StorageConfig
|
|
model?: 'fast' | 'small' | 'auto' | ModelConfig
|
|
features?: 'minimal' | 'default' | 'full' | string[]
|
|
|
|
// Everything else hidden
|
|
advanced?: LegacyConfig
|
|
}
|
|
```
|
|
|
|
#### 2.2 Mode Presets
|
|
```typescript
|
|
const PRESETS = {
|
|
development: {
|
|
storage: 'memory',
|
|
model: 'fast',
|
|
features: 'full',
|
|
logging: { verbose: true }
|
|
},
|
|
production: {
|
|
storage: 'disk',
|
|
model: 'auto',
|
|
features: 'default',
|
|
logging: { verbose: false }
|
|
},
|
|
minimal: {
|
|
storage: 'memory',
|
|
model: 'small',
|
|
features: 'minimal',
|
|
logging: { verbose: false }
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 2.3 Smart Defaults by Environment
|
|
```typescript
|
|
constructor(config?: string | BrainyConfig) {
|
|
// String shorthand
|
|
if (typeof config === 'string') {
|
|
this.config = PRESETS[config]
|
|
return
|
|
}
|
|
|
|
// Auto-detect everything if no config
|
|
if (!config) {
|
|
config = {
|
|
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development'
|
|
}
|
|
}
|
|
|
|
// Expand simple config to full config
|
|
this.config = expandConfig(config)
|
|
}
|
|
```
|
|
|
|
### Phase 3: Intelligent Resource Adaptation (v3.1)
|
|
|
|
#### 3.1 Dynamic Performance Tuning
|
|
```typescript
|
|
class ResourceAdaptiveConfig {
|
|
async adapt() {
|
|
const resources = await detectResources()
|
|
|
|
// Auto-configure based on available resources
|
|
if (resources.memoryGB > 8) {
|
|
this.enableFeature('aggressive-caching')
|
|
this.setHNSW({ M: 32, efConstruction: 400 })
|
|
} else if (resources.memoryGB < 1) {
|
|
this.enableFeature('minimal-memory')
|
|
this.setHNSW({ M: 8, efConstruction: 100 })
|
|
}
|
|
|
|
// Adapt to data size
|
|
const dataSize = await this.estimateDataSize()
|
|
if (dataSize > 1_000_000) {
|
|
this.enableFeature('partitioned-index')
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 3.2 Usage-Based Optimization
|
|
```typescript
|
|
class UsageOptimizer {
|
|
async optimizeFromUsage() {
|
|
const patterns = await this.analyzeUsagePatterns()
|
|
|
|
if (patterns.readWriteRatio > 10) {
|
|
// Read-heavy: optimize for search
|
|
this.config.cache.size = 'large'
|
|
this.config.index.eager = true
|
|
} else if (patterns.readWriteRatio < 0.1) {
|
|
// Write-heavy: optimize for ingestion
|
|
this.config.batch.size = 'large'
|
|
this.config.index.lazy = true
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 Required Changes
|
|
|
|
### Immediate (v2.10)
|
|
1. **Add `embeddingOptions` support** or document correct usage
|
|
2. **Fix storage auto-detection** from environment variables
|
|
3. **Add model precision auto-selection**
|
|
4. **Create preset system** for common configurations
|
|
|
|
### Short-term (v3.0)
|
|
1. **New simplified config interface** with backward compatibility
|
|
2. **Mode-based presets** (development/production/minimal)
|
|
3. **Deprecation warnings** for complex configs
|
|
4. **Migration guide** from old to new config
|
|
|
|
### Long-term (v3.1+)
|
|
1. **Full resource adaptation** based on runtime environment
|
|
2. **Usage-based optimization** that learns from patterns
|
|
3. **Cloud config service** for centralized configuration
|
|
4. **Zero-config by default** with optional overrides
|
|
|
|
---
|
|
|
|
## 📊 Success Metrics
|
|
|
|
### Developer Experience
|
|
- **Time to first query**: < 30 seconds (from npm install)
|
|
- **Lines of config**: 0-5 (vs current 50+)
|
|
- **Documentation needed**: 1 page (vs current 10+)
|
|
|
|
### Performance
|
|
- **Auto-config performance**: Within 10% of manual tuning
|
|
- **Resource usage**: Automatically optimized for environment
|
|
- **Startup time**: < 2 seconds with auto-config
|
|
|
|
### Adoption
|
|
- **Zero-config usage**: > 80% of new projects
|
|
- **Migration rate**: > 50% of existing projects in 6 months
|
|
- **Support tickets**: 50% reduction in config-related issues
|
|
|
|
---
|
|
|
|
## 🚀 Next Steps
|
|
|
|
1. **Release v2.9.0** ✅ DONE - Fixed precision parameter
|
|
2. **Create feature flag** for new config system
|
|
3. **Implement auto-detection** functions
|
|
4. **Test in different environments** (browser, serverless, Node)
|
|
5. **Document migration path** from complex to simple config
|
|
6. **Release v2.10** with auto-detection
|
|
7. **Gather feedback** and iterate
|
|
8. **Release v3.0** with new config interface
|
|
|
|
---
|
|
|
|
## 📝 Notes
|
|
|
|
### What Makes Config Complex
|
|
- **Too many choices** that could be automatic
|
|
- **Nested structures** that hide important options
|
|
- **Unclear relationships** between options
|
|
- **Manual tuning** of performance parameters
|
|
- **Environment-specific** configurations
|
|
|
|
### What Users Actually Need
|
|
1. **Where to store data** (99% just want persistence)
|
|
2. **How fast vs how small** (model tradeoff)
|
|
3. **Feature level** (minimal/default/full)
|
|
|
|
Everything else should be automatic!
|
|
|
|
### Key Insight
|
|
> "The best configuration is no configuration. The second best is one that fits in a tweet."
|
|
|
|
Most users just want:
|
|
```typescript
|
|
const brain = new BrainyData({ mode: 'production' })
|
|
```
|
|
|
|
And everything else should just work perfectly.
|
|
|
|
---
|
|
|
|
## 🔍 Deep Codebase Analysis Results
|
|
|
|
### Environment Detection Already Available
|
|
```typescript
|
|
// src/utils/environment.ts
|
|
- isBrowser() ✅
|
|
- isNode() ✅
|
|
- isWebWorker() ✅
|
|
- isProductionEnvironment() ✅ (checks NODE_ENV, K_SERVICE, GOOGLE_CLOUD_PROJECT)
|
|
- areWorkerThreadsAvailable() ✅
|
|
- checkWebGPUSupport() ✅
|
|
|
|
// Serverless detection (src/embeddings/universal-memory-manager.ts)
|
|
- VERCEL ✅
|
|
- NETLIFY ✅
|
|
- AWS_LAMBDA_FUNCTION_NAME ✅
|
|
- FUNCTIONS_WORKER_RUNTIME ✅
|
|
```
|
|
|
|
### Resource Detection Capabilities
|
|
```typescript
|
|
// src/utils/autoConfiguration.ts - EXISTS but NOT USED!
|
|
class AutoConfiguration {
|
|
detectEnvironment() ✅
|
|
detectResources() ✅ // CPU cores, memory
|
|
detectStorageCapabilities() ✅
|
|
generateRecommendedConfig() ✅
|
|
adaptToDataset() ✅
|
|
}
|
|
|
|
// src/utils/cacheAutoConfig.ts - ACTIVELY USED
|
|
class CacheAutoConfigurator {
|
|
autoDetectOptimalConfig() ✅
|
|
adaptConfiguration() ✅ // Runtime adaptation
|
|
detectEnvironment() ✅
|
|
}
|
|
```
|
|
|
|
### Environment Variables Already Checked
|
|
```typescript
|
|
// Model paths
|
|
BRAINY_MODELS_PATH ✅
|
|
BRAINY_ALLOW_REMOTE_MODELS ✅
|
|
BRAINY_Q8_CONFIRMED ✅
|
|
|
|
// Distributed mode
|
|
BRAINY_ROLE ✅ (writer/reader/hybrid)
|
|
SERVICE_ENDPOINT ✅
|
|
|
|
// Cloud storage
|
|
AWS_ACCESS_KEY_ID ✅ (but only in scaledHNSWSystem)
|
|
AWS_SECRET_ACCESS_KEY ✅
|
|
AWS_LAMBDA_FUNCTION_NAME ✅
|
|
|
|
// Environment
|
|
NODE_ENV ✅
|
|
K_SERVICE ✅ (Google Cloud Run)
|
|
GOOGLE_CLOUD_PROJECT ✅
|
|
VERCEL ✅
|
|
NETLIFY ✅
|
|
|
|
// Memory optimization
|
|
ORT_DISABLE_MEMORY_ARENA ✅
|
|
```
|
|
|
|
### Storage Auto-Detection MISSING
|
|
```typescript
|
|
// createStorage() in storageFactory.ts
|
|
// Currently requires explicit type specification
|
|
// NO auto-detection from environment!
|
|
|
|
// What we need to add:
|
|
function autoDetectStorageType(): StorageType {
|
|
// Check cloud providers
|
|
if (process.env.AWS_BUCKET || process.env.AWS_ACCESS_KEY_ID) return 's3'
|
|
if (process.env.GCS_BUCKET || process.env.GOOGLE_APPLICATION_CREDENTIALS) return 'gcs'
|
|
if (process.env.AZURE_STORAGE_ACCOUNT) return 'azure'
|
|
|
|
// Check environment
|
|
if (isBrowser()) return 'opfs'
|
|
if (process.env.VERCEL || process.env.NETLIFY) return 'memory'
|
|
|
|
// Default to filesystem
|
|
return 'filesystem'
|
|
}
|
|
```
|
|
|
|
### The BIG Discovery: AutoConfiguration EXISTS but UNUSED!
|
|
```typescript
|
|
// src/utils/autoConfiguration.ts
|
|
// COMPLETE auto-configuration system already built!
|
|
// But NEVER called from BrainyData constructor!
|
|
|
|
// It can detect:
|
|
- Environment (browser/nodejs/serverless)
|
|
- Available memory
|
|
- CPU cores
|
|
- Threading availability
|
|
- Storage capabilities
|
|
- S3 availability
|
|
- Recommended HNSW params
|
|
- Optimization flags
|
|
|
|
// But it's just sitting there unused! 😱
|
|
```
|
|
|
|
### What Needs to be Connected
|
|
|
|
1. **Wire up AutoConfiguration in constructor**
|
|
```typescript
|
|
constructor(config?: BrainyConfig) {
|
|
if (!config) {
|
|
// Use the existing AutoConfiguration!
|
|
const autoConfig = await AutoConfiguration.getInstance().detectAndConfigure()
|
|
config = this.convertAutoConfigToBrainyConfig(autoConfig)
|
|
}
|
|
}
|
|
```
|
|
|
|
2. **Add embedding options to config**
|
|
```typescript
|
|
// Currently embeddingOptions doesn't exist in BrainyDataConfig
|
|
// But explorer uses it!
|
|
interface BrainyDataConfig {
|
|
embeddingOptions?: {
|
|
precision?: 'fp32' | 'q8'
|
|
modelCachePath?: string
|
|
}
|
|
}
|
|
```
|
|
|
|
3. **Create preset system**
|
|
```typescript
|
|
const PRESETS = {
|
|
'zero': {}, // True zero config
|
|
'production': { storage: 'disk', model: 'q8', features: 'default' },
|
|
'development': { storage: 'memory', model: 'fp32', features: 'full' },
|
|
'serverless': { storage: 'memory', model: 'q8', features: 'minimal' }
|
|
}
|
|
```
|
|
|
|
### The Path Forward is Clear!
|
|
|
|
**90% of the auto-detection code already exists!** We just need to:
|
|
1. Connect AutoConfiguration to BrainyData constructor
|
|
2. Add embeddingOptions to config interface
|
|
3. Create preset system
|
|
4. Add storage auto-detection from env vars
|
|
5. Wire model precision to embedding function creation
|
|
|
|
This could literally be done in < 200 lines of code! |