@sparkleideas/agentdb-onnx 1.0.1

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/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@sparkleideas/agentdb-onnx",
3
+ "version": "1.0.1",
4
+ "description": "AgentDB with optimized ONNX embeddings - 100% local, GPU-accelerated AI agent memory",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "dev": "tsx src/cli.ts",
11
+ "test": "vitest run",
12
+ "test:watch": "vitest",
13
+ "benchmark": "tsx src/benchmarks/benchmark-runner.ts",
14
+ "example": "tsx examples/complete-workflow.ts"
15
+ },
16
+ "keywords": [
17
+ "agentdb",
18
+ "onnx",
19
+ "embeddings",
20
+ "vector-database",
21
+ "ai-agents",
22
+ "local-inference",
23
+ "gpu-acceleration"
24
+ ],
25
+ "dependencies": {
26
+ "onnxruntime-node": "^1.20.1",
27
+ "@xenova/transformers": "^2.17.2",
28
+ "commander": "^12.1.0",
29
+ "chalk": "^5.3.0",
30
+ "@sparkleideas/agentdb": "*"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^22.10.2",
34
+ "tsx": "^4.19.2",
35
+ "typescript": "^5.7.2",
36
+ "vitest": "^2.1.8"
37
+ },
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ }
41
+ }
@@ -0,0 +1,301 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Comprehensive Performance Benchmarks for AgentDB + ONNX
4
+ */
5
+
6
+ import { createONNXAgentDB } from '../index.js';
7
+ import { unlink } from 'fs/promises';
8
+ import chalk from 'chalk';
9
+
10
+ interface BenchmarkResult {
11
+ name: string;
12
+ operations: number;
13
+ totalTime: number;
14
+ opsPerSec: number;
15
+ avgLatency: number;
16
+ p50: number;
17
+ p95: number;
18
+ p99: number;
19
+ }
20
+
21
+ /**
22
+ * Run a benchmark and collect statistics
23
+ */
24
+ async function benchmark(
25
+ name: string,
26
+ operations: number,
27
+ fn: () => Promise<void>
28
+ ): Promise<BenchmarkResult> {
29
+ const latencies: number[] = [];
30
+
31
+ console.log(chalk.blue(`\nšŸƒ Running: ${name}`));
32
+ console.log(chalk.gray(` Operations: ${operations}`));
33
+
34
+ const startTime = Date.now();
35
+
36
+ for (let i = 0; i < operations; i++) {
37
+ const opStart = Date.now();
38
+ await fn();
39
+ const opLatency = Date.now() - opStart;
40
+ latencies.push(opLatency);
41
+
42
+ if ((i + 1) % Math.max(1, Math.floor(operations / 10)) === 0) {
43
+ process.stdout.write(chalk.gray(`.`));
44
+ }
45
+ }
46
+
47
+ const totalTime = Date.now() - startTime;
48
+ const opsPerSec = (operations / totalTime) * 1000;
49
+
50
+ // Calculate percentiles
51
+ latencies.sort((a, b) => a - b);
52
+ const p50 = latencies[Math.floor(latencies.length * 0.5)];
53
+ const p95 = latencies[Math.floor(latencies.length * 0.95)];
54
+ const p99 = latencies[Math.floor(latencies.length * 0.99)];
55
+ const avgLatency = latencies.reduce((a, b) => a + b, 0) / latencies.length;
56
+
57
+ console.log(); // Newline after dots
58
+
59
+ return {
60
+ name,
61
+ operations,
62
+ totalTime,
63
+ opsPerSec,
64
+ avgLatency,
65
+ p50,
66
+ p95,
67
+ p99
68
+ };
69
+ }
70
+
71
+ /**
72
+ * Print benchmark results
73
+ */
74
+ function printResult(result: BenchmarkResult) {
75
+ console.log(chalk.green(`\nāœ… ${result.name}`));
76
+ console.log(chalk.white(` Total time: ${result.totalTime.toFixed(2)}ms`));
77
+ console.log(chalk.white(` Throughput: ${result.opsPerSec.toFixed(2)} ops/sec`));
78
+ console.log(chalk.white(` Avg latency: ${result.avgLatency.toFixed(2)}ms`));
79
+ console.log(chalk.white(` P50 latency: ${result.p50.toFixed(2)}ms`));
80
+ console.log(chalk.white(` P95 latency: ${result.p95.toFixed(2)}ms`));
81
+ console.log(chalk.white(` P99 latency: ${result.p99.toFixed(2)}ms`));
82
+ }
83
+
84
+ /**
85
+ * Main benchmark suite
86
+ */
87
+ async function main() {
88
+ console.log(chalk.bold.cyan('\n╔════════════════════════════════════════╗'));
89
+ console.log(chalk.bold.cyan('ā•‘ AgentDB + ONNX Performance Benchmark ā•‘'));
90
+ console.log(chalk.bold.cyan('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n'));
91
+
92
+ const dbPath = './benchmark-agentdb-onnx.db';
93
+
94
+ try {
95
+ // Initialize AgentDB
96
+ console.log(chalk.yellow('šŸ“¦ Initializing AgentDB + ONNX...'));
97
+ const agentdb = await createONNXAgentDB({
98
+ dbPath,
99
+ modelName: 'Xenova/all-MiniLM-L6-v2',
100
+ useGPU: false,
101
+ batchSize: 32,
102
+ cacheSize: 10000
103
+ });
104
+
105
+ console.log(chalk.green('āœ… Initialization complete\n'));
106
+
107
+ const results: BenchmarkResult[] = [];
108
+
109
+ // Benchmark 1: Single embedding generation
110
+ results.push(await benchmark(
111
+ 'Single Embedding Generation',
112
+ 100,
113
+ async () => {
114
+ await agentdb.embedder.embed(`Test embedding ${Math.random()}`);
115
+ }
116
+ ));
117
+
118
+ // Benchmark 2: Cached embedding access
119
+ const cachedText = 'This text will be cached';
120
+ await agentdb.embedder.embed(cachedText); // Warm up cache
121
+
122
+ results.push(await benchmark(
123
+ 'Cached Embedding Access',
124
+ 1000,
125
+ async () => {
126
+ await agentdb.embedder.embed(cachedText);
127
+ }
128
+ ));
129
+
130
+ // Benchmark 3: Batch embedding (10 items)
131
+ results.push(await benchmark(
132
+ 'Batch Embedding (10 items)',
133
+ 50,
134
+ async () => {
135
+ const texts = Array.from({ length: 10 }, (_, i) =>
136
+ `Batch text ${i} ${Math.random()}`
137
+ );
138
+ await agentdb.embedder.embedBatch(texts);
139
+ }
140
+ ));
141
+
142
+ // Benchmark 4: Batch embedding (100 items)
143
+ results.push(await benchmark(
144
+ 'Batch Embedding (100 items)',
145
+ 10,
146
+ async () => {
147
+ const texts = Array.from({ length: 100 }, (_, i) =>
148
+ `Large batch text ${i} ${Math.random()}`
149
+ );
150
+ await agentdb.embedder.embedBatch(texts);
151
+ }
152
+ ));
153
+
154
+ // Benchmark 5: Pattern storage
155
+ results.push(await benchmark(
156
+ 'Pattern Storage (Single)',
157
+ 100,
158
+ async () => {
159
+ await agentdb.reasoningBank.storePattern({
160
+ taskType: 'benchmark',
161
+ approach: `Approach ${Math.random()}`,
162
+ successRate: Math.random()
163
+ });
164
+ }
165
+ ));
166
+
167
+ // Benchmark 6: Pattern batch storage (using loops)
168
+ results.push(await benchmark(
169
+ 'Pattern Storage (Batch of 10)',
170
+ 20,
171
+ async () => {
172
+ const patterns = Array.from({ length: 10 }, (_, i) => ({
173
+ taskType: 'batch-benchmark',
174
+ approach: `Batch approach ${i} ${Math.random()}`,
175
+ successRate: Math.random()
176
+ }));
177
+ for (const pattern of patterns) {
178
+ await agentdb.reasoningBank.storePattern(pattern);
179
+ }
180
+ }
181
+ ));
182
+
183
+ // Benchmark 7: Pattern search - pre-populate database
184
+ for (let i = 0; i < 100; i++) {
185
+ await agentdb.reasoningBank.storePattern({
186
+ taskType: 'search-test',
187
+ approach: `Search approach ${i}`,
188
+ successRate: Math.random()
189
+ });
190
+ }
191
+
192
+ results.push(await benchmark(
193
+ 'Pattern Search (k=10)',
194
+ 100,
195
+ async () => {
196
+ await agentdb.reasoningBank.searchPatterns({
197
+ task: 'search approach',
198
+ k: 10
199
+ });
200
+ }
201
+ ));
202
+
203
+ // Benchmark 8: Episode storage
204
+ results.push(await benchmark(
205
+ 'Episode Storage (Single)',
206
+ 100,
207
+ async () => {
208
+ await agentdb.reflexionMemory.storeEpisode({
209
+ sessionId: 'benchmark',
210
+ task: `Task ${Math.random()}`,
211
+ reward: Math.random(),
212
+ success: Math.random() > 0.5,
213
+ critique: 'Benchmark critique'
214
+ });
215
+ }
216
+ ));
217
+
218
+ // Benchmark 9: Episode batch storage (using loops)
219
+ results.push(await benchmark(
220
+ 'Episode Storage (Batch of 10)',
221
+ 20,
222
+ async () => {
223
+ const episodes = Array.from({ length: 10 }, (_, i) => ({
224
+ sessionId: 'batch-benchmark',
225
+ task: `Batch task ${i} ${Math.random()}`,
226
+ reward: Math.random(),
227
+ success: Math.random() > 0.5,
228
+ critique: `Batch critique ${i}`
229
+ }));
230
+ for (const episode of episodes) {
231
+ await agentdb.reflexionMemory.storeEpisode(episode);
232
+ }
233
+ }
234
+ ));
235
+
236
+ // Benchmark 10: Episode retrieval - pre-populate database
237
+ for (let i = 0; i < 100; i++) {
238
+ await agentdb.reflexionMemory.storeEpisode({
239
+ sessionId: 'retrieval-test',
240
+ task: `Retrieval task ${i}`,
241
+ reward: Math.random(),
242
+ success: Math.random() > 0.5
243
+ });
244
+ }
245
+
246
+ results.push(await benchmark(
247
+ 'Episode Retrieval (k=10)',
248
+ 100,
249
+ async () => {
250
+ await agentdb.reflexionMemory.retrieveRelevant({
251
+ task: 'retrieval task',
252
+ k: 10
253
+ });
254
+ }
255
+ ));
256
+
257
+ // Print all results
258
+ console.log(chalk.bold.cyan('\n\n╔════════════════════════════════════════╗'));
259
+ console.log(chalk.bold.cyan('ā•‘ Benchmark Results ā•‘'));
260
+ console.log(chalk.bold.cyan('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•'));
261
+
262
+ results.forEach(printResult);
263
+
264
+ // Print summary
265
+ console.log(chalk.bold.cyan('\n\n╔════════════════════════════════════════╗'));
266
+ console.log(chalk.bold.cyan('ā•‘ Summary ā•‘'));
267
+ console.log(chalk.bold.cyan('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n'));
268
+
269
+ const stats = agentdb.getStats();
270
+
271
+ console.log(chalk.white('šŸ“Š Overall Statistics:'));
272
+ console.log(chalk.white(` Total embeddings: ${stats.embedder.totalEmbeddings}`));
273
+ console.log(chalk.white(` Avg embedding time: ${stats.embedder.avgLatency.toFixed(2)}ms`));
274
+ console.log(chalk.white(` Cache hit rate: ${(stats.embedder.cache.hitRate * 100).toFixed(1)}%`));
275
+ console.log(chalk.white(` Cache size: ${stats.embedder.cache.size}/${stats.embedder.cache.maxSize}`));
276
+
277
+ // Calculate speedup from batching
278
+ const singlePattern = results.find(r => r.name === 'Pattern Storage (Single)');
279
+ const batchPattern = results.find(r => r.name === 'Pattern Storage (Batch of 10)');
280
+
281
+ if (singlePattern && batchPattern) {
282
+ const speedup = (singlePattern.opsPerSec * 10) / batchPattern.opsPerSec;
283
+ console.log(chalk.white(`\nšŸš€ Batch speedup: ${speedup.toFixed(2)}x faster`));
284
+ }
285
+
286
+ // Cleanup
287
+ await agentdb.close();
288
+
289
+ console.log(chalk.green('\nāœ… Benchmark complete!\n'));
290
+ } catch (error) {
291
+ console.error(chalk.red('\nāŒ Benchmark failed:'), error);
292
+ process.exit(1);
293
+ } finally {
294
+ try {
295
+ await unlink(dbPath);
296
+ } catch {}
297
+ }
298
+ }
299
+
300
+ // Run benchmarks
301
+ main().catch(console.error);
package/src/cli.ts ADDED
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI for AgentDB + ONNX
4
+ */
5
+
6
+ import { Command } from 'commander';
7
+ import chalk from 'chalk';
8
+ import { createONNXAgentDB } from './index.js';
9
+ import { unlink } from 'fs/promises';
10
+
11
+ const program = new Command();
12
+
13
+ program
14
+ .name('agentdb-onnx')
15
+ .description('AgentDB with optimized ONNX embeddings')
16
+ .version('1.0.0');
17
+
18
+ // Init command
19
+ program
20
+ .command('init')
21
+ .description('Initialize a new AgentDB with ONNX embeddings')
22
+ .argument('<db-path>', 'Path to database file')
23
+ .option('-m, --model <name>', 'Model name', 'Xenova/all-MiniLM-L6-v2')
24
+ .option('--gpu', 'Enable GPU acceleration')
25
+ .option('-b, --batch-size <size>', 'Batch size', '32')
26
+ .option('-c, --cache-size <size>', 'Cache size', '10000')
27
+ .action(async (dbPath, options) => {
28
+ try {
29
+ console.log(chalk.blue('Initializing AgentDB + ONNX...'));
30
+ console.log(chalk.gray(` Database: ${dbPath}`));
31
+ console.log(chalk.gray(` Model: ${options.model}`));
32
+ console.log(chalk.gray(` GPU: ${options.gpu ? 'enabled' : 'disabled'}`));
33
+
34
+ const agentdb = await createONNXAgentDB({
35
+ dbPath,
36
+ modelName: options.model,
37
+ useGPU: options.gpu,
38
+ batchSize: parseInt(options.batchSize),
39
+ cacheSize: parseInt(options.cacheSize)
40
+ });
41
+
42
+ console.log(chalk.green('āœ… Initialized successfully'));
43
+
44
+ await agentdb.close();
45
+ } catch (error) {
46
+ console.error(chalk.red('āŒ Error:'), error);
47
+ process.exit(1);
48
+ }
49
+ });
50
+
51
+ // Store pattern command
52
+ program
53
+ .command('store-pattern')
54
+ .description('Store a reasoning pattern')
55
+ .argument('<db-path>', 'Database path')
56
+ .requiredOption('-t, --task-type <type>', 'Task type')
57
+ .requiredOption('-a, --approach <approach>', 'Approach description')
58
+ .requiredOption('-s, --success-rate <rate>', 'Success rate (0-1)')
59
+ .option('--tags <tags>', 'Comma-separated tags')
60
+ .action(async (dbPath, options) => {
61
+ try {
62
+ const agentdb = await createONNXAgentDB({ dbPath, useGPU: false });
63
+
64
+ const id = await agentdb.reasoningBank.storePattern({
65
+ taskType: options.taskType,
66
+ approach: options.approach,
67
+ successRate: parseFloat(options.successRate),
68
+ tags: options.tags?.split(',')
69
+ });
70
+
71
+ console.log(chalk.green(`āœ… Pattern stored with ID: ${id}`));
72
+
73
+ await agentdb.close();
74
+ } catch (error) {
75
+ console.error(chalk.red('āŒ Error:'), error);
76
+ process.exit(1);
77
+ }
78
+ });
79
+
80
+ // Search patterns command
81
+ program
82
+ .command('search-patterns')
83
+ .description('Search for similar patterns')
84
+ .argument('<db-path>', 'Database path')
85
+ .argument('<query>', 'Search query')
86
+ .option('-k, --top-k <k>', 'Number of results', '10')
87
+ .option('--threshold <threshold>', 'Similarity threshold', '0.7')
88
+ .option('--task-type <type>', 'Filter by task type')
89
+ .action(async (dbPath, query, options) => {
90
+ try {
91
+ const agentdb = await createONNXAgentDB({ dbPath, useGPU: false });
92
+
93
+ const results = await agentdb.reasoningBank.searchPatterns({
94
+ task: query,
95
+ k: parseInt(options.topK),
96
+ threshold: parseFloat(options.threshold),
97
+ filters: options.taskType ? { taskType: options.taskType } : undefined
98
+ });
99
+
100
+ console.log(chalk.blue(`\nFound ${results.length} patterns:\n`));
101
+
102
+ results.forEach((r, i) => {
103
+ console.log(chalk.white(`${i + 1}. ${r.approach}`));
104
+ console.log(chalk.gray(` Type: ${r.taskType}`));
105
+ console.log(chalk.gray(` Success: ${(r.successRate * 100).toFixed(1)}%`));
106
+ console.log(chalk.gray(` Similarity: ${(r.similarity * 100).toFixed(1)}%`));
107
+ if (r.tags && r.tags.length > 0) {
108
+ console.log(chalk.gray(` Tags: ${r.tags.join(', ')}`));
109
+ }
110
+ console.log();
111
+ });
112
+
113
+ await agentdb.close();
114
+ } catch (error) {
115
+ console.error(chalk.red('āŒ Error:'), error);
116
+ process.exit(1);
117
+ }
118
+ });
119
+
120
+ // Store episode command
121
+ program
122
+ .command('store-episode')
123
+ .description('Store a reflexion episode')
124
+ .argument('<db-path>', 'Database path')
125
+ .requiredOption('-s, --session <id>', 'Session ID')
126
+ .requiredOption('-t, --task <task>', 'Task description')
127
+ .requiredOption('-r, --reward <reward>', 'Reward (0-1)')
128
+ .requiredOption('--success', 'Task succeeded')
129
+ .option('--critique <critique>', 'Self-critique')
130
+ .action(async (dbPath, options) => {
131
+ try {
132
+ const agentdb = await createONNXAgentDB({ dbPath, useGPU: false });
133
+
134
+ const id = await agentdb.reflexionMemory.storeEpisode({
135
+ sessionId: options.session,
136
+ task: options.task,
137
+ reward: parseFloat(options.reward),
138
+ success: true,
139
+ critique: options.critique
140
+ });
141
+
142
+ console.log(chalk.green(`āœ… Episode stored with ID: ${id}`));
143
+
144
+ await agentdb.close();
145
+ } catch (error) {
146
+ console.error(chalk.red('āŒ Error:'), error);
147
+ process.exit(1);
148
+ }
149
+ });
150
+
151
+ // Search episodes command
152
+ program
153
+ .command('search-episodes')
154
+ .description('Search for similar episodes')
155
+ .argument('<db-path>', 'Database path')
156
+ .argument('<query>', 'Search query')
157
+ .option('-k, --top-k <k>', 'Number of results', '10')
158
+ .option('--only-successes', 'Only successful episodes')
159
+ .option('--min-reward <reward>', 'Minimum reward threshold')
160
+ .action(async (dbPath, query, options) => {
161
+ try {
162
+ const agentdb = await createONNXAgentDB({ dbPath, useGPU: false });
163
+
164
+ const results = await agentdb.reflexionMemory.retrieveRelevant({
165
+ task: query,
166
+ k: parseInt(options.topK),
167
+ onlySuccesses: options.onlySuccesses,
168
+ minReward: options.minReward ? parseFloat(options.minReward) : undefined
169
+ });
170
+
171
+ console.log(chalk.blue(`\nFound ${results.length} episodes:\n`));
172
+
173
+ results.forEach((r, i) => {
174
+ console.log(chalk.white(`${i + 1}. ${r.task}`));
175
+ console.log(chalk.gray(` Session: ${r.sessionId}`));
176
+ console.log(chalk.gray(` Reward: ${(r.reward * 100).toFixed(1)}%`));
177
+ console.log(chalk.gray(` Success: ${r.success ? 'Yes' : 'No'}`));
178
+ console.log(chalk.gray(` Similarity: ${(r.similarity * 100).toFixed(1)}%`));
179
+ if (r.critique) {
180
+ console.log(chalk.gray(` Critique: ${r.critique.substring(0, 80)}${r.critique.length > 80 ? '...' : ''}`));
181
+ }
182
+ console.log();
183
+ });
184
+
185
+ await agentdb.close();
186
+ } catch (error) {
187
+ console.error(chalk.red('āŒ Error:'), error);
188
+ process.exit(1);
189
+ }
190
+ });
191
+
192
+ // Stats command
193
+ program
194
+ .command('stats')
195
+ .description('Show database statistics')
196
+ .argument('<db-path>', 'Database path')
197
+ .action(async (dbPath) => {
198
+ try {
199
+ const agentdb = await createONNXAgentDB({ dbPath, useGPU: false });
200
+
201
+ const stats = agentdb.getStats();
202
+
203
+ console.log(chalk.blue('\nšŸ“Š AgentDB + ONNX Statistics\n'));
204
+
205
+ console.log(chalk.white('Embeddings:'));
206
+ console.log(chalk.gray(` Model: ${stats.embedder.model}`));
207
+ console.log(chalk.gray(` Total: ${stats.embedder.totalEmbeddings}`));
208
+ console.log(chalk.gray(` Avg latency: ${stats.embedder.avgLatency.toFixed(2)}ms`));
209
+ console.log(chalk.gray(` Cache hit rate: ${(stats.embedder.cache.hitRate * 100).toFixed(1)}%`));
210
+ console.log(chalk.gray(` Cache size: ${stats.embedder.cache.size}/${stats.embedder.cache.maxSize}`));
211
+
212
+ console.log(chalk.white('\nDatabase:'));
213
+ if (stats.database) {
214
+ Object.entries(stats.database).forEach(([key, value]) => {
215
+ console.log(chalk.gray(` ${key}: ${value}`));
216
+ });
217
+ }
218
+
219
+ console.log();
220
+
221
+ await agentdb.close();
222
+ } catch (error) {
223
+ console.error(chalk.red('āŒ Error:'), error);
224
+ process.exit(1);
225
+ }
226
+ });
227
+
228
+ // Benchmark command
229
+ program
230
+ .command('benchmark')
231
+ .description('Run performance benchmarks')
232
+ .option('--operations <n>', 'Number of operations per test', '100')
233
+ .action(async (options) => {
234
+ console.log(chalk.blue('Running benchmarks...\n'));
235
+
236
+ try {
237
+ // Import and run benchmark dynamically
238
+ await import('./benchmarks/benchmark-runner.js');
239
+ } catch (error) {
240
+ console.error(chalk.red('āŒ Benchmark failed:'), error);
241
+ process.exit(1);
242
+ }
243
+ });
244
+
245
+ program.parse();