vecbox 0.2.2 → 0.2.3

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.
package/README.md CHANGED
@@ -5,7 +5,6 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
6
 
7
7
  **One API, multiple providers.** Switch between OpenAI, Gemini, Mistral, or run locally with Llama.cpp using native N-API performance.
8
-
9
8
  ```typescript
10
9
  import { autoEmbed } from 'vecbox';
11
10
 
@@ -15,47 +14,53 @@ console.log(result.embedding); // [0.1, 0.2, ...]
15
14
  console.log(result.provider); // 'llamacpp' | 'openai' | 'gemini' | 'mistral'
16
15
  ```
17
16
 
18
- ## Installation
17
+ ## Why Vecbox?
18
+
19
+ **Universal API** - Write once, run anywhere. Switch providers without changing code.
20
+
21
+ **Local-First** - Runs on your machine with Llama.cpp. No API costs, no data leaving your server, full privacy.
19
22
 
23
+ **Production Ready** - Cloud APIs (OpenAI, Gemini, Mistral) available when you need scale or specific models.
24
+
25
+ **Native Speed** - C++ bindings via N-API make local embeddings 10x faster than HTTP-based solutions.
26
+
27
+ ## Installation
20
28
  ```bash
21
29
  npm install vecbox
22
30
  # or
23
31
  pnpm add vecbox
24
32
  ```
25
33
 
26
- **Zero setup required!** Everything is included - native N-API module automatically compiled during installation.
34
+ The native module compiles automatically during installation. No manual build steps required.
27
35
 
28
36
  ## Quick Start
29
37
 
30
- ### Auto-detection (Recommended)
38
+ ### Auto Mode (Recommended)
31
39
 
40
+ Let Vecbox choose the best available provider:
32
41
  ```typescript
33
42
  import { autoEmbed } from 'vecbox';
34
43
 
35
- // Automatically picks the best available provider
36
- const result = await autoEmbed({ text: 'Your text' });
37
- console.log(result.embedding); // [0.1, 0.2, ...]
38
- console.log(result.provider); // 'llamacpp' | 'openai' | 'gemini' | 'mistral'
44
+ const result = await autoEmbed({ text: 'Your text here' });
45
+ console.log(result.embedding); // [0.1, 0.2, ...]
46
+ console.log(result.provider); // Shows which provider was used
39
47
  ```
40
48
 
41
- ### Specific Provider
49
+ Priority order: Llama.cpp (local) → OpenAI → Gemini → Mistral
42
50
 
51
+ ### Specific Provider
43
52
  ```typescript
44
53
  import { embed } from 'vecbox';
45
54
 
46
- // Use specific provider
55
+ // OpenAI
47
56
  const result = await embed(
48
57
  { provider: 'openai', apiKey: process.env.OPENAI_API_KEY },
49
58
  { text: 'Your text' }
50
59
  );
51
60
  ```
52
61
 
53
- ### File Input
54
-
62
+ ### From Files
55
63
  ```typescript
56
- import { embed } from 'vecbox';
57
-
58
- // Embed text from files
59
64
  const result = await embed(
60
65
  { provider: 'gemini', apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY },
61
66
  { filePath: './document.txt' }
@@ -63,14 +68,11 @@ const result = await embed(
63
68
  ```
64
69
 
65
70
  ### Batch Processing
66
-
67
71
  ```typescript
68
- import { embed } from 'vecbox';
69
-
70
72
  const inputs = [
71
- { text: 'First text' },
72
- { text: 'Second text' },
73
- { text: 'Third text' }
73
+ { text: 'First document' },
74
+ { text: 'Second document' },
75
+ { text: 'Third document' }
74
76
  ];
75
77
 
76
78
  const result = await embed(
@@ -81,60 +83,60 @@ const result = await embed(
81
83
  console.log(result.embeddings.length); // 3
82
84
  ```
83
85
 
84
- ## 🚀 Local Llama.cpp with Native N-API
86
+ ## Providers
85
87
 
86
- **Automatic Native Detection:**
87
- ```typescript
88
- import { autoEmbed } from 'vecbox';
88
+ ### Llama.cpp (Local - Free & Private)
89
89
 
90
- // Automatically uses native N-API when available
91
- const result = await autoEmbed({ text: 'Your text' });
92
- console.log(result.provider); // 'llamacpp' (native)
90
+ **Advantages:**
91
+ - Zero API costs
92
+ - ✅ Full privacy (data never leaves your machine)
93
+ - ✅ Works offline
94
+ - ✅ Native C++ performance via N-API
95
+
96
+ **Setup:**
97
+ ```bash
98
+ # 1. Download a GGUF embedding model
99
+ wget https://huggingface.co/nomic-ai/nomic-embed-text-v1.5-GGUF/resolve/main/nomic-embed-text-v1.5.Q4_K_M.gguf
100
+
101
+ # 2. Place in your project
102
+ mkdir models
103
+ mv nomic-embed-text-v1.5.Q4_K_M.gguf models/
93
104
  ```
94
105
 
95
- **Manual Native Configuration:**
106
+ **Usage:**
96
107
  ```typescript
97
- import { embed } from 'vecbox';
108
+ // Auto-detect (uses local model automatically)
109
+ const result = await autoEmbed({ text: 'Your text' });
98
110
 
99
- // Force native module usage
111
+ // Explicit path
100
112
  const result = await embed(
101
113
  { provider: 'llamacpp', model: './models/nomic-embed-text-v1.5.Q4_K_M.gguf' },
102
114
  { text: 'Your text' }
103
115
  );
104
116
  ```
105
117
 
106
- **Setup for Local Models:**
107
- ```bash
108
- # Download a GGUF embedding model
109
- wget https://huggingface.co/nomic-ai/nomic-embed-text-v1.5-GGUF/resolve/main/nomic-embed-text-v1.5.Q4_K_M.gguf
110
-
111
- # Place it in your project directory
112
- mkdir models && mv nomic-embed-text-v1.5.Q4_K_M.gguf models/
113
- ```
114
-
115
- ## 🌍 Environment Variables
116
-
117
- ```bash
118
- # .env file
119
- OPENAI_API_KEY=sk-...
120
- GOOGLE_GENERATIVE_AI_API_KEY=...
121
- MISTRAL_API_KEY=...
122
- ```
123
-
124
- ## 📚 Providers
118
+ **Recommended Models:**
119
+ - `nomic-embed-text-v1.5.Q4_K_M.gguf` (81MB) - Best overall
120
+ - `bge-base-en-v1.5.Q4_K_M.gguf` (133MB) - Higher quality
121
+ - `bge-small-en-v1.5.Q4_0.gguf` (33MB) - Fastest, smaller
125
122
 
126
123
  ### OpenAI
127
124
  ```typescript
128
125
  await embed(
129
126
  {
130
127
  provider: 'openai',
131
- model: 'text-embedding-3-small', // or text-embedding-3-large
128
+ model: 'text-embedding-3-small', // or 'text-embedding-3-large'
132
129
  apiKey: process.env.OPENAI_API_KEY
133
130
  },
134
131
  { text: 'Your text' }
135
132
  );
136
133
  ```
137
- **Setup:** Get API key at [platform.openai.com](https://platform.openai.com)
134
+
135
+ **Setup:** Get API key at [platform.openai.com/api-keys](https://platform.openai.com/api-keys)
136
+
137
+ **Models:**
138
+ - `text-embedding-3-small` - Fast, cost-effective
139
+ - `text-embedding-3-large` - Highest quality
138
140
 
139
141
  ### Google Gemini
140
142
  ```typescript
@@ -147,9 +149,10 @@ await embed(
147
149
  { text: 'Your text' }
148
150
  );
149
151
  ```
150
- **Setup:** Get API key at [aistudio.google.com](https://aistudio.google.com)
151
152
 
152
- ### Mistral
153
+ **Setup:** Get API key at [aistudio.google.com/apikey](https://aistudio.google.com/apikey)
154
+
155
+ ### Mistral AI
153
156
  ```typescript
154
157
  await embed(
155
158
  {
@@ -160,59 +163,39 @@ await embed(
160
163
  { text: 'Your text' }
161
164
  );
162
165
  ```
163
- **Setup:** Get API key at [mistral.ai](https://mistral.ai)
164
166
 
165
- ### Llama.cpp (Local)
166
- ```typescript
167
- await embed(
168
- { provider: 'llamacpp', model: './models/nomic-embed-text-v1.5.Q4_K_M.gguf' },
169
- { text: 'Your text' }
170
- );
171
- ```
172
- **Setup:** Download GGUF model and place in your project directory
167
+ **Setup:** Get API key at [console.mistral.ai](https://console.mistral.ai)
173
168
 
174
- ## 🚀 Features
169
+ ## Environment Variables
175
170
 
176
- - **🎯 One API, Multiple Providers** - Switch between OpenAI, Gemini, Mistral, or local Llama.cpp
177
- - **🤖 Auto-Detection** - Automatically picks the best available provider
178
- - **⚡ Native Performance** - Llama.cpp integration with N-API (10x faster than HTTP)
179
- - **🔄 Smart Fallbacks** - Never fails, always has a backup provider
180
- - **📁 File Support** - Embed text from files directly
181
- - **📦 Batch Processing** - Process multiple texts efficiently
182
- - **🛡️ Type Safe** - Full TypeScript support
183
- - **🌍 Zero Dependencies** - No external downloads or setup required
171
+ Create a `.env` file in your project root:
172
+ ```bash
173
+ # Optional - only needed for cloud providers
174
+ OPENAI_API_KEY=sk-...
175
+ GOOGLE_GENERATIVE_AI_API_KEY=...
176
+ MISTRAL_API_KEY=...
177
+ ```
184
178
 
185
- ## 📖 API Reference
179
+ Vecbox works without any API keys when using Llama.cpp locally.
186
180
 
187
- ### `autoEmbed(input)`
181
+ ## API Reference
188
182
 
189
- Auto-detects best provider in priority order:
190
- 1. **Llama.cpp** (Local & Free)
191
- 2. **OpenAI** (if API key available)
192
- 3. **Gemini** (if API key available)
193
- 4. **Mistral** (if API key available)
183
+ ### `autoEmbed(input: Input): Promise<Result>`
194
184
 
195
- ```typescript
196
- await autoEmbed({ text: string } | { filePath: string })
197
- ```
198
-
199
- ### `embed(config, input)`
185
+ Automatically selects the best available provider.
200
186
 
201
- Explicit provider selection.
187
+ **Input:**
202
188
  ```typescript
203
- await embed(
204
- { provider, model?, apiKey?, baseUrl?, timeout?, maxRetries? },
205
- { text: string } | { filePath: string } | Array
206
- )
189
+ { text: string } | { filePath: string }
207
190
  ```
208
191
 
209
192
  **Returns:**
210
193
  ```typescript
211
194
  {
212
- embedding: number[],
213
- dimensions: number,
214
- provider: string,
215
- model: string,
195
+ embedding: number[]; // The embedding vector
196
+ dimensions: number; // Vector dimensions
197
+ provider: string; // Which provider was used
198
+ model: string; // Model name
216
199
  usage?: {
217
200
  promptTokens?: number;
218
201
  totalTokens?: number;
@@ -220,94 +203,215 @@ await embed(
220
203
  }
221
204
  ```
222
205
 
223
- ## 🧪 Examples
206
+ ### `embed(config: Config, input: Input | Input[]): Promise<Result>`
207
+
208
+ Use a specific provider.
209
+
210
+ **Config:**
211
+ ```typescript
212
+ {
213
+ provider: 'llamacpp' | 'openai' | 'gemini' | 'mistral';
214
+ model?: string; // Provider-specific model
215
+ apiKey?: string; // Required for cloud providers
216
+ baseUrl?: string; // Custom API endpoint
217
+ timeout?: number; // Request timeout in ms
218
+ maxRetries?: number; // Retry attempts
219
+ }
220
+ ```
221
+
222
+ **Input:**
223
+ ```typescript
224
+ { text: string } | { filePath: string } | Array<{text: string} | {filePath: string}>
225
+ ```
226
+
227
+ **Returns:** Same as `autoEmbed`, but `embeddings: number[][]` for batch inputs.
228
+
229
+ ## Examples
224
230
 
225
231
  ### Semantic Search
226
232
  ```typescript
227
- function cosineSimilarity(vecA: number[], vecB: number[]): number {
228
- const dotProduct = vecA.reduce((sum, val, i) => sum + val * vecB[i], 0);
229
- const magnitudeA = Math.sqrt(vecA.reduce((sum, val) => sum + val * val, 0));
230
- const magnitudeB = Math.sqrt(vecB.reduce((sum, val) => sum + val * val, 0));
231
- return dotProduct / (magnitudeA * magnitudeB);
233
+ import { autoEmbed } from 'vecbox';
234
+
235
+ function cosineSimilarity(a: number[], b: number[]): number {
236
+ const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
237
+ const magA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
238
+ const magB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
239
+ return dotProduct / (magA * magB);
232
240
  }
233
241
 
234
- const query = await autoEmbed({ text: 'machine learning' });
235
- const docs = await Promise.all(
236
- documents.map(doc => autoEmbed({ text: doc }))
237
- );
242
+ // Embed query and documents
243
+ const query = await autoEmbed({ text: 'machine learning tutorials' });
244
+ const docs = await Promise.all([
245
+ autoEmbed({ text: 'Introduction to neural networks' }),
246
+ autoEmbed({ text: 'Python web scraping guide' }),
247
+ autoEmbed({ text: 'Deep learning fundamentals' })
248
+ ]);
238
249
 
239
- // Find most similar
240
- const scores = docs.map(doc =>
250
+ // Calculate similarity scores
251
+ const similarities = docs.map(doc =>
241
252
  cosineSimilarity(query.embedding, doc.embedding)
242
253
  );
243
- const mostSimilar = scores.indexOf(Math.max(...scores));
244
- console.log(`Best match: ${documents[mostSimilar]}`);
254
+
255
+ // Find best match
256
+ const bestIdx = similarities.indexOf(Math.max(...similarities));
257
+ console.log(`Best match: Document ${bestIdx + 1} (score: ${similarities[bestIdx].toFixed(3)})`);
245
258
  ```
246
259
 
247
- ### File Processing
260
+ ### Batch File Processing
248
261
  ```typescript
262
+ import { embed } from 'vecbox';
249
263
  import { readdir } from 'fs/promises';
250
264
  import { join } from 'path';
251
265
 
252
- async function embedAllFiles(dirPath: string) {
266
+ async function embedDirectory(dirPath: string) {
253
267
  const files = await readdir(dirPath);
254
- const textFiles = files.filter(file => file.endsWith('.txt'));
268
+ const textFiles = files.filter(f => f.endsWith('.txt'));
255
269
 
256
- const inputs = textFiles.map(file => ({
257
- filePath: join(dirPath, file)
258
- }));
259
-
260
- const results = await embed(
270
+ // Process all files in one batch
271
+ const result = await embed(
261
272
  { provider: 'llamacpp' },
262
- inputs
273
+ textFiles.map(file => ({ filePath: join(dirPath, file) }))
263
274
  );
264
275
 
265
- return textFiles.map((file, index) => ({
266
- file,
267
- embedding: results.embeddings[index]
276
+ return textFiles.map((file, i) => ({
277
+ filename: file,
278
+ embedding: result.embeddings[i]
268
279
  }));
269
280
  }
270
281
 
271
- const embeddings = await embedAllFiles('./documents');
272
- console.log(`Processed ${embeddings.length} files`);
282
+ const results = await embedDirectory('./documents');
283
+ console.log(`Embedded ${results.length} files`);
273
284
  ```
274
285
 
275
- ## 🐛 Troubleshooting
286
+ ### Document Clustering
287
+ ```typescript
288
+ import { autoEmbed } from 'vecbox';
289
+
290
+ const documents = [
291
+ 'The cat sat on the mat',
292
+ 'Dogs are loyal pets',
293
+ 'Python is a programming language',
294
+ 'JavaScript runs in browsers',
295
+ 'Birds can fly high'
296
+ ];
297
+
298
+ // Get embeddings
299
+ const embeddings = await Promise.all(
300
+ documents.map(doc => autoEmbed({ text: doc }))
301
+ );
302
+
303
+ // Simple clustering by similarity threshold
304
+ function findClusters(embeddings: number[][], threshold = 0.7) {
305
+ const clusters: number[][] = [];
306
+ const assigned = new Set<number>();
307
+
308
+ embeddings.forEach((emb, i) => {
309
+ if (assigned.has(i)) return;
310
+
311
+ const cluster = [i];
312
+ assigned.add(i);
313
+
314
+ embeddings.forEach((other, j) => {
315
+ if (i !== j && !assigned.has(j)) {
316
+ const sim = cosineSimilarity(emb, other);
317
+ if (sim > threshold) {
318
+ cluster.push(j);
319
+ assigned.add(j);
320
+ }
321
+ }
322
+ });
323
+
324
+ clusters.push(cluster);
325
+ });
326
+
327
+ return clusters;
328
+ }
329
+
330
+ const clusters = findClusters(embeddings.map(e => e.embedding));
331
+ console.log('Clusters:', clusters);
332
+ // Output: [[0, 1, 4], [2, 3]] - animals vs programming
333
+ ```
334
+
335
+ ## Troubleshooting
276
336
 
277
337
  ### Native Module Issues
278
338
 
279
- **Problem:** `binding.createModel is not a function`
339
+ **Error: `Cannot find module './build/Release/vecbox.node'`**
340
+
341
+ The native module failed to compile. Rebuild it:
280
342
  ```bash
281
- # Solution: Rebuild native module
282
343
  npm run build:native
344
+ # or
345
+ node-gyp rebuild
346
+ ```
347
+
348
+ **Error: `binding.createModel is not a function`**
349
+
350
+ Your native module is outdated. Clean and rebuild:
351
+ ```bash
352
+ rm -rf build/
353
+ npm install
283
354
  ```
284
355
 
285
- **Problem:** Model file not found
356
+ ### Model Loading Issues
357
+
358
+ **Error: `Model file not found`**
359
+
360
+ Check that the model path is correct:
286
361
  ```bash
287
- # Solution: Check model path
288
- ls -la models/ # Verify model exists
362
+ ls -la models/ # Verify model exists
363
+ pwd # Check current directory
364
+ ```
365
+
366
+ Use absolute paths if relative paths fail:
367
+ ```typescript
368
+ const path = require('path');
369
+ const modelPath = path.join(__dirname, 'models', 'model.gguf');
289
370
  ```
290
371
 
291
- ### Performance Issues
372
+ ### Performance
292
373
 
293
- **Slow embeddings:**
294
- - Check model size (smaller = faster)
295
- - Use batch processing for multiple texts
296
- - Ensure native module is being used (not HTTP fallback)
374
+ **Embeddings are slow:**
375
+ - Use smaller quantized models (Q4_K_M is recommended)
376
+ - Process texts in batches instead of one-by-one
377
+ - Verify native module is loaded (check `result.provider === 'llamacpp'`)
297
378
 
298
- ## 📄 License
379
+ **High memory usage:**
380
+ - Models stay loaded in memory for performance
381
+ - Use smaller models (bge-small instead of bge-large)
382
+ - Process files in chunks for very large datasets
383
+
384
+ ## Features
385
+
386
+ - **🎯 Provider Agnostic** - One API for all embedding providers
387
+ - **🤖 Smart Auto-Detection** - Automatically uses the best available option
388
+ - **⚡ Native Performance** - C++ via N-API for maximum speed
389
+ - **🔄 Automatic Fallbacks** - Seamlessly switches providers if one fails
390
+ - **📁 File Support** - Read and embed text files directly
391
+ - **📦 Batch Processing** - Efficient multi-document embedding
392
+ - **🛡️ TypeScript First** - Full type safety and IDE autocomplete
393
+ - **🌍 Zero Setup** - Native module compiles automatically on install
394
+ - **🔒 Privacy-First** - Local processing keeps your data private
395
+
396
+ ## License
299
397
 
300
398
  MIT License - see [LICENSE](LICENSE) file for details.
301
399
 
302
- ## 🙏 Acknowledgments
400
+ ## Credits
401
+
402
+ Built on top of excellent open-source projects:
403
+
404
+ - [llama.cpp](https://github.com/ggml-org/llama.cpp) - High-performance LLM inference
405
+ - [OpenAI](https://openai.com/) - text-embedding-3 models
406
+ - [Google Gemini](https://ai.google.dev/) - gemini-embedding models
407
+ - [Mistral AI](https://mistral.ai/) - mistral-embed model
408
+
409
+ ## Contributing
303
410
 
304
- - [Llama.cpp](https://github.com/ggml-org/llama.cpp) - Core embedding engine
305
- - [OpenAI](https://openai.com/) - Embedding API
306
- - [Google Gemini](https://ai.google.dev/) - Embedding API
307
- - [Mistral AI](https://mistral.ai/) - Embedding API
411
+ Issues and pull requests welcome at [github.com/box-safe/vecbox](https://github.com/box-safe/vecbox)
308
412
 
309
413
  ---
310
414
 
311
- **⭐ Star us on GitHub!** [github.com/box-safe/vecbox](https://github.com/box-safe/vecbox)
415
+ **⭐ If Vecbox saves you time, star us on GitHub!**
312
416
 
313
- **Made with ❤️ by the Vecbox Team**
417
+ **Made with ❤️ for developers who value simplicity and performance**