@ruvector/ruvllm 3.0.0 → 4.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.
Files changed (151) hide show
  1. package/GPU-LOOP.md +229 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +9 -0
  4. package/README.md +159 -360
  5. package/examples/gpu-loop.example.json +26 -0
  6. package/package.json +50 -121
  7. package/src/adapters-cli.mjs +23 -0
  8. package/src/adapters.mjs +91 -0
  9. package/src/cli.mjs +30 -0
  10. package/src/engine.mjs +238 -0
  11. package/src/fixture.mjs +38 -0
  12. package/src/gpu-host.mjs +47 -0
  13. package/src/gpu-loop-cli.mjs +67 -0
  14. package/src/gpu-loop.mjs +184 -0
  15. package/src/gpu-spool-adapter.mjs +80 -0
  16. package/src/vast-host-adapter.mjs +274 -0
  17. package/bin/cli.js +0 -1040
  18. package/dist/cjs/benchmarks/embedding-benchmark.d.ts +0 -102
  19. package/dist/cjs/benchmarks/embedding-benchmark.d.ts.map +0 -1
  20. package/dist/cjs/benchmarks/embedding-benchmark.js +0 -436
  21. package/dist/cjs/benchmarks/index.d.ts +0 -34
  22. package/dist/cjs/benchmarks/index.d.ts.map +0 -1
  23. package/dist/cjs/benchmarks/index.js +0 -132
  24. package/dist/cjs/benchmarks/model-comparison.d.ts +0 -71
  25. package/dist/cjs/benchmarks/model-comparison.d.ts.map +0 -1
  26. package/dist/cjs/benchmarks/model-comparison.js +0 -476
  27. package/dist/cjs/benchmarks/routing-benchmark.d.ts +0 -70
  28. package/dist/cjs/benchmarks/routing-benchmark.d.ts.map +0 -1
  29. package/dist/cjs/benchmarks/routing-benchmark.js +0 -289
  30. package/dist/cjs/contrastive.d.ts +0 -229
  31. package/dist/cjs/contrastive.d.ts.map +0 -1
  32. package/dist/cjs/contrastive.js +0 -589
  33. package/dist/cjs/engine.d.ts +0 -160
  34. package/dist/cjs/engine.d.ts.map +0 -1
  35. package/dist/cjs/engine.js +0 -552
  36. package/dist/cjs/export.d.ts +0 -182
  37. package/dist/cjs/export.d.ts.map +0 -1
  38. package/dist/cjs/export.js +0 -422
  39. package/dist/cjs/federated.d.ts +0 -233
  40. package/dist/cjs/federated.d.ts.map +0 -1
  41. package/dist/cjs/federated.js +0 -525
  42. package/dist/cjs/index.d.ts +0 -68
  43. package/dist/cjs/index.d.ts.map +0 -1
  44. package/dist/cjs/index.js +0 -104
  45. package/dist/cjs/intelligence.d.ts +0 -136
  46. package/dist/cjs/intelligence.d.ts.map +0 -1
  47. package/dist/cjs/intelligence.js +0 -226
  48. package/dist/cjs/lora.d.ts +0 -251
  49. package/dist/cjs/lora.d.ts.map +0 -1
  50. package/dist/cjs/lora.js +0 -509
  51. package/dist/cjs/models.d.ts +0 -129
  52. package/dist/cjs/models.d.ts.map +0 -1
  53. package/dist/cjs/models.js +0 -323
  54. package/dist/cjs/native.d.ts +0 -140
  55. package/dist/cjs/native.d.ts.map +0 -1
  56. package/dist/cjs/native.js +0 -98
  57. package/dist/cjs/session.d.ts +0 -80
  58. package/dist/cjs/session.d.ts.map +0 -1
  59. package/dist/cjs/session.js +0 -203
  60. package/dist/cjs/simd.d.ts +0 -90
  61. package/dist/cjs/simd.d.ts.map +0 -1
  62. package/dist/cjs/simd.js +0 -209
  63. package/dist/cjs/sona.d.ts +0 -223
  64. package/dist/cjs/sona.d.ts.map +0 -1
  65. package/dist/cjs/sona.js +0 -562
  66. package/dist/cjs/streaming.d.ts +0 -55
  67. package/dist/cjs/streaming.d.ts.map +0 -1
  68. package/dist/cjs/streaming.js +0 -131
  69. package/dist/cjs/training.d.ts +0 -312
  70. package/dist/cjs/training.d.ts.map +0 -1
  71. package/dist/cjs/training.js +0 -610
  72. package/dist/cjs/types.d.ts +0 -696
  73. package/dist/cjs/types.d.ts.map +0 -1
  74. package/dist/cjs/types.js +0 -6
  75. package/dist/esm/benchmarks/embedding-benchmark.d.ts +0 -102
  76. package/dist/esm/benchmarks/embedding-benchmark.d.ts.map +0 -1
  77. package/dist/esm/benchmarks/embedding-benchmark.js +0 -427
  78. package/dist/esm/benchmarks/index.d.ts +0 -34
  79. package/dist/esm/benchmarks/index.d.ts.map +0 -1
  80. package/dist/esm/benchmarks/index.js +0 -110
  81. package/dist/esm/benchmarks/model-comparison.d.ts +0 -71
  82. package/dist/esm/benchmarks/model-comparison.d.ts.map +0 -1
  83. package/dist/esm/benchmarks/model-comparison.js +0 -434
  84. package/dist/esm/benchmarks/routing-benchmark.d.ts +0 -70
  85. package/dist/esm/benchmarks/routing-benchmark.d.ts.map +0 -1
  86. package/dist/esm/benchmarks/routing-benchmark.js +0 -283
  87. package/dist/esm/contrastive.d.ts +0 -229
  88. package/dist/esm/contrastive.d.ts.map +0 -1
  89. package/dist/esm/contrastive.js +0 -578
  90. package/dist/esm/engine.d.ts +0 -160
  91. package/dist/esm/engine.d.ts.map +0 -1
  92. package/dist/esm/engine.js +0 -548
  93. package/dist/esm/export.d.ts +0 -182
  94. package/dist/esm/export.d.ts.map +0 -1
  95. package/dist/esm/export.js +0 -414
  96. package/dist/esm/federated.d.ts +0 -233
  97. package/dist/esm/federated.d.ts.map +0 -1
  98. package/dist/esm/federated.js +0 -520
  99. package/dist/esm/index.d.ts +0 -68
  100. package/dist/esm/index.d.ts.map +0 -1
  101. package/dist/esm/index.js +0 -84
  102. package/dist/esm/intelligence.d.ts +0 -136
  103. package/dist/esm/intelligence.d.ts.map +0 -1
  104. package/dist/esm/intelligence.js +0 -188
  105. package/dist/esm/lora.d.ts +0 -251
  106. package/dist/esm/lora.d.ts.map +0 -1
  107. package/dist/esm/lora.js +0 -504
  108. package/dist/esm/models.d.ts +0 -129
  109. package/dist/esm/models.d.ts.map +0 -1
  110. package/dist/esm/models.js +0 -282
  111. package/dist/esm/native.d.ts +0 -140
  112. package/dist/esm/native.d.ts.map +0 -1
  113. package/dist/esm/native.js +0 -93
  114. package/dist/esm/session.d.ts +0 -80
  115. package/dist/esm/session.d.ts.map +0 -1
  116. package/dist/esm/session.js +0 -199
  117. package/dist/esm/simd.d.ts +0 -90
  118. package/dist/esm/simd.d.ts.map +0 -1
  119. package/dist/esm/simd.js +0 -205
  120. package/dist/esm/sona.d.ts +0 -223
  121. package/dist/esm/sona.d.ts.map +0 -1
  122. package/dist/esm/sona.js +0 -556
  123. package/dist/esm/streaming.d.ts +0 -55
  124. package/dist/esm/streaming.d.ts.map +0 -1
  125. package/dist/esm/streaming.js +0 -126
  126. package/dist/esm/training.d.ts +0 -312
  127. package/dist/esm/training.d.ts.map +0 -1
  128. package/dist/esm/training.js +0 -603
  129. package/dist/esm/types.d.ts +0 -696
  130. package/dist/esm/types.d.ts.map +0 -1
  131. package/dist/esm/types.js +0 -5
  132. package/scripts/ensemble-model-compare.js +0 -287
  133. package/scripts/fix-esm-extensions.mjs +0 -181
  134. package/scripts/huggingface/README.md +0 -537
  135. package/scripts/huggingface/publish.sh +0 -112
  136. package/scripts/hybrid-model-compare.js +0 -373
  137. package/scripts/improved-model-compare.js +0 -288
  138. package/scripts/optimized-model-compare.js +0 -364
  139. package/scripts/real-model-compare.js +0 -280
  140. package/scripts/smoke-esm.mjs +0 -82
  141. package/scripts/training/agentic-flow-capabilities.json +0 -329
  142. package/scripts/training/claude-code-synth.js +0 -505
  143. package/scripts/training/claude-flow-capabilities.json +0 -1322
  144. package/scripts/training/claude-hard-negatives.js +0 -222
  145. package/scripts/training/contrastive-finetune.js +0 -517
  146. package/scripts/training/ecosystem-triplets.jsonl +0 -1467
  147. package/scripts/training/generate-ecosystem-triplets.js +0 -1324
  148. package/scripts/training/routing-dataset.js +0 -634
  149. package/scripts/training/ruvector-capabilities.json +0 -798
  150. package/scripts/training/validate-ecosystem.js +0 -381
  151. package/scripts/training/validation-results.json +0 -23
@@ -1,517 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Contrastive Fine-tuning for RuvLTRA Claude Code Router
4
- *
5
- * Uses triplet loss to fine-tune embeddings:
6
- * - Anchor: task description
7
- * - Positive: correct agent description
8
- * - Negative: wrong agent description (hard negative)
9
- *
10
- * Goal: minimize distance(anchor, positive) and maximize distance(anchor, negative)
11
- */
12
-
13
- const { execSync } = require('child_process');
14
- const { existsSync, writeFileSync, readFileSync, mkdirSync } = require('fs');
15
- const { join } = require('path');
16
- const { homedir } = require('os');
17
-
18
- const MODELS_DIR = join(homedir(), '.ruvllm', 'models');
19
- const OUTPUT_DIR = join(homedir(), '.ruvllm', 'training');
20
- const RUVLTRA_MODEL = join(MODELS_DIR, 'ruvltra-claude-code-0.5b-q4_k_m.gguf');
21
-
22
- // Import training data
23
- const { AGENT_TRAINING_DATA, generateTrainingDataset, generateContrastivePairs, getDatasetStats } = require('./routing-dataset');
24
-
25
- // Build agent descriptions from training data
26
- const AGENT_DESCRIPTIONS = {};
27
- for (const [agent, data] of Object.entries(AGENT_TRAINING_DATA)) {
28
- AGENT_DESCRIPTIONS[agent] = data.description;
29
- }
30
-
31
- // Get training data
32
- const TRAINING_EXAMPLES = generateTrainingDataset();
33
- const CONTRASTIVE_PAIRS_RAW = generateContrastivePairs();
34
-
35
- // Training configuration
36
- const CONFIG = {
37
- epochs: 10,
38
- batchSize: 16,
39
- learningRate: 0.0001,
40
- margin: 0.5, // Triplet loss margin
41
- temperature: 0.07, // InfoNCE temperature
42
- hardNegativeRatio: 0.7, // Ratio of hard negatives
43
- outputPath: join(OUTPUT_DIR, 'ruvltra-finetuned'),
44
- };
45
-
46
- /**
47
- * Get embedding from model
48
- */
49
- function getEmbedding(modelPath, text) {
50
- try {
51
- const sanitized = text.replace(/"/g, '\\"').replace(/\n/g, ' ').slice(0, 500);
52
- const result = execSync(
53
- `llama-embedding -m "${modelPath}" -p "${sanitized}" --embd-output-format json 2>/dev/null`,
54
- { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 }
55
- );
56
- const json = JSON.parse(result);
57
- return json.data[json.data.length - 1].embedding;
58
- } catch {
59
- return null;
60
- }
61
- }
62
-
63
- /**
64
- * Compute cosine similarity
65
- */
66
- function cosineSimilarity(a, b) {
67
- if (!a || !b || a.length !== b.length) return 0;
68
- let dot = 0, normA = 0, normB = 0;
69
- for (let i = 0; i < a.length; i++) {
70
- dot += a[i] * b[i];
71
- normA += a[i] * a[i];
72
- normB += b[i] * b[i];
73
- }
74
- return dot / (Math.sqrt(normA) * Math.sqrt(normB) || 1);
75
- }
76
-
77
- /**
78
- * Compute triplet loss
79
- * L = max(0, margin + d(anchor, positive) - d(anchor, negative))
80
- */
81
- function tripletLoss(anchorEmb, positiveEmb, negativeEmb, margin = CONFIG.margin) {
82
- const posDist = 1 - cosineSimilarity(anchorEmb, positiveEmb);
83
- const negDist = 1 - cosineSimilarity(anchorEmb, negativeEmb);
84
- return Math.max(0, margin + posDist - negDist);
85
- }
86
-
87
- /**
88
- * Compute InfoNCE loss (contrastive)
89
- */
90
- function infoNCELoss(anchorEmb, positiveEmb, negativeEmbs, temperature = CONFIG.temperature) {
91
- const posSim = cosineSimilarity(anchorEmb, positiveEmb) / temperature;
92
- const negSims = negativeEmbs.map(neg => cosineSimilarity(anchorEmb, neg) / temperature);
93
-
94
- // Softmax denominator
95
- const maxSim = Math.max(posSim, ...negSims);
96
- const expPos = Math.exp(posSim - maxSim);
97
- const expNegs = negSims.map(sim => Math.exp(sim - maxSim));
98
- const denominator = expPos + expNegs.reduce((a, b) => a + b, 0);
99
-
100
- // Cross-entropy loss
101
- return -Math.log(expPos / denominator);
102
- }
103
-
104
- /**
105
- * Prepare training batches with triplets
106
- */
107
- function prepareTrainingData(modelPath) {
108
- console.log('Preparing training data...');
109
-
110
- // Pre-compute agent description embeddings
111
- const agentEmbeddings = {};
112
- for (const [agent, desc] of Object.entries(AGENT_DESCRIPTIONS)) {
113
- process.stdout.write(` Embedding ${agent}... `);
114
- agentEmbeddings[agent] = getEmbedding(modelPath, desc);
115
- console.log('done');
116
- }
117
-
118
- // Create triplets from training examples
119
- const triplets = [];
120
- const agents = Object.keys(AGENT_DESCRIPTIONS);
121
-
122
- console.log(`\nGenerating triplets from ${TRAINING_EXAMPLES.length} examples...`);
123
-
124
- // Group examples by agent
125
- const examplesByAgent = {};
126
- for (const ex of TRAINING_EXAMPLES) {
127
- if (!examplesByAgent[ex.agent]) examplesByAgent[ex.agent] = [];
128
- examplesByAgent[ex.agent].push(ex);
129
- }
130
-
131
- // Create triplets: anchor task, positive agent, negative agent
132
- for (const example of TRAINING_EXAMPLES.slice(0, 200)) { // Limit for speed
133
- const anchorEmb = getEmbedding(modelPath, example.task);
134
- if (!anchorEmb) continue;
135
-
136
- const positiveAgent = example.agent;
137
- const positiveEmb = agentEmbeddings[positiveAgent];
138
-
139
- // Get hard negatives (confusing agents)
140
- const hardNegatives = example.confusing_with
141
- ? [example.confusing_with]
142
- : agents.filter(a => a !== positiveAgent).slice(0, 2);
143
-
144
- for (const negAgent of hardNegatives) {
145
- const negativeEmb = agentEmbeddings[negAgent];
146
- if (negativeEmb) {
147
- triplets.push({
148
- anchor: example.task,
149
- anchorEmb,
150
- positive: positiveAgent,
151
- positiveEmb,
152
- negative: negAgent,
153
- negativeEmb,
154
- isHard: !!example.confusing_with,
155
- });
156
- }
157
- }
158
-
159
- // Add random negative for diversity
160
- const randomNeg = agents.filter(a => a !== positiveAgent)[Math.floor(Math.random() * (agents.length - 1))];
161
- if (agentEmbeddings[randomNeg]) {
162
- triplets.push({
163
- anchor: example.task,
164
- anchorEmb,
165
- positive: positiveAgent,
166
- positiveEmb,
167
- negative: randomNeg,
168
- negativeEmb: agentEmbeddings[randomNeg],
169
- isHard: false,
170
- });
171
- }
172
- }
173
-
174
- console.log(`Created ${triplets.length} triplets`);
175
- return { triplets, agentEmbeddings };
176
- }
177
-
178
- /**
179
- * Compute gradient for embedding update (simplified)
180
- * In practice, this would be done via proper backprop
181
- */
182
- function computeGradient(anchorEmb, positiveEmb, negativeEmb, lr = CONFIG.learningRate) {
183
- const dim = anchorEmb.length;
184
- const gradient = new Array(dim).fill(0);
185
-
186
- // Pull anchor towards positive
187
- for (let i = 0; i < dim; i++) {
188
- gradient[i] += lr * (positiveEmb[i] - anchorEmb[i]);
189
- }
190
-
191
- // Push anchor away from negative
192
- for (let i = 0; i < dim; i++) {
193
- gradient[i] -= lr * 0.5 * (negativeEmb[i] - anchorEmb[i]);
194
- }
195
-
196
- return gradient;
197
- }
198
-
199
- /**
200
- * Export training data for external fine-tuning tools
201
- */
202
- function exportTrainingData(triplets, outputPath) {
203
- console.log(`\nExporting training data to ${outputPath}...`);
204
-
205
- // JSONL format for fine-tuning
206
- const jsonlData = triplets.map(t => ({
207
- anchor: t.anchor,
208
- positive: t.positive,
209
- negative: t.negative,
210
- isHard: t.isHard,
211
- }));
212
-
213
- // CSV format for analysis
214
- const csvData = [
215
- 'anchor,positive,negative,is_hard',
216
- ...triplets.map(t => `"${t.anchor.replace(/"/g, '""')}",${t.positive},${t.negative},${t.isHard}`)
217
- ].join('\n');
218
-
219
- // Embedding matrix for direct training
220
- const embeddingData = {
221
- anchors: triplets.map(t => t.anchorEmb),
222
- positives: triplets.map(t => t.positiveEmb),
223
- negatives: triplets.map(t => t.negativeEmb),
224
- labels: triplets.map(t => t.positive),
225
- };
226
-
227
- mkdirSync(outputPath, { recursive: true });
228
- writeFileSync(join(outputPath, 'triplets.jsonl'), jsonlData.map(JSON.stringify).join('\n'));
229
- writeFileSync(join(outputPath, 'triplets.csv'), csvData);
230
- writeFileSync(join(outputPath, 'embeddings.json'), JSON.stringify(embeddingData, null, 2));
231
-
232
- console.log(` Exported ${triplets.length} triplets`);
233
- return outputPath;
234
- }
235
-
236
- /**
237
- * Simulate training loop (compute losses)
238
- */
239
- function simulateTraining(triplets, epochs = CONFIG.epochs) {
240
- console.log(`\nSimulating ${epochs} epochs of training...`);
241
-
242
- const batchSize = CONFIG.batchSize;
243
- const history = [];
244
-
245
- for (let epoch = 0; epoch < epochs; epoch++) {
246
- let epochLoss = 0;
247
- let batchCount = 0;
248
-
249
- // Shuffle triplets
250
- const shuffled = [...triplets].sort(() => Math.random() - 0.5);
251
-
252
- for (let i = 0; i < shuffled.length; i += batchSize) {
253
- const batch = shuffled.slice(i, i + batchSize);
254
- let batchLoss = 0;
255
-
256
- for (const triplet of batch) {
257
- const loss = tripletLoss(
258
- triplet.anchorEmb,
259
- triplet.positiveEmb,
260
- triplet.negativeEmb
261
- );
262
- batchLoss += loss;
263
- }
264
-
265
- epochLoss += batchLoss / batch.length;
266
- batchCount++;
267
- }
268
-
269
- const avgLoss = epochLoss / batchCount;
270
- history.push({ epoch: epoch + 1, loss: avgLoss });
271
-
272
- process.stdout.write(` Epoch ${epoch + 1}/${epochs}: loss = ${avgLoss.toFixed(4)}\r`);
273
- }
274
-
275
- console.log('\n');
276
- return history;
277
- }
278
-
279
- /**
280
- * Evaluate model on test set
281
- */
282
- function evaluateModel(modelPath, agentEmbeddings) {
283
- const ROUTING_TESTS = [
284
- { task: 'Implement a binary search function in TypeScript', expected: 'coder' },
285
- { task: 'Write unit tests for the authentication module', expected: 'tester' },
286
- { task: 'Review the pull request for security vulnerabilities', expected: 'reviewer' },
287
- { task: 'Research best practices for React state management', expected: 'researcher' },
288
- { task: 'Design the database schema for user profiles', expected: 'architect' },
289
- { task: 'Fix the null pointer exception in the login handler', expected: 'debugger' },
290
- { task: 'Audit the API endpoints for XSS vulnerabilities', expected: 'security-architect' },
291
- { task: 'Write JSDoc comments for the utility functions', expected: 'documenter' },
292
- { task: 'Refactor the payment module to use async/await', expected: 'refactorer' },
293
- { task: 'Optimize the database queries for the dashboard', expected: 'optimizer' },
294
- { task: 'Set up the CI/CD pipeline for the microservices', expected: 'devops' },
295
- { task: 'Generate OpenAPI documentation for the REST API', expected: 'api-docs' },
296
- { task: 'Create a sprint plan for the next two weeks', expected: 'planner' },
297
- { task: 'Build a React component for user registration', expected: 'coder' },
298
- { task: 'Debug memory leak in the WebSocket handler', expected: 'debugger' },
299
- { task: 'Investigate slow API response times', expected: 'researcher' },
300
- { task: 'Check code for potential race conditions', expected: 'reviewer' },
301
- { task: 'Add integration tests for the payment gateway', expected: 'tester' },
302
- { task: 'Plan the architecture for real-time notifications', expected: 'architect' },
303
- { task: 'Cache the frequently accessed user data', expected: 'optimizer' },
304
- ];
305
-
306
- let correct = 0;
307
- const results = [];
308
-
309
- for (const test of ROUTING_TESTS) {
310
- const taskEmb = getEmbedding(modelPath, test.task);
311
-
312
- let bestAgent = 'coder';
313
- let bestSim = -1;
314
-
315
- for (const [agent, emb] of Object.entries(agentEmbeddings)) {
316
- const sim = cosineSimilarity(taskEmb, emb);
317
- if (sim > bestSim) {
318
- bestSim = sim;
319
- bestAgent = agent;
320
- }
321
- }
322
-
323
- const isCorrect = bestAgent === test.expected;
324
- if (isCorrect) correct++;
325
- results.push({ task: test.task, expected: test.expected, got: bestAgent, correct: isCorrect });
326
- }
327
-
328
- return { accuracy: correct / ROUTING_TESTS.length, correct, total: ROUTING_TESTS.length, results };
329
- }
330
-
331
- /**
332
- * Generate LoRA adapter configuration
333
- */
334
- function generateLoRAConfig(outputPath) {
335
- const loraConfig = {
336
- model_type: 'qwen2',
337
- base_model: 'Qwen/Qwen2.5-0.5B',
338
- output_dir: outputPath,
339
-
340
- // LoRA parameters
341
- lora_r: 8,
342
- lora_alpha: 16,
343
- lora_dropout: 0.05,
344
- target_modules: ['q_proj', 'v_proj', 'k_proj', 'o_proj'],
345
-
346
- // Training parameters
347
- learning_rate: CONFIG.learningRate,
348
- num_train_epochs: CONFIG.epochs,
349
- per_device_train_batch_size: CONFIG.batchSize,
350
- gradient_accumulation_steps: 4,
351
- warmup_ratio: 0.1,
352
-
353
- // Contrastive loss parameters
354
- loss_type: 'triplet',
355
- margin: CONFIG.margin,
356
- temperature: CONFIG.temperature,
357
-
358
- // Data
359
- train_data: join(outputPath, 'triplets.jsonl'),
360
- eval_data: join(outputPath, 'eval.jsonl'),
361
- };
362
-
363
- writeFileSync(join(outputPath, 'lora_config.json'), JSON.stringify(loraConfig, null, 2));
364
- return loraConfig;
365
- }
366
-
367
- /**
368
- * Generate training script for external tools
369
- */
370
- function generateTrainingScript(outputPath) {
371
- const script = `#!/bin/bash
372
- # RuvLTRA Fine-tuning Script
373
- # Prerequisites: pip install transformers peft accelerate
374
-
375
- set -e
376
-
377
- MODEL_PATH="${outputPath}"
378
- BASE_MODEL="Qwen/Qwen2.5-0.5B"
379
-
380
- echo "=== RuvLTRA Contrastive Fine-tuning ==="
381
- echo "Base model: $BASE_MODEL"
382
- echo "Output: $MODEL_PATH"
383
-
384
- # Check for training data
385
- if [ ! -f "$MODEL_PATH/triplets.jsonl" ]; then
386
- echo "Error: Training data not found at $MODEL_PATH/triplets.jsonl"
387
- exit 1
388
- fi
389
-
390
- # Install dependencies if needed
391
- python3 -c "import transformers, peft" 2>/dev/null || {
392
- echo "Installing dependencies..."
393
- pip install transformers peft accelerate sentencepiece
394
- }
395
-
396
- # Fine-tune with LoRA
397
- python3 << 'PYTHON'
398
- import json
399
- import torch
400
- from pathlib import Path
401
- from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
402
- from peft import LoraConfig, get_peft_model, TaskType
403
-
404
- # Load config
405
- config_path = Path("${outputPath}/lora_config.json")
406
- with open(config_path) as f:
407
- config = json.load(f)
408
-
409
- print(f"Loading base model: {config['base_model']}")
410
-
411
- # Load model and tokenizer
412
- tokenizer = AutoTokenizer.from_pretrained(config['base_model'])
413
- model = AutoModelForCausalLM.from_pretrained(
414
- config['base_model'],
415
- torch_dtype=torch.float16,
416
- device_map='auto'
417
- )
418
-
419
- # Configure LoRA
420
- lora_config = LoraConfig(
421
- r=config['lora_r'],
422
- lora_alpha=config['lora_alpha'],
423
- lora_dropout=config['lora_dropout'],
424
- target_modules=config['target_modules'],
425
- task_type=TaskType.CAUSAL_LM,
426
- )
427
-
428
- model = get_peft_model(model, lora_config)
429
- model.print_trainable_parameters()
430
-
431
- print("Model ready for fine-tuning!")
432
- print(f"Training data: {config['train_data']}")
433
- print("Note: Full training requires GPU. This script validates the setup.")
434
- PYTHON
435
-
436
- echo ""
437
- echo "=== Setup Complete ==="
438
- echo "To train on GPU, run the full training pipeline."
439
- echo "Training data exported to: $MODEL_PATH/triplets.jsonl"
440
- `;
441
-
442
- writeFileSync(join(outputPath, 'train.sh'), script);
443
- execSync(`chmod +x "${join(outputPath, 'train.sh')}"`);
444
- return join(outputPath, 'train.sh');
445
- }
446
-
447
- /**
448
- * Main training pipeline
449
- */
450
- async function main() {
451
- console.log('╔═══════════════════════════════════════════════════════════════════════════════════╗');
452
- console.log('║ RuvLTRA Contrastive Fine-tuning Pipeline ║');
453
- console.log('╚═══════════════════════════════════════════════════════════════════════════════════╝\n');
454
-
455
- if (!existsSync(RUVLTRA_MODEL)) {
456
- console.error('RuvLTRA model not found. Run download-models.sh first.');
457
- process.exit(1);
458
- }
459
-
460
- const stats = getDatasetStats();
461
- console.log(`Model: ${RUVLTRA_MODEL}`);
462
- console.log(`Training examples: ${stats.totalExamples}`);
463
- console.log(`Contrastive pairs: ${stats.contrastivePairs}`);
464
- console.log(`Output: ${CONFIG.outputPath}\n`);
465
-
466
- // Prepare training data
467
- const { triplets, agentEmbeddings } = prepareTrainingData(RUVLTRA_MODEL);
468
-
469
- // Export for external training
470
- exportTrainingData(triplets, CONFIG.outputPath);
471
-
472
- // Generate LoRA config
473
- const loraConfig = generateLoRAConfig(CONFIG.outputPath);
474
- console.log('Generated LoRA config:', join(CONFIG.outputPath, 'lora_config.json'));
475
-
476
- // Generate training script
477
- const scriptPath = generateTrainingScript(CONFIG.outputPath);
478
- console.log('Generated training script:', scriptPath);
479
-
480
- // Simulate training to show expected loss curve
481
- const history = simulateTraining(triplets);
482
-
483
- // Evaluate current model
484
- console.log('─────────────────────────────────────────────────────────────────');
485
- console.log(' CURRENT MODEL EVALUATION');
486
- console.log('─────────────────────────────────────────────────────────────────\n');
487
-
488
- const evalResult = evaluateModel(RUVLTRA_MODEL, agentEmbeddings);
489
- console.log(`Embedding-only accuracy: ${(evalResult.accuracy * 100).toFixed(1)}%\n`);
490
-
491
- // Summary
492
- console.log('═══════════════════════════════════════════════════════════════════════════════════');
493
- console.log(' TRAINING SUMMARY');
494
- console.log('═══════════════════════════════════════════════════════════════════════════════════\n');
495
-
496
- console.log('Training data exported:');
497
- console.log(` - ${join(CONFIG.outputPath, 'triplets.jsonl')} (${triplets.length} triplets)`);
498
- console.log(` - ${join(CONFIG.outputPath, 'triplets.csv')} (spreadsheet format)`);
499
- console.log(` - ${join(CONFIG.outputPath, 'embeddings.json')} (precomputed embeddings)`);
500
- console.log(` - ${join(CONFIG.outputPath, 'lora_config.json')} (LoRA configuration)`);
501
- console.log(` - ${join(CONFIG.outputPath, 'train.sh')} (training script)\n`);
502
-
503
- console.log('Expected training loss (simulated):');
504
- console.log(` Initial: ${history[0].loss.toFixed(4)}`);
505
- console.log(` Final: ${history[history.length - 1].loss.toFixed(4)}`);
506
- console.log(` Improvement: ${((1 - history[history.length - 1].loss / history[0].loss) * 100).toFixed(1)}%\n`);
507
-
508
- console.log('To fine-tune on GPU:');
509
- console.log(` cd ${CONFIG.outputPath}`);
510
- console.log(' ./train.sh\n');
511
-
512
- console.log('After training, convert to GGUF:');
513
- console.log(' python convert_lora.py --base Qwen/Qwen2.5-0.5B --lora ./lora-adapter');
514
- console.log(' llama-quantize model-merged.gguf ruvltra-finetuned-q4_k_m.gguf q4_k_m\n');
515
- }
516
-
517
- main().catch(console.error);