@ruvector/edge-net 0.5.0 → 0.5.3
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 +281 -10
- package/core-invariants.js +942 -0
- package/models/adapter-hub.js +1008 -0
- package/models/adapter-security.js +792 -0
- package/models/benchmark.js +688 -0
- package/models/distribution.js +791 -0
- package/models/index.js +109 -0
- package/models/integrity.js +753 -0
- package/models/loader.js +725 -0
- package/models/microlora.js +1298 -0
- package/models/model-loader.js +922 -0
- package/models/model-optimizer.js +1245 -0
- package/models/model-registry.js +696 -0
- package/models/model-utils.js +548 -0
- package/models/models-cli.js +914 -0
- package/models/registry.json +214 -0
- package/models/training-utils.js +1418 -0
- package/models/wasm-core.js +1025 -0
- package/network-genesis.js +2847 -0
- package/onnx-worker.js +462 -8
- package/package.json +33 -3
- package/plugins/SECURITY-AUDIT.md +654 -0
- package/plugins/cli.js +43 -3
- package/plugins/implementations/e2e-encryption.js +57 -12
- package/plugins/plugin-loader.js +610 -21
- package/tests/model-optimizer.test.js +644 -0
- package/tests/network-genesis.test.js +562 -0
- package/tests/plugin-benchmark.js +1239 -0
- package/tests/plugin-system-test.js +163 -0
- package/tests/wasm-core.test.js +368 -0
package/onnx-worker.js
CHANGED
|
@@ -22,52 +22,173 @@ let loadedGenModel = null;
|
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Available embedding models (smallest first)
|
|
25
|
+
* Optimized for edge computing with size/quality tradeoffs
|
|
25
26
|
*/
|
|
26
27
|
export const EMBEDDING_MODELS = {
|
|
28
|
+
// Tier 1: Ultra-fast (~20-30MB)
|
|
27
29
|
'minilm-l6': {
|
|
28
30
|
id: 'Xenova/all-MiniLM-L6-v2',
|
|
29
31
|
dimensions: 384,
|
|
30
32
|
size: '~22MB',
|
|
31
33
|
description: 'Fast, good quality embeddings',
|
|
34
|
+
tier: 1,
|
|
32
35
|
},
|
|
36
|
+
'e5-small': {
|
|
37
|
+
id: 'Xenova/e5-small-v2',
|
|
38
|
+
dimensions: 384,
|
|
39
|
+
size: '~28MB',
|
|
40
|
+
description: 'Microsoft E5 - excellent retrieval',
|
|
41
|
+
tier: 1,
|
|
42
|
+
},
|
|
43
|
+
// Tier 2: Balanced (~30-70MB)
|
|
33
44
|
'minilm-l12': {
|
|
34
45
|
id: 'Xenova/all-MiniLM-L12-v2',
|
|
35
46
|
dimensions: 384,
|
|
36
47
|
size: '~33MB',
|
|
37
48
|
description: 'Better quality, slightly slower',
|
|
49
|
+
tier: 2,
|
|
50
|
+
},
|
|
51
|
+
'bge-small': {
|
|
52
|
+
id: 'Xenova/bge-small-en-v1.5',
|
|
53
|
+
dimensions: 384,
|
|
54
|
+
size: '~33MB',
|
|
55
|
+
description: 'Best for retrieval tasks',
|
|
56
|
+
tier: 2,
|
|
38
57
|
},
|
|
39
58
|
'gte-small': {
|
|
40
59
|
id: 'Xenova/gte-small',
|
|
41
60
|
dimensions: 384,
|
|
42
61
|
size: '~67MB',
|
|
43
62
|
description: 'High quality embeddings',
|
|
63
|
+
tier: 2,
|
|
44
64
|
},
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
// Tier 3: High quality (~100MB+)
|
|
66
|
+
'gte-base': {
|
|
67
|
+
id: 'Xenova/gte-base',
|
|
68
|
+
dimensions: 768,
|
|
69
|
+
size: '~100MB',
|
|
70
|
+
description: 'Higher quality, 768d',
|
|
71
|
+
tier: 3,
|
|
72
|
+
},
|
|
73
|
+
'bge-base': {
|
|
74
|
+
id: 'Xenova/bge-base-en-v1.5',
|
|
75
|
+
dimensions: 768,
|
|
76
|
+
size: '~108MB',
|
|
77
|
+
description: 'High quality BAAI retrieval',
|
|
78
|
+
tier: 3,
|
|
79
|
+
},
|
|
80
|
+
// Specialized: Multilingual
|
|
81
|
+
'multilingual-e5': {
|
|
82
|
+
id: 'Xenova/multilingual-e5-small',
|
|
47
83
|
dimensions: 384,
|
|
48
|
-
size: '~
|
|
49
|
-
description: '
|
|
84
|
+
size: '~118MB',
|
|
85
|
+
description: '100+ languages support',
|
|
86
|
+
tier: 3,
|
|
50
87
|
},
|
|
51
88
|
};
|
|
52
89
|
|
|
53
90
|
/**
|
|
54
91
|
* Available text generation models
|
|
92
|
+
* Organized by size and capability for edge deployment
|
|
55
93
|
*/
|
|
56
94
|
export const GENERATION_MODELS = {
|
|
95
|
+
// Tier 1: Ultra-small (< 100MB) - Fast inference
|
|
96
|
+
'tinystories': {
|
|
97
|
+
id: 'Xenova/TinyStories-33M',
|
|
98
|
+
size: '~65MB',
|
|
99
|
+
description: 'Ultra-small for stories',
|
|
100
|
+
tier: 1,
|
|
101
|
+
capabilities: ['stories', 'creative'],
|
|
102
|
+
},
|
|
57
103
|
'distilgpt2': {
|
|
58
104
|
id: 'Xenova/distilgpt2',
|
|
59
105
|
size: '~82MB',
|
|
60
106
|
description: 'Fast text generation',
|
|
107
|
+
tier: 1,
|
|
108
|
+
capabilities: ['general', 'completion'],
|
|
61
109
|
},
|
|
110
|
+
// Tier 2: Small (100-300MB) - Good quality
|
|
62
111
|
'gpt2': {
|
|
63
112
|
id: 'Xenova/gpt2',
|
|
64
113
|
size: '~250MB',
|
|
65
114
|
description: 'Classic GPT-2',
|
|
115
|
+
tier: 2,
|
|
116
|
+
capabilities: ['general', 'completion', 'creative'],
|
|
66
117
|
},
|
|
67
|
-
'
|
|
68
|
-
id: 'Xenova/
|
|
69
|
-
size: '~
|
|
70
|
-
description: '
|
|
118
|
+
'phi-1.5': {
|
|
119
|
+
id: 'Xenova/phi-1_5',
|
|
120
|
+
size: '~280MB',
|
|
121
|
+
description: 'Microsoft Phi-1.5 - code & reasoning',
|
|
122
|
+
tier: 2,
|
|
123
|
+
capabilities: ['code', 'reasoning', 'math'],
|
|
124
|
+
},
|
|
125
|
+
'phi-2': {
|
|
126
|
+
id: 'Xenova/phi-2',
|
|
127
|
+
size: '~550MB',
|
|
128
|
+
description: 'Microsoft Phi-2 - advanced reasoning',
|
|
129
|
+
tier: 3,
|
|
130
|
+
capabilities: ['code', 'reasoning', 'math', 'general'],
|
|
131
|
+
},
|
|
132
|
+
// Tier 3: Medium (300MB-1GB) - High quality
|
|
133
|
+
'qwen-0.5b': {
|
|
134
|
+
id: 'Xenova/Qwen1.5-0.5B',
|
|
135
|
+
size: '~430MB',
|
|
136
|
+
description: 'Qwen 0.5B - multilingual small model',
|
|
137
|
+
tier: 3,
|
|
138
|
+
capabilities: ['multilingual', 'general', 'code'],
|
|
139
|
+
},
|
|
140
|
+
'gemma-2b': {
|
|
141
|
+
id: 'Xenova/gemma-2b-it',
|
|
142
|
+
size: '~1.1GB',
|
|
143
|
+
description: 'Google Gemma 2B instruction-tuned',
|
|
144
|
+
tier: 4,
|
|
145
|
+
capabilities: ['instruction', 'general', 'code', 'reasoning'],
|
|
146
|
+
},
|
|
147
|
+
// Code-specialized models
|
|
148
|
+
'codegen-350m': {
|
|
149
|
+
id: 'Xenova/codegen-350M-mono',
|
|
150
|
+
size: '~320MB',
|
|
151
|
+
description: 'Salesforce CodeGen - Python specialist',
|
|
152
|
+
tier: 2,
|
|
153
|
+
capabilities: ['code', 'python'],
|
|
154
|
+
},
|
|
155
|
+
'starcoder-tiny': {
|
|
156
|
+
id: 'Xenova/tiny_starcoder_py',
|
|
157
|
+
size: '~40MB',
|
|
158
|
+
description: 'Ultra-small Python code model',
|
|
159
|
+
tier: 1,
|
|
160
|
+
capabilities: ['code', 'python'],
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Recommended models by use case
|
|
166
|
+
*/
|
|
167
|
+
export const MODEL_RECOMMENDATIONS = {
|
|
168
|
+
'edge-minimal': {
|
|
169
|
+
embedding: 'minilm-l6',
|
|
170
|
+
generation: 'distilgpt2',
|
|
171
|
+
description: 'Minimal footprint for constrained devices',
|
|
172
|
+
},
|
|
173
|
+
'edge-balanced': {
|
|
174
|
+
embedding: 'e5-small',
|
|
175
|
+
generation: 'phi-1.5',
|
|
176
|
+
description: 'Best quality/size ratio for edge',
|
|
177
|
+
},
|
|
178
|
+
'edge-code': {
|
|
179
|
+
embedding: 'bge-small',
|
|
180
|
+
generation: 'starcoder-tiny',
|
|
181
|
+
description: 'Optimized for code tasks',
|
|
182
|
+
},
|
|
183
|
+
'edge-full': {
|
|
184
|
+
embedding: 'gte-base',
|
|
185
|
+
generation: 'phi-2',
|
|
186
|
+
description: 'Maximum quality on edge',
|
|
187
|
+
},
|
|
188
|
+
'cloud-optimal': {
|
|
189
|
+
embedding: 'bge-base',
|
|
190
|
+
generation: 'gemma-2b',
|
|
191
|
+
description: 'Best quality for cloud deployment',
|
|
71
192
|
},
|
|
72
193
|
};
|
|
73
194
|
|
|
@@ -475,6 +596,339 @@ export class OnnxWorkerPool extends EventEmitter {
|
|
|
475
596
|
}
|
|
476
597
|
}
|
|
477
598
|
|
|
599
|
+
// ============================================
|
|
600
|
+
// ONLINE LEARNING FROM CORRECTIONS
|
|
601
|
+
// ============================================
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* OnlineLearner - Learns from user corrections in real-time
|
|
605
|
+
*
|
|
606
|
+
* Uses RAG + few-shot learning to improve model outputs
|
|
607
|
+
* without actual weight updates (inference-time adaptation)
|
|
608
|
+
*/
|
|
609
|
+
export class OnlineLearner {
|
|
610
|
+
constructor(options = {}) {
|
|
611
|
+
this.corrections = [];
|
|
612
|
+
this.maxCorrections = options.maxCorrections || 100;
|
|
613
|
+
this.patterns = new Map(); // Pattern -> correction mapping
|
|
614
|
+
this.stats = {
|
|
615
|
+
totalCorrections: 0,
|
|
616
|
+
successfulApplications: 0,
|
|
617
|
+
avgSimilarityThreshold: 0.65,
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Record a correction for learning
|
|
623
|
+
* @param {string} input - Original input
|
|
624
|
+
* @param {string} wrongOutput - Incorrect model output
|
|
625
|
+
* @param {string} correctOutput - User-provided correction
|
|
626
|
+
* @param {object} metadata - Optional metadata (task type, domain, etc.)
|
|
627
|
+
*/
|
|
628
|
+
async recordCorrection(input, wrongOutput, correctOutput, metadata = {}) {
|
|
629
|
+
// Generate embedding for the input pattern
|
|
630
|
+
const result = await embed(input);
|
|
631
|
+
const embedding = result.embeddings?.[0]?.embedding || null;
|
|
632
|
+
|
|
633
|
+
const correction = {
|
|
634
|
+
input,
|
|
635
|
+
wrongOutput,
|
|
636
|
+
correctOutput,
|
|
637
|
+
embedding,
|
|
638
|
+
metadata,
|
|
639
|
+
timestamp: Date.now(),
|
|
640
|
+
useCount: 0,
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
// Store in corrections list
|
|
644
|
+
this.corrections.push(correction);
|
|
645
|
+
this.stats.totalCorrections++;
|
|
646
|
+
|
|
647
|
+
// Evict oldest if over capacity
|
|
648
|
+
if (this.corrections.length > this.maxCorrections) {
|
|
649
|
+
// Remove least used correction
|
|
650
|
+
this.corrections.sort((a, b) => b.useCount - a.useCount);
|
|
651
|
+
this.corrections = this.corrections.slice(0, this.maxCorrections);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Extract and store pattern
|
|
655
|
+
const pattern = this.extractPattern(input, wrongOutput, correctOutput);
|
|
656
|
+
if (pattern) {
|
|
657
|
+
this.patterns.set(pattern.key, pattern);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
return correction;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Extract reusable pattern from correction
|
|
665
|
+
*/
|
|
666
|
+
extractPattern(input, wrongOutput, correctOutput) {
|
|
667
|
+
// Simple pattern extraction - can be enhanced
|
|
668
|
+
const inputTokens = input.toLowerCase().split(/\s+/);
|
|
669
|
+
const wrongTokens = wrongOutput.toLowerCase().split(/\s+/);
|
|
670
|
+
const correctTokens = correctOutput.toLowerCase().split(/\s+/);
|
|
671
|
+
|
|
672
|
+
// Find common elements that indicate the pattern
|
|
673
|
+
if (inputTokens.length > 0 && wrongTokens.length > 0) {
|
|
674
|
+
const key = inputTokens.slice(0, 3).join('_');
|
|
675
|
+
return {
|
|
676
|
+
key,
|
|
677
|
+
inputPattern: inputTokens.slice(0, 5).join(' '),
|
|
678
|
+
wrongPattern: wrongTokens.slice(0, 5).join(' '),
|
|
679
|
+
correctPattern: correctTokens.slice(0, 5).join(' '),
|
|
680
|
+
fullCorrection: correctOutput,
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
return null;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Find relevant corrections for a new input (RAG-style)
|
|
688
|
+
* @param {string} input - New input to find corrections for
|
|
689
|
+
* @param {number} topK - Number of corrections to return
|
|
690
|
+
*/
|
|
691
|
+
async findRelevantCorrections(input, topK = 3) {
|
|
692
|
+
if (this.corrections.length === 0) return [];
|
|
693
|
+
|
|
694
|
+
// Embed the input
|
|
695
|
+
const result = await embed(input);
|
|
696
|
+
const queryEmb = result.embeddings?.[0]?.embedding;
|
|
697
|
+
if (!queryEmb) return [];
|
|
698
|
+
|
|
699
|
+
// Score all corrections by similarity
|
|
700
|
+
const scored = this.corrections
|
|
701
|
+
.filter(c => c.embedding)
|
|
702
|
+
.map(c => {
|
|
703
|
+
const sim = this.cosineSimilarity(queryEmb, c.embedding);
|
|
704
|
+
return { correction: c, similarity: sim };
|
|
705
|
+
})
|
|
706
|
+
.filter(s => s.similarity > this.stats.avgSimilarityThreshold)
|
|
707
|
+
.sort((a, b) => b.similarity - a.similarity)
|
|
708
|
+
.slice(0, topK);
|
|
709
|
+
|
|
710
|
+
// Update use counts
|
|
711
|
+
for (const s of scored) {
|
|
712
|
+
s.correction.useCount++;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
return scored;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* Generate few-shot examples from corrections
|
|
720
|
+
* @param {string} input - Current input
|
|
721
|
+
*/
|
|
722
|
+
async generateFewShotExamples(input) {
|
|
723
|
+
const relevant = await this.findRelevantCorrections(input, 3);
|
|
724
|
+
if (relevant.length === 0) return '';
|
|
725
|
+
|
|
726
|
+
let examples = '\n\n# Previous corrections (apply similar fixes):\n';
|
|
727
|
+
for (const { correction, similarity } of relevant) {
|
|
728
|
+
examples += `\nInput: ${correction.input.slice(0, 100)}`;
|
|
729
|
+
examples += `\nWrong: ${correction.wrongOutput.slice(0, 100)}`;
|
|
730
|
+
examples += `\nCorrect: ${correction.correctOutput.slice(0, 100)}`;
|
|
731
|
+
examples += `\nSimilarity: ${(similarity * 100).toFixed(1)}%\n`;
|
|
732
|
+
}
|
|
733
|
+
return examples;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Apply learned corrections to generation
|
|
738
|
+
* @param {string} prompt - Original prompt
|
|
739
|
+
* @param {object} options - Generation options
|
|
740
|
+
*/
|
|
741
|
+
async generateWithLearning(prompt, options = {}) {
|
|
742
|
+
// Find relevant corrections
|
|
743
|
+
const fewShot = await this.generateFewShotExamples(prompt);
|
|
744
|
+
|
|
745
|
+
// Inject few-shot examples into prompt
|
|
746
|
+
const enhancedPrompt = fewShot ? `${fewShot}\n\nNow handle this:\n${prompt}` : prompt;
|
|
747
|
+
|
|
748
|
+
// Generate with enhanced prompt
|
|
749
|
+
const result = await generate(enhancedPrompt, {
|
|
750
|
+
...options,
|
|
751
|
+
maxTokens: options.maxTokens || 128,
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
if (fewShot) {
|
|
755
|
+
this.stats.successfulApplications++;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
return result;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
cosineSimilarity(a, b) {
|
|
762
|
+
let dot = 0, normA = 0, normB = 0;
|
|
763
|
+
for (let i = 0; i < a.length && i < b.length; i++) {
|
|
764
|
+
dot += a[i] * b[i];
|
|
765
|
+
normA += a[i] * a[i];
|
|
766
|
+
normB += b[i] * b[i];
|
|
767
|
+
}
|
|
768
|
+
return dot / (Math.sqrt(normA) * Math.sqrt(normB) + 1e-8);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
getStats() {
|
|
772
|
+
return {
|
|
773
|
+
...this.stats,
|
|
774
|
+
storedCorrections: this.corrections.length,
|
|
775
|
+
extractedPatterns: this.patterns.size,
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
export() {
|
|
780
|
+
return {
|
|
781
|
+
corrections: this.corrections,
|
|
782
|
+
patterns: Array.from(this.patterns.entries()),
|
|
783
|
+
stats: this.stats,
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
import(data) {
|
|
788
|
+
if (data.corrections) this.corrections = data.corrections;
|
|
789
|
+
if (data.patterns) this.patterns = new Map(data.patterns);
|
|
790
|
+
if (data.stats) this.stats = { ...this.stats, ...data.stats };
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// ============================================
|
|
795
|
+
// ADAPTER INJECTION LAYER
|
|
796
|
+
// ============================================
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* AdapterInjector - Applies lightweight adapters to ONNX model outputs
|
|
800
|
+
*
|
|
801
|
+
* Since we can't modify ONNX weights at runtime, this applies post-hoc
|
|
802
|
+
* transformations to model outputs using learned patterns
|
|
803
|
+
*/
|
|
804
|
+
export class AdapterInjector {
|
|
805
|
+
constructor(options = {}) {
|
|
806
|
+
this.rank = options.rank || 8;
|
|
807
|
+
this.dimension = options.dimension || 384;
|
|
808
|
+
this.scale = options.scale || 0.1;
|
|
809
|
+
|
|
810
|
+
// LoRA-style adapters (applied to embeddings)
|
|
811
|
+
this.adapterA = this.initMatrix(this.dimension, this.rank);
|
|
812
|
+
this.adapterB = this.initMatrix(this.rank, this.dimension, 0.01);
|
|
813
|
+
|
|
814
|
+
// Domain-specific bias terms
|
|
815
|
+
this.domainBiases = new Map();
|
|
816
|
+
|
|
817
|
+
this.stats = {
|
|
818
|
+
adaptations: 0,
|
|
819
|
+
domains: 0,
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
initMatrix(rows, cols, scale = 1) {
|
|
824
|
+
const matrix = [];
|
|
825
|
+
const std = Math.sqrt(2 / (rows + cols)) * scale;
|
|
826
|
+
for (let i = 0; i < rows; i++) {
|
|
827
|
+
const row = [];
|
|
828
|
+
for (let j = 0; j < cols; j++) {
|
|
829
|
+
row.push((Math.random() - 0.5) * 2 * std);
|
|
830
|
+
}
|
|
831
|
+
matrix.push(row);
|
|
832
|
+
}
|
|
833
|
+
return matrix;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* Apply adapter transformation to embedding
|
|
838
|
+
* output = input + scale * (input @ A @ B)
|
|
839
|
+
*/
|
|
840
|
+
adapt(embedding, domain = null) {
|
|
841
|
+
const adapted = [...embedding];
|
|
842
|
+
|
|
843
|
+
// Apply LoRA-style transformation
|
|
844
|
+
// Step 1: input @ A (dim -> rank)
|
|
845
|
+
const hidden = new Array(this.rank).fill(0);
|
|
846
|
+
for (let r = 0; r < this.rank; r++) {
|
|
847
|
+
for (let d = 0; d < Math.min(embedding.length, this.dimension); d++) {
|
|
848
|
+
hidden[r] += embedding[d] * this.adapterA[d][r];
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// Step 2: hidden @ B (rank -> dim)
|
|
853
|
+
for (let d = 0; d < Math.min(adapted.length, this.dimension); d++) {
|
|
854
|
+
let delta = 0;
|
|
855
|
+
for (let r = 0; r < this.rank; r++) {
|
|
856
|
+
delta += hidden[r] * this.adapterB[r][d];
|
|
857
|
+
}
|
|
858
|
+
adapted[d] += this.scale * delta;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// Apply domain-specific bias if available
|
|
862
|
+
if (domain && this.domainBiases.has(domain)) {
|
|
863
|
+
const bias = this.domainBiases.get(domain);
|
|
864
|
+
for (let i = 0; i < adapted.length && i < bias.length; i++) {
|
|
865
|
+
adapted[i] += bias[i];
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
this.stats.adaptations++;
|
|
870
|
+
return adapted;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
/**
|
|
874
|
+
* Learn from positive/negative example pairs
|
|
875
|
+
*/
|
|
876
|
+
learn(anchor, positive, negatives = [], learningRate = 0.01) {
|
|
877
|
+
// Simple gradient descent on adapter weights
|
|
878
|
+
// Pull anchor closer to positive, push away from negatives
|
|
879
|
+
|
|
880
|
+
const anchorAdapted = this.adapt(anchor);
|
|
881
|
+
|
|
882
|
+
// Gradient from positive pair (pull closer)
|
|
883
|
+
if (positive) {
|
|
884
|
+
for (let d = 0; d < this.dimension && d < anchor.length; d++) {
|
|
885
|
+
for (let r = 0; r < this.rank; r++) {
|
|
886
|
+
const grad = anchor[d] * (positive[r % positive.length] - anchorAdapted[r % anchorAdapted.length]);
|
|
887
|
+
this.adapterA[d][r] += learningRate * grad * this.scale;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
return this.stats.adaptations;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/**
|
|
896
|
+
* Register a domain-specific bias
|
|
897
|
+
*/
|
|
898
|
+
registerDomain(domain, examples) {
|
|
899
|
+
if (!examples || examples.length === 0) return;
|
|
900
|
+
|
|
901
|
+
// Compute mean of examples as domain bias
|
|
902
|
+
const bias = new Array(this.dimension).fill(0);
|
|
903
|
+
for (const emb of examples) {
|
|
904
|
+
for (let i = 0; i < this.dimension && i < emb.length; i++) {
|
|
905
|
+
bias[i] += emb[i] / examples.length;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
this.domainBiases.set(domain, bias);
|
|
910
|
+
this.stats.domains = this.domainBiases.size;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
export() {
|
|
914
|
+
return {
|
|
915
|
+
adapterA: this.adapterA,
|
|
916
|
+
adapterB: this.adapterB,
|
|
917
|
+
domainBiases: Array.from(this.domainBiases.entries()),
|
|
918
|
+
stats: this.stats,
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
import(data) {
|
|
923
|
+
if (data.adapterA) this.adapterA = data.adapterA;
|
|
924
|
+
if (data.adapterB) this.adapterB = data.adapterB;
|
|
925
|
+
if (data.domainBiases) {
|
|
926
|
+
this.domainBiases = new Map(data.domainBiases);
|
|
927
|
+
}
|
|
928
|
+
if (data.stats) this.stats = data.stats;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
478
932
|
// ============================================
|
|
479
933
|
// EXPORTS
|
|
480
934
|
// ============================================
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ruvector/edge-net",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Distributed compute intelligence network with WASM cryptographic security - contribute browser compute, spawn distributed AI agents, earn credits. Features Ed25519 signing, PiKey identity, Time Crystal coordination, Neural DAG attention, P2P swarm intelligence, ONNX inference, WebRTC signaling, CRDT ledger, and multi-agent workflows.",
|
|
6
6
|
"main": "ruvector_edge_net.js",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"edge-net-join": "./join.js",
|
|
13
13
|
"edge-net-genesis": "./genesis.js",
|
|
14
14
|
"edge-net-firebase-setup": "./firebase-setup.js",
|
|
15
|
-
"edge-net-plugins": "./plugins/cli.js"
|
|
15
|
+
"edge-net-plugins": "./plugins/cli.js",
|
|
16
|
+
"edge-net-models": "./models/models-cli.js"
|
|
16
17
|
},
|
|
17
18
|
"keywords": [
|
|
18
19
|
"wasm",
|
|
@@ -80,6 +81,7 @@
|
|
|
80
81
|
"node/",
|
|
81
82
|
"deploy/",
|
|
82
83
|
"tests/",
|
|
84
|
+
"models/",
|
|
83
85
|
"index.js",
|
|
84
86
|
"cli.js",
|
|
85
87
|
"join.js",
|
|
@@ -107,6 +109,8 @@
|
|
|
107
109
|
"credits.js",
|
|
108
110
|
"task-execution-handler.js",
|
|
109
111
|
"plugins/",
|
|
112
|
+
"network-genesis.js",
|
|
113
|
+
"core-invariants.js",
|
|
110
114
|
"README.md",
|
|
111
115
|
"LICENSE"
|
|
112
116
|
],
|
|
@@ -189,6 +193,24 @@
|
|
|
189
193
|
},
|
|
190
194
|
"./plugins/catalog": {
|
|
191
195
|
"import": "./plugins/plugin-manifest.js"
|
|
196
|
+
},
|
|
197
|
+
"./genesis": {
|
|
198
|
+
"import": "./network-genesis.js"
|
|
199
|
+
},
|
|
200
|
+
"./models": {
|
|
201
|
+
"import": "./models/model-utils.js"
|
|
202
|
+
},
|
|
203
|
+
"./models/cli": {
|
|
204
|
+
"import": "./models/models-cli.js"
|
|
205
|
+
},
|
|
206
|
+
"./models/registry": {
|
|
207
|
+
"import": "./models/registry.json"
|
|
208
|
+
},
|
|
209
|
+
"./models/optimizer": {
|
|
210
|
+
"import": "./models/model-optimizer.js"
|
|
211
|
+
},
|
|
212
|
+
"./models/benchmark": {
|
|
213
|
+
"import": "./models/benchmark.js"
|
|
192
214
|
}
|
|
193
215
|
},
|
|
194
216
|
"sideEffects": [
|
|
@@ -218,11 +240,19 @@
|
|
|
218
240
|
"p2p": "node -e \"import('./p2p.js').then(m => m.createP2PNetwork({ nodeId: 'test' }))\"",
|
|
219
241
|
"monitor": "node -e \"import('./monitor.js').then(m => { const mon = new m.Monitor(); mon.start(); setInterval(() => console.log(JSON.stringify(mon.generateReport(), null, 2)), 5000); })\"",
|
|
220
242
|
"firebase:setup": "node firebase-setup.js",
|
|
221
|
-
"firebase:check": "node firebase-setup.js --check"
|
|
243
|
+
"firebase:check": "node firebase-setup.js --check",
|
|
244
|
+
"models:list": "node models/models-cli.js list",
|
|
245
|
+
"models:download": "node models/models-cli.js download",
|
|
246
|
+
"models:optimize": "node models/models-cli.js optimize",
|
|
247
|
+
"models:benchmark": "node models/models-cli.js benchmark",
|
|
248
|
+
"models:upload": "node models/models-cli.js upload",
|
|
249
|
+
"models:train": "node models/models-cli.js train",
|
|
250
|
+
"models:cache": "node models/models-cli.js cache"
|
|
222
251
|
},
|
|
223
252
|
"dependencies": {
|
|
224
253
|
"@ruvector/ruvllm": "^0.2.3",
|
|
225
254
|
"@xenova/transformers": "^2.17.2",
|
|
255
|
+
"commander": "^12.1.0",
|
|
226
256
|
"firebase": "^10.14.1",
|
|
227
257
|
"wrtc": "^0.4.7",
|
|
228
258
|
"ws": "^8.18.3"
|