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.
This commit is contained in:
parent
746b1b8e24
commit
e6769d6d9f
6 changed files with 37 additions and 163 deletions
|
|
@ -177,7 +177,6 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
...this.config,
|
...this.config,
|
||||||
...configOverrides,
|
...configOverrides,
|
||||||
storage: { ...this.config.storage, ...configOverrides.storage },
|
storage: { ...this.config.storage, ...configOverrides.storage },
|
||||||
model: { ...this.config.model, ...configOverrides.model },
|
|
||||||
index: { ...this.config.index, ...configOverrides.index },
|
index: { ...this.config.index, ...configOverrides.index },
|
||||||
augmentations: { ...this.config.augmentations, ...configOverrides.augmentations },
|
augmentations: { ...this.config.augmentations, ...configOverrides.augmentations },
|
||||||
verbose: configOverrides.verbose ?? this.config.verbose,
|
verbose: configOverrides.verbose ?? this.config.verbose,
|
||||||
|
|
@ -4972,11 +4971,6 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
// Both 'gcs' and 'gcs-native' can now use either gcsStorage or gcsNativeStorage
|
// 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
|
// Validate numeric configurations
|
||||||
if (config?.index?.m && (config.index.m < 1 || config.index.m > 128)) {
|
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`)
|
throw new Error(`Invalid index m parameter: ${config.index.m}. Must be between 1 and 128`)
|
||||||
|
|
@ -4995,7 +4989,6 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
storage: config?.storage || { type: 'auto' },
|
storage: config?.storage || { type: 'auto' },
|
||||||
model: config?.model || { type: 'fast' },
|
|
||||||
index: config?.index || {},
|
index: config?.index || {},
|
||||||
cache: config?.cache ?? true,
|
cache: config?.cache ?? true,
|
||||||
augmentations: config?.augmentations || {},
|
augmentations: config?.augmentations || {},
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,13 @@
|
||||||
* Main entry point for all auto-configuration features
|
* Main entry point for all auto-configuration features
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Model configuration
|
// Model configuration (simplified - always Q8 WASM)
|
||||||
export {
|
export {
|
||||||
autoSelectModelPrecision,
|
getModelPrecision,
|
||||||
ModelPrecision as ModelPrecisionType, // Avoid conflict
|
|
||||||
ModelPreset,
|
|
||||||
shouldAutoDownloadModels,
|
shouldAutoDownloadModels,
|
||||||
getModelPath,
|
getModelPath
|
||||||
logModelConfig
|
|
||||||
} from './modelAutoConfig.js'
|
} from './modelAutoConfig.js'
|
||||||
|
|
||||||
// Model precision - Always Q8 now (99% accuracy, 75% smaller)
|
|
||||||
export const getModelPrecision = () => 'q8' as const
|
|
||||||
|
|
||||||
// Storage configuration
|
// Storage configuration
|
||||||
export {
|
export {
|
||||||
autoDetectStorage,
|
autoDetectStorage,
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,24 @@
|
||||||
/**
|
/**
|
||||||
* Model Configuration Auto-Selection
|
* Model Configuration
|
||||||
* Always uses Q8 for optimal size/performance balance (99% accuracy, 75% smaller)
|
* Brainy uses Q8 WASM embeddings - no configuration needed (zero-config)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isBrowser, isNode } from '../utils/environment.js'
|
import { isBrowser, isNode } from '../utils/environment.js'
|
||||||
|
|
||||||
export type ModelPrecision = 'q8'
|
|
||||||
export type ModelPreset = 'small' | 'auto'
|
|
||||||
|
|
||||||
interface ModelConfigResult {
|
interface ModelConfigResult {
|
||||||
precision: ModelPrecision
|
precision: 'q8'
|
||||||
reason: string
|
reason: string
|
||||||
autoSelected: boolean
|
autoSelected: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto-select model precision - Always returns Q8
|
* Get model precision configuration
|
||||||
* Q8 provides 99% accuracy with 75% smaller size
|
* Always returns Q8 - the optimal balance of size and accuracy
|
||||||
* @param override - For backward compatibility, ignored
|
|
||||||
*/
|
*/
|
||||||
export function autoSelectModelPrecision(override?: ModelPrecision | ModelPreset): ModelConfigResult {
|
export function getModelPrecision(): 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).')
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
precision: 'q8',
|
precision: 'q8',
|
||||||
reason: 'Q8 precision (99% accuracy, 75% smaller)',
|
reason: 'Q8 WASM (23MB bundled, no downloads)',
|
||||||
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)',
|
|
||||||
autoSelected: true
|
autoSelected: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -53,7 +28,7 @@ function autoDetectBestPrecision(): ModelConfigResult {
|
||||||
*/
|
*/
|
||||||
function isServerlessEnvironment(): boolean {
|
function isServerlessEnvironment(): boolean {
|
||||||
if (!isNode()) return false
|
if (!isNode()) return false
|
||||||
|
|
||||||
return !!(
|
return !!(
|
||||||
process.env.AWS_LAMBDA_FUNCTION_NAME ||
|
process.env.AWS_LAMBDA_FUNCTION_NAME ||
|
||||||
process.env.VERCEL ||
|
process.env.VERCEL ||
|
||||||
|
|
@ -65,104 +40,42 @@ function isServerlessEnvironment(): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get available memory in MB
|
* Check if models need to be downloaded
|
||||||
*/
|
* With bundled WASM model, this is rarely needed
|
||||||
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
|
|
||||||
*/
|
*/
|
||||||
export function shouldAutoDownloadModels(): boolean {
|
export function shouldAutoDownloadModels(): boolean {
|
||||||
// Always allow downloads unless explicitly disabled
|
// Model is bundled - no downloads needed in normal operation
|
||||||
// This eliminates the need for BRAINY_ALLOW_REMOTE_MODELS
|
// This flag exists for edge cases only
|
||||||
const explicitlyDisabled = process.env.BRAINY_ALLOW_REMOTE_MODELS === 'false'
|
const explicitlyDisabled = process.env.BRAINY_ALLOW_REMOTE_MODELS === 'false'
|
||||||
|
return !explicitlyDisabled
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the model path with intelligent defaults
|
* Get the model path
|
||||||
* This replaces the need for BRAINY_MODELS_PATH env var
|
* With bundled WASM model, this points to the package assets
|
||||||
*/
|
*/
|
||||||
export function getModelPath(): string {
|
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) {
|
if (process.env.BRAINY_MODELS_PATH) {
|
||||||
return 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()) {
|
if (isBrowser()) {
|
||||||
return 'browser-cache'
|
return 'browser-cache'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serverless - use /tmp for ephemeral storage
|
// Serverless - use /tmp for ephemeral storage
|
||||||
if (isServerlessEnvironment()) {
|
if (isServerlessEnvironment()) {
|
||||||
return '/tmp/.brainy/models'
|
return '/tmp/.brainy/models'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node.js - use home directory for persistent storage
|
// Node.js - use home directory for persistent storage
|
||||||
if (isNode()) {
|
if (isNode()) {
|
||||||
// Use process.env.HOME as a fallback
|
|
||||||
const homeDir = process.env.HOME || process.env.USERPROFILE || '~'
|
const homeDir = process.env.HOME || process.env.USERPROFILE || '~'
|
||||||
return `${homeDir}/.brainy/models`
|
return `${homeDir}/.brainy/models`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback
|
// Fallback
|
||||||
return './.brainy/models'
|
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}`)
|
|
||||||
}
|
|
||||||
|
|
@ -3,14 +3,13 @@
|
||||||
* Ensures configuration consistency across multiple instances using shared storage
|
* Ensures configuration consistency across multiple instances using shared storage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ModelPrecision } from './modelAutoConfig.js'
|
|
||||||
import { StorageType } from './storageAutoConfig.js'
|
import { StorageType } from './storageAutoConfig.js'
|
||||||
import { getBrainyVersion } from '../utils/version.js'
|
import { getBrainyVersion } from '../utils/version.js'
|
||||||
|
|
||||||
export interface SharedConfig {
|
export interface SharedConfig {
|
||||||
// Critical parameters that MUST match across instances
|
// Critical parameters that MUST match across instances
|
||||||
version: string
|
version: string
|
||||||
precision: ModelPrecision
|
precision: 'q8'
|
||||||
dimensions: number
|
dimensions: number
|
||||||
hnswM: number
|
hnswM: number
|
||||||
hnswEfConstruction: number
|
hnswEfConstruction: number
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* Provides intelligent defaults while preserving full control
|
* 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 { autoDetectStorage, StorageType, StoragePreset } from './storageAutoConfig.js'
|
||||||
import { AutoConfiguration } from '../utils/autoConfiguration.js'
|
import { AutoConfiguration } from '../utils/autoConfiguration.js'
|
||||||
|
|
||||||
|
|
@ -23,16 +23,6 @@ export interface BrainyZeroConfig {
|
||||||
*/
|
*/
|
||||||
mode?: 'production' | 'development' | 'minimal' | 'zero' | 'writer' | 'reader'
|
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
|
* Storage configuration
|
||||||
* - 'memory': In-memory only (no persistence)
|
* - 'memory': In-memory only (no persistence)
|
||||||
|
|
@ -72,31 +62,26 @@ export interface BrainyZeroConfig {
|
||||||
const PRESETS = {
|
const PRESETS = {
|
||||||
production: {
|
production: {
|
||||||
storage: 'disk' as const,
|
storage: 'disk' as const,
|
||||||
model: 'auto' as const,
|
|
||||||
features: 'default' as const,
|
features: 'default' as const,
|
||||||
verbose: false
|
verbose: false
|
||||||
},
|
},
|
||||||
development: {
|
development: {
|
||||||
storage: 'memory' as const,
|
storage: 'memory' as const,
|
||||||
model: 'q8' as const, // Q8 is now the default for all presets
|
|
||||||
features: 'full' as const,
|
features: 'full' as const,
|
||||||
verbose: true
|
verbose: true
|
||||||
},
|
},
|
||||||
minimal: {
|
minimal: {
|
||||||
storage: 'memory' as const,
|
storage: 'memory' as const,
|
||||||
model: 'q8' as const,
|
|
||||||
features: 'minimal' as const,
|
features: 'minimal' as const,
|
||||||
verbose: false
|
verbose: false
|
||||||
},
|
},
|
||||||
zero: {
|
zero: {
|
||||||
storage: 'auto' as const,
|
storage: 'auto' as const,
|
||||||
model: 'auto' as const,
|
|
||||||
features: 'default' as const,
|
features: 'default' as const,
|
||||||
verbose: false
|
verbose: false
|
||||||
},
|
},
|
||||||
writer: {
|
writer: {
|
||||||
storage: 'auto' as const,
|
storage: 'auto' as const,
|
||||||
model: 'auto' as const,
|
|
||||||
features: 'minimal' as const,
|
features: 'minimal' as const,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
// Writer-specific settings
|
// Writer-specific settings
|
||||||
|
|
@ -107,7 +92,6 @@ const PRESETS = {
|
||||||
},
|
},
|
||||||
reader: {
|
reader: {
|
||||||
storage: 'auto' as const,
|
storage: 'auto' as const,
|
||||||
model: 'auto' as const,
|
|
||||||
features: 'default' as const,
|
features: 'default' as const,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
// Reader-specific settings
|
// Reader-specific settings
|
||||||
|
|
@ -180,18 +164,17 @@ export async function processZeroConfig(input?: string | BrainyZeroConfig): Prom
|
||||||
...preset,
|
...preset,
|
||||||
...config,
|
...config,
|
||||||
// Preserve explicit overrides
|
// Preserve explicit overrides
|
||||||
model: config.model ?? preset.model,
|
|
||||||
storage: config.storage ?? preset.storage,
|
storage: config.storage ?? preset.storage,
|
||||||
features: config.features ?? preset.features,
|
features: config.features ?? preset.features,
|
||||||
verbose: config.verbose ?? preset.verbose
|
verbose: config.verbose ?? preset.verbose
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto-detect environment if not in preset mode
|
// Auto-detect environment if not in preset mode
|
||||||
const environment = detectEnvironmentMode()
|
const environment = detectEnvironmentMode()
|
||||||
|
|
||||||
// Process model configuration
|
// Get model configuration (always Q8 WASM)
|
||||||
const modelConfig = autoSelectModelPrecision(config.model)
|
const modelConfig = getModelPrecision()
|
||||||
|
|
||||||
// Process storage configuration
|
// Process storage configuration
|
||||||
const storageConfig = await autoDetectStorage(config.storage)
|
const storageConfig = await autoDetectStorage(config.storage)
|
||||||
|
|
@ -376,15 +359,14 @@ function logConfigurationSummary(config: any): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create embedding function with specified precision
|
* Create embedding function (always Q8 WASM)
|
||||||
* This ensures the model precision is respected
|
|
||||||
*/
|
*/
|
||||||
export async function createEmbeddingFunctionWithPrecision(precision: ModelPrecision): Promise<any> {
|
export async function createEmbeddingFunctionWithPrecision(): Promise<any> {
|
||||||
const { createEmbeddingFunction } = await import('../utils/embedding.js')
|
const { createEmbeddingFunction } = await import('../utils/embedding.js')
|
||||||
|
|
||||||
// Create embedding function with specified precision
|
// Create embedding function - always Q8 WASM
|
||||||
return createEmbeddingFunction({
|
return createEmbeddingFunction({
|
||||||
precision: precision,
|
precision: 'q8',
|
||||||
verbose: false // Silent by default in zero-config
|
verbose: false // Silent by default in zero-config
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -632,14 +632,7 @@ export interface BrainyConfig {
|
||||||
options?: any
|
options?: any
|
||||||
branch?: string // COW branch name (default: 'main')
|
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 configuration
|
||||||
index?: {
|
index?: {
|
||||||
m?: number // HNSW M parameter
|
m?: number // HNSW M parameter
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue