@soulcraft/brainy 6.5.0 → 6.6.0

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.
@@ -2,39 +2,34 @@
2
2
  * Unified Embedding Manager
3
3
  *
4
4
  * THE single source of truth for all embedding operations in Brainy.
5
- * Combines model management, precision configuration, and embedding generation
6
- * into one clean, maintainable class.
5
+ * Uses direct ONNX WASM inference for universal compatibility.
7
6
  *
8
7
  * Features:
9
8
  * - Singleton pattern ensures ONE model instance
10
- * - Automatic Q8 (default) or FP32 precision
11
- * - Model downloading and caching
12
- * - Thread-safe initialization
9
+ * - Direct ONNX WASM (no transformers.js dependency)
10
+ * - Bundled model (no runtime downloads)
11
+ * - Works everywhere: Node.js, Bun, Bun --compile, browsers
13
12
  * - Memory monitoring
14
- *
15
- * This replaces: SingletonModelManager, TransformerEmbedding, ModelPrecisionManager,
16
- * hybridModelManager, universalMemoryManager, and more.
17
13
  */
18
- import { pipeline, env } from '@huggingface/transformers';
19
- import { isNode } from '../utils/environment.js';
14
+ import { WASMEmbeddingEngine } from './wasm/index.js';
20
15
  // Global state for true singleton across entire process
21
16
  let globalInstance = null;
22
17
  let globalInitPromise = null;
23
18
  /**
24
19
  * Unified Embedding Manager - Clean, simple, reliable
20
+ *
21
+ * Now powered by direct ONNX WASM for universal compatibility.
25
22
  */
26
23
  export class EmbeddingManager {
27
24
  constructor() {
28
- this.model = null;
29
- this.modelName = 'Xenova/all-MiniLM-L6-v2';
25
+ this.precision = 'q8';
26
+ this.modelName = 'all-MiniLM-L6-v2';
30
27
  this.initialized = false;
31
28
  this.initTime = null;
32
29
  this.embedCount = 0;
33
30
  this.locked = false;
34
- this.modelsPathCache = null;
35
- // Always use Q8 for optimal size/performance (99% accuracy, 75% smaller)
36
- this.precision = 'q8';
37
- console.log(`🎯 EmbeddingManager: Using Q8 precision`);
31
+ this.engine = WASMEmbeddingEngine.getInstance();
32
+ console.log('🎯 EmbeddingManager: Using Q8 precision (WASM)');
38
33
  }
39
34
  /**
40
35
  * Get the singleton instance
@@ -50,9 +45,10 @@ export class EmbeddingManager {
50
45
  */
51
46
  async init() {
52
47
  // In unit test mode, skip real model initialization
53
- const isTestMode = process.env.BRAINY_UNIT_TEST === 'true' || globalThis.__BRAINY_UNIT_TEST__;
48
+ const isTestMode = process.env.BRAINY_UNIT_TEST === 'true' ||
49
+ globalThis.__BRAINY_UNIT_TEST__;
54
50
  if (isTestMode) {
55
- // Production safeguard: Warn if mock mode is active but NODE_ENV is production
51
+ // Production safeguard
56
52
  if (process.env.NODE_ENV === 'production') {
57
53
  throw new Error('CRITICAL: Mock embeddings detected in production environment! ' +
58
54
  'BRAINY_UNIT_TEST or __BRAINY_UNIT_TEST__ is set while NODE_ENV=production. ' +
@@ -66,7 +62,7 @@ export class EmbeddingManager {
66
62
  return;
67
63
  }
68
64
  // Already initialized
69
- if (this.initialized && this.model) {
65
+ if (this.initialized && this.engine.isInitialized()) {
70
66
  return;
71
67
  }
72
68
  // Initialization in progress
@@ -88,62 +84,20 @@ export class EmbeddingManager {
88
84
  */
89
85
  async performInit() {
90
86
  const startTime = Date.now();
91
- console.log(`🚀 Initializing embedding model (${this.precision.toUpperCase()})...`);
92
87
  try {
93
- // Configure transformers.js environment
94
- const modelsPath = this.getModelsPath();
95
- env.cacheDir = modelsPath;
96
- env.allowLocalModels = true;
97
- env.useFSCache = true;
98
- // Check if models exist locally (only in Node.js)
99
- if (isNode()) {
100
- try {
101
- const nodeRequire = typeof require !== 'undefined' ? require : null;
102
- if (nodeRequire) {
103
- const path = nodeRequire('node:path');
104
- const fs = nodeRequire('node:fs');
105
- const modelPath = path.join(modelsPath, ...this.modelName.split('/'));
106
- const hasLocalModels = fs.existsSync(modelPath);
107
- if (hasLocalModels) {
108
- console.log('✅ Using cached models from:', modelPath);
109
- }
110
- }
111
- }
112
- catch {
113
- // Silently continue if require fails
114
- }
115
- }
116
- // Configure pipeline options for the selected precision
117
- const pipelineOptions = {
118
- cache_dir: modelsPath,
119
- local_files_only: false,
120
- // Always use Q8 precision
121
- dtype: 'q8',
122
- quantized: true,
123
- // Memory optimizations
124
- session_options: {
125
- enableCpuMemArena: false,
126
- enableMemPattern: false,
127
- interOpNumThreads: 1,
128
- intraOpNumThreads: 1,
129
- graphOptimizationLevel: 'disabled'
130
- }
131
- };
132
- // Load the model
133
- this.model = await pipeline('feature-extraction', this.modelName, pipelineOptions);
88
+ // Initialize WASM engine (handles all model loading)
89
+ await this.engine.initialize();
134
90
  // Lock precision after successful initialization
135
91
  this.locked = true;
136
92
  this.initialized = true;
137
93
  this.initTime = Date.now() - startTime;
138
94
  // Log success
139
95
  const memoryMB = this.getMemoryUsage();
140
- console.log(`✅ Model loaded in ${this.initTime}ms`);
141
96
  console.log(`📊 Precision: Q8 | Memory: ${memoryMB}MB`);
142
- console.log(`🔒 Configuration locked`);
97
+ console.log('🔒 Configuration locked');
143
98
  }
144
99
  catch (error) {
145
100
  this.initialized = false;
146
- this.model = null;
147
101
  throw new Error(`Failed to initialize embedding model: ${error instanceof Error ? error.message : String(error)}`);
148
102
  }
149
103
  }
@@ -151,10 +105,10 @@ export class EmbeddingManager {
151
105
  * Generate embeddings
152
106
  */
153
107
  async embed(text) {
154
- // Check for unit test environment - use mocks to prevent ONNX conflicts
155
- const isTestMode = process.env.BRAINY_UNIT_TEST === 'true' || globalThis.__BRAINY_UNIT_TEST__;
108
+ // Check for unit test environment
109
+ const isTestMode = process.env.BRAINY_UNIT_TEST === 'true' ||
110
+ globalThis.__BRAINY_UNIT_TEST__;
156
111
  if (isTestMode) {
157
- // Production safeguard
158
112
  if (process.env.NODE_ENV === 'production') {
159
113
  throw new Error('CRITICAL: Mock embeddings in production!');
160
114
  }
@@ -162,38 +116,26 @@ export class EmbeddingManager {
162
116
  }
163
117
  // Ensure initialized
164
118
  await this.init();
165
- if (!this.model) {
166
- throw new Error('Model not initialized');
167
- }
168
- // CRITICAL FIX: Ensure input is always a string
119
+ // Normalize input to string
169
120
  let input;
170
121
  if (Array.isArray(text)) {
171
- // Join array elements, converting each to string first
172
- input = text.map(t => typeof t === 'string' ? t : String(t)).join(' ');
122
+ input = text.map((t) => (typeof t === 'string' ? t : String(t))).join(' ');
173
123
  }
174
124
  else if (typeof text === 'string') {
175
125
  input = text;
176
126
  }
177
127
  else if (typeof text === 'object') {
178
- // Convert object to string representation
179
128
  input = JSON.stringify(text);
180
129
  }
181
130
  else {
182
- // This shouldn't happen but let's be defensive
183
131
  console.warn('EmbeddingManager.embed received unexpected input type:', typeof text);
184
132
  input = String(text);
185
133
  }
186
- // Generate embedding
187
- const output = await this.model(input, {
188
- pooling: 'mean',
189
- normalize: true
190
- });
191
- // Extract embedding vector
192
- const embedding = Array.from(output.data);
134
+ // Generate embedding using WASM engine
135
+ const embedding = await this.engine.embed(input);
193
136
  // Validate dimensions
194
137
  if (embedding.length !== 384) {
195
138
  console.warn(`Unexpected embedding dimension: ${embedding.length}`);
196
- // Pad or truncate
197
139
  if (embedding.length < 384) {
198
140
  return [...embedding, ...new Array(384 - embedding.length).fill(0)];
199
141
  }
@@ -208,7 +150,6 @@ export class EmbeddingManager {
208
150
  * Generate mock embeddings for unit tests
209
151
  */
210
152
  getMockEmbedding(text) {
211
- // Use the same mock logic as setup-unit.ts for consistency
212
153
  const input = Array.isArray(text) ? text.join(' ') : text;
213
154
  const str = typeof input === 'string' ? input : JSON.stringify(input);
214
155
  const vector = new Array(384).fill(0);
@@ -220,7 +161,6 @@ export class EmbeddingManager {
220
161
  for (let i = 0; i < 384; i++) {
221
162
  vector[i] += Math.sin(i * 0.1 + str.length) * 0.1;
222
163
  }
223
- // Track mock embedding count
224
164
  this.embedCount++;
225
165
  return vector;
226
166
  }
@@ -232,55 +172,6 @@ export class EmbeddingManager {
232
172
  return await this.embed(data);
233
173
  };
234
174
  }
235
- /**
236
- * Get models directory path
237
- * Note: In browser environments, returns a simple default path
238
- * In Node.js, checks multiple locations for the models directory
239
- */
240
- getModelsPath() {
241
- // In browser environments, use a default path
242
- if (!isNode()) {
243
- return './models';
244
- }
245
- // Node.js-specific model path resolution
246
- // Cache the result for performance
247
- if (!this.modelsPathCache) {
248
- this.modelsPathCache = this.resolveModelsPathSync();
249
- }
250
- return this.modelsPathCache;
251
- }
252
- resolveModelsPathSync() {
253
- // For Node.js environments, we can safely assume these modules exist
254
- // TypeScript will handle the imports at build time
255
- // At runtime, these will only be called if isNode() is true
256
- // Default fallback path
257
- const defaultPath = './models';
258
- try {
259
- // Create a conditional require function that only works in Node
260
- const nodeRequire = typeof require !== 'undefined' ? require : null;
261
- if (!nodeRequire)
262
- return defaultPath;
263
- const fs = nodeRequire('node:fs');
264
- const path = nodeRequire('node:path');
265
- const paths = [
266
- process.env.BRAINY_MODELS_PATH,
267
- './models',
268
- path.join(process.cwd(), 'models'),
269
- path.join(process.env.HOME || '', '.brainy', 'models')
270
- ];
271
- for (const p of paths) {
272
- if (p && fs.existsSync(p)) {
273
- return p;
274
- }
275
- }
276
- // Default Node.js path
277
- return path.join(process.cwd(), 'models');
278
- }
279
- catch {
280
- // Fallback if require fails
281
- return defaultPath;
282
- }
283
- }
284
175
  /**
285
176
  * Get memory usage in MB
286
177
  */
@@ -295,13 +186,14 @@ export class EmbeddingManager {
295
186
  * Get current statistics
296
187
  */
297
188
  getStats() {
189
+ const engineStats = this.engine.getStats();
298
190
  return {
299
191
  initialized: this.initialized,
300
192
  precision: this.precision,
301
193
  modelName: this.modelName,
302
- embedCount: this.embedCount,
194
+ embedCount: this.embedCount + engineStats.embedCount,
303
195
  initTime: this.initTime,
304
- memoryMB: this.getMemoryUsage()
196
+ memoryMB: this.getMemoryUsage(),
305
197
  };
306
198
  }
307
199
  /**
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Asset Loader
3
+ *
4
+ * Resolves paths to model files (ONNX model, vocabulary) across environments.
5
+ * Handles Node.js, Bun, and bundled scenarios.
6
+ *
7
+ * Asset Resolution Order:
8
+ * 1. Environment variable: BRAINY_MODEL_PATH
9
+ * 2. Package-relative: node_modules/@soulcraft/brainy/assets/models/
10
+ * 3. Project-relative: ./assets/models/
11
+ */
12
+ /**
13
+ * Asset loader for model files
14
+ */
15
+ export declare class AssetLoader {
16
+ private modelDir;
17
+ /**
18
+ * Get the model directory path
19
+ */
20
+ getModelDir(): Promise<string>;
21
+ /**
22
+ * Resolve the model directory across environments
23
+ */
24
+ private resolveModelDir;
25
+ /**
26
+ * Get package root path (Node.js/Bun only)
27
+ */
28
+ private getPackageRootPath;
29
+ /**
30
+ * Check if path exists (works in Node.js/Bun)
31
+ */
32
+ private pathExists;
33
+ /**
34
+ * Get path to ONNX model file
35
+ */
36
+ getModelPath(): Promise<string>;
37
+ /**
38
+ * Get path to vocabulary file
39
+ */
40
+ getVocabPath(): Promise<string>;
41
+ /**
42
+ * Load vocabulary from JSON file
43
+ */
44
+ loadVocab(): Promise<Record<string, number>>;
45
+ /**
46
+ * Load model as ArrayBuffer (for ONNX session)
47
+ */
48
+ loadModel(): Promise<ArrayBuffer>;
49
+ /**
50
+ * Verify all required assets exist
51
+ */
52
+ verifyAssets(): Promise<{
53
+ valid: boolean;
54
+ modelPath: string;
55
+ vocabPath: string;
56
+ errors: string[];
57
+ }>;
58
+ /**
59
+ * Clear cached paths (for testing)
60
+ */
61
+ clearCache(): void;
62
+ }
63
+ /**
64
+ * Create asset loader instance
65
+ */
66
+ export declare function createAssetLoader(): AssetLoader;
67
+ export declare function getAssetLoader(): AssetLoader;
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Asset Loader
3
+ *
4
+ * Resolves paths to model files (ONNX model, vocabulary) across environments.
5
+ * Handles Node.js, Bun, and bundled scenarios.
6
+ *
7
+ * Asset Resolution Order:
8
+ * 1. Environment variable: BRAINY_MODEL_PATH
9
+ * 2. Package-relative: node_modules/@soulcraft/brainy/assets/models/
10
+ * 3. Project-relative: ./assets/models/
11
+ */
12
+ import { MODEL_CONSTANTS } from './types.js';
13
+ // Cache resolved paths
14
+ let cachedModelDir = null;
15
+ let cachedVocab = null;
16
+ /**
17
+ * Asset loader for model files
18
+ */
19
+ export class AssetLoader {
20
+ constructor() {
21
+ this.modelDir = null;
22
+ }
23
+ /**
24
+ * Get the model directory path
25
+ */
26
+ async getModelDir() {
27
+ if (this.modelDir) {
28
+ return this.modelDir;
29
+ }
30
+ if (cachedModelDir) {
31
+ this.modelDir = cachedModelDir;
32
+ return cachedModelDir;
33
+ }
34
+ // Try to resolve model directory
35
+ const resolved = await this.resolveModelDir();
36
+ this.modelDir = resolved;
37
+ cachedModelDir = resolved;
38
+ return resolved;
39
+ }
40
+ /**
41
+ * Resolve the model directory across environments
42
+ */
43
+ async resolveModelDir() {
44
+ // 1. Check environment variable
45
+ if (typeof process !== 'undefined' && process.env?.BRAINY_MODEL_PATH) {
46
+ const envPath = process.env.BRAINY_MODEL_PATH;
47
+ if (await this.pathExists(envPath)) {
48
+ return envPath;
49
+ }
50
+ }
51
+ // 2. Try common locations
52
+ const modelName = MODEL_CONSTANTS.MODEL_NAME + '-q8';
53
+ const possiblePaths = [
54
+ // Package assets (when installed as dependency)
55
+ `./assets/models/${modelName}`,
56
+ `./node_modules/@soulcraft/brainy/assets/models/${modelName}`,
57
+ // Development paths
58
+ `../assets/models/${modelName}`,
59
+ // Absolute from package root
60
+ this.getPackageRootPath(`assets/models/${modelName}`),
61
+ ].filter(Boolean);
62
+ for (const path of possiblePaths) {
63
+ if (await this.pathExists(path)) {
64
+ return path;
65
+ }
66
+ }
67
+ // If no path found, return default (will error on use)
68
+ return `./assets/models/${modelName}`;
69
+ }
70
+ /**
71
+ * Get package root path (Node.js/Bun only)
72
+ */
73
+ getPackageRootPath(relativePath) {
74
+ if (typeof process === 'undefined') {
75
+ return null;
76
+ }
77
+ try {
78
+ // Use __dirname equivalent
79
+ const url = new URL(import.meta.url);
80
+ const currentDir = url.pathname.replace(/\/[^/]*$/, '');
81
+ // Go up from src/embeddings/wasm to package root
82
+ const packageRoot = currentDir.replace(/\/src\/embeddings\/wasm$/, '');
83
+ return `${packageRoot}/${relativePath}`;
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ }
89
+ /**
90
+ * Check if path exists (works in Node.js/Bun)
91
+ */
92
+ async pathExists(path) {
93
+ if (typeof process === 'undefined') {
94
+ // Browser - check via fetch
95
+ try {
96
+ const response = await fetch(path, { method: 'HEAD' });
97
+ return response.ok;
98
+ }
99
+ catch {
100
+ return false;
101
+ }
102
+ }
103
+ // Node.js/Bun
104
+ try {
105
+ const fs = await import('node:fs/promises');
106
+ await fs.access(path);
107
+ return true;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ /**
114
+ * Get path to ONNX model file
115
+ */
116
+ async getModelPath() {
117
+ const dir = await this.getModelDir();
118
+ return `${dir}/model.onnx`;
119
+ }
120
+ /**
121
+ * Get path to vocabulary file
122
+ */
123
+ async getVocabPath() {
124
+ const dir = await this.getModelDir();
125
+ return `${dir}/vocab.json`;
126
+ }
127
+ /**
128
+ * Load vocabulary from JSON file
129
+ */
130
+ async loadVocab() {
131
+ if (cachedVocab) {
132
+ return cachedVocab;
133
+ }
134
+ const vocabPath = await this.getVocabPath();
135
+ if (typeof process !== 'undefined') {
136
+ // Node.js/Bun - read from filesystem
137
+ try {
138
+ const fs = await import('node:fs/promises');
139
+ const content = await fs.readFile(vocabPath, 'utf-8');
140
+ cachedVocab = JSON.parse(content);
141
+ return cachedVocab;
142
+ }
143
+ catch (error) {
144
+ throw new Error(`Failed to load vocabulary from ${vocabPath}: ${error instanceof Error ? error.message : String(error)}`);
145
+ }
146
+ }
147
+ else {
148
+ // Browser - fetch
149
+ try {
150
+ const response = await fetch(vocabPath);
151
+ if (!response.ok) {
152
+ throw new Error(`HTTP ${response.status}`);
153
+ }
154
+ cachedVocab = await response.json();
155
+ return cachedVocab;
156
+ }
157
+ catch (error) {
158
+ throw new Error(`Failed to fetch vocabulary from ${vocabPath}: ${error instanceof Error ? error.message : String(error)}`);
159
+ }
160
+ }
161
+ }
162
+ /**
163
+ * Load model as ArrayBuffer (for ONNX session)
164
+ */
165
+ async loadModel() {
166
+ const modelPath = await this.getModelPath();
167
+ if (typeof process !== 'undefined') {
168
+ // Node.js/Bun - read from filesystem
169
+ try {
170
+ const fs = await import('node:fs/promises');
171
+ const buffer = await fs.readFile(modelPath);
172
+ // Convert Node.js Buffer to ArrayBuffer
173
+ return new Uint8Array(buffer).buffer;
174
+ }
175
+ catch (error) {
176
+ throw new Error(`Failed to load model from ${modelPath}: ${error instanceof Error ? error.message : String(error)}`);
177
+ }
178
+ }
179
+ else {
180
+ // Browser - fetch
181
+ try {
182
+ const response = await fetch(modelPath);
183
+ if (!response.ok) {
184
+ throw new Error(`HTTP ${response.status}`);
185
+ }
186
+ return await response.arrayBuffer();
187
+ }
188
+ catch (error) {
189
+ throw new Error(`Failed to fetch model from ${modelPath}: ${error instanceof Error ? error.message : String(error)}`);
190
+ }
191
+ }
192
+ }
193
+ /**
194
+ * Verify all required assets exist
195
+ */
196
+ async verifyAssets() {
197
+ const errors = [];
198
+ const modelPath = await this.getModelPath();
199
+ const vocabPath = await this.getVocabPath();
200
+ if (!(await this.pathExists(modelPath))) {
201
+ errors.push(`Model file not found: ${modelPath}`);
202
+ }
203
+ if (!(await this.pathExists(vocabPath))) {
204
+ errors.push(`Vocabulary file not found: ${vocabPath}`);
205
+ }
206
+ return {
207
+ valid: errors.length === 0,
208
+ modelPath,
209
+ vocabPath,
210
+ errors,
211
+ };
212
+ }
213
+ /**
214
+ * Clear cached paths (for testing)
215
+ */
216
+ clearCache() {
217
+ this.modelDir = null;
218
+ cachedModelDir = null;
219
+ cachedVocab = null;
220
+ }
221
+ }
222
+ /**
223
+ * Create asset loader instance
224
+ */
225
+ export function createAssetLoader() {
226
+ return new AssetLoader();
227
+ }
228
+ /**
229
+ * Singleton asset loader
230
+ */
231
+ let singletonLoader = null;
232
+ export function getAssetLoader() {
233
+ if (!singletonLoader) {
234
+ singletonLoader = new AssetLoader();
235
+ }
236
+ return singletonLoader;
237
+ }
238
+ //# sourceMappingURL=AssetLoader.js.map
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Embedding Post-Processor
3
+ *
4
+ * Converts raw ONNX model output to final embedding vectors.
5
+ * Implements mean pooling and L2 normalization as used by sentence-transformers.
6
+ *
7
+ * Pipeline:
8
+ * 1. Mean Pooling: Average token embeddings (weighted by attention mask)
9
+ * 2. L2 Normalization: Normalize to unit length for cosine similarity
10
+ */
11
+ /**
12
+ * Post-processor for converting ONNX output to sentence embeddings
13
+ */
14
+ export declare class EmbeddingPostProcessor {
15
+ private hiddenSize;
16
+ constructor(hiddenSize?: number);
17
+ /**
18
+ * Mean pool token embeddings weighted by attention mask
19
+ *
20
+ * @param hiddenStates - Raw model output [seqLen * hiddenSize] flattened
21
+ * @param attentionMask - Attention mask [seqLen] (1 for real tokens, 0 for padding)
22
+ * @param seqLen - Sequence length
23
+ * @returns Mean-pooled embedding [hiddenSize]
24
+ */
25
+ meanPool(hiddenStates: Float32Array, attentionMask: number[], seqLen: number): Float32Array;
26
+ /**
27
+ * L2 normalize embedding to unit length
28
+ *
29
+ * @param embedding - Input embedding
30
+ * @returns Normalized embedding with ||x|| = 1
31
+ */
32
+ normalize(embedding: Float32Array): Float32Array;
33
+ /**
34
+ * Full post-processing pipeline: mean pool then normalize
35
+ *
36
+ * @param hiddenStates - Raw model output [seqLen * hiddenSize]
37
+ * @param attentionMask - Attention mask [seqLen]
38
+ * @param seqLen - Sequence length
39
+ * @returns Final normalized embedding [hiddenSize]
40
+ */
41
+ process(hiddenStates: Float32Array, attentionMask: number[], seqLen: number): Float32Array;
42
+ /**
43
+ * Process batch of embeddings
44
+ *
45
+ * @param hiddenStates - Raw model output [batchSize * seqLen * hiddenSize]
46
+ * @param attentionMasks - Attention masks [batchSize][seqLen]
47
+ * @param batchSize - Number of sequences in batch
48
+ * @param seqLen - Sequence length (same for all in batch due to padding)
49
+ * @returns Array of normalized embeddings
50
+ */
51
+ processBatch(hiddenStates: Float32Array, attentionMasks: number[][], batchSize: number, seqLen: number): Float32Array[];
52
+ /**
53
+ * Convert Float32Array to number array
54
+ */
55
+ toNumberArray(embedding: Float32Array): number[];
56
+ }
57
+ /**
58
+ * Create a post-processor with default configuration
59
+ */
60
+ export declare function createPostProcessor(): EmbeddingPostProcessor;