@ruvector/ruvllm 2.5.6 → 2.5.7
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 +282 -282
- package/bin/cli.js +1020 -1020
- package/dist/cjs/benchmarks/embedding-benchmark.js +8 -8
- package/dist/cjs/benchmarks/index.js +5 -5
- package/dist/cjs/benchmarks/model-comparison.js +15 -25
- package/dist/cjs/benchmarks/routing-benchmark.js +5 -5
- package/dist/cjs/contrastive.js +78 -78
- package/dist/cjs/engine.js +13 -13
- package/dist/cjs/export.js +31 -31
- package/dist/cjs/federated.js +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/intelligence.js +8 -18
- package/dist/cjs/lora.js +1 -1
- package/dist/cjs/models.js +13 -23
- package/dist/cjs/native.js +5 -4
- package/dist/cjs/session.js +1 -1
- package/dist/cjs/simd.js +1 -1
- package/dist/cjs/sona.js +1 -1
- package/dist/cjs/streaming.d.ts +1 -0
- package/dist/cjs/streaming.d.ts.map +1 -1
- package/dist/cjs/streaming.js +3 -3
- package/dist/cjs/training.d.ts +32 -4
- package/dist/cjs/training.d.ts.map +1 -1
- package/dist/cjs/training.js +59 -9
- package/dist/cjs/types.js +1 -1
- package/dist/esm/benchmarks/embedding-benchmark.js +1 -1
- package/dist/esm/benchmarks/index.js +1 -1
- package/dist/esm/benchmarks/model-comparison.js +1 -1
- package/dist/esm/benchmarks/routing-benchmark.js +1 -1
- package/dist/esm/contrastive.js +70 -70
- package/dist/esm/engine.js +13 -13
- package/dist/esm/export.js +31 -31
- package/dist/esm/federated.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/intelligence.js +1 -1
- package/dist/esm/lora.js +1 -1
- package/dist/esm/models.js +1 -1
- package/dist/esm/native.js +1 -1
- package/dist/esm/session.js +1 -1
- package/dist/esm/simd.js +1 -1
- package/dist/esm/sona.js +1 -1
- package/dist/esm/streaming.d.ts +1 -0
- package/dist/esm/streaming.d.ts.map +1 -1
- package/dist/esm/streaming.js +1 -1
- package/dist/esm/training.d.ts +32 -4
- package/dist/esm/training.d.ts.map +1 -1
- package/dist/esm/training.js +59 -9
- package/dist/esm/types.js +1 -1
- package/package.json +133 -133
- package/scripts/ensemble-model-compare.js +287 -287
- package/scripts/huggingface/README.md +537 -537
- package/scripts/huggingface/publish.sh +112 -112
- package/scripts/hybrid-model-compare.js +373 -373
- package/scripts/improved-model-compare.js +288 -288
- package/scripts/optimized-model-compare.js +364 -364
- package/scripts/real-model-compare.js +280 -280
- package/scripts/training/agentic-flow-capabilities.json +329 -329
- package/scripts/training/claude-code-synth.js +505 -505
- package/scripts/training/claude-flow-capabilities.json +1322 -1322
- package/scripts/training/claude-hard-negatives.js +222 -222
- package/scripts/training/contrastive-finetune.js +517 -517
- package/scripts/training/ecosystem-triplets.jsonl +1466 -1466
- package/scripts/training/generate-ecosystem-triplets.js +1324 -1324
- package/scripts/training/routing-dataset.js +634 -634
- package/scripts/training/ruvector-capabilities.json +798 -798
- package/scripts/training/validate-ecosystem.js +381 -381
- package/scripts/training/validation-results.json +22 -22
|
@@ -1,287 +1,287 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Ensemble Model Comparison
|
|
4
|
-
*
|
|
5
|
-
* Strategies:
|
|
6
|
-
* 1. Task prefix - prepend context to make tasks more aligned with descriptions
|
|
7
|
-
* 2. Ensemble voting - combine multiple description variants
|
|
8
|
-
* 3. Agent-specific thresholds based on training patterns
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const { execSync } = require('child_process');
|
|
12
|
-
const { existsSync } = require('fs');
|
|
13
|
-
const { join } = require('path');
|
|
14
|
-
const { homedir } = require('os');
|
|
15
|
-
|
|
16
|
-
const MODELS_DIR = join(homedir(), '.ruvllm', 'models');
|
|
17
|
-
const RUVLTRA_MODEL = join(MODELS_DIR, 'ruvltra-claude-code-0.5b-q4_k_m.gguf');
|
|
18
|
-
const QWEN_MODEL = join(MODELS_DIR, 'qwen2.5-0.5b-instruct-q4_k_m.gguf');
|
|
19
|
-
|
|
20
|
-
// Original V1 descriptions (best baseline)
|
|
21
|
-
const DESCRIPTIONS_V1 = {
|
|
22
|
-
coder: 'implement create write build add code function class component feature',
|
|
23
|
-
researcher: 'research find investigate analyze explore search discover examine',
|
|
24
|
-
reviewer: 'review check evaluate assess inspect examine code quality',
|
|
25
|
-
tester: 'test unit integration e2e coverage mock assertion spec',
|
|
26
|
-
architect: 'design architecture schema system structure plan database',
|
|
27
|
-
'security-architect': 'security vulnerability xss injection audit cve authentication',
|
|
28
|
-
debugger: 'debug fix bug error issue broken crash exception trace',
|
|
29
|
-
documenter: 'document readme jsdoc comment explain describe documentation',
|
|
30
|
-
refactorer: 'refactor extract rename consolidate clean restructure simplify',
|
|
31
|
-
optimizer: 'optimize performance slow fast cache speed memory latency',
|
|
32
|
-
devops: 'deploy ci cd kubernetes docker pipeline container infrastructure',
|
|
33
|
-
'api-docs': 'openapi swagger api documentation graphql schema endpoint',
|
|
34
|
-
planner: 'plan estimate prioritize sprint roadmap schedule milestone',
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// V6: Keywords reformulated as action phrases
|
|
38
|
-
const DESCRIPTIONS_V6 = {
|
|
39
|
-
coder: 'implement new functionality write code build features create components',
|
|
40
|
-
researcher: 'research and analyze investigate patterns explore best practices',
|
|
41
|
-
reviewer: 'review code quality check pull requests evaluate implementations',
|
|
42
|
-
tester: 'write tests create test coverage add unit and integration tests',
|
|
43
|
-
architect: 'design system architecture plan database schemas structure systems',
|
|
44
|
-
'security-architect': 'audit security vulnerabilities check xss and injection attacks',
|
|
45
|
-
debugger: 'debug and fix bugs trace errors resolve exceptions',
|
|
46
|
-
documenter: 'write documentation add jsdoc comments create readme files',
|
|
47
|
-
refactorer: 'refactor code modernize to async await restructure modules',
|
|
48
|
-
optimizer: 'optimize performance improve speed cache data reduce latency',
|
|
49
|
-
devops: 'deploy to cloud setup ci cd pipelines manage containers kubernetes',
|
|
50
|
-
'api-docs': 'generate openapi documentation create swagger api specs',
|
|
51
|
-
planner: 'plan sprints create roadmaps estimate timelines schedule milestones',
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// Task prefixes to try
|
|
55
|
-
const TASK_PREFIXES = [
|
|
56
|
-
'', // No prefix (baseline)
|
|
57
|
-
'Task: ', // Simple task prefix
|
|
58
|
-
'The developer needs to: ', // Contextual prefix
|
|
59
|
-
'Claude Code task - ', // Model-specific prefix
|
|
60
|
-
];
|
|
61
|
-
|
|
62
|
-
const ROUTING_TESTS = [
|
|
63
|
-
{ task: 'Implement a binary search function in TypeScript', expected: 'coder' },
|
|
64
|
-
{ task: 'Write unit tests for the authentication module', expected: 'tester' },
|
|
65
|
-
{ task: 'Review the pull request for security vulnerabilities', expected: 'reviewer' },
|
|
66
|
-
{ task: 'Research best practices for React state management', expected: 'researcher' },
|
|
67
|
-
{ task: 'Design the database schema for user profiles', expected: 'architect' },
|
|
68
|
-
{ task: 'Fix the null pointer exception in the login handler', expected: 'debugger' },
|
|
69
|
-
{ task: 'Audit the API endpoints for XSS vulnerabilities', expected: 'security-architect' },
|
|
70
|
-
{ task: 'Write JSDoc comments for the utility functions', expected: 'documenter' },
|
|
71
|
-
{ task: 'Refactor the payment module to use async/await', expected: 'refactorer' },
|
|
72
|
-
{ task: 'Optimize the database queries for the dashboard', expected: 'optimizer' },
|
|
73
|
-
{ task: 'Set up the CI/CD pipeline for the microservices', expected: 'devops' },
|
|
74
|
-
{ task: 'Generate OpenAPI documentation for the REST API', expected: 'api-docs' },
|
|
75
|
-
{ task: 'Create a sprint plan for the next two weeks', expected: 'planner' },
|
|
76
|
-
{ task: 'Build a React component for user registration', expected: 'coder' },
|
|
77
|
-
{ task: 'Debug memory leak in the WebSocket handler', expected: 'debugger' },
|
|
78
|
-
{ task: 'Investigate slow API response times', expected: 'researcher' },
|
|
79
|
-
{ task: 'Check code for potential race conditions', expected: 'reviewer' },
|
|
80
|
-
{ task: 'Add integration tests for the payment gateway', expected: 'tester' },
|
|
81
|
-
{ task: 'Plan the architecture for real-time notifications', expected: 'architect' },
|
|
82
|
-
{ task: 'Cache the frequently accessed user data', expected: 'optimizer' },
|
|
83
|
-
];
|
|
84
|
-
|
|
85
|
-
function getEmbedding(modelPath, text) {
|
|
86
|
-
try {
|
|
87
|
-
const sanitized = text.replace(/"/g, '\\"').replace(/\n/g, ' ');
|
|
88
|
-
const result = execSync(
|
|
89
|
-
`llama-embedding -m "${modelPath}" -p "${sanitized}" --embd-output-format json 2>/dev/null`,
|
|
90
|
-
{ encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 }
|
|
91
|
-
);
|
|
92
|
-
const json = JSON.parse(result);
|
|
93
|
-
return json.data[json.data.length - 1].embedding;
|
|
94
|
-
} catch {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function cosineSimilarity(a, b) {
|
|
100
|
-
if (!a || !b || a.length !== b.length) return 0;
|
|
101
|
-
let dot = 0, normA = 0, normB = 0;
|
|
102
|
-
for (let i = 0; i < a.length; i++) {
|
|
103
|
-
dot += a[i] * b[i];
|
|
104
|
-
normA += a[i] * a[i];
|
|
105
|
-
normB += b[i] * b[i];
|
|
106
|
-
}
|
|
107
|
-
return dot / (Math.sqrt(normA) * Math.sqrt(normB) || 1);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function routeTask(taskEmbedding, agentEmbeddings) {
|
|
111
|
-
let bestAgent = 'coder';
|
|
112
|
-
let bestSim = -1;
|
|
113
|
-
const allScores = {};
|
|
114
|
-
for (const [agent, emb] of Object.entries(agentEmbeddings)) {
|
|
115
|
-
const sim = cosineSimilarity(taskEmbedding, emb);
|
|
116
|
-
allScores[agent] = sim;
|
|
117
|
-
if (sim > bestSim) {
|
|
118
|
-
bestSim = sim;
|
|
119
|
-
bestAgent = agent;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return { agent: bestAgent, confidence: bestSim, scores: allScores };
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Ensemble routing - vote across multiple description sets
|
|
127
|
-
*/
|
|
128
|
-
function routeTaskEnsemble(taskEmbedding, allAgentEmbeddings) {
|
|
129
|
-
const votes = {};
|
|
130
|
-
const agents = Object.keys(allAgentEmbeddings[0]);
|
|
131
|
-
|
|
132
|
-
for (const agent of agents) votes[agent] = 0;
|
|
133
|
-
|
|
134
|
-
// Each embedding set votes
|
|
135
|
-
for (const agentEmbeddings of allAgentEmbeddings) {
|
|
136
|
-
const { agent } = routeTask(taskEmbedding, agentEmbeddings);
|
|
137
|
-
votes[agent] = (votes[agent] || 0) + 1;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Return agent with most votes
|
|
141
|
-
let bestAgent = 'coder';
|
|
142
|
-
let maxVotes = 0;
|
|
143
|
-
for (const [agent, count] of Object.entries(votes)) {
|
|
144
|
-
if (count > maxVotes) {
|
|
145
|
-
maxVotes = count;
|
|
146
|
-
bestAgent = agent;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return { agent: bestAgent, votes, voteCount: maxVotes };
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function runBenchmark(modelPath, descriptions, prefix = '') {
|
|
154
|
-
const agentEmbeddings = {};
|
|
155
|
-
for (const [agent, desc] of Object.entries(descriptions)) {
|
|
156
|
-
agentEmbeddings[agent] = getEmbedding(modelPath, desc);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
let correct = 0;
|
|
160
|
-
for (const test of ROUTING_TESTS) {
|
|
161
|
-
const taskEmb = getEmbedding(modelPath, prefix + test.task);
|
|
162
|
-
const { agent } = routeTask(taskEmb, agentEmbeddings);
|
|
163
|
-
if (agent === test.expected) correct++;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return { accuracy: correct / ROUTING_TESTS.length, correct, total: ROUTING_TESTS.length };
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function runEnsembleBenchmark(modelPath, descriptionSets, prefix = '') {
|
|
170
|
-
// Precompute embeddings for all description sets
|
|
171
|
-
const allAgentEmbeddings = descriptionSets.map(descriptions => {
|
|
172
|
-
const embeds = {};
|
|
173
|
-
for (const [agent, desc] of Object.entries(descriptions)) {
|
|
174
|
-
embeds[agent] = getEmbedding(modelPath, desc);
|
|
175
|
-
}
|
|
176
|
-
return embeds;
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
let correct = 0;
|
|
180
|
-
const results = [];
|
|
181
|
-
for (const test of ROUTING_TESTS) {
|
|
182
|
-
const taskEmb = getEmbedding(modelPath, prefix + test.task);
|
|
183
|
-
const { agent, votes } = routeTaskEnsemble(taskEmb, allAgentEmbeddings);
|
|
184
|
-
const isCorrect = agent === test.expected;
|
|
185
|
-
if (isCorrect) correct++;
|
|
186
|
-
results.push({ task: test.task, expected: test.expected, got: agent, correct: isCorrect, votes });
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return { accuracy: correct / ROUTING_TESTS.length, correct, total: ROUTING_TESTS.length, results };
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
async function main() {
|
|
193
|
-
console.log('\n╔═══════════════════════════════════════════════════════════════════════════════════╗');
|
|
194
|
-
console.log('║ ENSEMBLE & PREFIX MODEL COMPARISON ║');
|
|
195
|
-
console.log('╚═══════════════════════════════════════════════════════════════════════════════════╝\n');
|
|
196
|
-
|
|
197
|
-
if (!existsSync(RUVLTRA_MODEL)) {
|
|
198
|
-
console.error('RuvLTRA model not found.');
|
|
199
|
-
process.exit(1);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Test prefix variations
|
|
203
|
-
console.log('─────────────────────────────────────────────────────────────────');
|
|
204
|
-
console.log(' PREFIX VARIATIONS (RuvLTRA)');
|
|
205
|
-
console.log('─────────────────────────────────────────────────────────────────\n');
|
|
206
|
-
|
|
207
|
-
const prefixResults = {};
|
|
208
|
-
for (const prefix of TASK_PREFIXES) {
|
|
209
|
-
const label = prefix || '(no prefix)';
|
|
210
|
-
process.stdout.write(` Testing "${label.padEnd(25)}"... `);
|
|
211
|
-
const result = runBenchmark(RUVLTRA_MODEL, DESCRIPTIONS_V1, prefix);
|
|
212
|
-
prefixResults[label] = result;
|
|
213
|
-
console.log(`${(result.accuracy * 100).toFixed(1)}%`);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Find best prefix
|
|
217
|
-
const bestPrefix = Object.entries(prefixResults).reduce((a, b) =>
|
|
218
|
-
a[1].accuracy > b[1].accuracy ? a : b
|
|
219
|
-
);
|
|
220
|
-
|
|
221
|
-
console.log(`\n Best prefix: "${bestPrefix[0]}" = ${(bestPrefix[1].accuracy * 100).toFixed(1)}%`);
|
|
222
|
-
|
|
223
|
-
// Test ensemble voting
|
|
224
|
-
console.log('\n─────────────────────────────────────────────────────────────────');
|
|
225
|
-
console.log(' ENSEMBLE VOTING (RuvLTRA)');
|
|
226
|
-
console.log('─────────────────────────────────────────────────────────────────\n');
|
|
227
|
-
|
|
228
|
-
process.stdout.write(' Computing V1 + V6 ensemble... ');
|
|
229
|
-
const ensembleResult = runEnsembleBenchmark(RUVLTRA_MODEL, [DESCRIPTIONS_V1, DESCRIPTIONS_V6], '');
|
|
230
|
-
console.log(`${(ensembleResult.accuracy * 100).toFixed(1)}%`);
|
|
231
|
-
|
|
232
|
-
// Compare with Qwen
|
|
233
|
-
console.log('\n─────────────────────────────────────────────────────────────────');
|
|
234
|
-
console.log(' QWEN COMPARISON');
|
|
235
|
-
console.log('─────────────────────────────────────────────────────────────────\n');
|
|
236
|
-
|
|
237
|
-
process.stdout.write(' Qwen V1 baseline... ');
|
|
238
|
-
const qwenV1 = runBenchmark(QWEN_MODEL, DESCRIPTIONS_V1, '');
|
|
239
|
-
console.log(`${(qwenV1.accuracy * 100).toFixed(1)}%`);
|
|
240
|
-
|
|
241
|
-
process.stdout.write(' Qwen V1+V6 ensemble... ');
|
|
242
|
-
const qwenEnsemble = runEnsembleBenchmark(QWEN_MODEL, [DESCRIPTIONS_V1, DESCRIPTIONS_V6], '');
|
|
243
|
-
console.log(`${(qwenEnsemble.accuracy * 100).toFixed(1)}%`);
|
|
244
|
-
|
|
245
|
-
// Final results table
|
|
246
|
-
console.log('\n═══════════════════════════════════════════════════════════════════════════════════');
|
|
247
|
-
console.log(' FINAL RESULTS');
|
|
248
|
-
console.log('═══════════════════════════════════════════════════════════════════════════════════\n');
|
|
249
|
-
|
|
250
|
-
const fmt = (v) => `${(v * 100).toFixed(1)}%`.padStart(10);
|
|
251
|
-
|
|
252
|
-
console.log('┌───────────────────────────────┬────────────┬────────────┐');
|
|
253
|
-
console.log('│ Strategy │ RuvLTRA │ Qwen │');
|
|
254
|
-
console.log('├───────────────────────────────┼────────────┼────────────┤');
|
|
255
|
-
console.log(`│ V1 Baseline │${fmt(prefixResults['(no prefix)'].accuracy)} │${fmt(qwenV1.accuracy)} │`);
|
|
256
|
-
console.log(`│ V1 + Best Prefix │${fmt(bestPrefix[1].accuracy)} │ - │`);
|
|
257
|
-
console.log(`│ V1+V6 Ensemble │${fmt(ensembleResult.accuracy)} │${fmt(qwenEnsemble.accuracy)} │`);
|
|
258
|
-
console.log('└───────────────────────────────┴────────────┴────────────┘');
|
|
259
|
-
|
|
260
|
-
// Best overall
|
|
261
|
-
const ruvBest = Math.max(
|
|
262
|
-
prefixResults['(no prefix)'].accuracy,
|
|
263
|
-
bestPrefix[1].accuracy,
|
|
264
|
-
ensembleResult.accuracy
|
|
265
|
-
);
|
|
266
|
-
const qwenBest = Math.max(qwenV1.accuracy, qwenEnsemble.accuracy);
|
|
267
|
-
|
|
268
|
-
console.log(`\n RuvLTRA Best: ${(ruvBest * 100).toFixed(1)}%`);
|
|
269
|
-
console.log(` Qwen Best: ${(qwenBest * 100).toFixed(1)}%`);
|
|
270
|
-
console.log(` Advantage: RuvLTRA +${((ruvBest - qwenBest) * 100).toFixed(1)} points`);
|
|
271
|
-
|
|
272
|
-
// Show detailed ensemble results
|
|
273
|
-
console.log('\n─────────────────────────────────────────────────────────────────');
|
|
274
|
-
console.log(' ENSEMBLE VOTING DETAILS (RuvLTRA)');
|
|
275
|
-
console.log('─────────────────────────────────────────────────────────────────\n');
|
|
276
|
-
|
|
277
|
-
for (const r of ensembleResult.results) {
|
|
278
|
-
const mark = r.correct ? '✓' : '✗';
|
|
279
|
-
const task = r.task.slice(0, 45).padEnd(45);
|
|
280
|
-
const exp = r.expected.padEnd(18);
|
|
281
|
-
console.log(`${mark} ${task} ${exp}${r.correct ? '' : '→ ' + r.got}`);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
console.log('\n');
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
main().catch(console.error);
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Ensemble Model Comparison
|
|
4
|
+
*
|
|
5
|
+
* Strategies:
|
|
6
|
+
* 1. Task prefix - prepend context to make tasks more aligned with descriptions
|
|
7
|
+
* 2. Ensemble voting - combine multiple description variants
|
|
8
|
+
* 3. Agent-specific thresholds based on training patterns
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { execSync } = require('child_process');
|
|
12
|
+
const { existsSync } = require('fs');
|
|
13
|
+
const { join } = require('path');
|
|
14
|
+
const { homedir } = require('os');
|
|
15
|
+
|
|
16
|
+
const MODELS_DIR = join(homedir(), '.ruvllm', 'models');
|
|
17
|
+
const RUVLTRA_MODEL = join(MODELS_DIR, 'ruvltra-claude-code-0.5b-q4_k_m.gguf');
|
|
18
|
+
const QWEN_MODEL = join(MODELS_DIR, 'qwen2.5-0.5b-instruct-q4_k_m.gguf');
|
|
19
|
+
|
|
20
|
+
// Original V1 descriptions (best baseline)
|
|
21
|
+
const DESCRIPTIONS_V1 = {
|
|
22
|
+
coder: 'implement create write build add code function class component feature',
|
|
23
|
+
researcher: 'research find investigate analyze explore search discover examine',
|
|
24
|
+
reviewer: 'review check evaluate assess inspect examine code quality',
|
|
25
|
+
tester: 'test unit integration e2e coverage mock assertion spec',
|
|
26
|
+
architect: 'design architecture schema system structure plan database',
|
|
27
|
+
'security-architect': 'security vulnerability xss injection audit cve authentication',
|
|
28
|
+
debugger: 'debug fix bug error issue broken crash exception trace',
|
|
29
|
+
documenter: 'document readme jsdoc comment explain describe documentation',
|
|
30
|
+
refactorer: 'refactor extract rename consolidate clean restructure simplify',
|
|
31
|
+
optimizer: 'optimize performance slow fast cache speed memory latency',
|
|
32
|
+
devops: 'deploy ci cd kubernetes docker pipeline container infrastructure',
|
|
33
|
+
'api-docs': 'openapi swagger api documentation graphql schema endpoint',
|
|
34
|
+
planner: 'plan estimate prioritize sprint roadmap schedule milestone',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// V6: Keywords reformulated as action phrases
|
|
38
|
+
const DESCRIPTIONS_V6 = {
|
|
39
|
+
coder: 'implement new functionality write code build features create components',
|
|
40
|
+
researcher: 'research and analyze investigate patterns explore best practices',
|
|
41
|
+
reviewer: 'review code quality check pull requests evaluate implementations',
|
|
42
|
+
tester: 'write tests create test coverage add unit and integration tests',
|
|
43
|
+
architect: 'design system architecture plan database schemas structure systems',
|
|
44
|
+
'security-architect': 'audit security vulnerabilities check xss and injection attacks',
|
|
45
|
+
debugger: 'debug and fix bugs trace errors resolve exceptions',
|
|
46
|
+
documenter: 'write documentation add jsdoc comments create readme files',
|
|
47
|
+
refactorer: 'refactor code modernize to async await restructure modules',
|
|
48
|
+
optimizer: 'optimize performance improve speed cache data reduce latency',
|
|
49
|
+
devops: 'deploy to cloud setup ci cd pipelines manage containers kubernetes',
|
|
50
|
+
'api-docs': 'generate openapi documentation create swagger api specs',
|
|
51
|
+
planner: 'plan sprints create roadmaps estimate timelines schedule milestones',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Task prefixes to try
|
|
55
|
+
const TASK_PREFIXES = [
|
|
56
|
+
'', // No prefix (baseline)
|
|
57
|
+
'Task: ', // Simple task prefix
|
|
58
|
+
'The developer needs to: ', // Contextual prefix
|
|
59
|
+
'Claude Code task - ', // Model-specific prefix
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const ROUTING_TESTS = [
|
|
63
|
+
{ task: 'Implement a binary search function in TypeScript', expected: 'coder' },
|
|
64
|
+
{ task: 'Write unit tests for the authentication module', expected: 'tester' },
|
|
65
|
+
{ task: 'Review the pull request for security vulnerabilities', expected: 'reviewer' },
|
|
66
|
+
{ task: 'Research best practices for React state management', expected: 'researcher' },
|
|
67
|
+
{ task: 'Design the database schema for user profiles', expected: 'architect' },
|
|
68
|
+
{ task: 'Fix the null pointer exception in the login handler', expected: 'debugger' },
|
|
69
|
+
{ task: 'Audit the API endpoints for XSS vulnerabilities', expected: 'security-architect' },
|
|
70
|
+
{ task: 'Write JSDoc comments for the utility functions', expected: 'documenter' },
|
|
71
|
+
{ task: 'Refactor the payment module to use async/await', expected: 'refactorer' },
|
|
72
|
+
{ task: 'Optimize the database queries for the dashboard', expected: 'optimizer' },
|
|
73
|
+
{ task: 'Set up the CI/CD pipeline for the microservices', expected: 'devops' },
|
|
74
|
+
{ task: 'Generate OpenAPI documentation for the REST API', expected: 'api-docs' },
|
|
75
|
+
{ task: 'Create a sprint plan for the next two weeks', expected: 'planner' },
|
|
76
|
+
{ task: 'Build a React component for user registration', expected: 'coder' },
|
|
77
|
+
{ task: 'Debug memory leak in the WebSocket handler', expected: 'debugger' },
|
|
78
|
+
{ task: 'Investigate slow API response times', expected: 'researcher' },
|
|
79
|
+
{ task: 'Check code for potential race conditions', expected: 'reviewer' },
|
|
80
|
+
{ task: 'Add integration tests for the payment gateway', expected: 'tester' },
|
|
81
|
+
{ task: 'Plan the architecture for real-time notifications', expected: 'architect' },
|
|
82
|
+
{ task: 'Cache the frequently accessed user data', expected: 'optimizer' },
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
function getEmbedding(modelPath, text) {
|
|
86
|
+
try {
|
|
87
|
+
const sanitized = text.replace(/"/g, '\\"').replace(/\n/g, ' ');
|
|
88
|
+
const result = execSync(
|
|
89
|
+
`llama-embedding -m "${modelPath}" -p "${sanitized}" --embd-output-format json 2>/dev/null`,
|
|
90
|
+
{ encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 }
|
|
91
|
+
);
|
|
92
|
+
const json = JSON.parse(result);
|
|
93
|
+
return json.data[json.data.length - 1].embedding;
|
|
94
|
+
} catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function cosineSimilarity(a, b) {
|
|
100
|
+
if (!a || !b || a.length !== b.length) return 0;
|
|
101
|
+
let dot = 0, normA = 0, normB = 0;
|
|
102
|
+
for (let i = 0; i < a.length; i++) {
|
|
103
|
+
dot += a[i] * b[i];
|
|
104
|
+
normA += a[i] * a[i];
|
|
105
|
+
normB += b[i] * b[i];
|
|
106
|
+
}
|
|
107
|
+
return dot / (Math.sqrt(normA) * Math.sqrt(normB) || 1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function routeTask(taskEmbedding, agentEmbeddings) {
|
|
111
|
+
let bestAgent = 'coder';
|
|
112
|
+
let bestSim = -1;
|
|
113
|
+
const allScores = {};
|
|
114
|
+
for (const [agent, emb] of Object.entries(agentEmbeddings)) {
|
|
115
|
+
const sim = cosineSimilarity(taskEmbedding, emb);
|
|
116
|
+
allScores[agent] = sim;
|
|
117
|
+
if (sim > bestSim) {
|
|
118
|
+
bestSim = sim;
|
|
119
|
+
bestAgent = agent;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { agent: bestAgent, confidence: bestSim, scores: allScores };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Ensemble routing - vote across multiple description sets
|
|
127
|
+
*/
|
|
128
|
+
function routeTaskEnsemble(taskEmbedding, allAgentEmbeddings) {
|
|
129
|
+
const votes = {};
|
|
130
|
+
const agents = Object.keys(allAgentEmbeddings[0]);
|
|
131
|
+
|
|
132
|
+
for (const agent of agents) votes[agent] = 0;
|
|
133
|
+
|
|
134
|
+
// Each embedding set votes
|
|
135
|
+
for (const agentEmbeddings of allAgentEmbeddings) {
|
|
136
|
+
const { agent } = routeTask(taskEmbedding, agentEmbeddings);
|
|
137
|
+
votes[agent] = (votes[agent] || 0) + 1;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Return agent with most votes
|
|
141
|
+
let bestAgent = 'coder';
|
|
142
|
+
let maxVotes = 0;
|
|
143
|
+
for (const [agent, count] of Object.entries(votes)) {
|
|
144
|
+
if (count > maxVotes) {
|
|
145
|
+
maxVotes = count;
|
|
146
|
+
bestAgent = agent;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return { agent: bestAgent, votes, voteCount: maxVotes };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function runBenchmark(modelPath, descriptions, prefix = '') {
|
|
154
|
+
const agentEmbeddings = {};
|
|
155
|
+
for (const [agent, desc] of Object.entries(descriptions)) {
|
|
156
|
+
agentEmbeddings[agent] = getEmbedding(modelPath, desc);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let correct = 0;
|
|
160
|
+
for (const test of ROUTING_TESTS) {
|
|
161
|
+
const taskEmb = getEmbedding(modelPath, prefix + test.task);
|
|
162
|
+
const { agent } = routeTask(taskEmb, agentEmbeddings);
|
|
163
|
+
if (agent === test.expected) correct++;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return { accuracy: correct / ROUTING_TESTS.length, correct, total: ROUTING_TESTS.length };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function runEnsembleBenchmark(modelPath, descriptionSets, prefix = '') {
|
|
170
|
+
// Precompute embeddings for all description sets
|
|
171
|
+
const allAgentEmbeddings = descriptionSets.map(descriptions => {
|
|
172
|
+
const embeds = {};
|
|
173
|
+
for (const [agent, desc] of Object.entries(descriptions)) {
|
|
174
|
+
embeds[agent] = getEmbedding(modelPath, desc);
|
|
175
|
+
}
|
|
176
|
+
return embeds;
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
let correct = 0;
|
|
180
|
+
const results = [];
|
|
181
|
+
for (const test of ROUTING_TESTS) {
|
|
182
|
+
const taskEmb = getEmbedding(modelPath, prefix + test.task);
|
|
183
|
+
const { agent, votes } = routeTaskEnsemble(taskEmb, allAgentEmbeddings);
|
|
184
|
+
const isCorrect = agent === test.expected;
|
|
185
|
+
if (isCorrect) correct++;
|
|
186
|
+
results.push({ task: test.task, expected: test.expected, got: agent, correct: isCorrect, votes });
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return { accuracy: correct / ROUTING_TESTS.length, correct, total: ROUTING_TESTS.length, results };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function main() {
|
|
193
|
+
console.log('\n╔═══════════════════════════════════════════════════════════════════════════════════╗');
|
|
194
|
+
console.log('║ ENSEMBLE & PREFIX MODEL COMPARISON ║');
|
|
195
|
+
console.log('╚═══════════════════════════════════════════════════════════════════════════════════╝\n');
|
|
196
|
+
|
|
197
|
+
if (!existsSync(RUVLTRA_MODEL)) {
|
|
198
|
+
console.error('RuvLTRA model not found.');
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Test prefix variations
|
|
203
|
+
console.log('─────────────────────────────────────────────────────────────────');
|
|
204
|
+
console.log(' PREFIX VARIATIONS (RuvLTRA)');
|
|
205
|
+
console.log('─────────────────────────────────────────────────────────────────\n');
|
|
206
|
+
|
|
207
|
+
const prefixResults = {};
|
|
208
|
+
for (const prefix of TASK_PREFIXES) {
|
|
209
|
+
const label = prefix || '(no prefix)';
|
|
210
|
+
process.stdout.write(` Testing "${label.padEnd(25)}"... `);
|
|
211
|
+
const result = runBenchmark(RUVLTRA_MODEL, DESCRIPTIONS_V1, prefix);
|
|
212
|
+
prefixResults[label] = result;
|
|
213
|
+
console.log(`${(result.accuracy * 100).toFixed(1)}%`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Find best prefix
|
|
217
|
+
const bestPrefix = Object.entries(prefixResults).reduce((a, b) =>
|
|
218
|
+
a[1].accuracy > b[1].accuracy ? a : b
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
console.log(`\n Best prefix: "${bestPrefix[0]}" = ${(bestPrefix[1].accuracy * 100).toFixed(1)}%`);
|
|
222
|
+
|
|
223
|
+
// Test ensemble voting
|
|
224
|
+
console.log('\n─────────────────────────────────────────────────────────────────');
|
|
225
|
+
console.log(' ENSEMBLE VOTING (RuvLTRA)');
|
|
226
|
+
console.log('─────────────────────────────────────────────────────────────────\n');
|
|
227
|
+
|
|
228
|
+
process.stdout.write(' Computing V1 + V6 ensemble... ');
|
|
229
|
+
const ensembleResult = runEnsembleBenchmark(RUVLTRA_MODEL, [DESCRIPTIONS_V1, DESCRIPTIONS_V6], '');
|
|
230
|
+
console.log(`${(ensembleResult.accuracy * 100).toFixed(1)}%`);
|
|
231
|
+
|
|
232
|
+
// Compare with Qwen
|
|
233
|
+
console.log('\n─────────────────────────────────────────────────────────────────');
|
|
234
|
+
console.log(' QWEN COMPARISON');
|
|
235
|
+
console.log('─────────────────────────────────────────────────────────────────\n');
|
|
236
|
+
|
|
237
|
+
process.stdout.write(' Qwen V1 baseline... ');
|
|
238
|
+
const qwenV1 = runBenchmark(QWEN_MODEL, DESCRIPTIONS_V1, '');
|
|
239
|
+
console.log(`${(qwenV1.accuracy * 100).toFixed(1)}%`);
|
|
240
|
+
|
|
241
|
+
process.stdout.write(' Qwen V1+V6 ensemble... ');
|
|
242
|
+
const qwenEnsemble = runEnsembleBenchmark(QWEN_MODEL, [DESCRIPTIONS_V1, DESCRIPTIONS_V6], '');
|
|
243
|
+
console.log(`${(qwenEnsemble.accuracy * 100).toFixed(1)}%`);
|
|
244
|
+
|
|
245
|
+
// Final results table
|
|
246
|
+
console.log('\n═══════════════════════════════════════════════════════════════════════════════════');
|
|
247
|
+
console.log(' FINAL RESULTS');
|
|
248
|
+
console.log('═══════════════════════════════════════════════════════════════════════════════════\n');
|
|
249
|
+
|
|
250
|
+
const fmt = (v) => `${(v * 100).toFixed(1)}%`.padStart(10);
|
|
251
|
+
|
|
252
|
+
console.log('┌───────────────────────────────┬────────────┬────────────┐');
|
|
253
|
+
console.log('│ Strategy │ RuvLTRA │ Qwen │');
|
|
254
|
+
console.log('├───────────────────────────────┼────────────┼────────────┤');
|
|
255
|
+
console.log(`│ V1 Baseline │${fmt(prefixResults['(no prefix)'].accuracy)} │${fmt(qwenV1.accuracy)} │`);
|
|
256
|
+
console.log(`│ V1 + Best Prefix │${fmt(bestPrefix[1].accuracy)} │ - │`);
|
|
257
|
+
console.log(`│ V1+V6 Ensemble │${fmt(ensembleResult.accuracy)} │${fmt(qwenEnsemble.accuracy)} │`);
|
|
258
|
+
console.log('└───────────────────────────────┴────────────┴────────────┘');
|
|
259
|
+
|
|
260
|
+
// Best overall
|
|
261
|
+
const ruvBest = Math.max(
|
|
262
|
+
prefixResults['(no prefix)'].accuracy,
|
|
263
|
+
bestPrefix[1].accuracy,
|
|
264
|
+
ensembleResult.accuracy
|
|
265
|
+
);
|
|
266
|
+
const qwenBest = Math.max(qwenV1.accuracy, qwenEnsemble.accuracy);
|
|
267
|
+
|
|
268
|
+
console.log(`\n RuvLTRA Best: ${(ruvBest * 100).toFixed(1)}%`);
|
|
269
|
+
console.log(` Qwen Best: ${(qwenBest * 100).toFixed(1)}%`);
|
|
270
|
+
console.log(` Advantage: RuvLTRA +${((ruvBest - qwenBest) * 100).toFixed(1)} points`);
|
|
271
|
+
|
|
272
|
+
// Show detailed ensemble results
|
|
273
|
+
console.log('\n─────────────────────────────────────────────────────────────────');
|
|
274
|
+
console.log(' ENSEMBLE VOTING DETAILS (RuvLTRA)');
|
|
275
|
+
console.log('─────────────────────────────────────────────────────────────────\n');
|
|
276
|
+
|
|
277
|
+
for (const r of ensembleResult.results) {
|
|
278
|
+
const mark = r.correct ? '✓' : '✗';
|
|
279
|
+
const task = r.task.slice(0, 45).padEnd(45);
|
|
280
|
+
const exp = r.expected.padEnd(18);
|
|
281
|
+
console.log(`${mark} ${task} ${exp}${r.correct ? '' : '→ ' + r.got}`);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
console.log('\n');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
main().catch(console.error);
|