@holoscript/framework 6.0.3 → 6.0.4
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/CHANGELOG.md +1 -2
- package/ROADMAP.md +68 -66
- package/dist/{InvisibleWallet-BB6tFvRA.d.cts → InvisibleWallet-EFiuaLn3.d.cts} +1 -1
- package/dist/{OrchestratorAgent-BvWgf9uw.d.cts → OrchestratorAgent-CrLDGNL6.d.cts} +1 -1
- package/dist/agents/index.cjs +11 -10
- package/dist/agents/index.d.cts +4 -16
- package/dist/ai/index.cjs +2 -2
- package/dist/behavior.cjs +10 -0
- package/dist/economy/index.cjs +4 -4
- package/dist/economy/index.d.cts +2 -2
- package/dist/index.cjs +33 -11
- package/dist/index.d.cts +3 -3
- package/dist/swarm/index.cjs +3 -0
- package/package.json +14 -9
- package/src/__tests__/bounty-marketplace.test.ts +53 -21
- package/src/__tests__/delegation.test.ts +1 -4
- package/src/__tests__/done-log-audit.test.ts +38 -46
- package/src/__tests__/framework.test.ts +172 -53
- package/src/__tests__/goal-synthesizer.test.ts +9 -6
- package/src/__tests__/presence.test.ts +1 -1
- package/src/__tests__/protocol-agent.test.ts +12 -11
- package/src/__tests__/revenue-splitter.test.ts +22 -15
- package/src/__tests__/scenario-driven-todo.test.ts +55 -35
- package/src/__tests__/self-improve.test.ts +28 -9
- package/src/__tests__/service-lifecycle.test.ts +9 -3
- package/src/__tests__/skill-router.test.ts +3 -3
- package/src/agents/CulturalMemory.ts +6 -6
- package/src/agents/DelegationTraceHooks.ts +560 -0
- package/src/agents/FederatedRegistryAdapter.ts +1 -1
- package/src/agents/NormEngine.ts +3 -8
- package/src/agents/OrchestratorAgent.ts +1 -1
- package/src/agents/TaskDelegationService.ts +5 -9
- package/src/agents/__tests__/AgentWalletRegistry.test.ts +5 -4
- package/src/agents/__tests__/CrossRealityHandoff.test.ts +9 -3
- package/src/agents/__tests__/DelegationTraceHooks.test.ts +390 -0
- package/src/agents/__tests__/TaskDelegationService.test.ts +4 -2
- package/src/agents/spatial-comms/Layer1RealTime.ts +36 -19
- package/src/agents/spatial-comms/Layer2A2A.ts +1 -3
- package/src/agents/spatial-comms/Layer3MCP.ts +13 -4
- package/src/agents/spatial-comms/ProtocolTypes.ts +5 -2
- package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +2 -2
- package/src/ai/HoloScriptGenerator.ts +2 -2
- package/src/ai/__tests__/PerceptionSystem.prod.test.ts +1 -1
- package/src/ai/__tests__/PerceptionSystem.test.ts +14 -14
- package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +1 -1
- package/src/ai/index.ts +5 -1
- package/src/board/audit.ts +17 -6
- package/src/board/board-ops.ts +45 -15
- package/src/board/board-types.ts +94 -20
- package/src/delegation.ts +5 -3
- package/src/distributed-claimer.ts +13 -2
- package/src/economy/BountyManager.ts +40 -18
- package/src/economy/KnowledgeMarketplace.ts +27 -8
- package/src/economy/PaymentWebhookService.ts +0 -1
- package/src/economy/RevenueSplitter.ts +2 -4
- package/src/economy/UnifiedBudgetOptimizer.ts +8 -9
- package/src/economy/_core-stubs.ts +1 -1
- package/src/economy/x402-facilitator.ts +17 -8
- package/src/index.ts +16 -12
- package/src/knowledge/__tests__/knowledge-consolidator.test.ts +138 -89
- package/src/knowledge/__tests__/knowledge-store-vector.test.ts +59 -16
- package/src/knowledge/brain.ts +7 -7
- package/src/knowledge/consolidation.ts +16 -16
- package/src/knowledge/knowledge-consolidator.ts +60 -30
- package/src/knowledge/knowledge-store.ts +83 -45
- package/src/learning/ProceduralCompiler.ts +6 -1
- package/src/learning/learning/MemoryConsolidator.ts +102 -0
- package/src/learning/learning/MemoryScorer.ts +69 -0
- package/src/learning/learning/ProceduralCompiler.ts +45 -0
- package/src/learning/learning/SemanticClusterer.ts +66 -0
- package/src/llm/llm-adapter.ts +24 -10
- package/src/mesh/index.ts +37 -17
- package/src/protocol/goal-synthesizer.ts +24 -34
- package/src/protocol/implementations.ts +91 -22
- package/src/protocol/micro-phase-decomposer.ts +25 -17
- package/src/protocol/micro-step-decomposer.test.ts +104 -39
- package/src/protocol-agent.test.ts +17 -7
- package/src/protocol-agent.ts +45 -42
- package/src/self-improve/absorb-scanner.ts +9 -6
- package/src/self-improve/evolution-engine.ts +36 -18
- package/src/self-improve/framework-absorber.ts +21 -16
- package/src/self-improve/index.ts +2 -10
- package/src/self-improve/prompt-optimizer.ts +31 -19
- package/src/self-improve/test-generator.ts +16 -12
- package/src/skill-router.ts +7 -6
- package/src/swarm/messaging/GossipProtocol.ts +1 -1
- package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +31 -9
- package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +21 -7
- package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +24 -8
- package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +6 -2
- package/src/team.ts +277 -122
- package/src/training/scripts/generate-spatial-dataset.ts +1 -1
- package/src/training/training/LRScheduler.ts +377 -0
- package/src/training/training/QualityScoringPipeline.ts +139 -0
- package/src/training/training/SoftDedup.ts +461 -0
- package/src/training/training/SparsityMonitor.ts +685 -0
- package/src/training/training/SparsityMonitorTypes.ts +209 -0
- package/src/training/training/SpatialTrainingDataGenerator.ts +1526 -0
- package/src/training/training/SpatialTrainingDataTypes.ts +216 -0
- package/src/training/training/TrainingPipelineConfig.ts +215 -0
- package/src/training/training/__tests__/CorpusValidation.test.ts +87 -0
- package/src/training/training/__tests__/LRScheduler.test.ts +592 -0
- package/src/training/training/__tests__/SoftDedup.test.ts +415 -0
- package/src/training/training/__tests__/SparsityMonitor.test.ts +1623 -0
- package/src/training/training/__tests__/SpatialCorpusValidation.test.ts +72 -0
- package/src/training/training/__tests__/SpatialTrainingDataGenerator.test.ts +1244 -0
- package/src/training/training/__tests__/TrainingMonkeyIntegration.test.ts +897 -0
- package/src/training/training/__tests__/TrainingPipelineConfig.test.ts +202 -0
- package/src/training/training/__tests__/schema.test.ts +72 -0
- package/src/training/training/__tests__/training-constants.test.ts +106 -0
- package/src/training/training/__tests__/trait-mappings.test.ts +81 -0
- package/src/training/training/constants.ts +94 -0
- package/src/training/training/index.ts +17 -0
- package/src/training/training/schema.ts +147 -0
- package/src/training/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
- package/src/training/training/scripts/generate-spatial-dataset.ts +521 -0
- package/src/training/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
- package/src/training/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
- package/src/training/training/trainingmonkey/index.ts +26 -0
- package/src/training/training/trait-mappings.ts +157 -0
- package/src/types.ts +2 -7
- package/ALL-test-results.json +0 -1
- package/LICENSE +0 -21
- package/dist/AgentManifest-CB4xM-Ma.d.ts +0 -704
- package/dist/BehaviorTree-BrBFECv5.d.ts +0 -103
- package/dist/InvisibleWallet-rtRrBOA8.d.ts +0 -1732
- package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +0 -798
- package/dist/agents/index.d.ts +0 -1788
- package/dist/agents/index.js +0 -4695
- package/dist/ai/index.d.ts +0 -1753
- package/dist/ai/index.js +0 -5244
- package/dist/behavior.d.ts +0 -130
- package/dist/behavior.js +0 -407
- package/dist/economy/index.d.ts +0 -747
- package/dist/economy/index.js +0 -3617
- package/dist/implementations-D9T3un9D.d.ts +0 -236
- package/dist/index.d.ts +0 -1729
- package/dist/index.js +0 -24277
- package/dist/learning/index.d.ts +0 -104
- package/dist/learning/index.js +0 -189
- package/dist/negotiation/index.d.ts +0 -610
- package/dist/negotiation/index.js +0 -931
- package/dist/skills/index.d.ts +0 -289
- package/dist/skills/index.js +0 -1079
- package/dist/swarm/index.d.ts +0 -2433
- package/dist/swarm/index.js +0 -5221
- package/dist/training/index.d.ts +0 -1734
- package/dist/training/index.js +0 -2687
- package/extract-failures.js +0 -10
- package/src/training/training/data/novel-use-cases.jsonl +0 -153
- package/src/training/training/data/spatial-reasoning-10k.jsonl +0 -9354
- package/src/types/core-stubs.d.ts +0 -113
- package/test-output.txt +0 -0
- package/test-result.json +0 -1
- package/tsc-errors.txt +0 -4
- package/tsc_output.txt +0 -0
- package/typescript-errors-2.txt +0 -0
- package/typescript-errors.txt +0 -22
- package/vitest-log-utf8.txt +0 -268
- package/vitest-log.txt +0 -0
|
@@ -124,7 +124,7 @@ function deduplicateExamples(
|
|
|
124
124
|
const unique: SpatialTrainingExample[] = [];
|
|
125
125
|
let nearDupes = 0;
|
|
126
126
|
|
|
127
|
-
for (const [
|
|
127
|
+
for (const [_cat, catExamples] of categories) {
|
|
128
128
|
const catUnique: SpatialTrainingExample[] = [];
|
|
129
129
|
const ngramCache: Array<Set<string>> = [];
|
|
130
130
|
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LRScheduler - Learning Rate Scheduler with Warmup + Cosine Decay
|
|
3
|
+
*
|
|
4
|
+
* Implements the learning rate schedule described in training rule W.009:
|
|
5
|
+
* "Always use warmup (10% steps) + cosine decay."
|
|
6
|
+
*
|
|
7
|
+
* The schedule has two phases:
|
|
8
|
+
* 1. **Linear Warmup**: LR ramps linearly from 0 to baseLR over the
|
|
9
|
+
* first warmupSteps (typically 10% of total steps).
|
|
10
|
+
* 2. **Cosine Decay**: LR decays from baseLR to minLR following a
|
|
11
|
+
* cosine curve over the remaining steps.
|
|
12
|
+
*
|
|
13
|
+
* This prevents early divergence in deep networks and enables smooth
|
|
14
|
+
* convergence. Pairs with W.006 base LR (2e-4 for SFT, 1e-6 for GRPO).
|
|
15
|
+
*
|
|
16
|
+
* @module training/LRScheduler
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// TYPES
|
|
21
|
+
// =============================================================================
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Configuration for the LR scheduler.
|
|
25
|
+
*/
|
|
26
|
+
export interface LRSchedulerConfig {
|
|
27
|
+
/**
|
|
28
|
+
* Base (peak) learning rate.
|
|
29
|
+
* Per W.006: 2e-4 for SFT, 1e-6 for GRPO.
|
|
30
|
+
*/
|
|
31
|
+
baseLR: number;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Total number of training steps.
|
|
35
|
+
* Computed as: (dataset_size / effective_batch_size) * num_epochs.
|
|
36
|
+
*/
|
|
37
|
+
totalSteps: number;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Warmup ratio: fraction of totalSteps used for linear warmup.
|
|
41
|
+
* Per W.009: 10% warmup steps (warmupRatio = 0.1).
|
|
42
|
+
* Must be in range [0, 1).
|
|
43
|
+
*/
|
|
44
|
+
warmupRatio: number;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Minimum learning rate at the end of cosine decay.
|
|
48
|
+
* Typically 0 or a very small value (e.g., 1e-7).
|
|
49
|
+
* Must be in range [0, baseLR).
|
|
50
|
+
*/
|
|
51
|
+
minLR: number;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Number of cosine annealing cycles.
|
|
55
|
+
* Default: 1 (single cosine decay from peak to min).
|
|
56
|
+
* Values > 1 create "cosine annealing with warm restarts" (SGDR).
|
|
57
|
+
*/
|
|
58
|
+
numCycles: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Snapshot of the LR scheduler state at a given step.
|
|
63
|
+
*/
|
|
64
|
+
export interface LRSchedulerSnapshot {
|
|
65
|
+
/** Current training step */
|
|
66
|
+
step: number;
|
|
67
|
+
|
|
68
|
+
/** Current learning rate */
|
|
69
|
+
learningRate: number;
|
|
70
|
+
|
|
71
|
+
/** Current phase: 'warmup' or 'decay' */
|
|
72
|
+
phase: 'warmup' | 'decay';
|
|
73
|
+
|
|
74
|
+
/** Progress through current phase (0 to 1) */
|
|
75
|
+
phaseProgress: number;
|
|
76
|
+
|
|
77
|
+
/** Overall training progress (0 to 1) */
|
|
78
|
+
overallProgress: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Summary statistics for the full LR schedule.
|
|
83
|
+
*/
|
|
84
|
+
export interface LRScheduleStats {
|
|
85
|
+
/** Peak learning rate (baseLR) */
|
|
86
|
+
peakLR: number;
|
|
87
|
+
|
|
88
|
+
/** Minimum learning rate (minLR or end-of-decay value) */
|
|
89
|
+
minLR: number;
|
|
90
|
+
|
|
91
|
+
/** Number of warmup steps */
|
|
92
|
+
warmupSteps: number;
|
|
93
|
+
|
|
94
|
+
/** Number of decay steps */
|
|
95
|
+
decaySteps: number;
|
|
96
|
+
|
|
97
|
+
/** Total training steps */
|
|
98
|
+
totalSteps: number;
|
|
99
|
+
|
|
100
|
+
/** Average learning rate across all steps */
|
|
101
|
+
avgLR: number;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// =============================================================================
|
|
105
|
+
// DEFAULT CONFIGURATION
|
|
106
|
+
// =============================================================================
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Default LR scheduler configuration for HoloScript/Brittney SFT training.
|
|
110
|
+
* Based on W.006 (baseLR=2e-4) and W.009 (warmupRatio=0.1, cosine decay).
|
|
111
|
+
*/
|
|
112
|
+
export const DEFAULT_LR_SCHEDULER_CONFIG: LRSchedulerConfig = {
|
|
113
|
+
baseLR: 2e-4,
|
|
114
|
+
totalSteps: 1000,
|
|
115
|
+
warmupRatio: 0.1,
|
|
116
|
+
minLR: 0,
|
|
117
|
+
numCycles: 1,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* LR scheduler configuration for GRPO training.
|
|
122
|
+
* Uses lower baseLR (1e-6) per GRPOConfig.ts.
|
|
123
|
+
*/
|
|
124
|
+
export const GRPO_LR_SCHEDULER_CONFIG: LRSchedulerConfig = {
|
|
125
|
+
baseLR: 1e-6,
|
|
126
|
+
totalSteps: 1000,
|
|
127
|
+
warmupRatio: 0.1,
|
|
128
|
+
minLR: 0,
|
|
129
|
+
numCycles: 1,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// =============================================================================
|
|
133
|
+
// LR SCHEDULER CLASS
|
|
134
|
+
// =============================================================================
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Learning Rate Scheduler with warmup + cosine decay.
|
|
138
|
+
*
|
|
139
|
+
* Computes the learning rate at any given training step.
|
|
140
|
+
* Stateless: does not track the current step internally. This makes it
|
|
141
|
+
* safe to use in distributed training where multiple workers may query
|
|
142
|
+
* different steps simultaneously.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* const scheduler = new LRScheduler({
|
|
147
|
+
* baseLR: 2e-4,
|
|
148
|
+
* totalSteps: 10000,
|
|
149
|
+
* warmupRatio: 0.1,
|
|
150
|
+
* minLR: 1e-7,
|
|
151
|
+
* numCycles: 1,
|
|
152
|
+
* });
|
|
153
|
+
*
|
|
154
|
+
* // Step 0: LR = 0 (start of warmup)
|
|
155
|
+
* scheduler.getLR(0); // 0
|
|
156
|
+
*
|
|
157
|
+
* // Step 500: LR = 1e-4 (midway through warmup)
|
|
158
|
+
* scheduler.getLR(500); // ~0.0001
|
|
159
|
+
*
|
|
160
|
+
* // Step 1000: LR = 2e-4 (end of warmup, peak LR)
|
|
161
|
+
* scheduler.getLR(1000); // 0.0002
|
|
162
|
+
*
|
|
163
|
+
* // Step 5500: LR ~= 1e-4 (midway through cosine decay)
|
|
164
|
+
* scheduler.getLR(5500);
|
|
165
|
+
*
|
|
166
|
+
* // Step 10000: LR ~= 1e-7 (end of training)
|
|
167
|
+
* scheduler.getLR(10000); // ~0.0000001
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export class LRScheduler {
|
|
171
|
+
private config: LRSchedulerConfig;
|
|
172
|
+
private warmupSteps: number;
|
|
173
|
+
|
|
174
|
+
constructor(config: Partial<LRSchedulerConfig> = {}) {
|
|
175
|
+
this.config = { ...DEFAULT_LR_SCHEDULER_CONFIG, ...config };
|
|
176
|
+
this.validateConfig();
|
|
177
|
+
this.warmupSteps = Math.floor(this.config.totalSteps * this.config.warmupRatio);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Get the learning rate at a given training step.
|
|
182
|
+
*
|
|
183
|
+
* @param step - Current training step (0-indexed)
|
|
184
|
+
* @returns The learning rate at this step
|
|
185
|
+
*/
|
|
186
|
+
getLR(step: number): number {
|
|
187
|
+
const { baseLR, totalSteps, minLR, numCycles } = this.config;
|
|
188
|
+
|
|
189
|
+
// Clamp step to valid range
|
|
190
|
+
const clampedStep = Math.max(0, Math.min(step, totalSteps));
|
|
191
|
+
|
|
192
|
+
// Phase 1: Linear warmup
|
|
193
|
+
if (clampedStep < this.warmupSteps) {
|
|
194
|
+
if (this.warmupSteps === 0) {
|
|
195
|
+
return baseLR;
|
|
196
|
+
}
|
|
197
|
+
return baseLR * (clampedStep / this.warmupSteps);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Phase 2: Cosine decay
|
|
201
|
+
const decaySteps = totalSteps - this.warmupSteps;
|
|
202
|
+
if (decaySteps <= 0) {
|
|
203
|
+
return baseLR;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const decayProgress = (clampedStep - this.warmupSteps) / decaySteps;
|
|
207
|
+
|
|
208
|
+
// Cosine annealing with optional warm restarts
|
|
209
|
+
const cosineArg = Math.PI * numCycles * decayProgress;
|
|
210
|
+
const cosineValue = (1 + Math.cos(cosineArg)) / 2;
|
|
211
|
+
|
|
212
|
+
// Scale between minLR and baseLR
|
|
213
|
+
return minLR + (baseLR - minLR) * cosineValue;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get a detailed snapshot of the scheduler state at a given step.
|
|
218
|
+
*
|
|
219
|
+
* @param step - Current training step (0-indexed)
|
|
220
|
+
* @returns LRSchedulerSnapshot with full state information
|
|
221
|
+
*/
|
|
222
|
+
getSnapshot(step: number): LRSchedulerSnapshot {
|
|
223
|
+
const { totalSteps } = this.config;
|
|
224
|
+
const clampedStep = Math.max(0, Math.min(step, totalSteps));
|
|
225
|
+
const learningRate = this.getLR(step);
|
|
226
|
+
|
|
227
|
+
const isWarmup = clampedStep < this.warmupSteps;
|
|
228
|
+
const phase: 'warmup' | 'decay' = isWarmup ? 'warmup' : 'decay';
|
|
229
|
+
|
|
230
|
+
let phaseProgress: number;
|
|
231
|
+
if (isWarmup) {
|
|
232
|
+
phaseProgress = this.warmupSteps === 0 ? 1 : clampedStep / this.warmupSteps;
|
|
233
|
+
} else {
|
|
234
|
+
const decaySteps = totalSteps - this.warmupSteps;
|
|
235
|
+
phaseProgress = decaySteps <= 0 ? 1 : (clampedStep - this.warmupSteps) / decaySteps;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const overallProgress = totalSteps === 0 ? 1 : clampedStep / totalSteps;
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
step: clampedStep,
|
|
242
|
+
learningRate,
|
|
243
|
+
phase,
|
|
244
|
+
phaseProgress,
|
|
245
|
+
overallProgress,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Compute summary statistics for the full LR schedule.
|
|
251
|
+
* Samples every step to compute the average LR.
|
|
252
|
+
*
|
|
253
|
+
* For large totalSteps, this samples at most 10000 evenly-spaced points
|
|
254
|
+
* for efficiency.
|
|
255
|
+
*/
|
|
256
|
+
getStats(): LRScheduleStats {
|
|
257
|
+
const { baseLR, minLR, totalSteps } = this.config;
|
|
258
|
+
const decaySteps = totalSteps - this.warmupSteps;
|
|
259
|
+
|
|
260
|
+
// Compute average LR by sampling
|
|
261
|
+
let sumLR = 0;
|
|
262
|
+
const sampleCount = Math.min(totalSteps + 1, 10000);
|
|
263
|
+
const stepSize = totalSteps / Math.max(sampleCount - 1, 1);
|
|
264
|
+
|
|
265
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
266
|
+
const step = Math.round(i * stepSize);
|
|
267
|
+
sumLR += this.getLR(step);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const avgLR = sampleCount > 0 ? sumLR / sampleCount : 0;
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
peakLR: baseLR,
|
|
274
|
+
minLR,
|
|
275
|
+
warmupSteps: this.warmupSteps,
|
|
276
|
+
decaySteps: Math.max(0, decaySteps),
|
|
277
|
+
totalSteps,
|
|
278
|
+
avgLR,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Generate the full LR schedule as an array of [step, lr] pairs.
|
|
284
|
+
* Useful for plotting or debugging.
|
|
285
|
+
*
|
|
286
|
+
* @param numPoints - Number of points to sample (default: 100)
|
|
287
|
+
* @returns Array of [step, learningRate] tuples
|
|
288
|
+
*/
|
|
289
|
+
getSchedule(numPoints: number = 100): Array<[number, number]> {
|
|
290
|
+
const { totalSteps } = this.config;
|
|
291
|
+
const points: Array<[number, number]> = [];
|
|
292
|
+
const clampedPoints = Math.max(2, numPoints);
|
|
293
|
+
|
|
294
|
+
for (let i = 0; i < clampedPoints; i++) {
|
|
295
|
+
const step = Math.round((i / (clampedPoints - 1)) * totalSteps);
|
|
296
|
+
points.push([step, this.getLR(step)]);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return points;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Get the number of warmup steps.
|
|
304
|
+
*/
|
|
305
|
+
getWarmupSteps(): number {
|
|
306
|
+
return this.warmupSteps;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Get the current configuration.
|
|
311
|
+
*/
|
|
312
|
+
getConfig(): Readonly<LRSchedulerConfig> {
|
|
313
|
+
return { ...this.config };
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ===========================================================================
|
|
317
|
+
// INTERNAL METHODS
|
|
318
|
+
// ===========================================================================
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Validate configuration parameters.
|
|
322
|
+
* @throws Error if configuration is invalid
|
|
323
|
+
*/
|
|
324
|
+
private validateConfig(): void {
|
|
325
|
+
const { baseLR, totalSteps, warmupRatio, minLR, numCycles } = this.config;
|
|
326
|
+
|
|
327
|
+
if (baseLR <= 0) {
|
|
328
|
+
throw new Error(`LRScheduler: baseLR must be > 0, got ${baseLR}`);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (totalSteps < 0 || !Number.isInteger(totalSteps)) {
|
|
332
|
+
throw new Error(`LRScheduler: totalSteps must be a non-negative integer, got ${totalSteps}`);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (warmupRatio < 0 || warmupRatio >= 1) {
|
|
336
|
+
throw new Error(`LRScheduler: warmupRatio must be in [0, 1), got ${warmupRatio}`);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (minLR < 0 || minLR >= baseLR) {
|
|
340
|
+
throw new Error(`LRScheduler: minLR must be in [0, baseLR), got ${minLR}`);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (numCycles < 1 || !Number.isInteger(numCycles)) {
|
|
344
|
+
throw new Error(`LRScheduler: numCycles must be a positive integer, got ${numCycles}`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// =============================================================================
|
|
350
|
+
// FACTORY FUNCTIONS
|
|
351
|
+
// =============================================================================
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Create an LR scheduler for SFT training with optional overrides.
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```ts
|
|
358
|
+
* const scheduler = createSFTScheduler({ totalSteps: 5000 });
|
|
359
|
+
* const lr = scheduler.getLR(100);
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
export function createSFTScheduler(config: Partial<LRSchedulerConfig> = {}): LRScheduler {
|
|
363
|
+
return new LRScheduler({ ...DEFAULT_LR_SCHEDULER_CONFIG, ...config });
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Create an LR scheduler for GRPO training with optional overrides.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```ts
|
|
371
|
+
* const scheduler = createGRPOScheduler({ totalSteps: 2000 });
|
|
372
|
+
* const lr = scheduler.getLR(100);
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
export function createGRPOScheduler(config: Partial<LRSchedulerConfig> = {}): LRScheduler {
|
|
376
|
+
return new LRScheduler({ ...GRPO_LR_SCHEDULER_CONFIG, ...config });
|
|
377
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiler-Based Quality Scoring Pipeline for Training Data
|
|
3
|
+
* Metrics: syntax_validity, schema_compliance, semantic_correctness
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
export interface QualityScore {
|
|
7
|
+
syntaxValidity: number; // 0-1
|
|
8
|
+
schemaCompliance: number; // 0-1
|
|
9
|
+
semanticCorrectness: number; // 0-1
|
|
10
|
+
compositeScore: number; // weighted average 0-1
|
|
11
|
+
details: QualityDetail[];
|
|
12
|
+
}
|
|
13
|
+
export interface QualityDetail {
|
|
14
|
+
metric: string;
|
|
15
|
+
score: number;
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface QualityScoringConfig {
|
|
20
|
+
syntaxWeight: number;
|
|
21
|
+
schemaWeight: number;
|
|
22
|
+
semanticWeight: number;
|
|
23
|
+
minPassScore: number;
|
|
24
|
+
knownTraits: Set<string>;
|
|
25
|
+
knownTypes: Set<string>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const DEFAULT_SCORING_CONFIG: QualityScoringConfig = {
|
|
29
|
+
syntaxWeight: 0.4,
|
|
30
|
+
schemaWeight: 0.3,
|
|
31
|
+
semanticWeight: 0.3,
|
|
32
|
+
minPassScore: 0.7,
|
|
33
|
+
knownTraits: new Set(['Grabbable', 'Physics', 'Animation', 'GaussianSplat', 'Tradeable', 'NPC']),
|
|
34
|
+
knownTypes: new Set(['orb', 'world', 'composition', 'template']),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export class QualityScoringPipeline {
|
|
38
|
+
private config: QualityScoringConfig;
|
|
39
|
+
constructor(config: Partial<QualityScoringConfig> = {}) {
|
|
40
|
+
this.config = { ...DEFAULT_SCORING_CONFIG, ...config };
|
|
41
|
+
}
|
|
42
|
+
score(source: string): QualityScore {
|
|
43
|
+
const details: QualityDetail[] = [];
|
|
44
|
+
const syntax = this.scoreSyntax(source, details);
|
|
45
|
+
const schema = this.scoreSchema(source, details);
|
|
46
|
+
const semantic = this.scoreSemantic(source, details);
|
|
47
|
+
const composite =
|
|
48
|
+
syntax * this.config.syntaxWeight +
|
|
49
|
+
schema * this.config.schemaWeight +
|
|
50
|
+
semantic * this.config.semanticWeight;
|
|
51
|
+
return {
|
|
52
|
+
syntaxValidity: syntax,
|
|
53
|
+
schemaCompliance: schema,
|
|
54
|
+
semanticCorrectness: semantic,
|
|
55
|
+
compositeScore: composite,
|
|
56
|
+
details,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
passes(score: QualityScore): boolean {
|
|
60
|
+
return score.compositeScore >= this.config.minPassScore;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private scoreSyntax(source: string, details: QualityDetail[]): number {
|
|
64
|
+
let score = 1.0;
|
|
65
|
+
if (!source.trim()) {
|
|
66
|
+
details.push({ metric: 'syntax', score: 0, message: 'Empty source' });
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
const open = (source.match(/{/g) || []).length;
|
|
70
|
+
const close = (source.match(/}/g) || []).length;
|
|
71
|
+
if (open !== close) {
|
|
72
|
+
score -= 0.5;
|
|
73
|
+
details.push({
|
|
74
|
+
metric: 'syntax',
|
|
75
|
+
score: 0.5,
|
|
76
|
+
message: `Unbalanced braces: ${open} open, ${close} close`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (
|
|
80
|
+
/composition\s+\w+/.test(source) ||
|
|
81
|
+
/orb\s+\w+/.test(source) ||
|
|
82
|
+
/world\s+\w+/.test(source)
|
|
83
|
+
) {
|
|
84
|
+
details.push({ metric: 'syntax', score: 1.0, message: 'Valid composition structure' });
|
|
85
|
+
} else {
|
|
86
|
+
score -= 0.3;
|
|
87
|
+
details.push({
|
|
88
|
+
metric: 'syntax',
|
|
89
|
+
score: 0.7,
|
|
90
|
+
message: 'No recognized top-level declaration',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return Math.max(0, score);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private scoreSchema(source: string, details: QualityDetail[]): number {
|
|
97
|
+
let score = 1.0;
|
|
98
|
+
const traitPattern = /(\w+)\s*{/g;
|
|
99
|
+
let match;
|
|
100
|
+
while ((match = traitPattern.exec(source)) !== null) {
|
|
101
|
+
const name = match[1];
|
|
102
|
+
if (this.config.knownTraits.has(name) || this.config.knownTypes.has(name)) continue;
|
|
103
|
+
if (/^[A-Z]/.test(name) && !this.config.knownTraits.has(name)) {
|
|
104
|
+
score -= 0.1;
|
|
105
|
+
details.push({ metric: 'schema', score: 0.9, message: `Unknown trait: ${name}` });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return Math.max(0, score);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private scoreSemantic(source: string, details: QualityDetail[]): number {
|
|
112
|
+
let score = 1.0;
|
|
113
|
+
if (/physics\s*{/.test(source) && !/mass|gravity|friction/.test(source)) {
|
|
114
|
+
score -= 0.2;
|
|
115
|
+
details.push({
|
|
116
|
+
metric: 'semantic',
|
|
117
|
+
score: 0.8,
|
|
118
|
+
message: 'Physics block without mass/gravity/friction',
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (/animation\s*{/.test(source) && !/clip|duration|speed/.test(source)) {
|
|
122
|
+
score -= 0.2;
|
|
123
|
+
details.push({
|
|
124
|
+
metric: 'semantic',
|
|
125
|
+
score: 0.8,
|
|
126
|
+
message: 'Animation block without clip/duration',
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (source.length < 20) {
|
|
130
|
+
score -= 0.3;
|
|
131
|
+
details.push({
|
|
132
|
+
metric: 'semantic',
|
|
133
|
+
score: 0.7,
|
|
134
|
+
message: 'Source too short for meaningful composition',
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return Math.max(0, score);
|
|
138
|
+
}
|
|
139
|
+
}
|