brainy/docs/technical/THREADING.md
David Snelling 52a43d51d4 refactor: simplify build system and improve model loading flexibility
- Remove Rollup bundling in favor of direct TypeScript compilation
- Move from bundled models to dynamic model loading with configurable paths
- Add Docker deployment examples and documentation
- Implement robust model loader with fallback mechanisms
- Update storage adapters for better cross-environment compatibility
- Add comprehensive tests for model loading and package installation
- Simplify package.json scripts and remove complex build configurations
- Clean up deprecated demo files and old bundling scripts

BREAKING CHANGE: Models are no longer bundled with the package. They are now loaded dynamically from CDN or custom paths.
2025-08-05 16:09:30 -07:00

180 lines
5.2 KiB
Markdown

# Brainy Threading Implementation
This document explains how Brainy's threading implementation works across different environments.
## Overview
Brainy uses a unified threading approach that adapts to the environment it's running in:
1. **Node.js**: Uses Worker Threads API (optimized for Node.js 24+)
2. **Browser**: Uses Web Workers API
3. **Fallback**: Executes on the main thread when neither Worker Threads nor Web Workers are available
This implementation ensures that compute-intensive operations (like embedding generation and vector calculations) can be
performed efficiently without blocking the main thread, while maintaining compatibility across all environments.
## Implementation Details
### Environment Detection
Brainy automatically detects the environment it's running in:
```typescript
// From unified.ts
export const environment = {
isBrowser: typeof window !== 'undefined',
isNode: typeof process !== 'undefined' && process.versions && process.versions.node,
isServerless: typeof window === 'undefined' &&
(typeof process === 'undefined' || !process.versions || !process.versions.node)
}
```
Additional environment detection functions are available in `src/utils/environment.ts`:
```typescript
// Check if threading is available
export function isThreadingAvailable(): boolean {
return areWebWorkersAvailable() || areWorkerThreadsAvailable();
}
// Check if Web Workers are available (browser)
export function areWebWorkersAvailable(): boolean {
return isBrowser() && typeof Worker !== 'undefined';
}
// Check if Worker Threads are available (Node.js)
export function areWorkerThreadsAvailable(): boolean {
if (!isNode()) return false;
try {
require('worker_threads');
return true;
} catch (e) {
return false;
}
}
```
### Thread Execution
The core of the threading implementation is the `executeInThread` function in `src/utils/workerUtils.ts`:
```typescript
export function executeInThread<T>(fnString: string, args: any): Promise<T> {
if (environment.isNode) {
return executeInNodeWorker<T>(fnString, args)
} else if (environment.isBrowser && typeof window !== 'undefined' && window.Worker) {
return executeInWebWorker<T>(fnString, args)
} else {
// Fallback to main thread execution
try {
const fn = new Function('return ' + fnString)()
return Promise.resolve(fn(args) as T)
} catch (error) {
return Promise.reject(error)
}
}
}
```
This function:
1. Checks if it's running in Node.js and uses Worker Threads if available
2. Checks if it's running in a browser and uses Web Workers if available
3. Falls back to executing on the main thread if neither is available
### Node.js Implementation
For Node.js environments, Brainy uses the Worker Threads API with optimizations for Node.js 24:
```typescript
function executeInNodeWorker<T>(fnString: string, args: any): Promise<T> {
// Implementation using Node.js Worker Threads
// Includes worker pool management for better performance
// Uses dynamic imports with the 'node:' protocol prefix
// ...
}
```
Key optimizations:
- Worker pool to reuse workers and minimize overhead
- Dynamic imports with the `node:` protocol prefix
- Error handling and cleanup
### Browser Implementation
For browser environments, Brainy uses the Web Workers API:
```typescript
function executeInWebWorker<T>(fnString: string, args: any): Promise<T> {
// Implementation using browser Web Workers
// Creates a blob URL for the worker code
// Handles message passing and error handling
// ...
}
```
Key features:
- Creates workers using Blob URLs
- Proper cleanup of resources (terminating workers and revoking URLs)
- Error handling
### Fallback Mechanism
When neither Worker Threads nor Web Workers are available, Brainy falls back to executing on the main thread:
```typescript
// Fallback to main thread execution
try {
const fn = new Function('return ' + fnString)()
return Promise.resolve(fn(args) as T)
} catch (error) {
return Promise.reject(error)
}
```
This ensures that Brainy works in all environments, even if threading is not available.
## Usage
The threading implementation is used throughout Brainy, particularly for compute-intensive operations like embedding
generation:
```typescript
export function createThreadedEmbeddingFunction(
model: EmbeddingModel
): EmbeddingFunction {
const embeddingFunction = createEmbeddingFunction(model)
return async (data: any): Promise<Vector> => {
// Convert the embedding function to a string
const fnString = embeddingFunction.toString()
// Execute the embedding function in a thread
return await executeInThread<Vector>(fnString, data)
}
}
```
## Testing
// Demo references removed: The demo is now maintained in the separate @soulcraft/demos project.
## Compatibility
The threading implementation has been tested and works in:
- Node.js 24+ (using Worker Threads)
- Modern browsers (using Web Workers):
- Chrome
- Firefox
- Safari
- Edge
- Environments without threading support (using fallback mechanism)
## Conclusion
Brainy's threading implementation provides efficient execution of compute-intensive operations across all environments,
with optimizations for Node.js 24 and modern browsers, and a fallback mechanism for environments where threading is not
available.