From e6769d6d9f1dd2b8faeaa8933af4ed2a2ca06fe3 Mon Sep 17 00:00:00 2001 From: David Snelling Date: Thu, 18 Dec 2025 10:31:02 -0800 Subject: [PATCH] fix: remove dead model config code for true zero-config - Remove unused model.type validation that caused Workshop error - Remove model config from BrainyConfig type (never used) - Simplify modelAutoConfig.ts (always Q8 WASM) - Clean up zeroConfig.ts model references This fixes the "Invalid model type: balanced" error and removes unnecessary configuration options that did nothing. --- src/brainy.ts | 7 -- src/config/index.ts | 14 +--- src/config/modelAutoConfig.ts | 129 +++++------------------------- src/config/sharedConfigManager.ts | 3 +- src/config/zeroConfig.ts | 38 +++------ src/types/brainy.types.ts | 9 +-- 6 files changed, 37 insertions(+), 163 deletions(-) diff --git a/src/brainy.ts b/src/brainy.ts index 3f73de5c..e39262a1 100644 --- a/src/brainy.ts +++ b/src/brainy.ts @@ -177,7 +177,6 @@ export class Brainy implements BrainyInterface { ...this.config, ...configOverrides, storage: { ...this.config.storage, ...configOverrides.storage }, - model: { ...this.config.model, ...configOverrides.model }, index: { ...this.config.index, ...configOverrides.index }, augmentations: { ...this.config.augmentations, ...configOverrides.augmentations }, verbose: configOverrides.verbose ?? this.config.verbose, @@ -4972,11 +4971,6 @@ export class Brainy implements BrainyInterface { // Both 'gcs' and 'gcs-native' can now use either gcsStorage or gcsNativeStorage } - // Validate model configuration - if (config?.model?.type && !['fast', 'accurate', 'custom'].includes(config.model.type)) { - throw new Error(`Invalid model type: ${config.model.type}. Must be one of: fast, accurate, custom`) - } - // Validate numeric configurations if (config?.index?.m && (config.index.m < 1 || config.index.m > 128)) { throw new Error(`Invalid index m parameter: ${config.index.m}. Must be between 1 and 128`) @@ -4995,7 +4989,6 @@ export class Brainy implements BrainyInterface { return { storage: config?.storage || { type: 'auto' }, - model: config?.model || { type: 'fast' }, index: config?.index || {}, cache: config?.cache ?? true, augmentations: config?.augmentations || {}, diff --git a/src/config/index.ts b/src/config/index.ts index b52790ea..7d7309a8 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -3,19 +3,13 @@ * Main entry point for all auto-configuration features */ -// Model configuration -export { - autoSelectModelPrecision, - ModelPrecision as ModelPrecisionType, // Avoid conflict - ModelPreset, +// Model configuration (simplified - always Q8 WASM) +export { + getModelPrecision, shouldAutoDownloadModels, - getModelPath, - logModelConfig + getModelPath } from './modelAutoConfig.js' -// Model precision - Always Q8 now (99% accuracy, 75% smaller) -export const getModelPrecision = () => 'q8' as const - // Storage configuration export { autoDetectStorage, diff --git a/src/config/modelAutoConfig.ts b/src/config/modelAutoConfig.ts index fff9aa09..120e3c76 100644 --- a/src/config/modelAutoConfig.ts +++ b/src/config/modelAutoConfig.ts @@ -1,49 +1,24 @@ /** - * Model Configuration Auto-Selection - * Always uses Q8 for optimal size/performance balance (99% accuracy, 75% smaller) + * Model Configuration + * Brainy uses Q8 WASM embeddings - no configuration needed (zero-config) */ import { isBrowser, isNode } from '../utils/environment.js' -export type ModelPrecision = 'q8' -export type ModelPreset = 'small' | 'auto' - interface ModelConfigResult { - precision: ModelPrecision + precision: 'q8' reason: string autoSelected: boolean } /** - * Auto-select model precision - Always returns Q8 - * Q8 provides 99% accuracy with 75% smaller size - * @param override - For backward compatibility, ignored + * Get model precision configuration + * Always returns Q8 - the optimal balance of size and accuracy */ -export function autoSelectModelPrecision(override?: ModelPrecision | ModelPreset): ModelConfigResult { - // Always use Q8 regardless of override for simplicity - // Q8 is optimal: 33MB vs 130MB, 99% accuracy retained - - // Log deprecation notice if FP32 was requested - if (typeof override === 'string' && override.toLowerCase().includes('fp32')) { - console.log('Note: FP32 precision is deprecated. Using Q8 (99% accuracy, 75% smaller).') - } - +export function getModelPrecision(): ModelConfigResult { return { precision: 'q8', - reason: 'Q8 precision (99% accuracy, 75% smaller)', - autoSelected: true - } -} - -/** - * Automatically detect the best model precision for the environment - * DEPRECATED: Always returns Q8 now - */ -function autoDetectBestPrecision(): ModelConfigResult { - // Always return Q8 - deprecated function kept for backward compatibility - return { - precision: 'q8', - reason: 'Q8 precision (99% accuracy, 75% smaller)', + reason: 'Q8 WASM (23MB bundled, no downloads)', autoSelected: true } } @@ -53,7 +28,7 @@ function autoDetectBestPrecision(): ModelConfigResult { */ function isServerlessEnvironment(): boolean { if (!isNode()) return false - + return !!( process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.VERCEL || @@ -65,104 +40,42 @@ function isServerlessEnvironment(): boolean { } /** - * Get available memory in MB - */ -function getAvailableMemoryMB(): number { - if (isBrowser()) { - // @ts-ignore - navigator.deviceMemory is experimental - if (navigator.deviceMemory) { - // @ts-ignore - return navigator.deviceMemory * 1024 // Device memory in GB - } - return 256 // Conservative default for browsers - } - - if (isNode()) { - try { - // Try to get memory info synchronously for Node.js - // This will be available in Node.js environments - if (typeof process !== 'undefined' && process.memoryUsage) { - // Use RSS (Resident Set Size) as a proxy for available memory - const rss = process.memoryUsage().rss - // Assume we can use up to 4GB or 50% more than current usage - return Math.min(4096, Math.floor(rss / (1024 * 1024) * 1.5)) - } - } catch { - // Fall through to default - } - return 1024 // Default 1GB for Node.js - } - - return 512 // Conservative default -} - -/** - * Convenience function to check if models need to be downloaded - * This replaces the need for BRAINY_ALLOW_REMOTE_MODELS + * Check if models need to be downloaded + * With bundled WASM model, this is rarely needed */ export function shouldAutoDownloadModels(): boolean { - // Always allow downloads unless explicitly disabled - // This eliminates the need for BRAINY_ALLOW_REMOTE_MODELS + // Model is bundled - no downloads needed in normal operation + // This flag exists for edge cases only const explicitlyDisabled = process.env.BRAINY_ALLOW_REMOTE_MODELS === 'false' - - if (explicitlyDisabled) { - console.warn('Model downloads disabled via BRAINY_ALLOW_REMOTE_MODELS=false') - return false - } - - // In production, always allow downloads for seamless operation - if (process.env.NODE_ENV === 'production') { - return true - } - - // In development, allow downloads with a one-time notice - if (process.env.NODE_ENV === 'development') { - return true - } - - // Default: allow downloads - return true + return !explicitlyDisabled } /** - * Get the model path with intelligent defaults - * This replaces the need for BRAINY_MODELS_PATH env var + * Get the model path + * With bundled WASM model, this points to the package assets */ export function getModelPath(): string { - // Check if user explicitly set a path (keeping this for advanced users) + // Check if user explicitly set a path (for advanced users) if (process.env.BRAINY_MODELS_PATH) { return process.env.BRAINY_MODELS_PATH } - - // Browser - use cache API or IndexedDB (handled by transformers.js) + + // Browser - use cache API or IndexedDB if (isBrowser()) { return 'browser-cache' } - + // Serverless - use /tmp for ephemeral storage if (isServerlessEnvironment()) { return '/tmp/.brainy/models' } - + // Node.js - use home directory for persistent storage if (isNode()) { - // Use process.env.HOME as a fallback const homeDir = process.env.HOME || process.env.USERPROFILE || '~' return `${homeDir}/.brainy/models` } - + // Fallback return './.brainy/models' } - -/** - * Log model configuration decision (only in verbose mode) - */ -export function logModelConfig(config: ModelConfigResult, verbose: boolean = false): void { - if (!verbose && process.env.NODE_ENV === 'production') { - return // Silent in production unless verbose - } - - const icon = config.autoSelected ? '🤖' : '👤' - console.log(`${icon} Model: ${config.precision.toUpperCase()} - ${config.reason}`) -} \ No newline at end of file diff --git a/src/config/sharedConfigManager.ts b/src/config/sharedConfigManager.ts index 98fee475..2b52c199 100644 --- a/src/config/sharedConfigManager.ts +++ b/src/config/sharedConfigManager.ts @@ -3,14 +3,13 @@ * Ensures configuration consistency across multiple instances using shared storage */ -import { ModelPrecision } from './modelAutoConfig.js' import { StorageType } from './storageAutoConfig.js' import { getBrainyVersion } from '../utils/version.js' export interface SharedConfig { // Critical parameters that MUST match across instances version: string - precision: ModelPrecision + precision: 'q8' dimensions: number hnswM: number hnswEfConstruction: number diff --git a/src/config/zeroConfig.ts b/src/config/zeroConfig.ts index 2ed1ddff..039b164b 100644 --- a/src/config/zeroConfig.ts +++ b/src/config/zeroConfig.ts @@ -3,7 +3,7 @@ * Provides intelligent defaults while preserving full control */ -import { autoSelectModelPrecision, ModelPrecision, ModelPreset, getModelPath, shouldAutoDownloadModels } from './modelAutoConfig.js' +import { getModelPrecision, getModelPath, shouldAutoDownloadModels } from './modelAutoConfig.js' import { autoDetectStorage, StorageType, StoragePreset } from './storageAutoConfig.js' import { AutoConfiguration } from '../utils/autoConfiguration.js' @@ -23,16 +23,6 @@ export interface BrainyZeroConfig { */ mode?: 'production' | 'development' | 'minimal' | 'zero' | 'writer' | 'reader' - /** - * Model precision configuration - * - 'fp32': Full precision (best quality, larger size) - * - 'q8': Quantized 8-bit (smaller size, slightly lower quality) - * - 'fast': Alias for fp32 - * - 'small': Alias for q8 - * - 'auto': Auto-detect based on environment (default) - */ - model?: ModelPrecision | ModelPreset - /** * Storage configuration * - 'memory': In-memory only (no persistence) @@ -72,31 +62,26 @@ export interface BrainyZeroConfig { const PRESETS = { production: { storage: 'disk' as const, - model: 'auto' as const, features: 'default' as const, verbose: false }, development: { storage: 'memory' as const, - model: 'q8' as const, // Q8 is now the default for all presets features: 'full' as const, verbose: true }, minimal: { storage: 'memory' as const, - model: 'q8' as const, features: 'minimal' as const, verbose: false }, zero: { storage: 'auto' as const, - model: 'auto' as const, features: 'default' as const, verbose: false }, writer: { storage: 'auto' as const, - model: 'auto' as const, features: 'minimal' as const, verbose: false, // Writer-specific settings @@ -107,7 +92,6 @@ const PRESETS = { }, reader: { storage: 'auto' as const, - model: 'auto' as const, features: 'default' as const, verbose: false, // Reader-specific settings @@ -180,18 +164,17 @@ export async function processZeroConfig(input?: string | BrainyZeroConfig): Prom ...preset, ...config, // Preserve explicit overrides - model: config.model ?? preset.model, storage: config.storage ?? preset.storage, features: config.features ?? preset.features, verbose: config.verbose ?? preset.verbose } } - + // Auto-detect environment if not in preset mode const environment = detectEnvironmentMode() - - // Process model configuration - const modelConfig = autoSelectModelPrecision(config.model) + + // Get model configuration (always Q8 WASM) + const modelConfig = getModelPrecision() // Process storage configuration const storageConfig = await autoDetectStorage(config.storage) @@ -376,15 +359,14 @@ function logConfigurationSummary(config: any): void { } /** - * Create embedding function with specified precision - * This ensures the model precision is respected + * Create embedding function (always Q8 WASM) */ -export async function createEmbeddingFunctionWithPrecision(precision: ModelPrecision): Promise { +export async function createEmbeddingFunctionWithPrecision(): Promise { const { createEmbeddingFunction } = await import('../utils/embedding.js') - - // Create embedding function with specified precision + + // Create embedding function - always Q8 WASM return createEmbeddingFunction({ - precision: precision, + precision: 'q8', verbose: false // Silent by default in zero-config }) } \ No newline at end of file diff --git a/src/types/brainy.types.ts b/src/types/brainy.types.ts index 4ba1e056..f251ed92 100644 --- a/src/types/brainy.types.ts +++ b/src/types/brainy.types.ts @@ -632,14 +632,7 @@ export interface BrainyConfig { options?: any branch?: string // COW branch name (default: 'main') } - - // Model configuration - model?: { - type: 'fast' | 'accurate' | 'balanced' | 'custom' - name?: string // Custom model name - precision?: 'q8' - } - + // Index configuration index?: { m?: number // HNSW M parameter