@sparkleideas/embeddings 3.0.0-alpha.15 → 3.0.0-alpha.17
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 +17 -308
- package/dist/__tests__/embedding-service.test.d.ts +2 -0
- package/dist/__tests__/embedding-service.test.d.ts.map +1 -0
- package/dist/__tests__/embedding-service.test.js +98 -0
- package/dist/__tests__/embedding-service.test.js.map +1 -0
- package/dist/embedding-service.d.ts +113 -0
- package/dist/embedding-service.d.ts.map +1 -0
- package/dist/embedding-service.js +543 -0
- package/dist/embedding-service.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +178 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/package.json +7 -19
- package/src/embedding-service.ts +6 -478
- package/src/index.ts +1 -78
- package/src/types.ts +3 -62
- package/src/chunking.ts +0 -351
- package/src/hyperbolic.ts +0 -458
- package/src/neural-integration.ts +0 -295
- package/src/normalization.ts +0 -267
- package/src/persistent-cache.ts +0 -410
package/README.md
CHANGED
|
@@ -4,27 +4,26 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/@claude-flow/embeddings)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
|
-
[](https://github.com/ruvnet/claude-flow)
|
|
8
8
|
|
|
9
|
-
> High-performance embedding generation module for Claude Flow V3 - multi-provider support
|
|
9
|
+
> High-performance embedding generation module for Claude Flow V3 - multi-provider support, LRU caching, batch processing, and similarity computation.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
- **
|
|
15
|
-
- **Auto-Install** - Automatically installs agentic-flow when using `provider: 'auto'`
|
|
16
|
-
- **Smart Fallback** - Graceful fallback chain: agentic-flow → transformers → mock
|
|
17
|
-
- **LRU + Disk Caching** - In-memory LRU + SQLite persistent cache with TTL
|
|
13
|
+
- **Multiple Providers** - OpenAI, Transformers.js (local), and Mock for testing
|
|
14
|
+
- **LRU Caching** - Intelligent caching with configurable size and hit rate tracking
|
|
18
15
|
- **Batch Processing** - Efficient batch embedding with partial cache hits
|
|
19
16
|
- **Similarity Functions** - Cosine, Euclidean, and dot product metrics
|
|
20
|
-
- **
|
|
17
|
+
- **Event System** - Observable embedding operations with event listeners
|
|
18
|
+
- **Type-Safe** - Full TypeScript support with comprehensive type definitions
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
## Performance Targets
|
|
21
|
+
|
|
22
|
+
| Operation | API Provider | Local Provider |
|
|
23
|
+
|-----------|--------------|----------------|
|
|
24
|
+
| Single embedding | <100ms | <50ms |
|
|
25
|
+
| Batch (10 items) | <500ms | <200ms |
|
|
26
|
+
| Cache hit | <1ms | <1ms |
|
|
28
27
|
|
|
29
28
|
## Installation
|
|
30
29
|
|
|
@@ -67,45 +66,19 @@ const similarity = cosineSimilarity(
|
|
|
67
66
|
console.log(`Similarity: ${similarity.toFixed(4)}`);
|
|
68
67
|
```
|
|
69
68
|
|
|
70
|
-
## CLI Usage
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
# Generate embedding from CLI
|
|
74
|
-
claude-flow embeddings embed "Your text here"
|
|
75
|
-
|
|
76
|
-
# Batch embed from file
|
|
77
|
-
claude-flow embeddings batch documents.txt -o embeddings.json
|
|
78
|
-
|
|
79
|
-
# Similarity search
|
|
80
|
-
claude-flow embeddings search "query" --index ./vectors
|
|
81
|
-
|
|
82
|
-
# Initialize agentic-flow model
|
|
83
|
-
claude-flow embeddings init --provider agentic-flow
|
|
84
|
-
```
|
|
85
|
-
|
|
86
69
|
## API Reference
|
|
87
70
|
|
|
88
71
|
### Factory Functions
|
|
89
72
|
|
|
90
73
|
```typescript
|
|
91
|
-
import {
|
|
92
|
-
createEmbeddingService,
|
|
93
|
-
createEmbeddingServiceAsync,
|
|
94
|
-
getEmbedding
|
|
95
|
-
} from '@claude-flow/embeddings';
|
|
74
|
+
import { createEmbeddingService, getEmbedding } from '@claude-flow/embeddings';
|
|
96
75
|
|
|
97
|
-
//
|
|
76
|
+
// Create a service instance
|
|
98
77
|
const service = createEmbeddingService({
|
|
99
78
|
provider: 'openai',
|
|
100
79
|
apiKey: 'your-api-key',
|
|
101
80
|
model: 'text-embedding-3-small',
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
// Async: Auto-select best provider with fallback
|
|
105
|
-
const autoService = await createEmbeddingServiceAsync({
|
|
106
|
-
provider: 'auto', // agentic-flow → transformers → mock
|
|
107
|
-
autoInstall: true, // Install agentic-flow if missing
|
|
108
|
-
fallback: 'transformers', // Custom fallback
|
|
81
|
+
cacheSize: 1000,
|
|
109
82
|
});
|
|
110
83
|
|
|
111
84
|
// Quick one-off embedding
|
|
@@ -135,22 +108,6 @@ const result = await service.embed('Your text here');
|
|
|
135
108
|
console.log('Tokens used:', result.usage?.totalTokens);
|
|
136
109
|
```
|
|
137
110
|
|
|
138
|
-
### Agentic-Flow Provider (Fastest)
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
import { AgenticFlowEmbeddingService } from '@claude-flow/embeddings';
|
|
142
|
-
|
|
143
|
-
const service = new AgenticFlowEmbeddingService({
|
|
144
|
-
provider: 'agentic-flow',
|
|
145
|
-
modelId: 'default', // Uses optimized ONNX model
|
|
146
|
-
cacheSize: 256,
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// 75x faster than Transformers.js (3ms vs 233ms)
|
|
150
|
-
const result = await service.embed('Your text here');
|
|
151
|
-
console.log(`ONNX embedding in ${result.latencyMs}ms`);
|
|
152
|
-
```
|
|
153
|
-
|
|
154
111
|
### Transformers.js Provider (Local)
|
|
155
112
|
|
|
156
113
|
```typescript
|
|
@@ -286,17 +243,10 @@ service.removeEventListener(listener);
|
|
|
286
243
|
|
|
287
244
|
| Provider | Latency | Quality | Cost | Offline |
|
|
288
245
|
|----------|---------|---------|------|---------|
|
|
289
|
-
| **Agentic-Flow** | ~3ms | Good | Free | Yes |
|
|
290
246
|
| **OpenAI** | ~50-100ms | Excellent | $0.02-0.13/1M tokens | No |
|
|
291
|
-
| **Transformers.js** | ~
|
|
247
|
+
| **Transformers.js** | ~20-50ms | Good | Free | Yes |
|
|
292
248
|
| **Mock** | <1ms | N/A | Free | Yes |
|
|
293
249
|
|
|
294
|
-
### Agentic-Flow (Recommended)
|
|
295
|
-
|
|
296
|
-
| Model | Dimensions | Speed | Best For |
|
|
297
|
-
|-------|------------|-------|----------|
|
|
298
|
-
| `default` | 384 | 3ms | General purpose, fastest |
|
|
299
|
-
|
|
300
250
|
### OpenAI Models
|
|
301
251
|
|
|
302
252
|
| Model | Dimensions | Max Tokens | Best For |
|
|
@@ -322,9 +272,7 @@ import type {
|
|
|
322
272
|
EmbeddingConfig,
|
|
323
273
|
OpenAIEmbeddingConfig,
|
|
324
274
|
TransformersEmbeddingConfig,
|
|
325
|
-
AgenticFlowEmbeddingConfig,
|
|
326
275
|
MockEmbeddingConfig,
|
|
327
|
-
AutoEmbeddingConfig,
|
|
328
276
|
|
|
329
277
|
// Result types
|
|
330
278
|
EmbeddingResult,
|
|
@@ -401,245 +349,6 @@ const queryResult = await embeddings.embed('Search query');
|
|
|
401
349
|
const results = await index.search(new Float32Array(queryResult.embedding), 5);
|
|
402
350
|
```
|
|
403
351
|
|
|
404
|
-
## Document Chunking
|
|
405
|
-
|
|
406
|
-
Split long documents into overlapping chunks for embedding:
|
|
407
|
-
|
|
408
|
-
```typescript
|
|
409
|
-
import { chunkText, estimateTokens, reconstructFromChunks } from '@claude-flow/embeddings';
|
|
410
|
-
|
|
411
|
-
// Chunk by sentence (default)
|
|
412
|
-
const result = chunkText(longDocument, {
|
|
413
|
-
maxChunkSize: 512,
|
|
414
|
-
overlap: 50,
|
|
415
|
-
strategy: 'sentence', // 'character' | 'sentence' | 'paragraph' | 'token'
|
|
416
|
-
minChunkSize: 100,
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
console.log('Chunks:', result.totalChunks);
|
|
420
|
-
result.chunks.forEach((chunk, i) => {
|
|
421
|
-
console.log(`Chunk ${i}: ${chunk.length} chars, ~${chunk.tokenCount} tokens`);
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
// Estimate tokens
|
|
425
|
-
const tokens = estimateTokens('Hello world'); // ~3 tokens
|
|
426
|
-
|
|
427
|
-
// Reconstruct (approximate)
|
|
428
|
-
const reconstructed = reconstructFromChunks(result.chunks);
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
## Normalization
|
|
432
|
-
|
|
433
|
-
Normalize embeddings for consistent similarity computation:
|
|
434
|
-
|
|
435
|
-
```typescript
|
|
436
|
-
import {
|
|
437
|
-
l2Normalize, // Unit vector (Euclidean norm = 1)
|
|
438
|
-
l1Normalize, // Manhattan norm = 1
|
|
439
|
-
minMaxNormalize, // Values in [0, 1]
|
|
440
|
-
zScoreNormalize, // Mean 0, std 1
|
|
441
|
-
normalize, // Generic with type option
|
|
442
|
-
l2Norm,
|
|
443
|
-
isNormalized,
|
|
444
|
-
} from '@claude-flow/embeddings';
|
|
445
|
-
|
|
446
|
-
const embedding = new Float32Array([3, 4, 0]);
|
|
447
|
-
|
|
448
|
-
// L2 normalize (most common for cosine similarity)
|
|
449
|
-
const l2 = l2Normalize(embedding); // [0.6, 0.8, 0]
|
|
450
|
-
console.log('L2 norm:', l2Norm(l2)); // 1.0
|
|
451
|
-
|
|
452
|
-
// Check if already normalized
|
|
453
|
-
console.log(isNormalized(l2)); // true
|
|
454
|
-
console.log(isNormalized(embedding)); // false
|
|
455
|
-
|
|
456
|
-
// Generic normalize with type
|
|
457
|
-
const normalized = normalize(embedding, { type: 'l2' });
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
## Hyperbolic Embeddings (Poincaré Ball)
|
|
461
|
-
|
|
462
|
-
Transform embeddings to hyperbolic space for better hierarchical representation:
|
|
463
|
-
|
|
464
|
-
```typescript
|
|
465
|
-
import {
|
|
466
|
-
euclideanToPoincare,
|
|
467
|
-
poincareToEuclidean,
|
|
468
|
-
hyperbolicDistance,
|
|
469
|
-
mobiusAdd,
|
|
470
|
-
isInPoincareBall,
|
|
471
|
-
batchEuclideanToPoincare,
|
|
472
|
-
hyperbolicCentroid,
|
|
473
|
-
} from '@claude-flow/embeddings';
|
|
474
|
-
|
|
475
|
-
// Convert Euclidean embedding to Poincaré ball
|
|
476
|
-
const euclidean = new Float32Array([0.5, 0.3, 0.2]);
|
|
477
|
-
const poincare = euclideanToPoincare(euclidean);
|
|
478
|
-
|
|
479
|
-
// Check if point is in the ball
|
|
480
|
-
console.log(isInPoincareBall(poincare)); // true
|
|
481
|
-
|
|
482
|
-
// Round-trip conversion
|
|
483
|
-
const back = poincareToEuclidean(poincare);
|
|
484
|
-
|
|
485
|
-
// Hyperbolic distance (geodesic in Poincaré ball)
|
|
486
|
-
const a = euclideanToPoincare(new Float32Array([0.1, 0.2, 0.1]));
|
|
487
|
-
const b = euclideanToPoincare(new Float32Array([0.3, 0.1, 0.2]));
|
|
488
|
-
const dist = hyperbolicDistance(a, b);
|
|
489
|
-
|
|
490
|
-
// Möbius addition (hyperbolic "plus")
|
|
491
|
-
const sum = mobiusAdd(a, b);
|
|
492
|
-
|
|
493
|
-
// Batch conversion
|
|
494
|
-
const embeddings = [vec1, vec2, vec3];
|
|
495
|
-
const hyperbolic = batchEuclideanToPoincare(embeddings);
|
|
496
|
-
|
|
497
|
-
// Hyperbolic centroid (Fréchet mean)
|
|
498
|
-
const centroid = hyperbolicCentroid(hyperbolic);
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
### Why Hyperbolic?
|
|
502
|
-
|
|
503
|
-
Hyperbolic space has natural properties for representing hierarchical data:
|
|
504
|
-
- **Exponential growth** - Tree-like structures fit naturally
|
|
505
|
-
- **Better hierarchy** - Parent-child relationships preserved
|
|
506
|
-
- **Lower distortion** - Taxonomies represented with less error
|
|
507
|
-
|
|
508
|
-
## Neural Substrate Integration
|
|
509
|
-
|
|
510
|
-
Access agentic-flow's neural features for advanced embedding operations:
|
|
511
|
-
|
|
512
|
-
```typescript
|
|
513
|
-
import {
|
|
514
|
-
NeuralEmbeddingService,
|
|
515
|
-
createNeuralService,
|
|
516
|
-
isNeuralAvailable,
|
|
517
|
-
listEmbeddingModels,
|
|
518
|
-
downloadEmbeddingModel,
|
|
519
|
-
} from '@claude-flow/embeddings';
|
|
520
|
-
|
|
521
|
-
// Check if neural features are available
|
|
522
|
-
const available = await isNeuralAvailable();
|
|
523
|
-
|
|
524
|
-
// Create neural service
|
|
525
|
-
const neural = createNeuralService({ dimension: 384 });
|
|
526
|
-
await neural.init();
|
|
527
|
-
|
|
528
|
-
if (neural.isAvailable()) {
|
|
529
|
-
// Semantic drift detection
|
|
530
|
-
await neural.setDriftBaseline('Initial context about the topic');
|
|
531
|
-
const drift = await neural.detectDrift('New input to check for drift');
|
|
532
|
-
console.log('Drift:', drift?.trend); // 'stable' | 'drifting' | 'accelerating'
|
|
533
|
-
|
|
534
|
-
// Memory with interference detection
|
|
535
|
-
const stored = await neural.storeMemory('mem-1', 'Important information');
|
|
536
|
-
console.log('Interference:', stored?.interference);
|
|
537
|
-
|
|
538
|
-
// Recall by similarity
|
|
539
|
-
const memories = await neural.recallMemories('query', 5);
|
|
540
|
-
|
|
541
|
-
// Swarm coordination
|
|
542
|
-
await neural.addSwarmAgent('agent-1', 'researcher');
|
|
543
|
-
const coordination = await neural.coordinateSwarm('Analyze this task');
|
|
544
|
-
|
|
545
|
-
// Coherence checking
|
|
546
|
-
await neural.calibrateCoherence(['good output 1', 'good output 2']);
|
|
547
|
-
const coherence = await neural.checkCoherence('Output to check');
|
|
548
|
-
|
|
549
|
-
// Health status
|
|
550
|
-
const health = neural.health();
|
|
551
|
-
console.log('Memory count:', health?.memoryCount);
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// List available ONNX models
|
|
555
|
-
const models = await listEmbeddingModels();
|
|
556
|
-
console.log(models);
|
|
557
|
-
// [{ id: 'all-MiniLM-L6-v2', dimension: 384, size: '23MB', ... }]
|
|
558
|
-
|
|
559
|
-
// Download model
|
|
560
|
-
const path = await downloadEmbeddingModel('all-MiniLM-L6-v2', '.models');
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
## Persistent Disk Cache
|
|
564
|
-
|
|
565
|
-
SQLite-backed persistent cache for embeddings:
|
|
566
|
-
|
|
567
|
-
```typescript
|
|
568
|
-
import { PersistentEmbeddingCache, isPersistentCacheAvailable } from '@claude-flow/embeddings';
|
|
569
|
-
|
|
570
|
-
// Check if SQLite is available
|
|
571
|
-
const hasSQLite = await isPersistentCacheAvailable();
|
|
572
|
-
|
|
573
|
-
// Create persistent cache
|
|
574
|
-
const cache = new PersistentEmbeddingCache({
|
|
575
|
-
dbPath: './embeddings.db', // SQLite database path
|
|
576
|
-
maxSize: 10000, // Max entries before LRU eviction
|
|
577
|
-
ttlMs: 7 * 24 * 60 * 60 * 1000, // 7 day TTL
|
|
578
|
-
});
|
|
579
|
-
|
|
580
|
-
// Initialize
|
|
581
|
-
await cache.init();
|
|
582
|
-
|
|
583
|
-
// Store embedding
|
|
584
|
-
await cache.set('my text', new Float32Array([0.1, 0.2, 0.3]));
|
|
585
|
-
|
|
586
|
-
// Retrieve
|
|
587
|
-
const embedding = await cache.get('my text');
|
|
588
|
-
|
|
589
|
-
// Get stats
|
|
590
|
-
const stats = await cache.getStats();
|
|
591
|
-
console.log('Cache stats:', {
|
|
592
|
-
size: stats.totalEntries,
|
|
593
|
-
hitRate: stats.hitRate,
|
|
594
|
-
avgLatency: stats.avgLatencyMs,
|
|
595
|
-
});
|
|
596
|
-
|
|
597
|
-
// Close when done
|
|
598
|
-
await cache.close();
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
### Enable in Embedding Service
|
|
602
|
-
|
|
603
|
-
```typescript
|
|
604
|
-
const service = createEmbeddingService({
|
|
605
|
-
provider: 'openai',
|
|
606
|
-
apiKey: process.env.OPENAI_API_KEY!,
|
|
607
|
-
persistentCache: {
|
|
608
|
-
enabled: true,
|
|
609
|
-
dbPath: './cache/embeddings.db',
|
|
610
|
-
maxSize: 50000,
|
|
611
|
-
ttlMs: 30 * 24 * 60 * 60 * 1000, // 30 days
|
|
612
|
-
},
|
|
613
|
-
normalization: 'l2', // Auto-normalize embeddings
|
|
614
|
-
});
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
## CLI Commands (New)
|
|
618
|
-
|
|
619
|
-
```bash
|
|
620
|
-
# Document chunking
|
|
621
|
-
claude-flow embeddings chunk document.txt --strategy sentence --max-size 512
|
|
622
|
-
|
|
623
|
-
# Normalize embedding file
|
|
624
|
-
claude-flow embeddings normalize embeddings.json --type l2 -o normalized.json
|
|
625
|
-
|
|
626
|
-
# Convert to hyperbolic
|
|
627
|
-
claude-flow embeddings hyperbolic embeddings.json -o poincare.json
|
|
628
|
-
|
|
629
|
-
# Neural operations
|
|
630
|
-
claude-flow embeddings neural drift --baseline "context" --input "check this"
|
|
631
|
-
claude-flow embeddings neural store --id mem-1 --content "data"
|
|
632
|
-
claude-flow embeddings neural recall "query" --top-k 5
|
|
633
|
-
|
|
634
|
-
# List/download models
|
|
635
|
-
claude-flow embeddings models list
|
|
636
|
-
claude-flow embeddings models download all-MiniLM-L6-v2
|
|
637
|
-
|
|
638
|
-
# Cache management
|
|
639
|
-
claude-flow embeddings cache stats
|
|
640
|
-
claude-flow embeddings cache clear --older-than 7d
|
|
641
|
-
```
|
|
642
|
-
|
|
643
352
|
## Related Packages
|
|
644
353
|
|
|
645
354
|
- [@claude-flow/memory](../memory) - HNSW indexing and vector storage
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-service.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/embedding-service.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for EmbeddingService
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
5
|
+
import { createEmbeddingService, MockEmbeddingService, cosineSimilarity, euclideanDistance, dotProduct, computeSimilarity, } from '../index.js';
|
|
6
|
+
describe('EmbeddingService', () => {
|
|
7
|
+
describe('MockEmbeddingService', () => {
|
|
8
|
+
let service;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
service = new MockEmbeddingService({ provider: 'mock', dimensions: 128 });
|
|
11
|
+
});
|
|
12
|
+
it('should generate embeddings with correct dimensions', async () => {
|
|
13
|
+
const result = await service.embed('Hello, world!');
|
|
14
|
+
expect(result.embedding).toHaveLength(128);
|
|
15
|
+
});
|
|
16
|
+
it('should generate deterministic embeddings for same text', async () => {
|
|
17
|
+
const result1 = await service.embed('test text');
|
|
18
|
+
const result2 = await service.embed('test text');
|
|
19
|
+
// Mock service should be deterministic
|
|
20
|
+
expect(Array.from(result1.embedding)).toEqual(Array.from(result2.embedding));
|
|
21
|
+
});
|
|
22
|
+
it('should handle batch embeddings', async () => {
|
|
23
|
+
const texts = ['text1', 'text2', 'text3'];
|
|
24
|
+
const results = await service.embedBatch(texts);
|
|
25
|
+
expect(results.embeddings).toHaveLength(3);
|
|
26
|
+
// Each embedding should have correct dimensions
|
|
27
|
+
results.embeddings.forEach((emb) => {
|
|
28
|
+
expect(emb.length).toBe(128);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('createEmbeddingService', () => {
|
|
33
|
+
it('should create mock service', () => {
|
|
34
|
+
const service = createEmbeddingService({
|
|
35
|
+
provider: 'mock',
|
|
36
|
+
dimensions: 64,
|
|
37
|
+
});
|
|
38
|
+
expect(service).toBeInstanceOf(MockEmbeddingService);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('Similarity Functions', () => {
|
|
43
|
+
const vec1 = new Float32Array([1, 0, 0]);
|
|
44
|
+
const vec2 = new Float32Array([1, 0, 0]);
|
|
45
|
+
const vec3 = new Float32Array([0, 1, 0]);
|
|
46
|
+
const vec4 = new Float32Array([-1, 0, 0]);
|
|
47
|
+
describe('cosineSimilarity', () => {
|
|
48
|
+
it('should return 1 for identical vectors', () => {
|
|
49
|
+
expect(cosineSimilarity(vec1, vec2)).toBeCloseTo(1);
|
|
50
|
+
});
|
|
51
|
+
it('should return 0 for orthogonal vectors', () => {
|
|
52
|
+
expect(cosineSimilarity(vec1, vec3)).toBeCloseTo(0);
|
|
53
|
+
});
|
|
54
|
+
it('should return -1 for opposite vectors', () => {
|
|
55
|
+
expect(cosineSimilarity(vec1, vec4)).toBeCloseTo(-1);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe('euclideanDistance', () => {
|
|
59
|
+
it('should return 0 for identical vectors', () => {
|
|
60
|
+
expect(euclideanDistance(vec1, vec2)).toBeCloseTo(0);
|
|
61
|
+
});
|
|
62
|
+
it('should return sqrt(2) for unit orthogonal vectors', () => {
|
|
63
|
+
expect(euclideanDistance(vec1, vec3)).toBeCloseTo(Math.sqrt(2));
|
|
64
|
+
});
|
|
65
|
+
it('should return 2 for opposite unit vectors', () => {
|
|
66
|
+
expect(euclideanDistance(vec1, vec4)).toBeCloseTo(2);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('dotProduct', () => {
|
|
70
|
+
it('should return 1 for identical unit vectors', () => {
|
|
71
|
+
expect(dotProduct(vec1, vec2)).toBeCloseTo(1);
|
|
72
|
+
});
|
|
73
|
+
it('should return 0 for orthogonal vectors', () => {
|
|
74
|
+
expect(dotProduct(vec1, vec3)).toBeCloseTo(0);
|
|
75
|
+
});
|
|
76
|
+
it('should return -1 for opposite unit vectors', () => {
|
|
77
|
+
expect(dotProduct(vec1, vec4)).toBeCloseTo(-1);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe('computeSimilarity', () => {
|
|
81
|
+
it('should use cosine metric by default', () => {
|
|
82
|
+
const result = computeSimilarity(vec1, vec2);
|
|
83
|
+
expect(result.metric).toBe('cosine');
|
|
84
|
+
expect(result.score).toBeCloseTo(1);
|
|
85
|
+
});
|
|
86
|
+
it('should support euclidean metric', () => {
|
|
87
|
+
const result = computeSimilarity(vec1, vec3, 'euclidean');
|
|
88
|
+
expect(result.metric).toBe('euclidean');
|
|
89
|
+
expect(result.score).toBeCloseTo(Math.sqrt(2));
|
|
90
|
+
});
|
|
91
|
+
it('should support dot product metric', () => {
|
|
92
|
+
const result = computeSimilarity(vec1, vec4, 'dot');
|
|
93
|
+
expect(result.metric).toBe('dot');
|
|
94
|
+
expect(result.score).toBeCloseTo(-1);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
//# sourceMappingURL=embedding-service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-service.test.js","sourceRoot":"","sources":["../../src/__tests__/embedding-service.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V3 Embedding Service Implementation
|
|
3
|
+
*
|
|
4
|
+
* Production embedding service aligned with agentic-flow@alpha:
|
|
5
|
+
* - OpenAI provider (text-embedding-3-small/large)
|
|
6
|
+
* - Transformers.js provider (local ONNX models)
|
|
7
|
+
* - Mock provider (development/testing)
|
|
8
|
+
*
|
|
9
|
+
* Performance Targets:
|
|
10
|
+
* - Single embedding: <100ms (API), <50ms (local)
|
|
11
|
+
* - Batch embedding: <500ms for 10 items
|
|
12
|
+
* - Cache hit: <1ms
|
|
13
|
+
*/
|
|
14
|
+
import { EventEmitter } from 'events';
|
|
15
|
+
import type { EmbeddingProvider, EmbeddingConfig, OpenAIEmbeddingConfig, TransformersEmbeddingConfig, MockEmbeddingConfig, EmbeddingResult, BatchEmbeddingResult, IEmbeddingService, EmbeddingEvent, EmbeddingEventListener, SimilarityMetric, SimilarityResult } from './types.js';
|
|
16
|
+
declare class LRUCache<K, V> {
|
|
17
|
+
private readonly maxSize;
|
|
18
|
+
private cache;
|
|
19
|
+
private hits;
|
|
20
|
+
private misses;
|
|
21
|
+
constructor(maxSize: number);
|
|
22
|
+
get(key: K): V | undefined;
|
|
23
|
+
set(key: K, value: V): void;
|
|
24
|
+
clear(): void;
|
|
25
|
+
get size(): number;
|
|
26
|
+
get hitRate(): number;
|
|
27
|
+
getStats(): {
|
|
28
|
+
size: number;
|
|
29
|
+
maxSize: number;
|
|
30
|
+
hits: number;
|
|
31
|
+
misses: number;
|
|
32
|
+
hitRate: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
declare abstract class BaseEmbeddingService extends EventEmitter implements IEmbeddingService {
|
|
36
|
+
protected readonly config: EmbeddingConfig;
|
|
37
|
+
abstract readonly provider: EmbeddingProvider;
|
|
38
|
+
protected cache: LRUCache<string, Float32Array>;
|
|
39
|
+
protected embeddingListeners: Set<EmbeddingEventListener>;
|
|
40
|
+
constructor(config: EmbeddingConfig);
|
|
41
|
+
abstract embed(text: string): Promise<EmbeddingResult>;
|
|
42
|
+
abstract embedBatch(texts: string[]): Promise<BatchEmbeddingResult>;
|
|
43
|
+
protected emitEvent(event: EmbeddingEvent): void;
|
|
44
|
+
addEventListener(listener: EmbeddingEventListener): void;
|
|
45
|
+
removeEventListener(listener: EmbeddingEventListener): void;
|
|
46
|
+
clearCache(): void;
|
|
47
|
+
getCacheStats(): {
|
|
48
|
+
size: number;
|
|
49
|
+
maxSize: number;
|
|
50
|
+
hitRate: number;
|
|
51
|
+
};
|
|
52
|
+
shutdown(): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
export declare class OpenAIEmbeddingService extends BaseEmbeddingService {
|
|
55
|
+
readonly provider: EmbeddingProvider;
|
|
56
|
+
private readonly apiKey;
|
|
57
|
+
private readonly model;
|
|
58
|
+
private readonly baseURL;
|
|
59
|
+
private readonly timeout;
|
|
60
|
+
private readonly maxRetries;
|
|
61
|
+
constructor(config: OpenAIEmbeddingConfig);
|
|
62
|
+
embed(text: string): Promise<EmbeddingResult>;
|
|
63
|
+
embedBatch(texts: string[]): Promise<BatchEmbeddingResult>;
|
|
64
|
+
private callOpenAI;
|
|
65
|
+
}
|
|
66
|
+
export declare class TransformersEmbeddingService extends BaseEmbeddingService {
|
|
67
|
+
readonly provider: EmbeddingProvider;
|
|
68
|
+
private pipeline;
|
|
69
|
+
private readonly modelName;
|
|
70
|
+
private initialized;
|
|
71
|
+
constructor(config: TransformersEmbeddingConfig);
|
|
72
|
+
private initialize;
|
|
73
|
+
embed(text: string): Promise<EmbeddingResult>;
|
|
74
|
+
embedBatch(texts: string[]): Promise<BatchEmbeddingResult>;
|
|
75
|
+
}
|
|
76
|
+
export declare class MockEmbeddingService extends BaseEmbeddingService {
|
|
77
|
+
readonly provider: EmbeddingProvider;
|
|
78
|
+
private readonly dimensions;
|
|
79
|
+
private readonly simulatedLatency;
|
|
80
|
+
constructor(config: MockEmbeddingConfig);
|
|
81
|
+
embed(text: string): Promise<EmbeddingResult>;
|
|
82
|
+
embedBatch(texts: string[]): Promise<BatchEmbeddingResult>;
|
|
83
|
+
/**
|
|
84
|
+
* Generate deterministic hash-based embedding
|
|
85
|
+
*/
|
|
86
|
+
private hashEmbedding;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Create embedding service based on configuration
|
|
90
|
+
*/
|
|
91
|
+
export declare function createEmbeddingService(config: EmbeddingConfig): IEmbeddingService;
|
|
92
|
+
/**
|
|
93
|
+
* Convenience function for quick embeddings
|
|
94
|
+
*/
|
|
95
|
+
export declare function getEmbedding(text: string, config?: Partial<EmbeddingConfig>): Promise<Float32Array | number[]>;
|
|
96
|
+
/**
|
|
97
|
+
* Compute cosine similarity between two embeddings
|
|
98
|
+
*/
|
|
99
|
+
export declare function cosineSimilarity(a: Float32Array | number[], b: Float32Array | number[]): number;
|
|
100
|
+
/**
|
|
101
|
+
* Compute Euclidean distance between two embeddings
|
|
102
|
+
*/
|
|
103
|
+
export declare function euclideanDistance(a: Float32Array | number[], b: Float32Array | number[]): number;
|
|
104
|
+
/**
|
|
105
|
+
* Compute dot product between two embeddings
|
|
106
|
+
*/
|
|
107
|
+
export declare function dotProduct(a: Float32Array | number[], b: Float32Array | number[]): number;
|
|
108
|
+
/**
|
|
109
|
+
* Compute similarity using specified metric
|
|
110
|
+
*/
|
|
111
|
+
export declare function computeSimilarity(a: Float32Array | number[], b: Float32Array | number[], metric?: SimilarityMetric): SimilarityResult;
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=embedding-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-service.d.ts","sourceRoot":"","sources":["../src/embedding-service.ts"],"names":[],"mappings":"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"}
|