@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
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TrainingMonkey Integration Module
|
|
3
|
+
*
|
|
4
|
+
* Converts HoloScript spatial reasoning JSONL training data into
|
|
5
|
+
* TrainingMonkey's Alpaca format with:
|
|
6
|
+
* 1. JSONL reading and parsing
|
|
7
|
+
* 2. Alpaca format conversion (instruction/input/output)
|
|
8
|
+
* 3. SoftDedup (W.008) n-gram reweighting for sampling
|
|
9
|
+
* 4. Stratified train/validation splits (90/10)
|
|
10
|
+
* 5. TrainingMonkey-compatible training config (W.006 hyperparameters)
|
|
11
|
+
* 6. Ready-to-upload output file generation
|
|
12
|
+
*
|
|
13
|
+
* @module training/trainingmonkey/TrainingMonkeyIntegration
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { SoftDedup } from '../SoftDedup';
|
|
17
|
+
import type { SoftDedupResult } from '../SoftDedup';
|
|
18
|
+
import type { SpatialTrainingJSONLEntry } from '../SpatialTrainingDataTypes';
|
|
19
|
+
import type {
|
|
20
|
+
AlpacaEntry,
|
|
21
|
+
WeightedAlpacaEntry,
|
|
22
|
+
DatasetSplit,
|
|
23
|
+
SplitStats,
|
|
24
|
+
TrainingMonkeyConfig,
|
|
25
|
+
TrainingMonkeyIntegrationConfig,
|
|
26
|
+
IntegrationResult,
|
|
27
|
+
} from './TrainingMonkeyTypes';
|
|
28
|
+
import { DEFAULT_INTEGRATION_CONFIG } from './TrainingMonkeyTypes';
|
|
29
|
+
|
|
30
|
+
// =============================================================================
|
|
31
|
+
// SEEDED PRNG (Fisher-Yates shuffle requires deterministic randomness)
|
|
32
|
+
// =============================================================================
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Simple seeded PRNG (mulberry32) for deterministic shuffling.
|
|
36
|
+
* Produces values in [0, 1).
|
|
37
|
+
*/
|
|
38
|
+
function createSeededRandom(seed: number): () => number {
|
|
39
|
+
let state = seed | 0;
|
|
40
|
+
return () => {
|
|
41
|
+
state = (state + 0x6d2b79f5) | 0;
|
|
42
|
+
let t = Math.imul(state ^ (state >>> 15), 1 | state);
|
|
43
|
+
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
|
44
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// TRAINING MONKEY INTEGRATION CLASS
|
|
50
|
+
// =============================================================================
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Integrates HoloScript spatial reasoning data with TrainingMonkey.
|
|
54
|
+
*
|
|
55
|
+
* Full pipeline:
|
|
56
|
+
* readJsonl() -> convertToAlpaca() -> applySoftDedup() -> splitDataset() -> generateConfig()
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const integration = new TrainingMonkeyIntegration({
|
|
61
|
+
* inputPath: 'spatial-reasoning-10k.jsonl',
|
|
62
|
+
* outputDir: './output',
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* const jsonlContent = fs.readFileSync('spatial-reasoning-10k.jsonl', 'utf-8');
|
|
66
|
+
* const result = integration.process(jsonlContent);
|
|
67
|
+
*
|
|
68
|
+
* fs.writeFileSync('alpaca-train.jsonl', result.trainJsonl);
|
|
69
|
+
* fs.writeFileSync('alpaca-val.jsonl', result.validationJsonl);
|
|
70
|
+
* fs.writeFileSync('training-config.json', result.configJson);
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export class TrainingMonkeyIntegration {
|
|
74
|
+
private config: TrainingMonkeyIntegrationConfig;
|
|
75
|
+
private softDedup: SoftDedup;
|
|
76
|
+
|
|
77
|
+
constructor(config: Partial<TrainingMonkeyIntegrationConfig> = {}) {
|
|
78
|
+
this.config = { ...DEFAULT_INTEGRATION_CONFIG, ...config };
|
|
79
|
+
this.softDedup = new SoftDedup({
|
|
80
|
+
ngramSizes: [3, 5, 7],
|
|
81
|
+
wordLevel: false,
|
|
82
|
+
minWeight: 0.1,
|
|
83
|
+
maxWeight: 1.0,
|
|
84
|
+
temperature: 1.0,
|
|
85
|
+
commonThresholdPercentile: 0.7,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ===========================================================================
|
|
90
|
+
// PUBLIC API
|
|
91
|
+
// ===========================================================================
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Run the full integration pipeline on raw JSONL content.
|
|
95
|
+
*
|
|
96
|
+
* @param jsonlContent - Raw JSONL string content from the dataset file
|
|
97
|
+
* @returns Complete IntegrationResult with split data, config, and serialized output
|
|
98
|
+
*/
|
|
99
|
+
process(jsonlContent: string): IntegrationResult {
|
|
100
|
+
// Step 1: Parse JSONL
|
|
101
|
+
const entries = this.readJsonl(jsonlContent);
|
|
102
|
+
|
|
103
|
+
// Step 2: Convert to Alpaca format
|
|
104
|
+
const alpacaEntries = this.convertToAlpaca(entries);
|
|
105
|
+
|
|
106
|
+
// Step 3: Apply SoftDedup reweighting
|
|
107
|
+
const weightedEntries = this.config.enableSoftDedup
|
|
108
|
+
? this.applySoftDedup(alpacaEntries, entries)
|
|
109
|
+
: alpacaEntries.map(
|
|
110
|
+
(entry, index) =>
|
|
111
|
+
({
|
|
112
|
+
...entry,
|
|
113
|
+
sampling_weight: 1.0,
|
|
114
|
+
metadata: entries[index]?.metadata,
|
|
115
|
+
}) as WeightedAlpacaEntry
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Step 4: Split into train/validation
|
|
119
|
+
const split = this.splitDataset(weightedEntries);
|
|
120
|
+
|
|
121
|
+
// Step 5: Generate training config
|
|
122
|
+
const config = this.generateConfig(split);
|
|
123
|
+
|
|
124
|
+
// Step 6: Serialize outputs
|
|
125
|
+
const trainJsonl = this.serializeJsonl(split.train);
|
|
126
|
+
const validationJsonl = this.serializeJsonl(split.validation);
|
|
127
|
+
const configJson = JSON.stringify(config, null, 2);
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
split,
|
|
131
|
+
config,
|
|
132
|
+
trainJsonl,
|
|
133
|
+
validationJsonl,
|
|
134
|
+
configJson,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Parse raw JSONL content into SpatialTrainingJSONLEntry objects.
|
|
140
|
+
*
|
|
141
|
+
* @param jsonlContent - Raw JSONL string (one JSON object per line)
|
|
142
|
+
* @returns Array of parsed entries
|
|
143
|
+
* @throws Error if a line contains invalid JSON
|
|
144
|
+
*/
|
|
145
|
+
readJsonl(jsonlContent: string): SpatialTrainingJSONLEntry[] {
|
|
146
|
+
const lines = jsonlContent.split('\n').filter((line) => line.trim() !== '');
|
|
147
|
+
const entries: SpatialTrainingJSONLEntry[] = [];
|
|
148
|
+
|
|
149
|
+
for (let i = 0; i < lines.length; i++) {
|
|
150
|
+
try {
|
|
151
|
+
const parsed = JSON.parse(lines[i]) as SpatialTrainingJSONLEntry;
|
|
152
|
+
if (!parsed.instruction || !parsed.response) {
|
|
153
|
+
throw new Error(`Missing required fields (instruction/response)`);
|
|
154
|
+
}
|
|
155
|
+
entries.push(parsed);
|
|
156
|
+
} catch (e) {
|
|
157
|
+
throw new Error(`Failed to parse JSONL line ${i + 1}: ${(e as Error).message}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return entries;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Convert spatial training entries to Alpaca format.
|
|
166
|
+
*
|
|
167
|
+
* Mapping:
|
|
168
|
+
* instruction -> instruction (question/prompt)
|
|
169
|
+
* input -> extracted HoloScript scene from instruction (if present)
|
|
170
|
+
* output -> response (answer)
|
|
171
|
+
*
|
|
172
|
+
* @param entries - Parsed spatial training entries
|
|
173
|
+
* @returns Alpaca-formatted entries
|
|
174
|
+
*/
|
|
175
|
+
convertToAlpaca(entries: SpatialTrainingJSONLEntry[]): AlpacaEntry[] {
|
|
176
|
+
return entries.map((entry) => {
|
|
177
|
+
// Extract HoloScript scene block from instruction as separate input
|
|
178
|
+
const { questionPart, scenePart } = this.extractSceneFromInstruction(entry.instruction);
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
instruction: questionPart,
|
|
182
|
+
input: scenePart,
|
|
183
|
+
output: entry.response,
|
|
184
|
+
};
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Apply SoftDedup (W.008) n-gram reweighting to Alpaca entries.
|
|
190
|
+
*
|
|
191
|
+
* Uses the instruction + output text to compute n-gram commonness scores
|
|
192
|
+
* and assigns sampling weights. Template-generated near-duplicates receive
|
|
193
|
+
* lower weights (min 0.1), while unique examples keep weight 1.0.
|
|
194
|
+
*
|
|
195
|
+
* @param alpacaEntries - Converted Alpaca entries
|
|
196
|
+
* @param originalEntries - Original JSONL entries (for metadata preservation)
|
|
197
|
+
* @returns Weighted Alpaca entries with sampling_weight and metadata
|
|
198
|
+
*/
|
|
199
|
+
applySoftDedup(
|
|
200
|
+
alpacaEntries: AlpacaEntry[],
|
|
201
|
+
originalEntries: SpatialTrainingJSONLEntry[]
|
|
202
|
+
): WeightedAlpacaEntry[] {
|
|
203
|
+
// Build text corpus from instruction + output for n-gram analysis
|
|
204
|
+
const textCorpus = alpacaEntries.map((entry) => `${entry.instruction} ${entry.output}`);
|
|
205
|
+
|
|
206
|
+
// Run SoftDedup
|
|
207
|
+
const dedupResults: SoftDedupResult[] = this.softDedup.process(textCorpus);
|
|
208
|
+
|
|
209
|
+
// Merge weights with Alpaca entries
|
|
210
|
+
return alpacaEntries.map((entry, index) => ({
|
|
211
|
+
...entry,
|
|
212
|
+
sampling_weight: dedupResults[index]?.samplingWeight ?? 1.0,
|
|
213
|
+
metadata: originalEntries[index]?.metadata,
|
|
214
|
+
}));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Split weighted entries into train/validation sets.
|
|
219
|
+
*
|
|
220
|
+
* When stratified=true, the split preserves the distribution of
|
|
221
|
+
* relationship_type and difficulty across both sets.
|
|
222
|
+
*
|
|
223
|
+
* @param entries - Weighted Alpaca entries
|
|
224
|
+
* @returns DatasetSplit with train, validation, and stats
|
|
225
|
+
*/
|
|
226
|
+
splitDataset(entries: WeightedAlpacaEntry[]): DatasetSplit {
|
|
227
|
+
if (entries.length === 0) {
|
|
228
|
+
return {
|
|
229
|
+
train: [],
|
|
230
|
+
validation: [],
|
|
231
|
+
stats: {
|
|
232
|
+
totalExamples: 0,
|
|
233
|
+
trainCount: 0,
|
|
234
|
+
validationCount: 0,
|
|
235
|
+
trainRatio: 0,
|
|
236
|
+
validationRatio: 0,
|
|
237
|
+
stratified: this.config.stratify,
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const rng = createSeededRandom(this.config.seed);
|
|
243
|
+
|
|
244
|
+
let train: WeightedAlpacaEntry[];
|
|
245
|
+
let validation: WeightedAlpacaEntry[];
|
|
246
|
+
|
|
247
|
+
if (this.config.stratify && entries[0]?.metadata) {
|
|
248
|
+
({ train, validation } = this.stratifiedSplit(entries, rng));
|
|
249
|
+
} else {
|
|
250
|
+
({ train, validation } = this.randomSplit(entries, rng));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const stats: SplitStats = {
|
|
254
|
+
totalExamples: entries.length,
|
|
255
|
+
trainCount: train.length,
|
|
256
|
+
validationCount: validation.length,
|
|
257
|
+
trainRatio: train.length / entries.length,
|
|
258
|
+
validationRatio: validation.length / entries.length,
|
|
259
|
+
stratified: this.config.stratify && !!entries[0]?.metadata,
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
return { train, validation, stats };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Generate a TrainingMonkey-compatible training configuration.
|
|
267
|
+
*
|
|
268
|
+
* Uses W.006 hyperparameters:
|
|
269
|
+
* - Learning rate: 2e-4
|
|
270
|
+
* - Epochs: 2
|
|
271
|
+
* - Optimizer: paged_adamw_8bit
|
|
272
|
+
*
|
|
273
|
+
* Uses W.007 batch sizing:
|
|
274
|
+
* - Micro-batch: 8
|
|
275
|
+
* - Gradient accumulation: 4
|
|
276
|
+
* - Effective batch: 32
|
|
277
|
+
*
|
|
278
|
+
* Uses W.009 LR schedule:
|
|
279
|
+
* - Warmup: 10% of total steps
|
|
280
|
+
* - Schedule: cosine decay
|
|
281
|
+
*
|
|
282
|
+
* @param split - The dataset split result
|
|
283
|
+
* @returns TrainingMonkey-compatible config
|
|
284
|
+
*/
|
|
285
|
+
generateConfig(split: DatasetSplit): TrainingMonkeyConfig {
|
|
286
|
+
const microBatchSize = 8;
|
|
287
|
+
const gradientAccumulationSteps = 4;
|
|
288
|
+
const epochs = 2;
|
|
289
|
+
const effectiveBatchSize = microBatchSize * gradientAccumulationSteps;
|
|
290
|
+
const stepsPerEpoch = Math.ceil(split.stats.trainCount / effectiveBatchSize);
|
|
291
|
+
const totalSteps = stepsPerEpoch * epochs;
|
|
292
|
+
|
|
293
|
+
// Compute SoftDedup stats
|
|
294
|
+
const weights = split.train.map((e) => e.sampling_weight);
|
|
295
|
+
const meanWeight =
|
|
296
|
+
weights.length > 0 ? weights.reduce((sum, w) => sum + w, 0) / weights.length : 1.0;
|
|
297
|
+
const effectiveSize = weights.reduce((sum, w) => sum + w, 0);
|
|
298
|
+
const reductionRatio = weights.length > 0 ? 1 - effectiveSize / weights.length : 0;
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
model: {
|
|
302
|
+
name: this.config.modelName,
|
|
303
|
+
maxSeqLength: 2048,
|
|
304
|
+
},
|
|
305
|
+
hyperparameters: {
|
|
306
|
+
learningRate: 2e-4,
|
|
307
|
+
epochs,
|
|
308
|
+
optimizer: 'paged_adamw_8bit',
|
|
309
|
+
microBatchSize,
|
|
310
|
+
gradientAccumulationSteps,
|
|
311
|
+
maxGradNorm: 1.0,
|
|
312
|
+
weightDecay: 0.01,
|
|
313
|
+
},
|
|
314
|
+
lrSchedule: {
|
|
315
|
+
warmupRatio: 0.1,
|
|
316
|
+
type: 'cosine',
|
|
317
|
+
},
|
|
318
|
+
dataset: {
|
|
319
|
+
trainPath: `${this.config.outputDir}/alpaca-train.jsonl`,
|
|
320
|
+
validationPath: `${this.config.outputDir}/alpaca-val.jsonl`,
|
|
321
|
+
trainCount: split.stats.trainCount,
|
|
322
|
+
validationCount: split.stats.validationCount,
|
|
323
|
+
totalSteps,
|
|
324
|
+
},
|
|
325
|
+
softDedup: {
|
|
326
|
+
applied: this.config.enableSoftDedup,
|
|
327
|
+
meanWeight,
|
|
328
|
+
effectiveSize,
|
|
329
|
+
reductionRatio,
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Serialize weighted Alpaca entries to JSONL string.
|
|
336
|
+
*
|
|
337
|
+
* @param entries - Entries to serialize
|
|
338
|
+
* @returns JSONL string (one JSON object per line)
|
|
339
|
+
*/
|
|
340
|
+
serializeJsonl(entries: WeightedAlpacaEntry[]): string {
|
|
341
|
+
return entries.map((entry) => JSON.stringify(entry)).join('\n');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Get the current integration configuration.
|
|
346
|
+
*/
|
|
347
|
+
getConfig(): Readonly<TrainingMonkeyIntegrationConfig> {
|
|
348
|
+
return { ...this.config };
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// ===========================================================================
|
|
352
|
+
// INTERNAL METHODS
|
|
353
|
+
// ===========================================================================
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Extract the question part and HoloScript scene from an instruction string.
|
|
357
|
+
*
|
|
358
|
+
* The spatial reasoning dataset embeds HoloScript scenes in instructions:
|
|
359
|
+
* ```
|
|
360
|
+
* Does the spatial_adjacent constraint pass?
|
|
361
|
+
*
|
|
362
|
+
* HoloScript Scene:
|
|
363
|
+
* ```holoscript
|
|
364
|
+
* composition "SpatialScene" { ... }
|
|
365
|
+
* ```
|
|
366
|
+
* ```
|
|
367
|
+
*
|
|
368
|
+
* This method splits the instruction into the question (instruction field)
|
|
369
|
+
* and the scene source (input field) for the Alpaca format.
|
|
370
|
+
*/
|
|
371
|
+
private extractSceneFromInstruction(instruction: string): {
|
|
372
|
+
questionPart: string;
|
|
373
|
+
scenePart: string;
|
|
374
|
+
} {
|
|
375
|
+
// Look for "HoloScript Scene:" marker
|
|
376
|
+
const sceneMarkerIndex = instruction.indexOf('HoloScript Scene:');
|
|
377
|
+
|
|
378
|
+
if (sceneMarkerIndex === -1) {
|
|
379
|
+
// No scene embedded, use full instruction
|
|
380
|
+
return { questionPart: instruction.trim(), scenePart: '' };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const questionPart = instruction.substring(0, sceneMarkerIndex).trim();
|
|
384
|
+
const scenePart = instruction.substring(sceneMarkerIndex).trim();
|
|
385
|
+
|
|
386
|
+
return { questionPart, scenePart };
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Perform a stratified split preserving distribution of metadata fields.
|
|
391
|
+
* Groups by relationship_type + difficulty and splits each group proportionally.
|
|
392
|
+
*/
|
|
393
|
+
private stratifiedSplit(
|
|
394
|
+
entries: WeightedAlpacaEntry[],
|
|
395
|
+
rng: () => number
|
|
396
|
+
): { train: WeightedAlpacaEntry[]; validation: WeightedAlpacaEntry[] } {
|
|
397
|
+
// Group entries by stratification key
|
|
398
|
+
const groups = new Map<string, WeightedAlpacaEntry[]>();
|
|
399
|
+
|
|
400
|
+
for (const entry of entries) {
|
|
401
|
+
const key = entry.metadata
|
|
402
|
+
? `${entry.metadata.relationship_type}:${entry.metadata.difficulty}`
|
|
403
|
+
: 'unknown';
|
|
404
|
+
|
|
405
|
+
if (!groups.has(key)) {
|
|
406
|
+
groups.set(key, []);
|
|
407
|
+
}
|
|
408
|
+
groups.get(key)!.push(entry);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const train: WeightedAlpacaEntry[] = [];
|
|
412
|
+
const validation: WeightedAlpacaEntry[] = [];
|
|
413
|
+
|
|
414
|
+
// Split each group proportionally
|
|
415
|
+
for (const [, groupEntries] of groups) {
|
|
416
|
+
// Shuffle the group deterministically
|
|
417
|
+
const shuffled = this.fisherYatesShuffle([...groupEntries], rng);
|
|
418
|
+
|
|
419
|
+
const splitIndex = Math.round(shuffled.length * this.config.trainRatio);
|
|
420
|
+
train.push(...shuffled.slice(0, splitIndex));
|
|
421
|
+
validation.push(...shuffled.slice(splitIndex));
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return { train, validation };
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Perform a simple random split.
|
|
429
|
+
*/
|
|
430
|
+
private randomSplit(
|
|
431
|
+
entries: WeightedAlpacaEntry[],
|
|
432
|
+
rng: () => number
|
|
433
|
+
): { train: WeightedAlpacaEntry[]; validation: WeightedAlpacaEntry[] } {
|
|
434
|
+
const shuffled = this.fisherYatesShuffle([...entries], rng);
|
|
435
|
+
const splitIndex = Math.round(shuffled.length * this.config.trainRatio);
|
|
436
|
+
|
|
437
|
+
return {
|
|
438
|
+
train: shuffled.slice(0, splitIndex),
|
|
439
|
+
validation: shuffled.slice(splitIndex),
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Fisher-Yates shuffle with seeded PRNG for deterministic ordering.
|
|
445
|
+
*/
|
|
446
|
+
private fisherYatesShuffle<T>(array: T[], rng: () => number): T[] {
|
|
447
|
+
for (let i = array.length - 1; i > 0; i--) {
|
|
448
|
+
const j = Math.floor(rng() * (i + 1));
|
|
449
|
+
[array[i], array[j]] = [array[j], array[i]];
|
|
450
|
+
}
|
|
451
|
+
return array;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// =============================================================================
|
|
456
|
+
// FACTORY FUNCTION
|
|
457
|
+
// =============================================================================
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Create a TrainingMonkeyIntegration instance with optional config overrides.
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* ```ts
|
|
464
|
+
* const integration = createTrainingMonkeyIntegration({
|
|
465
|
+
* inputPath: 'spatial-reasoning-10k.jsonl',
|
|
466
|
+
* outputDir: './output',
|
|
467
|
+
* trainRatio: 0.9,
|
|
468
|
+
* });
|
|
469
|
+
*
|
|
470
|
+
* const result = integration.process(jsonlContent);
|
|
471
|
+
* ```
|
|
472
|
+
*/
|
|
473
|
+
export function createTrainingMonkeyIntegration(
|
|
474
|
+
config: Partial<TrainingMonkeyIntegrationConfig> = {}
|
|
475
|
+
): TrainingMonkeyIntegration {
|
|
476
|
+
return new TrainingMonkeyIntegration(config);
|
|
477
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TrainingMonkey Integration Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for integrating HoloScript spatial reasoning training data
|
|
5
|
+
* with the TrainingMonkey fine-tuning pipeline. Converts from the internal
|
|
6
|
+
* SpatialTrainingJSONLEntry format to TrainingMonkey's Alpaca-style format
|
|
7
|
+
* with SoftDedup (W.008) n-gram reweighting and train/validation splits.
|
|
8
|
+
*
|
|
9
|
+
* @module training/trainingmonkey/TrainingMonkeyTypes
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// ALPACA FORMAT (TrainingMonkey's Expected Input)
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Alpaca instruction-following format used by TrainingMonkey.
|
|
18
|
+
*
|
|
19
|
+
* TrainingMonkey's train_v43.py reads:
|
|
20
|
+
* - example.get("instruction", "")
|
|
21
|
+
* - example.get("output", "")
|
|
22
|
+
*
|
|
23
|
+
* The optional `input` field provides additional context (e.g., HoloScript scene).
|
|
24
|
+
*/
|
|
25
|
+
export interface AlpacaEntry {
|
|
26
|
+
/** The instruction/question for the model */
|
|
27
|
+
instruction: string;
|
|
28
|
+
|
|
29
|
+
/** Optional additional input context (HoloScript scene source) */
|
|
30
|
+
input: string;
|
|
31
|
+
|
|
32
|
+
/** The expected output/response from the model */
|
|
33
|
+
output: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Extended Alpaca entry with SoftDedup sampling weight and metadata.
|
|
38
|
+
* Used for weighted sampling during training.
|
|
39
|
+
*/
|
|
40
|
+
export interface WeightedAlpacaEntry extends AlpacaEntry {
|
|
41
|
+
/** SoftDedup sampling weight (0.1 to 1.0). Higher = more likely to be sampled */
|
|
42
|
+
sampling_weight: number;
|
|
43
|
+
|
|
44
|
+
/** Original metadata preserved from the spatial reasoning dataset */
|
|
45
|
+
metadata?: {
|
|
46
|
+
id: string;
|
|
47
|
+
relationship_type: string;
|
|
48
|
+
is_positive: boolean;
|
|
49
|
+
difficulty: string;
|
|
50
|
+
tags: string[];
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// =============================================================================
|
|
55
|
+
// DATASET SPLIT RESULT
|
|
56
|
+
// =============================================================================
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Result of splitting a dataset into train/validation sets.
|
|
60
|
+
*/
|
|
61
|
+
export interface DatasetSplit {
|
|
62
|
+
/** Training set entries */
|
|
63
|
+
train: WeightedAlpacaEntry[];
|
|
64
|
+
|
|
65
|
+
/** Validation set entries */
|
|
66
|
+
validation: WeightedAlpacaEntry[];
|
|
67
|
+
|
|
68
|
+
/** Split statistics */
|
|
69
|
+
stats: SplitStats;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Statistics about a train/validation split.
|
|
74
|
+
*/
|
|
75
|
+
export interface SplitStats {
|
|
76
|
+
/** Total examples before split */
|
|
77
|
+
totalExamples: number;
|
|
78
|
+
|
|
79
|
+
/** Number of training examples */
|
|
80
|
+
trainCount: number;
|
|
81
|
+
|
|
82
|
+
/** Number of validation examples */
|
|
83
|
+
validationCount: number;
|
|
84
|
+
|
|
85
|
+
/** Actual train ratio (trainCount / totalExamples) */
|
|
86
|
+
trainRatio: number;
|
|
87
|
+
|
|
88
|
+
/** Actual validation ratio (validationCount / totalExamples) */
|
|
89
|
+
validationRatio: number;
|
|
90
|
+
|
|
91
|
+
/** Whether the split is stratified by difficulty/relationship type */
|
|
92
|
+
stratified: boolean;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// =============================================================================
|
|
96
|
+
// TRAINING CONFIG OUTPUT
|
|
97
|
+
// =============================================================================
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* TrainingMonkey-compatible training configuration.
|
|
101
|
+
* Generated alongside the dataset for direct use with train_v43.py.
|
|
102
|
+
*/
|
|
103
|
+
export interface TrainingMonkeyConfig {
|
|
104
|
+
/** Model configuration */
|
|
105
|
+
model: {
|
|
106
|
+
/** Model identifier (e.g., "qwen7b", "phi35") */
|
|
107
|
+
name: string;
|
|
108
|
+
/** Maximum sequence length */
|
|
109
|
+
maxSeqLength: number;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/** Training hyperparameters (per W.006) */
|
|
113
|
+
hyperparameters: {
|
|
114
|
+
/** Learning rate. Per W.006: 2e-4 */
|
|
115
|
+
learningRate: number;
|
|
116
|
+
/** Number of epochs. Per W.006: 2 */
|
|
117
|
+
epochs: number;
|
|
118
|
+
/** Optimizer. Per W.006: paged_adamw_8bit */
|
|
119
|
+
optimizer: string;
|
|
120
|
+
/** Micro-batch size per device. Per W.007: 8-16 */
|
|
121
|
+
microBatchSize: number;
|
|
122
|
+
/** Gradient accumulation steps. Per W.007: 2-4 */
|
|
123
|
+
gradientAccumulationSteps: number;
|
|
124
|
+
/** Maximum gradient norm for clipping */
|
|
125
|
+
maxGradNorm: number;
|
|
126
|
+
/** Weight decay coefficient */
|
|
127
|
+
weightDecay: number;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/** LR schedule (per W.009) */
|
|
131
|
+
lrSchedule: {
|
|
132
|
+
/** Warmup ratio (10% of total steps) */
|
|
133
|
+
warmupRatio: number;
|
|
134
|
+
/** Schedule type */
|
|
135
|
+
type: 'cosine';
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/** Dataset paths */
|
|
139
|
+
dataset: {
|
|
140
|
+
/** Path to training JSONL */
|
|
141
|
+
trainPath: string;
|
|
142
|
+
/** Path to validation JSONL */
|
|
143
|
+
validationPath: string;
|
|
144
|
+
/** Number of training examples */
|
|
145
|
+
trainCount: number;
|
|
146
|
+
/** Number of validation examples */
|
|
147
|
+
validationCount: number;
|
|
148
|
+
/** Total computed training steps */
|
|
149
|
+
totalSteps: number;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/** SoftDedup statistics */
|
|
153
|
+
softDedup: {
|
|
154
|
+
/** Whether SoftDedup was applied */
|
|
155
|
+
applied: boolean;
|
|
156
|
+
/** Mean sampling weight */
|
|
157
|
+
meanWeight: number;
|
|
158
|
+
/** Effective dataset size after reweighting */
|
|
159
|
+
effectiveSize: number;
|
|
160
|
+
/** Reduction ratio */
|
|
161
|
+
reductionRatio: number;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// =============================================================================
|
|
166
|
+
// INTEGRATION CONFIGURATION
|
|
167
|
+
// =============================================================================
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Configuration for the TrainingMonkey integration pipeline.
|
|
171
|
+
*/
|
|
172
|
+
export interface TrainingMonkeyIntegrationConfig {
|
|
173
|
+
/** Path to the input JSONL file */
|
|
174
|
+
inputPath: string;
|
|
175
|
+
|
|
176
|
+
/** Directory for output files */
|
|
177
|
+
outputDir: string;
|
|
178
|
+
|
|
179
|
+
/** Train/validation split ratio (default: 0.9 = 90% train) */
|
|
180
|
+
trainRatio: number;
|
|
181
|
+
|
|
182
|
+
/** Random seed for reproducible splits */
|
|
183
|
+
seed: number;
|
|
184
|
+
|
|
185
|
+
/** Whether to apply SoftDedup reweighting (default: true) */
|
|
186
|
+
enableSoftDedup: boolean;
|
|
187
|
+
|
|
188
|
+
/** Target model name for config generation (default: "qwen7b") */
|
|
189
|
+
modelName: string;
|
|
190
|
+
|
|
191
|
+
/** Whether to stratify the split by metadata fields (default: true) */
|
|
192
|
+
stratify: boolean;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Default configuration for TrainingMonkey integration.
|
|
197
|
+
*/
|
|
198
|
+
export const DEFAULT_INTEGRATION_CONFIG: TrainingMonkeyIntegrationConfig = {
|
|
199
|
+
inputPath: '',
|
|
200
|
+
outputDir: '',
|
|
201
|
+
trainRatio: 0.9,
|
|
202
|
+
seed: 42,
|
|
203
|
+
enableSoftDedup: true,
|
|
204
|
+
modelName: 'qwen7b',
|
|
205
|
+
stratify: true,
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// =============================================================================
|
|
209
|
+
// PIPELINE RESULT
|
|
210
|
+
// =============================================================================
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Complete result of running the TrainingMonkey integration pipeline.
|
|
214
|
+
*/
|
|
215
|
+
export interface IntegrationResult {
|
|
216
|
+
/** The dataset split (train/validation) */
|
|
217
|
+
split: DatasetSplit;
|
|
218
|
+
|
|
219
|
+
/** Generated training configuration */
|
|
220
|
+
config: TrainingMonkeyConfig;
|
|
221
|
+
|
|
222
|
+
/** Serialized train JSONL content */
|
|
223
|
+
trainJsonl: string;
|
|
224
|
+
|
|
225
|
+
/** Serialized validation JSONL content */
|
|
226
|
+
validationJsonl: string;
|
|
227
|
+
|
|
228
|
+
/** Serialized config JSON content */
|
|
229
|
+
configJson: string;
|
|
230
|
+
}
|