agentic-flow 2.0.1-alpha.13 → 2.0.1-alpha.14
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/CHANGELOG.md +28 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/intelligence/EmbeddingService.d.ts +95 -0
- package/dist/intelligence/EmbeddingService.d.ts.map +1 -0
- package/dist/intelligence/EmbeddingService.js +297 -0
- package/dist/intelligence/EmbeddingService.js.map +1 -0
- package/dist/intelligence/embedding-benchmark.d.ts +7 -0
- package/dist/intelligence/embedding-benchmark.d.ts.map +1 -0
- package/dist/intelligence/embedding-benchmark.js +151 -0
- package/dist/intelligence/embedding-benchmark.js.map +1 -0
- package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.d.ts.map +1 -1
- package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.js +13 -17
- package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.js.map +1 -1
- package/package.json +3 -1
- package/wasm/reasoningbank/reasoningbank_wasm_bg.js +2 -2
- package/wasm/reasoningbank/reasoningbank_wasm_bg.wasm +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EmbeddingService - Unified embedding interface for agentic-flow
|
|
3
|
+
*
|
|
4
|
+
* Supports two backends:
|
|
5
|
+
* - Simple: Hash-based, ~0.01ms, not semantic
|
|
6
|
+
* - ONNX: Real neural embeddings via ruvector-onnx-embeddings-wasm, ~10-50ms, semantic
|
|
7
|
+
*
|
|
8
|
+
* Configure via:
|
|
9
|
+
* - AGENTIC_FLOW_EMBEDDINGS=simple|onnx (default: simple)
|
|
10
|
+
* - AGENTIC_FLOW_EMBEDDING_MODEL=all-MiniLM-L6-v2 (default)
|
|
11
|
+
*/
|
|
12
|
+
export type EmbeddingBackend = 'simple' | 'onnx' | 'onnx-native';
|
|
13
|
+
export interface EmbeddingStats {
|
|
14
|
+
backend: EmbeddingBackend;
|
|
15
|
+
dimension: number;
|
|
16
|
+
totalEmbeddings: number;
|
|
17
|
+
totalLatencyMs: number;
|
|
18
|
+
avgLatencyMs: number;
|
|
19
|
+
cacheHits: number;
|
|
20
|
+
modelLoaded: boolean;
|
|
21
|
+
modelName?: string;
|
|
22
|
+
simdAvailable?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare class EmbeddingService {
|
|
25
|
+
private static instance;
|
|
26
|
+
private backend;
|
|
27
|
+
private dimension;
|
|
28
|
+
private modelName;
|
|
29
|
+
private embedder;
|
|
30
|
+
private wasmModule;
|
|
31
|
+
private loadingPromise;
|
|
32
|
+
private modelLoaded;
|
|
33
|
+
private totalEmbeddings;
|
|
34
|
+
private totalLatencyMs;
|
|
35
|
+
private cacheHits;
|
|
36
|
+
private cache;
|
|
37
|
+
private cacheEnabled;
|
|
38
|
+
private constructor();
|
|
39
|
+
static getInstance(): EmbeddingService;
|
|
40
|
+
/**
|
|
41
|
+
* Get current backend
|
|
42
|
+
*/
|
|
43
|
+
getBackend(): EmbeddingBackend;
|
|
44
|
+
/**
|
|
45
|
+
* Get embedding dimension
|
|
46
|
+
*/
|
|
47
|
+
getDimension(): number;
|
|
48
|
+
/**
|
|
49
|
+
* Check if ONNX model is loaded
|
|
50
|
+
*/
|
|
51
|
+
isModelLoaded(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Initialize ONNX embedder (lazy load on first use)
|
|
54
|
+
*/
|
|
55
|
+
initOnnx(): Promise<void>;
|
|
56
|
+
private _loadOnnxModel;
|
|
57
|
+
/**
|
|
58
|
+
* Generate embedding for text
|
|
59
|
+
*/
|
|
60
|
+
embed(text: string): Promise<Float32Array>;
|
|
61
|
+
/**
|
|
62
|
+
* Generate embeddings for multiple texts
|
|
63
|
+
*/
|
|
64
|
+
embedBatch(texts: string[]): Promise<Float32Array[]>;
|
|
65
|
+
/**
|
|
66
|
+
* Compute similarity between two texts
|
|
67
|
+
*/
|
|
68
|
+
similarity(text1: string, text2: string): Promise<number>;
|
|
69
|
+
/**
|
|
70
|
+
* Simple hash-based embedding (fast, not semantic)
|
|
71
|
+
*/
|
|
72
|
+
simpleEmbed(text: string, dim?: number): Float32Array;
|
|
73
|
+
/**
|
|
74
|
+
* Compute cosine similarity between two embeddings
|
|
75
|
+
*/
|
|
76
|
+
cosineSimilarity(a: Float32Array, b: Float32Array): number;
|
|
77
|
+
/**
|
|
78
|
+
* Get statistics
|
|
79
|
+
*/
|
|
80
|
+
getStats(): EmbeddingStats;
|
|
81
|
+
/**
|
|
82
|
+
* Clear cache
|
|
83
|
+
*/
|
|
84
|
+
clearCache(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Reset instance (for testing)
|
|
87
|
+
*/
|
|
88
|
+
static reset(): void;
|
|
89
|
+
}
|
|
90
|
+
export declare function getEmbeddingService(): EmbeddingService;
|
|
91
|
+
export declare function embed(text: string): Promise<Float32Array>;
|
|
92
|
+
export declare function embedBatch(texts: string[]): Promise<Float32Array[]>;
|
|
93
|
+
export declare function textSimilarity(text1: string, text2: string): Promise<number>;
|
|
94
|
+
export declare function simpleEmbed(text: string, dim?: number): Float32Array;
|
|
95
|
+
//# sourceMappingURL=EmbeddingService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbeddingService.d.ts","sourceRoot":"","sources":["../../src/intelligence/EmbeddingService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiDH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,GAAG,aAAa,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAyCD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAiC;IAExD,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,WAAW,CAAkB;IAGrC,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,SAAS,CAAa;IAG9B,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,YAAY,CAAU;IAE9B,OAAO;IAQP,MAAM,CAAC,WAAW,IAAI,gBAAgB;IAOtC;;OAEG;IACH,UAAU,IAAI,gBAAgB;IAI9B;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAQjB,cAAc;IA+C5B;;OAEG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAqChD;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAkB1D;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAa/D;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAY,GAAG,YAAY;IAwB1D;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM;IAiB1D;;OAEG;IACH,QAAQ,IAAI,cAAc;IAc1B;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,MAAM,CAAC,KAAK,IAAI,IAAI;CAMrB;AAGD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAGD,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAE/D;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAEzE;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElF;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAY,GAAG,YAAY,CAEzE"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EmbeddingService - Unified embedding interface for agentic-flow
|
|
3
|
+
*
|
|
4
|
+
* Supports two backends:
|
|
5
|
+
* - Simple: Hash-based, ~0.01ms, not semantic
|
|
6
|
+
* - ONNX: Real neural embeddings via ruvector-onnx-embeddings-wasm, ~10-50ms, semantic
|
|
7
|
+
*
|
|
8
|
+
* Configure via:
|
|
9
|
+
* - AGENTIC_FLOW_EMBEDDINGS=simple|onnx (default: simple)
|
|
10
|
+
* - AGENTIC_FLOW_EMBEDDING_MODEL=all-MiniLM-L6-v2 (default)
|
|
11
|
+
*/
|
|
12
|
+
// Simple LRU cache for embeddings
|
|
13
|
+
class EmbeddingCache {
|
|
14
|
+
cache = new Map();
|
|
15
|
+
maxSize;
|
|
16
|
+
constructor(maxSize = 1000) {
|
|
17
|
+
this.maxSize = maxSize;
|
|
18
|
+
}
|
|
19
|
+
get(key) {
|
|
20
|
+
const value = this.cache.get(key);
|
|
21
|
+
if (value) {
|
|
22
|
+
// Move to end (most recently used)
|
|
23
|
+
this.cache.delete(key);
|
|
24
|
+
this.cache.set(key, value);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
set(key, value) {
|
|
29
|
+
if (this.cache.size >= this.maxSize) {
|
|
30
|
+
// Delete oldest (first) entry
|
|
31
|
+
const firstKey = this.cache.keys().next().value;
|
|
32
|
+
if (firstKey) {
|
|
33
|
+
this.cache.delete(firstKey);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
this.cache.set(key, value);
|
|
37
|
+
}
|
|
38
|
+
clear() {
|
|
39
|
+
this.cache.clear();
|
|
40
|
+
}
|
|
41
|
+
get size() {
|
|
42
|
+
return this.cache.size;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export class EmbeddingService {
|
|
46
|
+
static instance = null;
|
|
47
|
+
backend;
|
|
48
|
+
dimension;
|
|
49
|
+
modelName;
|
|
50
|
+
// ONNX state
|
|
51
|
+
embedder = null;
|
|
52
|
+
wasmModule = null;
|
|
53
|
+
loadingPromise = null;
|
|
54
|
+
modelLoaded = false;
|
|
55
|
+
// Stats
|
|
56
|
+
totalEmbeddings = 0;
|
|
57
|
+
totalLatencyMs = 0;
|
|
58
|
+
cacheHits = 0;
|
|
59
|
+
// Cache
|
|
60
|
+
cache;
|
|
61
|
+
cacheEnabled;
|
|
62
|
+
constructor() {
|
|
63
|
+
this.backend = process.env.AGENTIC_FLOW_EMBEDDINGS || 'simple';
|
|
64
|
+
this.modelName = process.env.AGENTIC_FLOW_EMBEDDING_MODEL || 'all-MiniLM-L6-v2';
|
|
65
|
+
this.dimension = this.backend === 'onnx' ? 384 : 256; // ONNX uses 384, simple uses 256
|
|
66
|
+
this.cacheEnabled = process.env.AGENTIC_FLOW_EMBEDDING_CACHE !== 'false';
|
|
67
|
+
this.cache = new EmbeddingCache(1000);
|
|
68
|
+
}
|
|
69
|
+
static getInstance() {
|
|
70
|
+
if (!EmbeddingService.instance) {
|
|
71
|
+
EmbeddingService.instance = new EmbeddingService();
|
|
72
|
+
}
|
|
73
|
+
return EmbeddingService.instance;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get current backend
|
|
77
|
+
*/
|
|
78
|
+
getBackend() {
|
|
79
|
+
return this.backend;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get embedding dimension
|
|
83
|
+
*/
|
|
84
|
+
getDimension() {
|
|
85
|
+
return this.dimension;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if ONNX model is loaded
|
|
89
|
+
*/
|
|
90
|
+
isModelLoaded() {
|
|
91
|
+
return this.modelLoaded;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Initialize ONNX embedder (lazy load on first use)
|
|
95
|
+
*/
|
|
96
|
+
async initOnnx() {
|
|
97
|
+
if (this.modelLoaded)
|
|
98
|
+
return;
|
|
99
|
+
if (this.loadingPromise)
|
|
100
|
+
return this.loadingPromise;
|
|
101
|
+
this.loadingPromise = this._loadOnnxModel();
|
|
102
|
+
await this.loadingPromise;
|
|
103
|
+
}
|
|
104
|
+
async _loadOnnxModel() {
|
|
105
|
+
try {
|
|
106
|
+
console.log(`[EmbeddingService] Loading ONNX model: ${this.modelName}`);
|
|
107
|
+
const startTime = performance.now();
|
|
108
|
+
// Import WASM module (auto-initializes with --experimental-wasm-modules)
|
|
109
|
+
const wasmModule = await import('ruvector-onnx-embeddings-wasm');
|
|
110
|
+
this.wasmModule = wasmModule;
|
|
111
|
+
// Import loader for model fetching
|
|
112
|
+
const loaderModule = await import('ruvector-onnx-embeddings-wasm/loader.js');
|
|
113
|
+
const { ModelLoader, MODELS } = loaderModule;
|
|
114
|
+
const modelConfig = MODELS[this.modelName];
|
|
115
|
+
if (!modelConfig) {
|
|
116
|
+
throw new Error(`Unknown model: ${this.modelName}`);
|
|
117
|
+
}
|
|
118
|
+
// Load model files
|
|
119
|
+
const loader = new ModelLoader();
|
|
120
|
+
const { modelBytes, tokenizerJson } = await loader.loadModel(this.modelName);
|
|
121
|
+
// Create embedder with configuration
|
|
122
|
+
const embedderConfig = new wasmModule.WasmEmbedderConfig()
|
|
123
|
+
.setMaxLength(modelConfig.maxLength)
|
|
124
|
+
.setNormalize(true)
|
|
125
|
+
.setPooling(0); // Mean pooling
|
|
126
|
+
this.embedder = wasmModule.WasmEmbedder.withConfig(modelBytes, tokenizerJson, embedderConfig);
|
|
127
|
+
this.dimension = this.embedder.dimension();
|
|
128
|
+
this.modelLoaded = true;
|
|
129
|
+
const loadTime = performance.now() - startTime;
|
|
130
|
+
console.log(`[EmbeddingService] Model loaded in ${loadTime.toFixed(0)}ms, dim=${this.dimension}`);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error('[EmbeddingService] Failed to load ONNX model:', error);
|
|
134
|
+
console.log('[EmbeddingService] Falling back to simple embeddings');
|
|
135
|
+
this.backend = 'simple';
|
|
136
|
+
this.dimension = 256;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Generate embedding for text
|
|
141
|
+
*/
|
|
142
|
+
async embed(text) {
|
|
143
|
+
const startTime = performance.now();
|
|
144
|
+
// Check cache
|
|
145
|
+
if (this.cacheEnabled) {
|
|
146
|
+
const cached = this.cache.get(text);
|
|
147
|
+
if (cached) {
|
|
148
|
+
this.cacheHits++;
|
|
149
|
+
return cached;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
let embedding;
|
|
153
|
+
if (this.backend === 'onnx') {
|
|
154
|
+
await this.initOnnx();
|
|
155
|
+
if (this.embedder) {
|
|
156
|
+
embedding = this.embedder.embedOne(text);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
embedding = this.simpleEmbed(text);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
embedding = this.simpleEmbed(text);
|
|
164
|
+
}
|
|
165
|
+
// Update stats
|
|
166
|
+
this.totalEmbeddings++;
|
|
167
|
+
this.totalLatencyMs += performance.now() - startTime;
|
|
168
|
+
// Cache result
|
|
169
|
+
if (this.cacheEnabled) {
|
|
170
|
+
this.cache.set(text, embedding);
|
|
171
|
+
}
|
|
172
|
+
return embedding;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Generate embeddings for multiple texts
|
|
176
|
+
*/
|
|
177
|
+
async embedBatch(texts) {
|
|
178
|
+
if (this.backend === 'onnx' && this.embedder) {
|
|
179
|
+
await this.initOnnx();
|
|
180
|
+
if (this.embedder) {
|
|
181
|
+
const batchEmbedding = this.embedder.embedBatch(texts);
|
|
182
|
+
const dim = this.dimension;
|
|
183
|
+
const embeddings = [];
|
|
184
|
+
for (let i = 0; i < texts.length; i++) {
|
|
185
|
+
embeddings.push(batchEmbedding.slice(i * dim, (i + 1) * dim));
|
|
186
|
+
}
|
|
187
|
+
return embeddings;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Fall back to sequential
|
|
191
|
+
return Promise.all(texts.map(t => this.embed(t)));
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Compute similarity between two texts
|
|
195
|
+
*/
|
|
196
|
+
async similarity(text1, text2) {
|
|
197
|
+
if (this.backend === 'onnx') {
|
|
198
|
+
await this.initOnnx();
|
|
199
|
+
if (this.embedder) {
|
|
200
|
+
return this.embedder.similarity(text1, text2);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Fall back to embedding + cosine
|
|
204
|
+
const [e1, e2] = await Promise.all([this.embed(text1), this.embed(text2)]);
|
|
205
|
+
return this.cosineSimilarity(e1, e2);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Simple hash-based embedding (fast, not semantic)
|
|
209
|
+
*/
|
|
210
|
+
simpleEmbed(text, dim = 256) {
|
|
211
|
+
const embedding = new Float32Array(dim);
|
|
212
|
+
// Multi-pass hash for better distribution
|
|
213
|
+
for (let i = 0; i < text.length; i++) {
|
|
214
|
+
const code = text.charCodeAt(i);
|
|
215
|
+
embedding[i % dim] += code / 255;
|
|
216
|
+
embedding[(i * 7) % dim] += (code * 0.3) / 255;
|
|
217
|
+
embedding[(i * 13) % dim] += (code * 0.2) / 255;
|
|
218
|
+
}
|
|
219
|
+
// Normalize
|
|
220
|
+
let norm = 0;
|
|
221
|
+
for (let i = 0; i < dim; i++) {
|
|
222
|
+
norm += embedding[i] * embedding[i];
|
|
223
|
+
}
|
|
224
|
+
norm = Math.sqrt(norm) || 1;
|
|
225
|
+
for (let i = 0; i < dim; i++) {
|
|
226
|
+
embedding[i] /= norm;
|
|
227
|
+
}
|
|
228
|
+
return embedding;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Compute cosine similarity between two embeddings
|
|
232
|
+
*/
|
|
233
|
+
cosineSimilarity(a, b) {
|
|
234
|
+
if (this.wasmModule) {
|
|
235
|
+
return this.wasmModule.cosineSimilarity(a, b);
|
|
236
|
+
}
|
|
237
|
+
// JS fallback
|
|
238
|
+
let dot = 0;
|
|
239
|
+
let normA = 0;
|
|
240
|
+
let normB = 0;
|
|
241
|
+
for (let i = 0; i < a.length; i++) {
|
|
242
|
+
dot += a[i] * b[i];
|
|
243
|
+
normA += a[i] * a[i];
|
|
244
|
+
normB += b[i] * b[i];
|
|
245
|
+
}
|
|
246
|
+
return dot / (Math.sqrt(normA) * Math.sqrt(normB) || 1);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get statistics
|
|
250
|
+
*/
|
|
251
|
+
getStats() {
|
|
252
|
+
return {
|
|
253
|
+
backend: this.backend,
|
|
254
|
+
dimension: this.dimension,
|
|
255
|
+
totalEmbeddings: this.totalEmbeddings,
|
|
256
|
+
totalLatencyMs: this.totalLatencyMs,
|
|
257
|
+
avgLatencyMs: this.totalEmbeddings > 0 ? this.totalLatencyMs / this.totalEmbeddings : 0,
|
|
258
|
+
cacheHits: this.cacheHits,
|
|
259
|
+
modelLoaded: this.modelLoaded,
|
|
260
|
+
modelName: this.backend === 'onnx' ? this.modelName : undefined,
|
|
261
|
+
simdAvailable: this.wasmModule?.simd_available?.() ?? undefined,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Clear cache
|
|
266
|
+
*/
|
|
267
|
+
clearCache() {
|
|
268
|
+
this.cache.clear();
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Reset instance (for testing)
|
|
272
|
+
*/
|
|
273
|
+
static reset() {
|
|
274
|
+
if (EmbeddingService.instance?.embedder) {
|
|
275
|
+
EmbeddingService.instance.embedder.free();
|
|
276
|
+
}
|
|
277
|
+
EmbeddingService.instance = null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Export singleton getter
|
|
281
|
+
export function getEmbeddingService() {
|
|
282
|
+
return EmbeddingService.getInstance();
|
|
283
|
+
}
|
|
284
|
+
// Export convenience functions
|
|
285
|
+
export async function embed(text) {
|
|
286
|
+
return getEmbeddingService().embed(text);
|
|
287
|
+
}
|
|
288
|
+
export async function embedBatch(texts) {
|
|
289
|
+
return getEmbeddingService().embedBatch(texts);
|
|
290
|
+
}
|
|
291
|
+
export async function textSimilarity(text1, text2) {
|
|
292
|
+
return getEmbeddingService().similarity(text1, text2);
|
|
293
|
+
}
|
|
294
|
+
export function simpleEmbed(text, dim = 256) {
|
|
295
|
+
return getEmbeddingService().simpleEmbed(text, dim);
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=EmbeddingService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbeddingService.js","sourceRoot":"","sources":["../../src/intelligence/EmbeddingService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * EmbeddingService - Unified embedding interface for agentic-flow\n *\n * Supports two backends:\n * - Simple: Hash-based, ~0.01ms, not semantic\n * - ONNX: Real neural embeddings via ruvector-onnx-embeddings-wasm, ~10-50ms, semantic\n *\n * Configure via:\n * - AGENTIC_FLOW_EMBEDDINGS=simple|onnx (default: simple)\n * - AGENTIC_FLOW_EMBEDDING_MODEL=all-MiniLM-L6-v2 (default)\n */\n\n// Types for ONNX Runtime\ninterface OnnxSession {\n run(feeds: Record<string, any>): Promise<Record<string, any>>;\n release(): void;\n}\n\ninterface Tokenizer {\n encode(text: string, addSpecialTokens?: boolean): { ids: number[]; attentionMask: number[] };\n}\n\n// Types for the WASM module\ninterface WasmEmbedder {\n embedOne(text: string): Float32Array;\n embedBatch(texts: string[]): Float32Array;\n similarity(text1: string, text2: string): number;\n dimension(): number;\n maxLength(): number;\n free(): void;\n}\n\ninterface WasmModule {\n default: () => Promise<void>;\n WasmEmbedder: {\n withConfig(modelBytes: Uint8Array, tokenizerJson: string, config: WasmEmbedderConfig): WasmEmbedder;\n };\n WasmEmbedderConfig: new () => WasmEmbedderConfig;\n cosineSimilarity(a: Float32Array, b: Float32Array): number;\n simd_available(): boolean;\n version(): string;\n}\n\ninterface WasmEmbedderConfig {\n setMaxLength(maxLength: number): WasmEmbedderConfig;\n setNormalize(normalize: boolean): WasmEmbedderConfig;\n setPooling(pooling: number): WasmEmbedderConfig;\n}\n\ninterface ModelConfig {\n name: string;\n dimension: number;\n maxLength: number;\n size: string;\n description: string;\n model: string;\n tokenizer: string;\n}\n\nexport type EmbeddingBackend = 'simple' | 'onnx' | 'onnx-native';\n\nexport interface EmbeddingStats {\n backend: EmbeddingBackend;\n dimension: number;\n totalEmbeddings: number;\n totalLatencyMs: number;\n avgLatencyMs: number;\n cacheHits: number;\n modelLoaded: boolean;\n modelName?: string;\n simdAvailable?: boolean;\n}\n\n// Simple LRU cache for embeddings\nclass EmbeddingCache {\n private cache: Map<string, Float32Array> = new Map();\n private maxSize: number;\n\n constructor(maxSize: number = 1000) {\n this.maxSize = maxSize;\n }\n\n get(key: string): Float32Array | undefined {\n const value = this.cache.get(key);\n if (value) {\n // Move to end (most recently used)\n this.cache.delete(key);\n this.cache.set(key, value);\n }\n return value;\n }\n\n set(key: string, value: Float32Array): void {\n if (this.cache.size >= this.maxSize) {\n // Delete oldest (first) entry\n const firstKey = this.cache.keys().next().value;\n if (firstKey) {\n this.cache.delete(firstKey);\n }\n }\n this.cache.set(key, value);\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n get size(): number {\n return this.cache.size;\n }\n}\n\nexport class EmbeddingService {\n private static instance: EmbeddingService | null = null;\n\n private backend: EmbeddingBackend;\n private dimension: number;\n private modelName: string;\n\n // ONNX state\n private embedder: WasmEmbedder | null = null;\n private wasmModule: WasmModule | null = null;\n private loadingPromise: Promise<void> | null = null;\n private modelLoaded: boolean = false;\n\n // Stats\n private totalEmbeddings: number = 0;\n private totalLatencyMs: number = 0;\n private cacheHits: number = 0;\n\n // Cache\n private cache: EmbeddingCache;\n private cacheEnabled: boolean;\n\n private constructor() {\n this.backend = (process.env.AGENTIC_FLOW_EMBEDDINGS as EmbeddingBackend) || 'simple';\n this.modelName = process.env.AGENTIC_FLOW_EMBEDDING_MODEL || 'all-MiniLM-L6-v2';\n this.dimension = this.backend === 'onnx' ? 384 : 256; // ONNX uses 384, simple uses 256\n this.cacheEnabled = process.env.AGENTIC_FLOW_EMBEDDING_CACHE !== 'false';\n this.cache = new EmbeddingCache(1000);\n }\n\n static getInstance(): EmbeddingService {\n if (!EmbeddingService.instance) {\n EmbeddingService.instance = new EmbeddingService();\n }\n return EmbeddingService.instance;\n }\n\n /**\n * Get current backend\n */\n getBackend(): EmbeddingBackend {\n return this.backend;\n }\n\n /**\n * Get embedding dimension\n */\n getDimension(): number {\n return this.dimension;\n }\n\n /**\n * Check if ONNX model is loaded\n */\n isModelLoaded(): boolean {\n return this.modelLoaded;\n }\n\n /**\n * Initialize ONNX embedder (lazy load on first use)\n */\n async initOnnx(): Promise<void> {\n if (this.modelLoaded) return;\n if (this.loadingPromise) return this.loadingPromise;\n\n this.loadingPromise = this._loadOnnxModel();\n await this.loadingPromise;\n }\n\n private async _loadOnnxModel(): Promise<void> {\n try {\n console.log(`[EmbeddingService] Loading ONNX model: ${this.modelName}`);\n const startTime = performance.now();\n\n // Import WASM module (auto-initializes with --experimental-wasm-modules)\n const wasmModule = await import('ruvector-onnx-embeddings-wasm');\n this.wasmModule = wasmModule as unknown as WasmModule;\n\n // Import loader for model fetching\n const loaderModule = await import('ruvector-onnx-embeddings-wasm/loader.js');\n const { ModelLoader, MODELS } = loaderModule;\n\n const modelConfig = MODELS[this.modelName] as ModelConfig;\n if (!modelConfig) {\n throw new Error(`Unknown model: ${this.modelName}`);\n }\n\n // Load model files\n const loader = new ModelLoader();\n const { modelBytes, tokenizerJson } = await loader.loadModel(this.modelName);\n\n // Create embedder with configuration\n const embedderConfig = new (wasmModule as any).WasmEmbedderConfig()\n .setMaxLength(modelConfig.maxLength)\n .setNormalize(true)\n .setPooling(0); // Mean pooling\n\n this.embedder = (wasmModule as any).WasmEmbedder.withConfig(\n modelBytes,\n tokenizerJson,\n embedderConfig\n );\n\n this.dimension = this.embedder!.dimension();\n this.modelLoaded = true;\n\n const loadTime = performance.now() - startTime;\n console.log(`[EmbeddingService] Model loaded in ${loadTime.toFixed(0)}ms, dim=${this.dimension}`);\n } catch (error) {\n console.error('[EmbeddingService] Failed to load ONNX model:', error);\n console.log('[EmbeddingService] Falling back to simple embeddings');\n this.backend = 'simple';\n this.dimension = 256;\n }\n }\n\n /**\n * Generate embedding for text\n */\n async embed(text: string): Promise<Float32Array> {\n const startTime = performance.now();\n\n // Check cache\n if (this.cacheEnabled) {\n const cached = this.cache.get(text);\n if (cached) {\n this.cacheHits++;\n return cached;\n }\n }\n\n let embedding: Float32Array;\n\n if (this.backend === 'onnx') {\n await this.initOnnx();\n if (this.embedder) {\n embedding = this.embedder.embedOne(text);\n } else {\n embedding = this.simpleEmbed(text);\n }\n } else {\n embedding = this.simpleEmbed(text);\n }\n\n // Update stats\n this.totalEmbeddings++;\n this.totalLatencyMs += performance.now() - startTime;\n\n // Cache result\n if (this.cacheEnabled) {\n this.cache.set(text, embedding);\n }\n\n return embedding;\n }\n\n /**\n * Generate embeddings for multiple texts\n */\n async embedBatch(texts: string[]): Promise<Float32Array[]> {\n if (this.backend === 'onnx' && this.embedder) {\n await this.initOnnx();\n if (this.embedder) {\n const batchEmbedding = this.embedder.embedBatch(texts);\n const dim = this.dimension;\n const embeddings: Float32Array[] = [];\n for (let i = 0; i < texts.length; i++) {\n embeddings.push(batchEmbedding.slice(i * dim, (i + 1) * dim));\n }\n return embeddings;\n }\n }\n\n // Fall back to sequential\n return Promise.all(texts.map(t => this.embed(t)));\n }\n\n /**\n * Compute similarity between two texts\n */\n async similarity(text1: string, text2: string): Promise<number> {\n if (this.backend === 'onnx') {\n await this.initOnnx();\n if (this.embedder) {\n return this.embedder.similarity(text1, text2);\n }\n }\n\n // Fall back to embedding + cosine\n const [e1, e2] = await Promise.all([this.embed(text1), this.embed(text2)]);\n return this.cosineSimilarity(e1, e2);\n }\n\n /**\n * Simple hash-based embedding (fast, not semantic)\n */\n simpleEmbed(text: string, dim: number = 256): Float32Array {\n const embedding = new Float32Array(dim);\n\n // Multi-pass hash for better distribution\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n embedding[i % dim] += code / 255;\n embedding[(i * 7) % dim] += (code * 0.3) / 255;\n embedding[(i * 13) % dim] += (code * 0.2) / 255;\n }\n\n // Normalize\n let norm = 0;\n for (let i = 0; i < dim; i++) {\n norm += embedding[i] * embedding[i];\n }\n norm = Math.sqrt(norm) || 1;\n for (let i = 0; i < dim; i++) {\n embedding[i] /= norm;\n }\n\n return embedding;\n }\n\n /**\n * Compute cosine similarity between two embeddings\n */\n cosineSimilarity(a: Float32Array, b: Float32Array): number {\n if (this.wasmModule) {\n return this.wasmModule.cosineSimilarity(a, b);\n }\n\n // JS fallback\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i++) {\n dot += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n return dot / (Math.sqrt(normA) * Math.sqrt(normB) || 1);\n }\n\n /**\n * Get statistics\n */\n getStats(): EmbeddingStats {\n return {\n backend: this.backend,\n dimension: this.dimension,\n totalEmbeddings: this.totalEmbeddings,\n totalLatencyMs: this.totalLatencyMs,\n avgLatencyMs: this.totalEmbeddings > 0 ? this.totalLatencyMs / this.totalEmbeddings : 0,\n cacheHits: this.cacheHits,\n modelLoaded: this.modelLoaded,\n modelName: this.backend === 'onnx' ? this.modelName : undefined,\n simdAvailable: this.wasmModule?.simd_available?.() ?? undefined,\n };\n }\n\n /**\n * Clear cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Reset instance (for testing)\n */\n static reset(): void {\n if (EmbeddingService.instance?.embedder) {\n EmbeddingService.instance.embedder.free();\n }\n EmbeddingService.instance = null;\n }\n}\n\n// Export singleton getter\nexport function getEmbeddingService(): EmbeddingService {\n return EmbeddingService.getInstance();\n}\n\n// Export convenience functions\nexport async function embed(text: string): Promise<Float32Array> {\n return getEmbeddingService().embed(text);\n}\n\nexport async function embedBatch(texts: string[]): Promise<Float32Array[]> {\n return getEmbeddingService().embedBatch(texts);\n}\n\nexport async function textSimilarity(text1: string, text2: string): Promise<number> {\n return getEmbeddingService().similarity(text1, text2);\n}\n\nexport function simpleEmbed(text: string, dim: number = 256): Float32Array {\n return getEmbeddingService().simpleEmbed(text, dim);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-benchmark.d.ts","sourceRoot":"","sources":["../../src/intelligence/embedding-benchmark.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding Benchmark - Compare simple vs ONNX embeddings
|
|
3
|
+
*
|
|
4
|
+
* Run with: npx ts-node src/intelligence/embedding-benchmark.ts
|
|
5
|
+
*/
|
|
6
|
+
import { getEmbeddingService, EmbeddingService } from './EmbeddingService.js';
|
|
7
|
+
const TEST_TEXTS = [
|
|
8
|
+
'Fix a bug in the authentication system',
|
|
9
|
+
'Implement user login functionality',
|
|
10
|
+
'Write unit tests for the API',
|
|
11
|
+
'Refactor the database layer',
|
|
12
|
+
'Optimize memory usage',
|
|
13
|
+
'Add dark mode to the UI',
|
|
14
|
+
'Deploy to production',
|
|
15
|
+
'Review pull request',
|
|
16
|
+
'Document the API endpoints',
|
|
17
|
+
'Set up CI/CD pipeline',
|
|
18
|
+
];
|
|
19
|
+
const SEMANTIC_PAIRS = [
|
|
20
|
+
{ a: 'I love dogs', b: 'I adore puppies', expected: 'high' },
|
|
21
|
+
{ a: 'Fix authentication bug', b: 'Repair login issue', expected: 'high' },
|
|
22
|
+
{ a: 'Write unit tests', b: 'Create test cases', expected: 'high' },
|
|
23
|
+
{ a: 'Deploy to production', b: 'The weather is nice', expected: 'low' },
|
|
24
|
+
{ a: 'Fix bug', b: 'Add feature', expected: 'medium' },
|
|
25
|
+
{ a: 'Machine learning', b: 'Artificial intelligence', expected: 'high' },
|
|
26
|
+
{ a: 'Pizza recipe', b: 'Quantum physics', expected: 'low' },
|
|
27
|
+
];
|
|
28
|
+
async function runBenchmark() {
|
|
29
|
+
console.log('='.repeat(60));
|
|
30
|
+
console.log('Embedding Benchmark: Simple vs ONNX');
|
|
31
|
+
console.log('='.repeat(60));
|
|
32
|
+
// Benchmark Simple Embeddings
|
|
33
|
+
console.log('\n--- Simple Embeddings ---');
|
|
34
|
+
process.env.AGENTIC_FLOW_EMBEDDINGS = 'simple';
|
|
35
|
+
EmbeddingService.reset();
|
|
36
|
+
const simpleService = getEmbeddingService();
|
|
37
|
+
const simpleResults = await benchmarkService(simpleService, 'simple');
|
|
38
|
+
// Benchmark ONNX Embeddings
|
|
39
|
+
console.log('\n--- ONNX Embeddings ---');
|
|
40
|
+
process.env.AGENTIC_FLOW_EMBEDDINGS = 'onnx';
|
|
41
|
+
EmbeddingService.reset();
|
|
42
|
+
const onnxService = getEmbeddingService();
|
|
43
|
+
const onnxResults = await benchmarkService(onnxService, 'onnx');
|
|
44
|
+
// Summary
|
|
45
|
+
console.log('\n' + '='.repeat(60));
|
|
46
|
+
console.log('SUMMARY');
|
|
47
|
+
console.log('='.repeat(60));
|
|
48
|
+
console.log(`
|
|
49
|
+
| Metric | Simple | ONNX |
|
|
50
|
+
|-----------------------|-------------|-------------|
|
|
51
|
+
| Avg Latency (cold) | ${simpleResults.avgColdLatency.toFixed(2)}ms | ${onnxResults.avgColdLatency.toFixed(2)}ms |
|
|
52
|
+
| Avg Latency (warm) | ${simpleResults.avgWarmLatency.toFixed(2)}ms | ${onnxResults.avgWarmLatency.toFixed(2)}ms |
|
|
53
|
+
| Batch 10 texts | ${simpleResults.batchLatency.toFixed(2)}ms | ${onnxResults.batchLatency.toFixed(2)}ms |
|
|
54
|
+
| Dimension | ${simpleResults.dimension} | ${onnxResults.dimension} |
|
|
55
|
+
| Semantic Accuracy | ${simpleResults.semanticAccuracy}% | ${onnxResults.semanticAccuracy}% |
|
|
56
|
+
`);
|
|
57
|
+
console.log('\nSemantic Similarity Comparison:');
|
|
58
|
+
console.log('-'.repeat(60));
|
|
59
|
+
for (let i = 0; i < SEMANTIC_PAIRS.length; i++) {
|
|
60
|
+
const pair = SEMANTIC_PAIRS[i];
|
|
61
|
+
console.log(`"${pair.a}" vs "${pair.b}"`);
|
|
62
|
+
console.log(` Expected: ${pair.expected}`);
|
|
63
|
+
console.log(` Simple: ${simpleResults.similarities[i].toFixed(3)}`);
|
|
64
|
+
console.log(` ONNX: ${onnxResults.similarities[i].toFixed(3)}`);
|
|
65
|
+
console.log();
|
|
66
|
+
}
|
|
67
|
+
// Recommendation
|
|
68
|
+
console.log('='.repeat(60));
|
|
69
|
+
console.log('RECOMMENDATION');
|
|
70
|
+
console.log('='.repeat(60));
|
|
71
|
+
if (onnxResults.semanticAccuracy > simpleResults.semanticAccuracy + 20) {
|
|
72
|
+
console.log(`
|
|
73
|
+
ONNX embeddings provide significantly better semantic accuracy
|
|
74
|
+
(${onnxResults.semanticAccuracy}% vs ${simpleResults.semanticAccuracy}%).
|
|
75
|
+
|
|
76
|
+
For tasks requiring semantic understanding (routing, pattern matching),
|
|
77
|
+
use ONNX embeddings:
|
|
78
|
+
|
|
79
|
+
export AGENTIC_FLOW_EMBEDDINGS=onnx
|
|
80
|
+
|
|
81
|
+
Note: First embedding takes ~${(onnxResults.avgColdLatency / 1000).toFixed(1)}s (model loading).
|
|
82
|
+
Subsequent embeddings: ~${onnxResults.avgWarmLatency.toFixed(1)}ms.
|
|
83
|
+
`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
console.log(`
|
|
87
|
+
Simple embeddings are sufficient for your use case.
|
|
88
|
+
Semantic accuracy difference is minimal.
|
|
89
|
+
|
|
90
|
+
Keep using simple embeddings for maximum speed:
|
|
91
|
+
|
|
92
|
+
export AGENTIC_FLOW_EMBEDDINGS=simple
|
|
93
|
+
`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function benchmarkService(service, name) {
|
|
97
|
+
// Cold start (first embedding, includes model loading for ONNX)
|
|
98
|
+
console.log(`\n[${name}] Cold start embedding...`);
|
|
99
|
+
const coldStart = performance.now();
|
|
100
|
+
await service.embed(TEST_TEXTS[0]);
|
|
101
|
+
const coldLatency = performance.now() - coldStart;
|
|
102
|
+
console.log(` Cold latency: ${coldLatency.toFixed(2)}ms`);
|
|
103
|
+
// Warm embeddings
|
|
104
|
+
console.log(`[${name}] Warm embeddings (${TEST_TEXTS.length} texts)...`);
|
|
105
|
+
service.clearCache();
|
|
106
|
+
const warmStart = performance.now();
|
|
107
|
+
for (const text of TEST_TEXTS) {
|
|
108
|
+
await service.embed(text);
|
|
109
|
+
}
|
|
110
|
+
const warmTotalLatency = performance.now() - warmStart;
|
|
111
|
+
const avgWarmLatency = warmTotalLatency / TEST_TEXTS.length;
|
|
112
|
+
console.log(` Total: ${warmTotalLatency.toFixed(2)}ms, Avg: ${avgWarmLatency.toFixed(2)}ms`);
|
|
113
|
+
// Batch embedding
|
|
114
|
+
console.log(`[${name}] Batch embedding...`);
|
|
115
|
+
service.clearCache();
|
|
116
|
+
const batchStart = performance.now();
|
|
117
|
+
await service.embedBatch(TEST_TEXTS);
|
|
118
|
+
const batchLatency = performance.now() - batchStart;
|
|
119
|
+
console.log(` Batch latency: ${batchLatency.toFixed(2)}ms`);
|
|
120
|
+
// Semantic similarity tests
|
|
121
|
+
console.log(`[${name}] Semantic similarity tests...`);
|
|
122
|
+
const similarities = [];
|
|
123
|
+
let correctCount = 0;
|
|
124
|
+
for (const pair of SEMANTIC_PAIRS) {
|
|
125
|
+
const sim = await service.similarity(pair.a, pair.b);
|
|
126
|
+
similarities.push(sim);
|
|
127
|
+
// For ONNX (semantic), use proper thresholds
|
|
128
|
+
// For simple (hash-based), it will score incorrectly on unrelated pairs
|
|
129
|
+
const isCorrect = (pair.expected === 'high' && sim > 0.5) ||
|
|
130
|
+
(pair.expected === 'medium' && sim >= 0.2 && sim <= 0.6) ||
|
|
131
|
+
(pair.expected === 'low' && sim < 0.3);
|
|
132
|
+
if (isCorrect)
|
|
133
|
+
correctCount++;
|
|
134
|
+
console.log(` "${pair.a.substring(0, 20)}..." vs "${pair.b.substring(0, 20)}...": ${sim.toFixed(3)} (expected: ${pair.expected})`);
|
|
135
|
+
}
|
|
136
|
+
const semanticAccuracy = Math.round((correctCount / SEMANTIC_PAIRS.length) * 100);
|
|
137
|
+
console.log(` Semantic accuracy: ${semanticAccuracy}%`);
|
|
138
|
+
const stats = service.getStats();
|
|
139
|
+
console.log(` Model: ${stats.modelName || 'N/A'}, SIMD: ${stats.simdAvailable ?? 'N/A'}`);
|
|
140
|
+
return {
|
|
141
|
+
avgColdLatency: coldLatency,
|
|
142
|
+
avgWarmLatency,
|
|
143
|
+
batchLatency,
|
|
144
|
+
dimension: stats.dimension,
|
|
145
|
+
semanticAccuracy,
|
|
146
|
+
similarities,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// Run if executed directly
|
|
150
|
+
runBenchmark().catch(console.error);
|
|
151
|
+
//# sourceMappingURL=embedding-benchmark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-benchmark.js","sourceRoot":"","sources":["../../src/intelligence/embedding-benchmark.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Embedding Benchmark - Compare simple vs ONNX embeddings\n *\n * Run with: npx ts-node src/intelligence/embedding-benchmark.ts\n */\n\nimport { getEmbeddingService, EmbeddingService } from './EmbeddingService.js';\n\nconst TEST_TEXTS = [\n 'Fix a bug in the authentication system',\n 'Implement user login functionality',\n 'Write unit tests for the API',\n 'Refactor the database layer',\n 'Optimize memory usage',\n 'Add dark mode to the UI',\n 'Deploy to production',\n 'Review pull request',\n 'Document the API endpoints',\n 'Set up CI/CD pipeline',\n];\n\nconst SEMANTIC_PAIRS = [\n { a: 'I love dogs', b: 'I adore puppies', expected: 'high' },\n { a: 'Fix authentication bug', b: 'Repair login issue', expected: 'high' },\n { a: 'Write unit tests', b: 'Create test cases', expected: 'high' },\n { a: 'Deploy to production', b: 'The weather is nice', expected: 'low' },\n { a: 'Fix bug', b: 'Add feature', expected: 'medium' },\n { a: 'Machine learning', b: 'Artificial intelligence', expected: 'high' },\n { a: 'Pizza recipe', b: 'Quantum physics', expected: 'low' },\n];\n\nasync function runBenchmark() {\n console.log('='.repeat(60));\n console.log('Embedding Benchmark: Simple vs ONNX');\n console.log('='.repeat(60));\n\n // Benchmark Simple Embeddings\n console.log('\\n--- Simple Embeddings ---');\n process.env.AGENTIC_FLOW_EMBEDDINGS = 'simple';\n EmbeddingService.reset();\n\n const simpleService = getEmbeddingService();\n const simpleResults = await benchmarkService(simpleService, 'simple');\n\n // Benchmark ONNX Embeddings\n console.log('\\n--- ONNX Embeddings ---');\n process.env.AGENTIC_FLOW_EMBEDDINGS = 'onnx';\n EmbeddingService.reset();\n\n const onnxService = getEmbeddingService();\n const onnxResults = await benchmarkService(onnxService, 'onnx');\n\n // Summary\n console.log('\\n' + '='.repeat(60));\n console.log('SUMMARY');\n console.log('='.repeat(60));\n\n console.log(`\n| Metric | Simple | ONNX |\n|-----------------------|-------------|-------------|\n| Avg Latency (cold) | ${simpleResults.avgColdLatency.toFixed(2)}ms | ${onnxResults.avgColdLatency.toFixed(2)}ms |\n| Avg Latency (warm) | ${simpleResults.avgWarmLatency.toFixed(2)}ms | ${onnxResults.avgWarmLatency.toFixed(2)}ms |\n| Batch 10 texts | ${simpleResults.batchLatency.toFixed(2)}ms | ${onnxResults.batchLatency.toFixed(2)}ms |\n| Dimension | ${simpleResults.dimension} | ${onnxResults.dimension} |\n| Semantic Accuracy | ${simpleResults.semanticAccuracy}% | ${onnxResults.semanticAccuracy}% |\n`);\n\n console.log('\\nSemantic Similarity Comparison:');\n console.log('-'.repeat(60));\n for (let i = 0; i < SEMANTIC_PAIRS.length; i++) {\n const pair = SEMANTIC_PAIRS[i];\n console.log(`\"${pair.a}\" vs \"${pair.b}\"`);\n console.log(` Expected: ${pair.expected}`);\n console.log(` Simple: ${simpleResults.similarities[i].toFixed(3)}`);\n console.log(` ONNX: ${onnxResults.similarities[i].toFixed(3)}`);\n console.log();\n }\n\n // Recommendation\n console.log('='.repeat(60));\n console.log('RECOMMENDATION');\n console.log('='.repeat(60));\n\n if (onnxResults.semanticAccuracy > simpleResults.semanticAccuracy + 20) {\n console.log(`\nONNX embeddings provide significantly better semantic accuracy\n(${onnxResults.semanticAccuracy}% vs ${simpleResults.semanticAccuracy}%).\n\nFor tasks requiring semantic understanding (routing, pattern matching),\nuse ONNX embeddings:\n\n export AGENTIC_FLOW_EMBEDDINGS=onnx\n\nNote: First embedding takes ~${(onnxResults.avgColdLatency / 1000).toFixed(1)}s (model loading).\nSubsequent embeddings: ~${onnxResults.avgWarmLatency.toFixed(1)}ms.\n`);\n } else {\n console.log(`\nSimple embeddings are sufficient for your use case.\nSemantic accuracy difference is minimal.\n\nKeep using simple embeddings for maximum speed:\n\n export AGENTIC_FLOW_EMBEDDINGS=simple\n`);\n }\n}\n\nasync function benchmarkService(\n service: EmbeddingService,\n name: string\n): Promise<{\n avgColdLatency: number;\n avgWarmLatency: number;\n batchLatency: number;\n dimension: number;\n semanticAccuracy: number;\n similarities: number[];\n}> {\n // Cold start (first embedding, includes model loading for ONNX)\n console.log(`\\n[${name}] Cold start embedding...`);\n const coldStart = performance.now();\n await service.embed(TEST_TEXTS[0]);\n const coldLatency = performance.now() - coldStart;\n console.log(` Cold latency: ${coldLatency.toFixed(2)}ms`);\n\n // Warm embeddings\n console.log(`[${name}] Warm embeddings (${TEST_TEXTS.length} texts)...`);\n service.clearCache();\n const warmStart = performance.now();\n for (const text of TEST_TEXTS) {\n await service.embed(text);\n }\n const warmTotalLatency = performance.now() - warmStart;\n const avgWarmLatency = warmTotalLatency / TEST_TEXTS.length;\n console.log(` Total: ${warmTotalLatency.toFixed(2)}ms, Avg: ${avgWarmLatency.toFixed(2)}ms`);\n\n // Batch embedding\n console.log(`[${name}] Batch embedding...`);\n service.clearCache();\n const batchStart = performance.now();\n await service.embedBatch(TEST_TEXTS);\n const batchLatency = performance.now() - batchStart;\n console.log(` Batch latency: ${batchLatency.toFixed(2)}ms`);\n\n // Semantic similarity tests\n console.log(`[${name}] Semantic similarity tests...`);\n const similarities: number[] = [];\n let correctCount = 0;\n\n for (const pair of SEMANTIC_PAIRS) {\n const sim = await service.similarity(pair.a, pair.b);\n similarities.push(sim);\n\n // For ONNX (semantic), use proper thresholds\n // For simple (hash-based), it will score incorrectly on unrelated pairs\n const isCorrect =\n (pair.expected === 'high' && sim > 0.5) ||\n (pair.expected === 'medium' && sim >= 0.2 && sim <= 0.6) ||\n (pair.expected === 'low' && sim < 0.3);\n\n if (isCorrect) correctCount++;\n\n console.log(` \"${pair.a.substring(0, 20)}...\" vs \"${pair.b.substring(0, 20)}...\": ${sim.toFixed(3)} (expected: ${pair.expected})`);\n }\n\n const semanticAccuracy = Math.round((correctCount / SEMANTIC_PAIRS.length) * 100);\n console.log(` Semantic accuracy: ${semanticAccuracy}%`);\n\n const stats = service.getStats();\n console.log(` Model: ${stats.modelName || 'N/A'}, SIMD: ${stats.simdAvailable ?? 'N/A'}`);\n\n return {\n avgColdLatency: coldLatency,\n avgWarmLatency,\n batchLatency,\n dimension: stats.dimension,\n semanticAccuracy,\n similarities,\n };\n}\n\n// Run if executed directly\nrunBenchmark().catch(console.error);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intelligence-bridge.d.ts","sourceRoot":"","sources":["../../../../../src/mcp/fastmcp/tools/hooks/intelligence-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,oBAAoB,EAGpB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,eAAe,EACrB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAwB,KAAK,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"intelligence-bridge.d.ts","sourceRoot":"","sources":["../../../../../src/mcp/fastmcp/tools/hooks/intelligence-bridge.ts"],"names":[],"mappings":"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"}
|