@sparkleideas/ruvector-upstream 3.0.0-alpha.11
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 +71 -0
- package/package.json +125 -0
- package/src/bridges/attention.ts +185 -0
- package/src/bridges/cognitive.ts +343 -0
- package/src/bridges/exotic.ts +277 -0
- package/src/bridges/gnn.ts +177 -0
- package/src/bridges/hnsw.ts +199 -0
- package/src/bridges/hyperbolic.ts +268 -0
- package/src/bridges/learning.ts +238 -0
- package/src/bridges/sona.ts +418 -0
- package/src/index.ts +22 -0
- package/src/registry.ts +182 -0
- package/src/types.ts +146 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reinforcement Learning Bridge
|
|
3
|
+
*
|
|
4
|
+
* Bridge to ruvector-learning-wasm for RL algorithms including
|
|
5
|
+
* Q-Learning, SARSA, Actor-Critic, PPO, DQN, and Decision Transformer.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { WasmBridge, WasmModuleStatus, LearningConfig } from '../types.js';
|
|
9
|
+
import { LearningConfigSchema } from '../types.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Learning experience tuple
|
|
13
|
+
*/
|
|
14
|
+
export interface Experience {
|
|
15
|
+
state: Float32Array;
|
|
16
|
+
action: number;
|
|
17
|
+
reward: number;
|
|
18
|
+
nextState: Float32Array;
|
|
19
|
+
done: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Learning trajectory
|
|
24
|
+
*/
|
|
25
|
+
export interface Trajectory {
|
|
26
|
+
experiences: Experience[];
|
|
27
|
+
totalReward: number;
|
|
28
|
+
metadata?: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Learning WASM module interface
|
|
33
|
+
*/
|
|
34
|
+
interface LearningModule {
|
|
35
|
+
// Core learning
|
|
36
|
+
train(trajectories: Trajectory[], config: LearningConfig): number;
|
|
37
|
+
predict(state: Float32Array): { action: number; qValues: Float32Array };
|
|
38
|
+
evaluate(state: Float32Array): number;
|
|
39
|
+
|
|
40
|
+
// Policy methods
|
|
41
|
+
getPolicy(): Float32Array;
|
|
42
|
+
setPolicy(weights: Float32Array): void;
|
|
43
|
+
|
|
44
|
+
// Experience replay
|
|
45
|
+
addExperience(experience: Experience): void;
|
|
46
|
+
sampleBatch(batchSize: number): Experience[];
|
|
47
|
+
|
|
48
|
+
// Decision transformer specific
|
|
49
|
+
sequencePredict(states: Float32Array[], actions: number[], rewards: number[], targetReturn: number): number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Reinforcement Learning Bridge implementation
|
|
54
|
+
*/
|
|
55
|
+
export class LearningBridge implements WasmBridge<LearningModule> {
|
|
56
|
+
readonly name = 'ruvector-learning-wasm';
|
|
57
|
+
readonly version = '0.1.0';
|
|
58
|
+
|
|
59
|
+
private _status: WasmModuleStatus = 'unloaded';
|
|
60
|
+
private _module: LearningModule | null = null;
|
|
61
|
+
private config: LearningConfig;
|
|
62
|
+
|
|
63
|
+
constructor(config?: Partial<LearningConfig>) {
|
|
64
|
+
this.config = LearningConfigSchema.parse(config ?? {});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get status(): WasmModuleStatus {
|
|
68
|
+
return this._status;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async init(): Promise<void> {
|
|
72
|
+
if (this._status === 'ready') return;
|
|
73
|
+
if (this._status === 'loading') return;
|
|
74
|
+
|
|
75
|
+
this._status = 'loading';
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const wasmModule = await import('@ruvector/learning-wasm').catch(() => null);
|
|
79
|
+
|
|
80
|
+
if (wasmModule) {
|
|
81
|
+
this._module = wasmModule as unknown as LearningModule;
|
|
82
|
+
} else {
|
|
83
|
+
this._module = this.createMockModule();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this._status = 'ready';
|
|
87
|
+
} catch (error) {
|
|
88
|
+
this._status = 'error';
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async destroy(): Promise<void> {
|
|
94
|
+
this._module = null;
|
|
95
|
+
this._status = 'unloaded';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
isReady(): boolean {
|
|
99
|
+
return this._status === 'ready';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
getModule(): LearningModule | null {
|
|
103
|
+
return this._module;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Train on trajectories
|
|
108
|
+
*/
|
|
109
|
+
train(trajectories: Trajectory[], config?: Partial<LearningConfig>): number {
|
|
110
|
+
if (!this._module) throw new Error('Learning module not initialized');
|
|
111
|
+
const mergedConfig = { ...this.config, ...config };
|
|
112
|
+
return this._module.train(trajectories, mergedConfig);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Predict action for state
|
|
117
|
+
*/
|
|
118
|
+
predict(state: Float32Array): { action: number; qValues: Float32Array } {
|
|
119
|
+
if (!this._module) throw new Error('Learning module not initialized');
|
|
120
|
+
return this._module.predict(state);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Evaluate state value
|
|
125
|
+
*/
|
|
126
|
+
evaluate(state: Float32Array): number {
|
|
127
|
+
if (!this._module) throw new Error('Learning module not initialized');
|
|
128
|
+
return this._module.evaluate(state);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Add experience to replay buffer
|
|
133
|
+
*/
|
|
134
|
+
addExperience(experience: Experience): void {
|
|
135
|
+
if (!this._module) throw new Error('Learning module not initialized');
|
|
136
|
+
this._module.addExperience(experience);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Decision Transformer sequence prediction
|
|
141
|
+
*/
|
|
142
|
+
sequencePredict(
|
|
143
|
+
states: Float32Array[],
|
|
144
|
+
actions: number[],
|
|
145
|
+
rewards: number[],
|
|
146
|
+
targetReturn: number
|
|
147
|
+
): number {
|
|
148
|
+
if (!this._module) throw new Error('Learning module not initialized');
|
|
149
|
+
return this._module.sequencePredict(states, actions, rewards, targetReturn);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Create mock module for development
|
|
154
|
+
*/
|
|
155
|
+
private createMockModule(): LearningModule {
|
|
156
|
+
const replayBuffer: Experience[] = [];
|
|
157
|
+
let policyWeights = new Float32Array(100);
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
train(trajectories: Trajectory[], config: LearningConfig): number {
|
|
161
|
+
let totalLoss = 0;
|
|
162
|
+
|
|
163
|
+
for (const trajectory of trajectories) {
|
|
164
|
+
for (const exp of trajectory.experiences) {
|
|
165
|
+
// Simple TD update approximation
|
|
166
|
+
const tdError = exp.reward + config.gamma * 0.5 - 0.3;
|
|
167
|
+
totalLoss += Math.abs(tdError);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return totalLoss / Math.max(1, trajectories.length);
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
predict(state: Float32Array): { action: number; qValues: Float32Array } {
|
|
175
|
+
const numActions = 4;
|
|
176
|
+
const qValues = new Float32Array(numActions);
|
|
177
|
+
|
|
178
|
+
for (let i = 0; i < numActions; i++) {
|
|
179
|
+
qValues[i] = state.reduce((s, v, j) => s + v * policyWeights[(i * 10 + j) % 100], 0);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let maxIdx = 0;
|
|
183
|
+
for (let i = 1; i < numActions; i++) {
|
|
184
|
+
if (qValues[i] > qValues[maxIdx]) maxIdx = i;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return { action: maxIdx, qValues };
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
evaluate(state: Float32Array): number {
|
|
191
|
+
return state.reduce((s, v) => s + v, 0) / state.length;
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
getPolicy(): Float32Array {
|
|
195
|
+
return new Float32Array(policyWeights);
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
setPolicy(weights: Float32Array): void {
|
|
199
|
+
policyWeights = new Float32Array(weights);
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
addExperience(experience: Experience): void {
|
|
203
|
+
replayBuffer.push(experience);
|
|
204
|
+
if (replayBuffer.length > 10000) {
|
|
205
|
+
replayBuffer.shift();
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
sampleBatch(batchSize: number): Experience[] {
|
|
210
|
+
const batch: Experience[] = [];
|
|
211
|
+
for (let i = 0; i < Math.min(batchSize, replayBuffer.length); i++) {
|
|
212
|
+
const idx = Math.floor(Math.random() * replayBuffer.length);
|
|
213
|
+
batch.push(replayBuffer[idx]);
|
|
214
|
+
}
|
|
215
|
+
return batch;
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
sequencePredict(
|
|
219
|
+
states: Float32Array[],
|
|
220
|
+
actions: number[],
|
|
221
|
+
rewards: number[],
|
|
222
|
+
targetReturn: number
|
|
223
|
+
): number {
|
|
224
|
+
// Decision Transformer: predict next action based on sequence and target return
|
|
225
|
+
const avgReward = rewards.reduce((s, r) => s + r, 0) / rewards.length;
|
|
226
|
+
const returnDiff = targetReturn - avgReward;
|
|
227
|
+
return returnDiff > 0 ? 1 : 0; // Simplified
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Create a new learning bridge
|
|
235
|
+
*/
|
|
236
|
+
export function createLearningBridge(config?: Partial<LearningConfig>): LearningBridge {
|
|
237
|
+
return new LearningBridge(config);
|
|
238
|
+
}
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SONA Bridge
|
|
3
|
+
*
|
|
4
|
+
* Bridge to SONA (Self-Optimizing Neural Architecture) for continuous
|
|
5
|
+
* learning with LoRA fine-tuning and EWC++ memory preservation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { WasmBridge, WasmModuleStatus, SonaConfig } from '../types.js';
|
|
9
|
+
import { SonaConfigSchema } from '../types.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* SONA trajectory for learning
|
|
13
|
+
*/
|
|
14
|
+
export interface SonaTrajectory {
|
|
15
|
+
id: string;
|
|
16
|
+
domain: string;
|
|
17
|
+
steps: SonaStep[];
|
|
18
|
+
qualityScore: number;
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* SONA learning step
|
|
24
|
+
*/
|
|
25
|
+
export interface SonaStep {
|
|
26
|
+
stateBefore: Float32Array;
|
|
27
|
+
action: string;
|
|
28
|
+
stateAfter: Float32Array;
|
|
29
|
+
reward: number;
|
|
30
|
+
timestamp: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* SONA pattern
|
|
35
|
+
*/
|
|
36
|
+
export interface SonaPattern {
|
|
37
|
+
id: string;
|
|
38
|
+
embedding: Float32Array;
|
|
39
|
+
successRate: number;
|
|
40
|
+
usageCount: number;
|
|
41
|
+
domain: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* LoRA weights
|
|
46
|
+
*/
|
|
47
|
+
export interface LoRAWeights {
|
|
48
|
+
A: Map<string, Float32Array>;
|
|
49
|
+
B: Map<string, Float32Array>;
|
|
50
|
+
rank: number;
|
|
51
|
+
alpha: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* EWC state
|
|
56
|
+
*/
|
|
57
|
+
export interface EWCState {
|
|
58
|
+
fisher: Map<string, Float32Array>;
|
|
59
|
+
means: Map<string, Float32Array>;
|
|
60
|
+
lambda: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* SONA WASM module interface
|
|
65
|
+
*/
|
|
66
|
+
interface SonaModule {
|
|
67
|
+
// Core learning
|
|
68
|
+
learn(trajectories: SonaTrajectory[], config: SonaConfig): number;
|
|
69
|
+
predict(state: Float32Array): { action: string; confidence: number };
|
|
70
|
+
|
|
71
|
+
// Pattern management
|
|
72
|
+
storePattern(pattern: SonaPattern): void;
|
|
73
|
+
findPatterns(query: Float32Array, k: number): SonaPattern[];
|
|
74
|
+
updatePatternSuccess(patternId: string, success: boolean): void;
|
|
75
|
+
|
|
76
|
+
// LoRA operations
|
|
77
|
+
applyLoRA(input: Float32Array, weights: LoRAWeights): Float32Array;
|
|
78
|
+
updateLoRA(gradients: Float32Array, config: SonaConfig): LoRAWeights;
|
|
79
|
+
|
|
80
|
+
// EWC operations
|
|
81
|
+
computeFisher(trajectories: SonaTrajectory[]): Map<string, Float32Array>;
|
|
82
|
+
consolidate(ewcState: EWCState): void;
|
|
83
|
+
|
|
84
|
+
// Mode-specific optimizations
|
|
85
|
+
setMode(mode: SonaConfig['mode']): void;
|
|
86
|
+
getMode(): SonaConfig['mode'];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* SONA Bridge implementation
|
|
91
|
+
*/
|
|
92
|
+
export class SonaBridge implements WasmBridge<SonaModule> {
|
|
93
|
+
readonly name = 'sona';
|
|
94
|
+
readonly version = '0.1.0';
|
|
95
|
+
|
|
96
|
+
private _status: WasmModuleStatus = 'unloaded';
|
|
97
|
+
private _module: SonaModule | null = null;
|
|
98
|
+
private config: SonaConfig;
|
|
99
|
+
|
|
100
|
+
constructor(config?: Partial<SonaConfig>) {
|
|
101
|
+
this.config = SonaConfigSchema.parse(config ?? {});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get status(): WasmModuleStatus {
|
|
105
|
+
return this._status;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async init(): Promise<void> {
|
|
109
|
+
if (this._status === 'ready') return;
|
|
110
|
+
if (this._status === 'loading') return;
|
|
111
|
+
|
|
112
|
+
this._status = 'loading';
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const wasmModule = await import('@ruvector/sona').catch(() => null);
|
|
116
|
+
|
|
117
|
+
if (wasmModule) {
|
|
118
|
+
this._module = wasmModule as unknown as SonaModule;
|
|
119
|
+
} else {
|
|
120
|
+
this._module = this.createMockModule();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this._module.setMode(this.config.mode);
|
|
124
|
+
this._status = 'ready';
|
|
125
|
+
} catch (error) {
|
|
126
|
+
this._status = 'error';
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async destroy(): Promise<void> {
|
|
132
|
+
this._module = null;
|
|
133
|
+
this._status = 'unloaded';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
isReady(): boolean {
|
|
137
|
+
return this._status === 'ready';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
getModule(): SonaModule | null {
|
|
141
|
+
return this._module;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Learn from trajectories
|
|
146
|
+
*/
|
|
147
|
+
learn(trajectories: SonaTrajectory[], config?: Partial<SonaConfig>): number {
|
|
148
|
+
if (!this._module) throw new Error('SONA module not initialized');
|
|
149
|
+
const mergedConfig = { ...this.config, ...config };
|
|
150
|
+
return this._module.learn(trajectories, mergedConfig);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Predict next action
|
|
155
|
+
*/
|
|
156
|
+
predict(state: Float32Array): { action: string; confidence: number } {
|
|
157
|
+
if (!this._module) throw new Error('SONA module not initialized');
|
|
158
|
+
return this._module.predict(state);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Store a pattern
|
|
163
|
+
*/
|
|
164
|
+
storePattern(pattern: SonaPattern): void {
|
|
165
|
+
if (!this._module) throw new Error('SONA module not initialized');
|
|
166
|
+
this._module.storePattern(pattern);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Find similar patterns
|
|
171
|
+
*/
|
|
172
|
+
findPatterns(query: Float32Array, k: number): SonaPattern[] {
|
|
173
|
+
if (!this._module) throw new Error('SONA module not initialized');
|
|
174
|
+
return this._module.findPatterns(query, k);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Apply LoRA transformation
|
|
179
|
+
*/
|
|
180
|
+
applyLoRA(input: Float32Array, weights: LoRAWeights): Float32Array {
|
|
181
|
+
if (!this._module) throw new Error('SONA module not initialized');
|
|
182
|
+
return this._module.applyLoRA(input, weights);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Consolidate memory with EWC
|
|
187
|
+
*/
|
|
188
|
+
consolidate(ewcState: EWCState): void {
|
|
189
|
+
if (!this._module) throw new Error('SONA module not initialized');
|
|
190
|
+
this._module.consolidate(ewcState);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Set operating mode
|
|
195
|
+
*/
|
|
196
|
+
setMode(mode: SonaConfig['mode']): void {
|
|
197
|
+
if (!this._module) throw new Error('SONA module not initialized');
|
|
198
|
+
this._module.setMode(mode);
|
|
199
|
+
this.config.mode = mode;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Get current mode
|
|
204
|
+
*/
|
|
205
|
+
getMode(): SonaConfig['mode'] {
|
|
206
|
+
return this._module?.getMode() ?? this.config.mode;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Create mock module for development
|
|
211
|
+
*/
|
|
212
|
+
private createMockModule(): SonaModule {
|
|
213
|
+
const patterns = new Map<string, SonaPattern>();
|
|
214
|
+
let currentMode: SonaConfig['mode'] = 'balanced';
|
|
215
|
+
let loraWeights: LoRAWeights = {
|
|
216
|
+
A: new Map(),
|
|
217
|
+
B: new Map(),
|
|
218
|
+
rank: 4,
|
|
219
|
+
alpha: 0.1,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
learn(trajectories: SonaTrajectory[], config: SonaConfig): number {
|
|
224
|
+
if (trajectories.length === 0) return 0;
|
|
225
|
+
|
|
226
|
+
const goodTrajectories = trajectories.filter(t => t.qualityScore >= 0.5);
|
|
227
|
+
if (goodTrajectories.length === 0) return 0;
|
|
228
|
+
|
|
229
|
+
// Extract patterns from good trajectories
|
|
230
|
+
for (const trajectory of goodTrajectories) {
|
|
231
|
+
if (trajectory.steps.length > 0) {
|
|
232
|
+
const lastStep = trajectory.steps[trajectory.steps.length - 1];
|
|
233
|
+
const patternId = `pattern_${patterns.size}`;
|
|
234
|
+
|
|
235
|
+
patterns.set(patternId, {
|
|
236
|
+
id: patternId,
|
|
237
|
+
embedding: new Float32Array(lastStep.stateAfter),
|
|
238
|
+
successRate: trajectory.qualityScore,
|
|
239
|
+
usageCount: 1,
|
|
240
|
+
domain: trajectory.domain,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const avgQuality = goodTrajectories.reduce((s, t) => s + t.qualityScore, 0) / goodTrajectories.length;
|
|
246
|
+
return Math.max(0, avgQuality - 0.5);
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
predict(state: Float32Array): { action: string; confidence: number } {
|
|
250
|
+
// Find most similar pattern
|
|
251
|
+
let bestPattern: SonaPattern | null = null;
|
|
252
|
+
let bestSim = -1;
|
|
253
|
+
|
|
254
|
+
for (const pattern of patterns.values()) {
|
|
255
|
+
const sim = cosineSimilarity(state, pattern.embedding);
|
|
256
|
+
if (sim > bestSim) {
|
|
257
|
+
bestSim = sim;
|
|
258
|
+
bestPattern = pattern;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (bestPattern && bestSim > 0.5) {
|
|
263
|
+
return {
|
|
264
|
+
action: bestPattern.domain,
|
|
265
|
+
confidence: bestSim * bestPattern.successRate,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return { action: 'explore', confidence: 0.3 };
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
storePattern(pattern: SonaPattern): void {
|
|
273
|
+
patterns.set(pattern.id, pattern);
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
findPatterns(query: Float32Array, k: number): SonaPattern[] {
|
|
277
|
+
const results: Array<{ pattern: SonaPattern; sim: number }> = [];
|
|
278
|
+
|
|
279
|
+
for (const pattern of patterns.values()) {
|
|
280
|
+
const sim = cosineSimilarity(query, pattern.embedding);
|
|
281
|
+
results.push({ pattern, sim });
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
results.sort((a, b) => b.sim - a.sim);
|
|
285
|
+
return results.slice(0, k).map(r => r.pattern);
|
|
286
|
+
},
|
|
287
|
+
|
|
288
|
+
updatePatternSuccess(patternId: string, success: boolean): void {
|
|
289
|
+
const pattern = patterns.get(patternId);
|
|
290
|
+
if (pattern) {
|
|
291
|
+
pattern.usageCount++;
|
|
292
|
+
const alpha = 1 / pattern.usageCount;
|
|
293
|
+
pattern.successRate = pattern.successRate * (1 - alpha) + (success ? 1 : 0) * alpha;
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
applyLoRA(input: Float32Array, weights: LoRAWeights): Float32Array {
|
|
298
|
+
const output = new Float32Array(input.length);
|
|
299
|
+
output.set(input);
|
|
300
|
+
|
|
301
|
+
// Apply LoRA: output = input + alpha * B @ A @ input
|
|
302
|
+
for (const [module, A] of weights.A) {
|
|
303
|
+
const B = weights.B.get(module);
|
|
304
|
+
if (!B) continue;
|
|
305
|
+
|
|
306
|
+
// Simplified LoRA application
|
|
307
|
+
let intermediate = 0;
|
|
308
|
+
for (let i = 0; i < Math.min(input.length, A.length); i++) {
|
|
309
|
+
intermediate += A[i] * input[i];
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
for (let i = 0; i < Math.min(output.length, B.length); i++) {
|
|
313
|
+
output[i] += weights.alpha * B[i] * intermediate;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return output;
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
updateLoRA(gradients: Float32Array, config: SonaConfig): LoRAWeights {
|
|
321
|
+
// Update LoRA weights based on gradients
|
|
322
|
+
const dim = gradients.length;
|
|
323
|
+
const rank = config.loraRank;
|
|
324
|
+
|
|
325
|
+
const A = new Float32Array(rank * dim);
|
|
326
|
+
const B = new Float32Array(dim * rank);
|
|
327
|
+
|
|
328
|
+
// Initialize with small random values scaled by gradients
|
|
329
|
+
for (let i = 0; i < A.length; i++) {
|
|
330
|
+
A[i] = (Math.random() - 0.5) * 0.01 * (gradients[i % dim] || 1);
|
|
331
|
+
}
|
|
332
|
+
for (let i = 0; i < B.length; i++) {
|
|
333
|
+
B[i] = (Math.random() - 0.5) * 0.01 * (gradients[i % dim] || 1);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
loraWeights.A.set('default', A);
|
|
337
|
+
loraWeights.B.set('default', B);
|
|
338
|
+
loraWeights.rank = rank;
|
|
339
|
+
|
|
340
|
+
return loraWeights;
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
computeFisher(trajectories: SonaTrajectory[]): Map<string, Float32Array> {
|
|
344
|
+
const fisher = new Map<string, Float32Array>();
|
|
345
|
+
|
|
346
|
+
for (const trajectory of trajectories) {
|
|
347
|
+
for (const step of trajectory.steps) {
|
|
348
|
+
const key = trajectory.domain;
|
|
349
|
+
let f = fisher.get(key);
|
|
350
|
+
|
|
351
|
+
if (!f) {
|
|
352
|
+
f = new Float32Array(step.stateAfter.length);
|
|
353
|
+
fisher.set(key, f);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Approximate Fisher information
|
|
357
|
+
for (let i = 0; i < step.stateAfter.length; i++) {
|
|
358
|
+
const grad = step.stateAfter[i] * step.reward;
|
|
359
|
+
f[i] += grad * grad;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Normalize
|
|
365
|
+
for (const f of fisher.values()) {
|
|
366
|
+
const sum = f.reduce((s, v) => s + v, 0);
|
|
367
|
+
if (sum > 0) {
|
|
368
|
+
for (let i = 0; i < f.length; i++) {
|
|
369
|
+
f[i] /= sum;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return fisher;
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
consolidate(ewcState: EWCState): void {
|
|
378
|
+
// Apply EWC penalty to prevent catastrophic forgetting
|
|
379
|
+
// This modifies the learning in future updates
|
|
380
|
+
},
|
|
381
|
+
|
|
382
|
+
setMode(mode: SonaConfig['mode']): void {
|
|
383
|
+
currentMode = mode;
|
|
384
|
+
},
|
|
385
|
+
|
|
386
|
+
getMode(): SonaConfig['mode'] {
|
|
387
|
+
return currentMode;
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Cosine similarity helper
|
|
395
|
+
*/
|
|
396
|
+
function cosineSimilarity(a: Float32Array, b: Float32Array): number {
|
|
397
|
+
if (a.length !== b.length) return 0;
|
|
398
|
+
|
|
399
|
+
let dot = 0;
|
|
400
|
+
let normA = 0;
|
|
401
|
+
let normB = 0;
|
|
402
|
+
|
|
403
|
+
for (let i = 0; i < a.length; i++) {
|
|
404
|
+
dot += a[i] * b[i];
|
|
405
|
+
normA += a[i] * a[i];
|
|
406
|
+
normB += b[i] * b[i];
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
410
|
+
return denom > 0 ? dot / denom : 0;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Create a new SONA bridge
|
|
415
|
+
*/
|
|
416
|
+
export function createSonaBridge(config?: Partial<SonaConfig>): SonaBridge {
|
|
417
|
+
return new SonaBridge(config);
|
|
418
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sparkleideas/ruvector-upstream
|
|
3
|
+
*
|
|
4
|
+
* RuVector WASM package bridges for Claude Flow plugins.
|
|
5
|
+
* Provides unified access to 15+ WASM packages from ruvnet/ruvector.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Bridge exports
|
|
9
|
+
export * from './bridges/hnsw.js';
|
|
10
|
+
export * from './bridges/attention.js';
|
|
11
|
+
export * from './bridges/gnn.js';
|
|
12
|
+
export * from './bridges/hyperbolic.js';
|
|
13
|
+
export * from './bridges/learning.js';
|
|
14
|
+
export * from './bridges/exotic.js';
|
|
15
|
+
export * from './bridges/cognitive.js';
|
|
16
|
+
export * from './bridges/sona.js';
|
|
17
|
+
|
|
18
|
+
// Types
|
|
19
|
+
export * from './types.js';
|
|
20
|
+
|
|
21
|
+
// Registry
|
|
22
|
+
export { WasmRegistry, getWasmRegistry } from './registry.js';
|