Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
484
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/README.md
vendored
Normal file
484
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/README.md
vendored
Normal file
@@ -0,0 +1,484 @@
|
||||
# Self-Learning System Examples
|
||||
|
||||
This directory contains comprehensive examples for generating synthetic data for self-learning AI systems, including reinforcement learning, feedback loops, and continual learning scenarios.
|
||||
|
||||
## Overview
|
||||
|
||||
These examples demonstrate how to use **agentic-synth** to generate training data for adaptive AI systems that learn continuously from experience and feedback.
|
||||
|
||||
## Files
|
||||
|
||||
### 1. `reinforcement-learning.ts`
|
||||
|
||||
Generates synthetic data for reinforcement learning systems.
|
||||
|
||||
**Key Features:**
|
||||
- State-Action-Reward (SAR) tuples for Q-learning
|
||||
- Complete episodes with temporal consistency
|
||||
- Exploration vs exploitation scenarios (multi-armed bandits)
|
||||
- Reward function testing data
|
||||
- Policy gradient training data
|
||||
- Multi-agent RL scenarios
|
||||
|
||||
**Examples:**
|
||||
```typescript
|
||||
import {
|
||||
generateSARTuples,
|
||||
generateEpisodes,
|
||||
generateExplorationData,
|
||||
generatePolicyGradientData,
|
||||
generateMultiAgentData
|
||||
} from './reinforcement-learning.js';
|
||||
|
||||
// Generate SAR tuples for Q-learning
|
||||
const sarData = await generateSARTuples();
|
||||
|
||||
// Generate complete episodes
|
||||
const episodes = await generateEpisodes();
|
||||
|
||||
// Generate exploration data
|
||||
const explorationData = await generateExplorationData();
|
||||
```
|
||||
|
||||
**Use Cases:**
|
||||
- Training RL agents (DQN, PPO, A3C, SAC)
|
||||
- Testing reward functions
|
||||
- Evaluating exploration strategies
|
||||
- Multi-agent coordination research
|
||||
|
||||
---
|
||||
|
||||
### 2. `feedback-loop.ts`
|
||||
|
||||
Generates data for self-improving systems with feedback mechanisms.
|
||||
|
||||
**Key Features:**
|
||||
- Quality scoring and automatic regeneration
|
||||
- A/B testing data for model comparison
|
||||
- Pattern learning from production data
|
||||
- Adaptive schema evolution
|
||||
- Active learning sample selection
|
||||
- Continuous model evaluation
|
||||
|
||||
**Examples:**
|
||||
```typescript
|
||||
import {
|
||||
qualityScoringLoop,
|
||||
abTestingData,
|
||||
patternLearningLoop,
|
||||
adaptiveSchemaEvolution,
|
||||
activeLearningData
|
||||
} from './feedback-loop.js';
|
||||
|
||||
// Generate and improve low-quality samples
|
||||
await qualityScoringLoop();
|
||||
|
||||
// Generate A/B test data
|
||||
const abTests = await abTestingData();
|
||||
|
||||
// Learn patterns from production
|
||||
const syntheticData = await patternLearningLoop();
|
||||
```
|
||||
|
||||
**Use Cases:**
|
||||
- Model improvement iterations
|
||||
- Quality assurance pipelines
|
||||
- Production data simulation
|
||||
- Active learning systems
|
||||
- Continuous integration/deployment
|
||||
|
||||
---
|
||||
|
||||
### 3. `continual-learning.ts`
|
||||
|
||||
Generates data for continual learning systems that adapt over time.
|
||||
|
||||
**Key Features:**
|
||||
- Incremental training data (multiple phases)
|
||||
- Domain adaptation (source → target)
|
||||
- Catastrophic forgetting prevention (replay buffers)
|
||||
- Transfer learning datasets (pre-training → fine-tuning)
|
||||
- Curriculum learning (easy → hard)
|
||||
- Online learning streams with concept drift
|
||||
|
||||
**Examples:**
|
||||
```typescript
|
||||
import {
|
||||
generateIncrementalData,
|
||||
generateDomainAdaptationData,
|
||||
generateAntiCatastrophicData,
|
||||
generateTransferLearningData,
|
||||
generateCurriculumData,
|
||||
generateOnlineLearningStream
|
||||
} from './continual-learning.js';
|
||||
|
||||
// Generate incremental training phases
|
||||
const phases = await generateIncrementalData();
|
||||
|
||||
// Generate domain adaptation data
|
||||
const { source, target, labeledTarget } = await generateDomainAdaptationData();
|
||||
|
||||
// Generate anti-forgetting data
|
||||
const { task1, task2, replay } = await generateAntiCatastrophicData();
|
||||
```
|
||||
|
||||
**Use Cases:**
|
||||
- Lifelong learning systems
|
||||
- Domain adaptation research
|
||||
- Transfer learning pipelines
|
||||
- Curriculum learning
|
||||
- Online/streaming learning
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
Ensure you have agentic-synth installed:
|
||||
|
||||
```bash
|
||||
npm install agentic-synth
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Set up your API key:
|
||||
|
||||
```bash
|
||||
# Gemini API (recommended)
|
||||
export GEMINI_API_KEY=your_api_key_here
|
||||
|
||||
# Or OpenRouter
|
||||
export OPENROUTER_API_KEY=your_api_key_here
|
||||
```
|
||||
|
||||
## Running Examples
|
||||
|
||||
### Run Individual Examples
|
||||
|
||||
```bash
|
||||
# Reinforcement learning examples
|
||||
npx tsx examples/self-learning/reinforcement-learning.ts
|
||||
|
||||
# Feedback loop examples
|
||||
npx tsx examples/self-learning/feedback-loop.ts
|
||||
|
||||
# Continual learning examples
|
||||
npx tsx examples/self-learning/continual-learning.ts
|
||||
```
|
||||
|
||||
### Run Specific Functions
|
||||
|
||||
```typescript
|
||||
import { generateSARTuples } from './reinforcement-learning.js';
|
||||
|
||||
// Run specific example
|
||||
await generateSARTuples();
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### 1. Training Loop Integration
|
||||
|
||||
```typescript
|
||||
import { createSynth } from 'agentic-synth';
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY,
|
||||
cacheStrategy: 'memory', // Cache for faster iterations
|
||||
});
|
||||
|
||||
// Generate training batch
|
||||
const batch = await synth.generateStructured({
|
||||
count: 1000,
|
||||
schema: {
|
||||
features: ['array of 10 numbers (0-1)'],
|
||||
label: 'number (0-4)',
|
||||
},
|
||||
});
|
||||
|
||||
// Use in training
|
||||
for (const sample of batch.data) {
|
||||
// Train model with sample.features and sample.label
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Quality-Based Regeneration
|
||||
|
||||
```typescript
|
||||
// Generate initial data
|
||||
const data = await synth.generateStructured({ count: 100, schema });
|
||||
|
||||
// Filter low-quality samples
|
||||
const lowQuality = data.data.filter(d => d.quality_score < 0.7);
|
||||
|
||||
// Regenerate with improved constraints
|
||||
const improved = await synth.generateStructured({
|
||||
count: lowQuality.length,
|
||||
schema: improvedSchema,
|
||||
constraints: ['quality_score should be >= 0.7', 'improve coherence'],
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Incremental Learning Pipeline
|
||||
|
||||
```typescript
|
||||
const phases = [];
|
||||
|
||||
// Generate multiple phases
|
||||
for (let phase = 1; phase <= 5; phase++) {
|
||||
const phaseData = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
phase: `number (${phase})`,
|
||||
features: { /* evolving features */ },
|
||||
label: 'number',
|
||||
},
|
||||
constraints: [`Bias toward new patterns in phase ${phase}`],
|
||||
});
|
||||
|
||||
phases.push(phaseData);
|
||||
|
||||
// Train model incrementally
|
||||
// model.train(phaseData.data);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Experience Replay
|
||||
|
||||
```typescript
|
||||
// Generate new task data
|
||||
const newTask = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: newTaskSchema,
|
||||
});
|
||||
|
||||
// Generate replay buffer from old task
|
||||
const replay = await synth.generateStructured({
|
||||
count: 50, // 25% of new data
|
||||
schema: oldTaskSchema,
|
||||
constraints: ['High importance samples', 'Diverse and difficult'],
|
||||
});
|
||||
|
||||
// Interleave for training
|
||||
const mixedBatch = [...newTask.data, ...replay.data];
|
||||
// model.train(shuffle(mixedBatch));
|
||||
```
|
||||
|
||||
## ML Framework Integration
|
||||
|
||||
### TensorFlow.js
|
||||
|
||||
```typescript
|
||||
import * as tf from '@tensorflow/tfjs';
|
||||
|
||||
const trainingData = await synth.generateStructured({
|
||||
count: 1000,
|
||||
schema: {
|
||||
features: ['array of 4 numbers (0-1)'],
|
||||
label: 'number (0 or 1)',
|
||||
},
|
||||
});
|
||||
|
||||
// Convert to tensors
|
||||
const xs = tf.tensor2d(trainingData.data.map(d => d.features));
|
||||
const ys = tf.tensor2d(trainingData.data.map(d => [d.label]));
|
||||
|
||||
// Train model
|
||||
await model.fit(xs, ys, { epochs: 100 });
|
||||
```
|
||||
|
||||
### PyTorch (via data export)
|
||||
|
||||
```typescript
|
||||
import { writeFileSync } from 'fs';
|
||||
|
||||
const data = await synth.generateStructured({
|
||||
count: 10000,
|
||||
schema: pytorchSchema,
|
||||
});
|
||||
|
||||
// Export as JSON for PyTorch DataLoader
|
||||
writeFileSync('training_data.json', JSON.stringify(data.data));
|
||||
```
|
||||
|
||||
```python
|
||||
# In Python
|
||||
import json
|
||||
import torch
|
||||
from torch.utils.data import Dataset, DataLoader
|
||||
|
||||
class SyntheticDataset(Dataset):
|
||||
def __init__(self, json_path):
|
||||
with open(json_path) as f:
|
||||
self.data = json.load(f)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.data)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
item = self.data[idx]
|
||||
return torch.tensor(item['features']), torch.tensor(item['label'])
|
||||
|
||||
dataset = SyntheticDataset('training_data.json')
|
||||
loader = DataLoader(dataset, batch_size=32, shuffle=True)
|
||||
```
|
||||
|
||||
### scikit-learn
|
||||
|
||||
```typescript
|
||||
const data = await synth.generateStructured({
|
||||
count: 500,
|
||||
schema: {
|
||||
feature1: 'number (0-100)',
|
||||
feature2: 'number (0-100)',
|
||||
feature3: 'number (0-100)',
|
||||
label: 'number (0 or 1)',
|
||||
},
|
||||
});
|
||||
|
||||
// Export for sklearn
|
||||
const X = data.data.map(d => [d.feature1, d.feature2, d.feature3]);
|
||||
const y = data.data.map(d => d.label);
|
||||
|
||||
console.log(JSON.stringify({ X, y }));
|
||||
```
|
||||
|
||||
## Advanced Use Cases
|
||||
|
||||
### 1. Curriculum Learning
|
||||
|
||||
Start with easy examples and gradually increase difficulty:
|
||||
|
||||
```typescript
|
||||
const curriculum = ['easy', 'medium', 'hard', 'expert'];
|
||||
|
||||
for (const level of curriculum) {
|
||||
const data = await generateCurriculumData(level);
|
||||
// Train model on current difficulty level
|
||||
await trainModel(data);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Domain Adaptation
|
||||
|
||||
Adapt from source domain to target domain:
|
||||
|
||||
```typescript
|
||||
// Pre-train on source domain
|
||||
const sourceData = await generateSourceDomain();
|
||||
await model.pretrain(sourceData);
|
||||
|
||||
// Fine-tune on small labeled target set
|
||||
const targetData = await generateLabeledTarget(count: 50);
|
||||
await model.finetune(targetData);
|
||||
```
|
||||
|
||||
### 3. Multi-Task Learning
|
||||
|
||||
Generate data for multiple related tasks:
|
||||
|
||||
```typescript
|
||||
const tasks = ['task1', 'task2', 'task3'];
|
||||
const taskData = {};
|
||||
|
||||
for (const task of tasks) {
|
||||
taskData[task] = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: taskSchemas[task],
|
||||
});
|
||||
}
|
||||
|
||||
// Train multi-task model
|
||||
await multiTaskModel.train(taskData);
|
||||
```
|
||||
|
||||
### 4. Meta-Learning (Learning to Learn)
|
||||
|
||||
Generate few-shot learning episodes:
|
||||
|
||||
```typescript
|
||||
const episodes = await synth.generateStructured({
|
||||
count: 100,
|
||||
schema: {
|
||||
support_set: [{ features: [], label: 'number' }],
|
||||
query_set: [{ features: [], label: 'number' }],
|
||||
task_id: 'UUID',
|
||||
},
|
||||
});
|
||||
|
||||
// Meta-train
|
||||
for (const episode of episodes.data) {
|
||||
await metalearner.adapt(episode.support_set);
|
||||
const loss = metalearner.evaluate(episode.query_set);
|
||||
metalearner.metaUpdate(loss);
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Use Caching**: Enable memory or disk caching for repeated generations
|
||||
```typescript
|
||||
const synth = createSynth({
|
||||
cacheStrategy: 'memory',
|
||||
cacheTTL: 3600, // 1 hour
|
||||
});
|
||||
```
|
||||
|
||||
2. **Batch Generation**: Generate multiple datasets in parallel
|
||||
```typescript
|
||||
const batches = await synth.generateBatch('structured', [
|
||||
{ count: 100, schema: schema1 },
|
||||
{ count: 100, schema: schema2 },
|
||||
{ count: 100, schema: schema3 },
|
||||
], 3); // 3 concurrent generations
|
||||
```
|
||||
|
||||
3. **Streaming**: Use streaming for large datasets
|
||||
```typescript
|
||||
for await (const sample of synth.generateStream('structured', options)) {
|
||||
// Process sample immediately
|
||||
processAndTrain(sample);
|
||||
}
|
||||
```
|
||||
|
||||
## Citation
|
||||
|
||||
If you use these examples in your research, please cite:
|
||||
|
||||
```bibtex
|
||||
@software{agentic_synth,
|
||||
title = {Agentic-Synth: AI-Powered Synthetic Data Generation},
|
||||
author = {Your Name},
|
||||
year = {2024},
|
||||
url = {https://github.com/yourusername/agentic-synth}
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please feel free to submit pull requests with:
|
||||
- New self-learning examples
|
||||
- Improved ML framework integrations
|
||||
- Performance optimizations
|
||||
- Bug fixes
|
||||
|
||||
## License
|
||||
|
||||
MIT License - see LICENSE file for details
|
||||
|
||||
## Support
|
||||
|
||||
- Documentation: [Main README](../../README.md)
|
||||
- Issues: [GitHub Issues](https://github.com/yourusername/agentic-synth/issues)
|
||||
- Discussions: [GitHub Discussions](https://github.com/yourusername/agentic-synth/discussions)
|
||||
|
||||
## Related Examples
|
||||
|
||||
- [Basic Usage](../basic-usage.ts) - Getting started with agentic-synth
|
||||
- [Integration Examples](../integration-examples.ts) - Framework integrations
|
||||
- [Benchmark Example](../benchmark-example.ts) - Performance testing
|
||||
|
||||
---
|
||||
|
||||
**Happy Learning!** 🚀🤖📈
|
||||
57
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/continual-learning.d.ts
vendored
Normal file
57
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/continual-learning.d.ts
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Continual Learning Dataset Generation
|
||||
*
|
||||
* This example demonstrates:
|
||||
* - Incremental training data generation
|
||||
* - Domain adaptation scenarios
|
||||
* - Catastrophic forgetting prevention data
|
||||
* - Transfer learning datasets
|
||||
*/
|
||||
import type { GenerationResult } from '../../src/types.js';
|
||||
/**
|
||||
* Generate incremental training batches for continual learning
|
||||
*/
|
||||
export declare function generateIncrementalData(): Promise<GenerationResult<unknown>[]>;
|
||||
/**
|
||||
* Generate source and target domain data for domain adaptation
|
||||
*/
|
||||
export declare function generateDomainAdaptationData(): Promise<{
|
||||
source: GenerationResult<unknown>;
|
||||
target: GenerationResult<unknown>;
|
||||
labeledTarget: GenerationResult<unknown>;
|
||||
}>;
|
||||
/**
|
||||
* Generate replay buffer and interleaved training data
|
||||
*/
|
||||
export declare function generateAntiCatastrophicData(): Promise<{
|
||||
task1: GenerationResult<unknown>;
|
||||
task2: GenerationResult<unknown>;
|
||||
replay: GenerationResult<unknown>;
|
||||
interleaved: GenerationResult<unknown>;
|
||||
}>;
|
||||
/**
|
||||
* Generate pre-training and fine-tuning datasets
|
||||
*/
|
||||
export declare function generateTransferLearningData(): Promise<{
|
||||
pretraining: GenerationResult<unknown>;
|
||||
finetuning: GenerationResult<unknown>;
|
||||
fewShot: GenerationResult<unknown>;
|
||||
}>;
|
||||
/**
|
||||
* Generate data organized by difficulty for curriculum learning
|
||||
*/
|
||||
export declare function generateCurriculumData(): Promise<{
|
||||
stage: number;
|
||||
difficulty: string;
|
||||
data: GenerationResult<unknown>;
|
||||
}[]>;
|
||||
/**
|
||||
* Generate streaming data for online learning
|
||||
*/
|
||||
export declare function generateOnlineLearningStream(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Demonstrate complete continual learning pipeline
|
||||
*/
|
||||
export declare function completeContinualLearningPipeline(): Promise<void>;
|
||||
export declare function runAllContinualLearningExamples(): Promise<void>;
|
||||
//# sourceMappingURL=continual-learning.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"continual-learning.d.ts","sourceRoot":"","sources":["continual-learning.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAM3D;;GAEG;AACH,wBAAsB,uBAAuB,yCA8D5C;AAMD;;GAEG;AACH,wBAAsB,4BAA4B;;;;GA6HjD;AAMD;;GAEG;AACH,wBAAsB,4BAA4B;;;;;GAsIjD;AAMD;;GAEG;AACH,wBAAsB,4BAA4B;;;;GAmHjD;AAMD;;GAEG;AACH,wBAAsB,sBAAsB;;;;KAoE3C;AAMD;;GAEG;AACH,wBAAsB,4BAA4B,uCA0DjD;AA6BD;;GAEG;AACH,wBAAsB,iCAAiC,kBA2BtD;AAMD,wBAAsB,+BAA+B,kBA2BpD"}
|
||||
591
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/continual-learning.js
vendored
Normal file
591
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/continual-learning.js
vendored
Normal file
@@ -0,0 +1,591 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Continual Learning Dataset Generation
|
||||
*
|
||||
* This example demonstrates:
|
||||
* - Incremental training data generation
|
||||
* - Domain adaptation scenarios
|
||||
* - Catastrophic forgetting prevention data
|
||||
* - Transfer learning datasets
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.generateIncrementalData = generateIncrementalData;
|
||||
exports.generateDomainAdaptationData = generateDomainAdaptationData;
|
||||
exports.generateAntiCatastrophicData = generateAntiCatastrophicData;
|
||||
exports.generateTransferLearningData = generateTransferLearningData;
|
||||
exports.generateCurriculumData = generateCurriculumData;
|
||||
exports.generateOnlineLearningStream = generateOnlineLearningStream;
|
||||
exports.completeContinualLearningPipeline = completeContinualLearningPipeline;
|
||||
exports.runAllContinualLearningExamples = runAllContinualLearningExamples;
|
||||
const index_js_1 = require("../../src/index.js");
|
||||
// ============================================================================
|
||||
// Example 1: Incremental Training Data
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate incremental training batches for continual learning
|
||||
*/
|
||||
async function generateIncrementalData() {
|
||||
console.log('\n📈 Example 1: Incremental Training Data\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
cacheStrategy: 'memory',
|
||||
});
|
||||
// Generate data for multiple training phases
|
||||
const phases = [];
|
||||
for (let phase = 1; phase <= 5; phase++) {
|
||||
console.log(`\nGenerating Phase ${phase} data...`);
|
||||
const phaseData = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
phase: `number (${phase})`,
|
||||
// Features (gradually evolving)
|
||||
features: {
|
||||
core_feature_1: 'number (0-100)',
|
||||
core_feature_2: 'number (0-100)',
|
||||
// New features introduced in later phases
|
||||
phase_specific_feature: `number (0-100) or null (null if phase < ${Math.min(phase + 1, 3)})`,
|
||||
evolving_feature: `number (${phase * 10}-${(phase + 1) * 10})`,
|
||||
},
|
||||
// Label (distribution shifts over phases)
|
||||
label: 'number (0-4)',
|
||||
label_distribution_bias: `number (${phase - 1}-${phase}, bias toward class ${phase - 1})`,
|
||||
// Data characteristics
|
||||
noise_level: `number (${0.05 * phase}-${0.05 * (phase + 1)}, increasing noise)`,
|
||||
difficulty: 'easy | medium | hard',
|
||||
// Metadata
|
||||
timestamp: 'ISO timestamp',
|
||||
data_source: `source_${phase}`,
|
||||
},
|
||||
constraints: [
|
||||
`Label distribution should be biased toward class ${phase - 1}`,
|
||||
'Noise level should increase with phase number',
|
||||
'Difficulty should vary across phases',
|
||||
'phase_specific_feature should be null for early phases',
|
||||
],
|
||||
});
|
||||
console.log(` - Generated ${phaseData.data.length} samples`);
|
||||
console.log(` - Avg noise level: ${calculateAverage(phaseData.data, 'noise_level').toFixed(3)}`);
|
||||
console.log(` - Label distribution:`, getLabelDistribution(phaseData.data));
|
||||
phases.push(phaseData);
|
||||
}
|
||||
console.log('\n✅ Incremental data generation complete');
|
||||
console.log(`Total phases: ${phases.length}`);
|
||||
console.log(`Total samples: ${phases.reduce((sum, p) => sum + p.data.length, 0)}`);
|
||||
return phases;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 2: Domain Adaptation Scenarios
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate source and target domain data for domain adaptation
|
||||
*/
|
||||
async function generateDomainAdaptationData() {
|
||||
console.log('\n🌍 Example 2: Domain Adaptation Data\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Source domain: Product reviews from electronics
|
||||
console.log('Generating source domain data (Electronics Reviews)...');
|
||||
const sourceData = await synth.generateStructured({
|
||||
count: 300,
|
||||
schema: {
|
||||
review_id: 'UUID',
|
||||
domain: 'string (source_electronics)',
|
||||
// Text data
|
||||
review_text: 'product review for electronics (2-4 sentences)',
|
||||
sentiment: 'positive | negative | neutral',
|
||||
// Domain-specific features
|
||||
domain_features: {
|
||||
mentions_battery: 'boolean',
|
||||
mentions_screen: 'boolean',
|
||||
mentions_performance: 'boolean',
|
||||
technical_terms_count: 'number (0-10)',
|
||||
},
|
||||
// Labels
|
||||
rating: 'number (1-5)',
|
||||
helpful_votes: 'number (0-100)',
|
||||
// Feature representation
|
||||
feature_vector: ['array of 50 numbers (0-1, embedding)'],
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Sentiment should correlate with rating',
|
||||
'Technical terms should be common (avg 3-5)',
|
||||
'Electronics-specific vocabulary',
|
||||
],
|
||||
});
|
||||
console.log(` - Source samples: ${sourceData.data.length}`);
|
||||
console.log(` - Avg rating: ${calculateAverage(sourceData.data, 'rating').toFixed(2)}`);
|
||||
// Target domain: Product reviews from home goods (different distribution)
|
||||
console.log('\nGenerating target domain data (Home Goods Reviews)...');
|
||||
const targetData = await synth.generateStructured({
|
||||
count: 300,
|
||||
schema: {
|
||||
review_id: 'UUID',
|
||||
domain: 'string (target_home_goods)',
|
||||
// Text data
|
||||
review_text: 'product review for home goods/furniture (2-4 sentences)',
|
||||
sentiment: 'positive | negative | neutral',
|
||||
// Domain-specific features (different from source)
|
||||
domain_features: {
|
||||
mentions_comfort: 'boolean',
|
||||
mentions_quality: 'boolean',
|
||||
mentions_design: 'boolean',
|
||||
technical_terms_count: 'number (0-3, fewer technical terms)',
|
||||
},
|
||||
// Labels (same task, different domain)
|
||||
rating: 'number (1-5)',
|
||||
helpful_votes: 'number (0-100)',
|
||||
// Feature representation (different distribution)
|
||||
feature_vector: ['array of 50 numbers (0-1, embedding with distribution shift)'],
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Sentiment should correlate with rating',
|
||||
'Fewer technical terms than source domain',
|
||||
'Home goods-specific vocabulary',
|
||||
'Feature vectors should have different distribution than source',
|
||||
],
|
||||
});
|
||||
console.log(` - Target samples: ${targetData.data.length}`);
|
||||
console.log(` - Avg rating: ${calculateAverage(targetData.data, 'rating').toFixed(2)}`);
|
||||
// Generate small labeled target set for adaptation
|
||||
console.log('\nGenerating labeled target samples for adaptation...');
|
||||
const labeledTargetData = await synth.generateStructured({
|
||||
count: 50, // Small labeled set
|
||||
schema: {
|
||||
review_id: 'UUID',
|
||||
domain: 'string (target_home_goods_labeled)',
|
||||
review_text: 'product review for home goods/furniture (2-4 sentences)',
|
||||
sentiment: 'positive | negative | neutral',
|
||||
domain_features: {
|
||||
mentions_comfort: 'boolean',
|
||||
mentions_quality: 'boolean',
|
||||
mentions_design: 'boolean',
|
||||
technical_terms_count: 'number (0-3)',
|
||||
},
|
||||
rating: 'number (1-5)',
|
||||
helpful_votes: 'number (0-100)',
|
||||
feature_vector: ['array of 50 numbers (0-1)'],
|
||||
// Adaptation metadata
|
||||
used_for_adaptation: 'boolean (true)',
|
||||
similarity_to_source: 'number (0-1, measure of domain similarity)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
});
|
||||
console.log(` - Labeled target samples: ${labeledTargetData.data.length}`);
|
||||
console.log('\n✅ Domain adaptation data generated');
|
||||
return {
|
||||
source: sourceData,
|
||||
target: targetData,
|
||||
labeledTarget: labeledTargetData,
|
||||
};
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 3: Catastrophic Forgetting Prevention Data
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate replay buffer and interleaved training data
|
||||
*/
|
||||
async function generateAntiCatastrophicData() {
|
||||
console.log('\n🧠 Example 3: Catastrophic Forgetting Prevention\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Task 1: Image classification (animals)
|
||||
console.log('Generating Task 1 data (Animal Classification)...');
|
||||
const task1Data = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
task_id: 'number (1)',
|
||||
task_name: 'string (animal_classification)',
|
||||
// Image features (simulated)
|
||||
image_features: ['array of 100 numbers (0-1, CNN features)'],
|
||||
// Labels
|
||||
category: 'cat | dog | bird | fish',
|
||||
subcategory: 'specific breed or species',
|
||||
// Importance for replay
|
||||
importance_score: 'number (0-1, for experience replay)',
|
||||
difficulty: 'number (0-1)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
});
|
||||
console.log(` - Task 1 samples: ${task1Data.data.length}`);
|
||||
// Task 2: Image classification (vehicles) - New task
|
||||
console.log('\nGenerating Task 2 data (Vehicle Classification)...');
|
||||
const task2Data = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
task_id: 'number (2)',
|
||||
task_name: 'string (vehicle_classification)',
|
||||
// Image features (different distribution)
|
||||
image_features: ['array of 100 numbers (0-1, CNN features)'],
|
||||
// Labels (different classes)
|
||||
category: 'car | truck | motorcycle | bicycle',
|
||||
subcategory: 'specific model or type',
|
||||
importance_score: 'number (0-1)',
|
||||
difficulty: 'number (0-1)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
});
|
||||
console.log(` - Task 2 samples: ${task2Data.data.length}`);
|
||||
// Generate replay buffer (selected samples from Task 1)
|
||||
console.log('\nGenerating replay buffer...');
|
||||
const replayBuffer = await synth.generateStructured({
|
||||
count: 50, // 25% of Task 1
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
task_id: 'number (1)',
|
||||
task_name: 'string (animal_classification)',
|
||||
image_features: ['array of 100 numbers (0-1)'],
|
||||
category: 'cat | dog | bird | fish',
|
||||
subcategory: 'specific breed or species',
|
||||
// Replay metadata
|
||||
importance_score: 'number (0.5-1.0, high importance)',
|
||||
replay_count: 'number (0-5)',
|
||||
last_replayed: 'ISO timestamp',
|
||||
is_replay_sample: 'boolean (true)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'importance_score should be high (>0.5)',
|
||||
'Select diverse and difficult samples for replay',
|
||||
],
|
||||
});
|
||||
console.log(` - Replay buffer size: ${replayBuffer.data.length}`);
|
||||
// Generate interleaved training data
|
||||
console.log('\nGenerating interleaved training batches...');
|
||||
const interleavedBatch = await synth.generateStructured({
|
||||
count: 100,
|
||||
schema: {
|
||||
batch_id: 'UUID',
|
||||
batch_number: 'number (1-20)',
|
||||
// Mix of Task 2 (new) and Task 1 (replay)
|
||||
samples: [
|
||||
{
|
||||
sample_id: 'UUID',
|
||||
task_id: 'number (1 or 2)',
|
||||
is_replay: 'boolean (true for task_id=1)',
|
||||
features: ['array of 100 numbers'],
|
||||
label: 'string',
|
||||
},
|
||||
],
|
||||
// Batch composition
|
||||
task1_ratio: 'number (0.2-0.3, 20-30% replay)',
|
||||
task2_ratio: 'number (0.7-0.8, 70-80% new task)',
|
||||
// Forgetting metrics
|
||||
task1_performance_estimate: 'number (0.7-0.95, should stay high)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Each batch should contain 20-30% Task 1 samples (replay)',
|
||||
'Replay samples should maintain Task 1 performance',
|
||||
],
|
||||
});
|
||||
console.log(` - Interleaved batches: ${interleavedBatch.data.length}`);
|
||||
console.log('\n✅ Anti-catastrophic forgetting data generated');
|
||||
return {
|
||||
task1: task1Data,
|
||||
task2: task2Data,
|
||||
replay: replayBuffer,
|
||||
interleaved: interleavedBatch,
|
||||
};
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 4: Transfer Learning Datasets
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate pre-training and fine-tuning datasets
|
||||
*/
|
||||
async function generateTransferLearningData() {
|
||||
console.log('\n🔄 Example 4: Transfer Learning Datasets\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Pre-training data: Large, general dataset
|
||||
console.log('Generating pre-training data (General Text)...');
|
||||
const pretrainingData = await synth.generateStructured({
|
||||
count: 1000,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
stage: 'string (pretraining)',
|
||||
// General text data
|
||||
text: 'general text passage (3-5 sentences)',
|
||||
domain: 'news | wikipedia | books | web',
|
||||
// Self-supervised labels
|
||||
masked_tokens: ['array of masked token positions'],
|
||||
next_sentence_label: 'boolean (is next sentence)',
|
||||
// Features
|
||||
embedding: ['array of 768 numbers (transformer embedding)'],
|
||||
token_count: 'number (50-200)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Diverse domains and topics',
|
||||
'General language patterns',
|
||||
'High-quality, grammatical text',
|
||||
],
|
||||
});
|
||||
console.log(` - Pre-training samples: ${pretrainingData.data.length}`);
|
||||
// Fine-tuning data: Smaller, task-specific dataset
|
||||
console.log('\nGenerating fine-tuning data (Sentiment Analysis)...');
|
||||
const finetuningData = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
stage: 'string (finetuning)',
|
||||
// Task-specific text
|
||||
text: 'product or movie review (2-4 sentences)',
|
||||
domain: 'string (reviews)',
|
||||
// Supervised labels
|
||||
sentiment: 'positive | negative | neutral',
|
||||
confidence: 'number (0-1)',
|
||||
// Features (initialized from pre-trained model)
|
||||
embedding: ['array of 768 numbers (fine-tuned embedding)'],
|
||||
token_count: 'number (30-150)',
|
||||
// Fine-tuning metadata
|
||||
learning_phase: 'early | middle | late',
|
||||
layer_to_finetune: 'all | last_2 | last_4 | classifier_only',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Domain-specific vocabulary',
|
||||
'Clear sentiment labels',
|
||||
'Smaller dataset than pre-training',
|
||||
],
|
||||
});
|
||||
console.log(` - Fine-tuning samples: ${finetuningData.data.length}`);
|
||||
// Generate few-shot learning data
|
||||
console.log('\nGenerating few-shot learning data...');
|
||||
const fewShotData = await synth.generateStructured({
|
||||
count: 50, // Very small
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
stage: 'string (few_shot)',
|
||||
// Task-specific examples
|
||||
text: 'specialized domain text (legal, medical, technical)',
|
||||
domain: 'legal | medical | scientific',
|
||||
// Labels
|
||||
category: 'specialized category',
|
||||
requires_expertise: 'boolean (true)',
|
||||
// Few-shot metadata
|
||||
support_set: 'boolean (used as few-shot example)',
|
||||
shot_number: 'number (1-5, which shot in few-shot set)',
|
||||
embedding: ['array of 768 numbers'],
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Highly specialized domain',
|
||||
'Very limited samples (few-shot)',
|
||||
'Clear, prototypical examples',
|
||||
],
|
||||
});
|
||||
console.log(` - Few-shot samples: ${fewShotData.data.length}`);
|
||||
console.log('\n✅ Transfer learning data generated');
|
||||
console.log('Data pipeline: Pre-training → Fine-tuning → Few-shot');
|
||||
return {
|
||||
pretraining: pretrainingData,
|
||||
finetuning: finetuningData,
|
||||
fewShot: fewShotData,
|
||||
};
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 5: Curriculum Learning Data
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate data organized by difficulty for curriculum learning
|
||||
*/
|
||||
async function generateCurriculumData() {
|
||||
console.log('\n🎓 Example 5: Curriculum Learning Data\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
const difficulties = ['easy', 'medium', 'hard', 'expert'];
|
||||
const curriculum = [];
|
||||
for (const difficulty of difficulties) {
|
||||
console.log(`\nGenerating ${difficulty} difficulty data...`);
|
||||
const difficultyData = await synth.generateStructured({
|
||||
count: 150,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
difficulty_level: `string (${difficulty})`,
|
||||
curriculum_stage: `number (${difficulties.indexOf(difficulty) + 1})`,
|
||||
// Math problem (example task)
|
||||
problem: {
|
||||
question: `math word problem (${difficulty} difficulty)`,
|
||||
steps_required: `number (${difficulties.indexOf(difficulty) + 1}-${difficulties.indexOf(difficulty) + 3})`,
|
||||
concepts: [`array of ${difficulties.indexOf(difficulty) + 1}-${difficulties.indexOf(difficulty) + 2} math concepts`],
|
||||
},
|
||||
// Solution
|
||||
solution: {
|
||||
answer: 'correct numerical answer',
|
||||
explanation: 'step-by-step solution',
|
||||
intermediate_steps: ['array of solution steps'],
|
||||
},
|
||||
// Difficulty metrics
|
||||
estimated_time_seconds: `number (${(difficulties.indexOf(difficulty) + 1) * 30}-${(difficulties.indexOf(difficulty) + 2) * 30})`,
|
||||
concept_complexity: `number (${difficulties.indexOf(difficulty) + 1}-${difficulties.indexOf(difficulty) + 2})`,
|
||||
prerequisite_skills: [`array of required skills (more for harder problems)`],
|
||||
// Learning metadata
|
||||
success_rate_expected: `number (${0.9 - difficulties.indexOf(difficulty) * 0.15}-${0.95 - difficulties.indexOf(difficulty) * 0.15})`,
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
`Problems should be ${difficulty} difficulty`,
|
||||
'Success rate should decrease with difficulty',
|
||||
'More concepts required for harder problems',
|
||||
'Prerequisite skills accumulate',
|
||||
],
|
||||
});
|
||||
console.log(` - ${difficulty} samples: ${difficultyData.data.length}`);
|
||||
console.log(` - Avg steps: ${calculateAverage(difficultyData.data, (d) => d.problem.steps_required)}`);
|
||||
curriculum.push({
|
||||
stage: difficulties.indexOf(difficulty) + 1,
|
||||
difficulty,
|
||||
data: difficultyData,
|
||||
});
|
||||
}
|
||||
console.log('\n✅ Curriculum learning data generated');
|
||||
console.log(`Curriculum stages: ${curriculum.length}`);
|
||||
console.log('Learning progression: easy → medium → hard → expert');
|
||||
return curriculum;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 6: Online Learning Stream
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate streaming data for online learning
|
||||
*/
|
||||
async function generateOnlineLearningStream() {
|
||||
console.log('\n📡 Example 6: Online Learning Stream\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Generate time-series data stream
|
||||
const streamData = await synth.generateTimeSeries({
|
||||
count: 500, // 500 time points
|
||||
interval: '1m', // One sample per minute
|
||||
schema: {
|
||||
timestamp: 'ISO timestamp',
|
||||
sequence_number: 'number (sequential)',
|
||||
// Incoming data point
|
||||
features: ['array of 20 numbers (0-1)'],
|
||||
label: 'number (0-4)',
|
||||
// Distribution characteristics
|
||||
distribution_shift: 'number (0-1, gradual increase over time)',
|
||||
concept_drift_indicator: 'boolean',
|
||||
// Model state
|
||||
current_model_accuracy: 'number (0.7-0.95, may degrade over time)',
|
||||
should_update_model: 'boolean (true if drift detected)',
|
||||
// Online learning metadata
|
||||
learning_rate: 'number (0.0001-0.01)',
|
||||
update_applied: 'boolean',
|
||||
samples_since_update: 'number (0-100)',
|
||||
// Performance tracking
|
||||
prediction_error: 'number (0-1)',
|
||||
cumulative_regret: 'number (increasing)',
|
||||
},
|
||||
trend: 'stable',
|
||||
seasonality: false,
|
||||
constraints: [
|
||||
'Distribution shift should gradually increase',
|
||||
'Model accuracy should correlate inversely with drift',
|
||||
'should_update_model when accuracy drops or drift detected',
|
||||
'cumulative_regret increases when predictions are wrong',
|
||||
],
|
||||
});
|
||||
const driftPoints = streamData.data.filter((d) => d.concept_drift_indicator);
|
||||
console.log('Online Learning Stream:');
|
||||
console.log(`- Stream length: ${streamData.data.length} samples`);
|
||||
console.log(`- Concept drift points: ${driftPoints.length}`);
|
||||
console.log(`- Avg accuracy: ${calculateAverage(streamData.data, 'current_model_accuracy').toFixed(3)}`);
|
||||
console.log(`- Model updates: ${streamData.data.filter((d) => d.update_applied).length}`);
|
||||
console.log('\n✅ Online learning stream generated');
|
||||
return streamData;
|
||||
}
|
||||
// ============================================================================
|
||||
// Utility Functions
|
||||
// ============================================================================
|
||||
function calculateAverage(data, field) {
|
||||
const values = typeof field === 'string'
|
||||
? data.map((d) => d[field]).filter((v) => typeof v === 'number')
|
||||
: data.map(field).filter((v) => typeof v === 'number');
|
||||
if (values.length === 0)
|
||||
return 0;
|
||||
return values.reduce((a, b) => a + b, 0) / values.length;
|
||||
}
|
||||
function getLabelDistribution(data) {
|
||||
const dist = {};
|
||||
data.forEach((d) => {
|
||||
const label = d.label.toString();
|
||||
dist[label] = (dist[label] || 0) + 1;
|
||||
});
|
||||
return dist;
|
||||
}
|
||||
// ============================================================================
|
||||
// Complete Continual Learning Pipeline
|
||||
// ============================================================================
|
||||
/**
|
||||
* Demonstrate complete continual learning pipeline
|
||||
*/
|
||||
async function completeContinualLearningPipeline() {
|
||||
console.log('\n🚀 Complete Continual Learning Pipeline\n');
|
||||
console.log('='.repeat(60));
|
||||
console.log('\nStage 1: Initial Training with Curriculum');
|
||||
const curriculum = await generateCurriculumData();
|
||||
console.log('\nStage 2: Domain Adaptation');
|
||||
const domainData = await generateDomainAdaptationData();
|
||||
console.log('\nStage 3: Incremental Learning');
|
||||
const incrementalData = await generateIncrementalData();
|
||||
console.log('\nStage 4: Catastrophic Forgetting Prevention');
|
||||
const antiForgetData = await generateAntiCatastrophicData();
|
||||
console.log('\nStage 5: Online Learning');
|
||||
const onlineData = await generateOnlineLearningStream();
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('✅ Complete continual learning pipeline executed');
|
||||
console.log('\nPipeline Summary:');
|
||||
console.log(' 1. Curriculum Learning (easy → hard)');
|
||||
console.log(' 2. Domain Adaptation (source → target)');
|
||||
console.log(' 3. Incremental Learning (phase 1 → phase N)');
|
||||
console.log(' 4. Experience Replay (prevent forgetting)');
|
||||
console.log(' 5. Online Learning (continuous stream)');
|
||||
}
|
||||
// ============================================================================
|
||||
// Run All Examples
|
||||
// ============================================================================
|
||||
async function runAllContinualLearningExamples() {
|
||||
console.log('🎯 Continual Learning Dataset Generation\n');
|
||||
console.log('='.repeat(60));
|
||||
try {
|
||||
await generateIncrementalData();
|
||||
console.log('='.repeat(60));
|
||||
await generateDomainAdaptationData();
|
||||
console.log('='.repeat(60));
|
||||
await generateAntiCatastrophicData();
|
||||
console.log('='.repeat(60));
|
||||
await generateTransferLearningData();
|
||||
console.log('='.repeat(60));
|
||||
await generateCurriculumData();
|
||||
console.log('='.repeat(60));
|
||||
await generateOnlineLearningStream();
|
||||
console.log('='.repeat(60));
|
||||
console.log('\n✅ All continual learning examples completed!\n');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('❌ Error:', error.message);
|
||||
}
|
||||
}
|
||||
// Run if executed directly
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runAllContinualLearningExamples().catch(console.error);
|
||||
}
|
||||
//# sourceMappingURL=continual-learning.js.map
|
||||
1
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/continual-learning.js.map
vendored
Normal file
1
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/continual-learning.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
725
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/continual-learning.ts
vendored
Normal file
725
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/continual-learning.ts
vendored
Normal file
@@ -0,0 +1,725 @@
|
||||
/**
|
||||
* Continual Learning Dataset Generation
|
||||
*
|
||||
* This example demonstrates:
|
||||
* - Incremental training data generation
|
||||
* - Domain adaptation scenarios
|
||||
* - Catastrophic forgetting prevention data
|
||||
* - Transfer learning datasets
|
||||
*/
|
||||
|
||||
import { AgenticSynth, createSynth } from '../../src/index.js';
|
||||
import type { GenerationResult } from '../../src/types.js';
|
||||
|
||||
// ============================================================================
|
||||
// Example 1: Incremental Training Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate incremental training batches for continual learning
|
||||
*/
|
||||
export async function generateIncrementalData() {
|
||||
console.log('\n📈 Example 1: Incremental Training Data\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
cacheStrategy: 'memory',
|
||||
});
|
||||
|
||||
// Generate data for multiple training phases
|
||||
const phases = [];
|
||||
|
||||
for (let phase = 1; phase <= 5; phase++) {
|
||||
console.log(`\nGenerating Phase ${phase} data...`);
|
||||
|
||||
const phaseData = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
phase: `number (${phase})`,
|
||||
|
||||
// Features (gradually evolving)
|
||||
features: {
|
||||
core_feature_1: 'number (0-100)',
|
||||
core_feature_2: 'number (0-100)',
|
||||
// New features introduced in later phases
|
||||
phase_specific_feature: `number (0-100) or null (null if phase < ${Math.min(phase + 1, 3)})`,
|
||||
evolving_feature: `number (${phase * 10}-${(phase + 1) * 10})`,
|
||||
},
|
||||
|
||||
// Label (distribution shifts over phases)
|
||||
label: 'number (0-4)',
|
||||
label_distribution_bias: `number (${phase - 1}-${phase}, bias toward class ${phase - 1})`,
|
||||
|
||||
// Data characteristics
|
||||
noise_level: `number (${0.05 * phase}-${0.05 * (phase + 1)}, increasing noise)`,
|
||||
difficulty: 'easy | medium | hard',
|
||||
|
||||
// Metadata
|
||||
timestamp: 'ISO timestamp',
|
||||
data_source: `source_${phase}`,
|
||||
},
|
||||
constraints: [
|
||||
`Label distribution should be biased toward class ${phase - 1}`,
|
||||
'Noise level should increase with phase number',
|
||||
'Difficulty should vary across phases',
|
||||
'phase_specific_feature should be null for early phases',
|
||||
],
|
||||
});
|
||||
|
||||
console.log(` - Generated ${phaseData.data.length} samples`);
|
||||
console.log(` - Avg noise level: ${calculateAverage(phaseData.data, 'noise_level').toFixed(3)}`);
|
||||
console.log(` - Label distribution:`, getLabelDistribution(phaseData.data));
|
||||
|
||||
phases.push(phaseData);
|
||||
}
|
||||
|
||||
console.log('\n✅ Incremental data generation complete');
|
||||
console.log(`Total phases: ${phases.length}`);
|
||||
console.log(`Total samples: ${phases.reduce((sum, p) => sum + p.data.length, 0)}`);
|
||||
|
||||
return phases;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 2: Domain Adaptation Scenarios
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate source and target domain data for domain adaptation
|
||||
*/
|
||||
export async function generateDomainAdaptationData() {
|
||||
console.log('\n🌍 Example 2: Domain Adaptation Data\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Source domain: Product reviews from electronics
|
||||
console.log('Generating source domain data (Electronics Reviews)...');
|
||||
const sourceData = await synth.generateStructured({
|
||||
count: 300,
|
||||
schema: {
|
||||
review_id: 'UUID',
|
||||
domain: 'string (source_electronics)',
|
||||
|
||||
// Text data
|
||||
review_text: 'product review for electronics (2-4 sentences)',
|
||||
sentiment: 'positive | negative | neutral',
|
||||
|
||||
// Domain-specific features
|
||||
domain_features: {
|
||||
mentions_battery: 'boolean',
|
||||
mentions_screen: 'boolean',
|
||||
mentions_performance: 'boolean',
|
||||
technical_terms_count: 'number (0-10)',
|
||||
},
|
||||
|
||||
// Labels
|
||||
rating: 'number (1-5)',
|
||||
helpful_votes: 'number (0-100)',
|
||||
|
||||
// Feature representation
|
||||
feature_vector: ['array of 50 numbers (0-1, embedding)'],
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Sentiment should correlate with rating',
|
||||
'Technical terms should be common (avg 3-5)',
|
||||
'Electronics-specific vocabulary',
|
||||
],
|
||||
});
|
||||
|
||||
console.log(` - Source samples: ${sourceData.data.length}`);
|
||||
console.log(` - Avg rating: ${calculateAverage(sourceData.data, 'rating').toFixed(2)}`);
|
||||
|
||||
// Target domain: Product reviews from home goods (different distribution)
|
||||
console.log('\nGenerating target domain data (Home Goods Reviews)...');
|
||||
const targetData = await synth.generateStructured({
|
||||
count: 300,
|
||||
schema: {
|
||||
review_id: 'UUID',
|
||||
domain: 'string (target_home_goods)',
|
||||
|
||||
// Text data
|
||||
review_text: 'product review for home goods/furniture (2-4 sentences)',
|
||||
sentiment: 'positive | negative | neutral',
|
||||
|
||||
// Domain-specific features (different from source)
|
||||
domain_features: {
|
||||
mentions_comfort: 'boolean',
|
||||
mentions_quality: 'boolean',
|
||||
mentions_design: 'boolean',
|
||||
technical_terms_count: 'number (0-3, fewer technical terms)',
|
||||
},
|
||||
|
||||
// Labels (same task, different domain)
|
||||
rating: 'number (1-5)',
|
||||
helpful_votes: 'number (0-100)',
|
||||
|
||||
// Feature representation (different distribution)
|
||||
feature_vector: ['array of 50 numbers (0-1, embedding with distribution shift)'],
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Sentiment should correlate with rating',
|
||||
'Fewer technical terms than source domain',
|
||||
'Home goods-specific vocabulary',
|
||||
'Feature vectors should have different distribution than source',
|
||||
],
|
||||
});
|
||||
|
||||
console.log(` - Target samples: ${targetData.data.length}`);
|
||||
console.log(` - Avg rating: ${calculateAverage(targetData.data, 'rating').toFixed(2)}`);
|
||||
|
||||
// Generate small labeled target set for adaptation
|
||||
console.log('\nGenerating labeled target samples for adaptation...');
|
||||
const labeledTargetData = await synth.generateStructured({
|
||||
count: 50, // Small labeled set
|
||||
schema: {
|
||||
review_id: 'UUID',
|
||||
domain: 'string (target_home_goods_labeled)',
|
||||
review_text: 'product review for home goods/furniture (2-4 sentences)',
|
||||
sentiment: 'positive | negative | neutral',
|
||||
|
||||
domain_features: {
|
||||
mentions_comfort: 'boolean',
|
||||
mentions_quality: 'boolean',
|
||||
mentions_design: 'boolean',
|
||||
technical_terms_count: 'number (0-3)',
|
||||
},
|
||||
|
||||
rating: 'number (1-5)',
|
||||
helpful_votes: 'number (0-100)',
|
||||
feature_vector: ['array of 50 numbers (0-1)'],
|
||||
|
||||
// Adaptation metadata
|
||||
used_for_adaptation: 'boolean (true)',
|
||||
similarity_to_source: 'number (0-1, measure of domain similarity)',
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
});
|
||||
|
||||
console.log(` - Labeled target samples: ${labeledTargetData.data.length}`);
|
||||
|
||||
console.log('\n✅ Domain adaptation data generated');
|
||||
|
||||
return {
|
||||
source: sourceData,
|
||||
target: targetData,
|
||||
labeledTarget: labeledTargetData,
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 3: Catastrophic Forgetting Prevention Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate replay buffer and interleaved training data
|
||||
*/
|
||||
export async function generateAntiCatastrophicData() {
|
||||
console.log('\n🧠 Example 3: Catastrophic Forgetting Prevention\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Task 1: Image classification (animals)
|
||||
console.log('Generating Task 1 data (Animal Classification)...');
|
||||
const task1Data = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
task_id: 'number (1)',
|
||||
task_name: 'string (animal_classification)',
|
||||
|
||||
// Image features (simulated)
|
||||
image_features: ['array of 100 numbers (0-1, CNN features)'],
|
||||
|
||||
// Labels
|
||||
category: 'cat | dog | bird | fish',
|
||||
subcategory: 'specific breed or species',
|
||||
|
||||
// Importance for replay
|
||||
importance_score: 'number (0-1, for experience replay)',
|
||||
difficulty: 'number (0-1)',
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
});
|
||||
|
||||
console.log(` - Task 1 samples: ${task1Data.data.length}`);
|
||||
|
||||
// Task 2: Image classification (vehicles) - New task
|
||||
console.log('\nGenerating Task 2 data (Vehicle Classification)...');
|
||||
const task2Data = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
task_id: 'number (2)',
|
||||
task_name: 'string (vehicle_classification)',
|
||||
|
||||
// Image features (different distribution)
|
||||
image_features: ['array of 100 numbers (0-1, CNN features)'],
|
||||
|
||||
// Labels (different classes)
|
||||
category: 'car | truck | motorcycle | bicycle',
|
||||
subcategory: 'specific model or type',
|
||||
|
||||
importance_score: 'number (0-1)',
|
||||
difficulty: 'number (0-1)',
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
});
|
||||
|
||||
console.log(` - Task 2 samples: ${task2Data.data.length}`);
|
||||
|
||||
// Generate replay buffer (selected samples from Task 1)
|
||||
console.log('\nGenerating replay buffer...');
|
||||
const replayBuffer = await synth.generateStructured({
|
||||
count: 50, // 25% of Task 1
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
task_id: 'number (1)',
|
||||
task_name: 'string (animal_classification)',
|
||||
|
||||
image_features: ['array of 100 numbers (0-1)'],
|
||||
|
||||
category: 'cat | dog | bird | fish',
|
||||
subcategory: 'specific breed or species',
|
||||
|
||||
// Replay metadata
|
||||
importance_score: 'number (0.5-1.0, high importance)',
|
||||
replay_count: 'number (0-5)',
|
||||
last_replayed: 'ISO timestamp',
|
||||
|
||||
is_replay_sample: 'boolean (true)',
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'importance_score should be high (>0.5)',
|
||||
'Select diverse and difficult samples for replay',
|
||||
],
|
||||
});
|
||||
|
||||
console.log(` - Replay buffer size: ${replayBuffer.data.length}`);
|
||||
|
||||
// Generate interleaved training data
|
||||
console.log('\nGenerating interleaved training batches...');
|
||||
const interleavedBatch = await synth.generateStructured({
|
||||
count: 100,
|
||||
schema: {
|
||||
batch_id: 'UUID',
|
||||
batch_number: 'number (1-20)',
|
||||
|
||||
// Mix of Task 2 (new) and Task 1 (replay)
|
||||
samples: [
|
||||
{
|
||||
sample_id: 'UUID',
|
||||
task_id: 'number (1 or 2)',
|
||||
is_replay: 'boolean (true for task_id=1)',
|
||||
features: ['array of 100 numbers'],
|
||||
label: 'string',
|
||||
},
|
||||
],
|
||||
|
||||
// Batch composition
|
||||
task1_ratio: 'number (0.2-0.3, 20-30% replay)',
|
||||
task2_ratio: 'number (0.7-0.8, 70-80% new task)',
|
||||
|
||||
// Forgetting metrics
|
||||
task1_performance_estimate: 'number (0.7-0.95, should stay high)',
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Each batch should contain 20-30% Task 1 samples (replay)',
|
||||
'Replay samples should maintain Task 1 performance',
|
||||
],
|
||||
});
|
||||
|
||||
console.log(` - Interleaved batches: ${interleavedBatch.data.length}`);
|
||||
|
||||
console.log('\n✅ Anti-catastrophic forgetting data generated');
|
||||
|
||||
return {
|
||||
task1: task1Data,
|
||||
task2: task2Data,
|
||||
replay: replayBuffer,
|
||||
interleaved: interleavedBatch,
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 4: Transfer Learning Datasets
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate pre-training and fine-tuning datasets
|
||||
*/
|
||||
export async function generateTransferLearningData() {
|
||||
console.log('\n🔄 Example 4: Transfer Learning Datasets\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Pre-training data: Large, general dataset
|
||||
console.log('Generating pre-training data (General Text)...');
|
||||
const pretrainingData = await synth.generateStructured({
|
||||
count: 1000,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
stage: 'string (pretraining)',
|
||||
|
||||
// General text data
|
||||
text: 'general text passage (3-5 sentences)',
|
||||
domain: 'news | wikipedia | books | web',
|
||||
|
||||
// Self-supervised labels
|
||||
masked_tokens: ['array of masked token positions'],
|
||||
next_sentence_label: 'boolean (is next sentence)',
|
||||
|
||||
// Features
|
||||
embedding: ['array of 768 numbers (transformer embedding)'],
|
||||
token_count: 'number (50-200)',
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Diverse domains and topics',
|
||||
'General language patterns',
|
||||
'High-quality, grammatical text',
|
||||
],
|
||||
});
|
||||
|
||||
console.log(` - Pre-training samples: ${pretrainingData.data.length}`);
|
||||
|
||||
// Fine-tuning data: Smaller, task-specific dataset
|
||||
console.log('\nGenerating fine-tuning data (Sentiment Analysis)...');
|
||||
const finetuningData = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
stage: 'string (finetuning)',
|
||||
|
||||
// Task-specific text
|
||||
text: 'product or movie review (2-4 sentences)',
|
||||
domain: 'string (reviews)',
|
||||
|
||||
// Supervised labels
|
||||
sentiment: 'positive | negative | neutral',
|
||||
confidence: 'number (0-1)',
|
||||
|
||||
// Features (initialized from pre-trained model)
|
||||
embedding: ['array of 768 numbers (fine-tuned embedding)'],
|
||||
token_count: 'number (30-150)',
|
||||
|
||||
// Fine-tuning metadata
|
||||
learning_phase: 'early | middle | late',
|
||||
layer_to_finetune: 'all | last_2 | last_4 | classifier_only',
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Domain-specific vocabulary',
|
||||
'Clear sentiment labels',
|
||||
'Smaller dataset than pre-training',
|
||||
],
|
||||
});
|
||||
|
||||
console.log(` - Fine-tuning samples: ${finetuningData.data.length}`);
|
||||
|
||||
// Generate few-shot learning data
|
||||
console.log('\nGenerating few-shot learning data...');
|
||||
const fewShotData = await synth.generateStructured({
|
||||
count: 50, // Very small
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
stage: 'string (few_shot)',
|
||||
|
||||
// Task-specific examples
|
||||
text: 'specialized domain text (legal, medical, technical)',
|
||||
domain: 'legal | medical | scientific',
|
||||
|
||||
// Labels
|
||||
category: 'specialized category',
|
||||
requires_expertise: 'boolean (true)',
|
||||
|
||||
// Few-shot metadata
|
||||
support_set: 'boolean (used as few-shot example)',
|
||||
shot_number: 'number (1-5, which shot in few-shot set)',
|
||||
|
||||
embedding: ['array of 768 numbers'],
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Highly specialized domain',
|
||||
'Very limited samples (few-shot)',
|
||||
'Clear, prototypical examples',
|
||||
],
|
||||
});
|
||||
|
||||
console.log(` - Few-shot samples: ${fewShotData.data.length}`);
|
||||
|
||||
console.log('\n✅ Transfer learning data generated');
|
||||
console.log('Data pipeline: Pre-training → Fine-tuning → Few-shot');
|
||||
|
||||
return {
|
||||
pretraining: pretrainingData,
|
||||
finetuning: finetuningData,
|
||||
fewShot: fewShotData,
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 5: Curriculum Learning Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate data organized by difficulty for curriculum learning
|
||||
*/
|
||||
export async function generateCurriculumData() {
|
||||
console.log('\n🎓 Example 5: Curriculum Learning Data\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
const difficulties = ['easy', 'medium', 'hard', 'expert'];
|
||||
const curriculum = [];
|
||||
|
||||
for (const difficulty of difficulties) {
|
||||
console.log(`\nGenerating ${difficulty} difficulty data...`);
|
||||
|
||||
const difficultyData = await synth.generateStructured({
|
||||
count: 150,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
difficulty_level: `string (${difficulty})`,
|
||||
curriculum_stage: `number (${difficulties.indexOf(difficulty) + 1})`,
|
||||
|
||||
// Math problem (example task)
|
||||
problem: {
|
||||
question: `math word problem (${difficulty} difficulty)`,
|
||||
steps_required: `number (${difficulties.indexOf(difficulty) + 1}-${difficulties.indexOf(difficulty) + 3})`,
|
||||
concepts: [`array of ${difficulties.indexOf(difficulty) + 1}-${difficulties.indexOf(difficulty) + 2} math concepts`],
|
||||
},
|
||||
|
||||
// Solution
|
||||
solution: {
|
||||
answer: 'correct numerical answer',
|
||||
explanation: 'step-by-step solution',
|
||||
intermediate_steps: ['array of solution steps'],
|
||||
},
|
||||
|
||||
// Difficulty metrics
|
||||
estimated_time_seconds: `number (${(difficulties.indexOf(difficulty) + 1) * 30}-${(difficulties.indexOf(difficulty) + 2) * 30})`,
|
||||
concept_complexity: `number (${difficulties.indexOf(difficulty) + 1}-${difficulties.indexOf(difficulty) + 2})`,
|
||||
prerequisite_skills: [`array of required skills (more for harder problems)`],
|
||||
|
||||
// Learning metadata
|
||||
success_rate_expected: `number (${0.9 - difficulties.indexOf(difficulty) * 0.15}-${0.95 - difficulties.indexOf(difficulty) * 0.15})`,
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
`Problems should be ${difficulty} difficulty`,
|
||||
'Success rate should decrease with difficulty',
|
||||
'More concepts required for harder problems',
|
||||
'Prerequisite skills accumulate',
|
||||
],
|
||||
});
|
||||
|
||||
console.log(` - ${difficulty} samples: ${difficultyData.data.length}`);
|
||||
console.log(` - Avg steps: ${calculateAverage(difficultyData.data, (d: any) => d.problem.steps_required)}`);
|
||||
|
||||
curriculum.push({
|
||||
stage: difficulties.indexOf(difficulty) + 1,
|
||||
difficulty,
|
||||
data: difficultyData,
|
||||
});
|
||||
}
|
||||
|
||||
console.log('\n✅ Curriculum learning data generated');
|
||||
console.log(`Curriculum stages: ${curriculum.length}`);
|
||||
console.log('Learning progression: easy → medium → hard → expert');
|
||||
|
||||
return curriculum;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 6: Online Learning Stream
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate streaming data for online learning
|
||||
*/
|
||||
export async function generateOnlineLearningStream() {
|
||||
console.log('\n📡 Example 6: Online Learning Stream\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Generate time-series data stream
|
||||
const streamData = await synth.generateTimeSeries({
|
||||
count: 500, // 500 time points
|
||||
interval: '1m', // One sample per minute
|
||||
schema: {
|
||||
timestamp: 'ISO timestamp',
|
||||
sequence_number: 'number (sequential)',
|
||||
|
||||
// Incoming data point
|
||||
features: ['array of 20 numbers (0-1)'],
|
||||
label: 'number (0-4)',
|
||||
|
||||
// Distribution characteristics
|
||||
distribution_shift: 'number (0-1, gradual increase over time)',
|
||||
concept_drift_indicator: 'boolean',
|
||||
|
||||
// Model state
|
||||
current_model_accuracy: 'number (0.7-0.95, may degrade over time)',
|
||||
should_update_model: 'boolean (true if drift detected)',
|
||||
|
||||
// Online learning metadata
|
||||
learning_rate: 'number (0.0001-0.01)',
|
||||
update_applied: 'boolean',
|
||||
samples_since_update: 'number (0-100)',
|
||||
|
||||
// Performance tracking
|
||||
prediction_error: 'number (0-1)',
|
||||
cumulative_regret: 'number (increasing)',
|
||||
},
|
||||
trend: 'stable',
|
||||
seasonality: false,
|
||||
constraints: [
|
||||
'Distribution shift should gradually increase',
|
||||
'Model accuracy should correlate inversely with drift',
|
||||
'should_update_model when accuracy drops or drift detected',
|
||||
'cumulative_regret increases when predictions are wrong',
|
||||
],
|
||||
});
|
||||
|
||||
const driftPoints = streamData.data.filter((d: any) => d.concept_drift_indicator);
|
||||
|
||||
console.log('Online Learning Stream:');
|
||||
console.log(`- Stream length: ${streamData.data.length} samples`);
|
||||
console.log(`- Concept drift points: ${driftPoints.length}`);
|
||||
console.log(`- Avg accuracy: ${calculateAverage(streamData.data, 'current_model_accuracy').toFixed(3)}`);
|
||||
console.log(`- Model updates: ${streamData.data.filter((d: any) => d.update_applied).length}`);
|
||||
|
||||
console.log('\n✅ Online learning stream generated');
|
||||
|
||||
return streamData;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Utility Functions
|
||||
// ============================================================================
|
||||
|
||||
function calculateAverage(data: any[], field: string | ((d: any) => number)): number {
|
||||
const values =
|
||||
typeof field === 'string'
|
||||
? data.map((d) => d[field]).filter((v) => typeof v === 'number')
|
||||
: data.map(field).filter((v) => typeof v === 'number');
|
||||
|
||||
if (values.length === 0) return 0;
|
||||
return values.reduce((a, b) => a + b, 0) / values.length;
|
||||
}
|
||||
|
||||
function getLabelDistribution(data: any[]): Record<string, number> {
|
||||
const dist: Record<string, number> = {};
|
||||
data.forEach((d) => {
|
||||
const label = d.label.toString();
|
||||
dist[label] = (dist[label] || 0) + 1;
|
||||
});
|
||||
return dist;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Complete Continual Learning Pipeline
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Demonstrate complete continual learning pipeline
|
||||
*/
|
||||
export async function completeContinualLearningPipeline() {
|
||||
console.log('\n🚀 Complete Continual Learning Pipeline\n');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
console.log('\nStage 1: Initial Training with Curriculum');
|
||||
const curriculum = await generateCurriculumData();
|
||||
|
||||
console.log('\nStage 2: Domain Adaptation');
|
||||
const domainData = await generateDomainAdaptationData();
|
||||
|
||||
console.log('\nStage 3: Incremental Learning');
|
||||
const incrementalData = await generateIncrementalData();
|
||||
|
||||
console.log('\nStage 4: Catastrophic Forgetting Prevention');
|
||||
const antiForgetData = await generateAntiCatastrophicData();
|
||||
|
||||
console.log('\nStage 5: Online Learning');
|
||||
const onlineData = await generateOnlineLearningStream();
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('✅ Complete continual learning pipeline executed');
|
||||
console.log('\nPipeline Summary:');
|
||||
console.log(' 1. Curriculum Learning (easy → hard)');
|
||||
console.log(' 2. Domain Adaptation (source → target)');
|
||||
console.log(' 3. Incremental Learning (phase 1 → phase N)');
|
||||
console.log(' 4. Experience Replay (prevent forgetting)');
|
||||
console.log(' 5. Online Learning (continuous stream)');
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Run All Examples
|
||||
// ============================================================================
|
||||
|
||||
export async function runAllContinualLearningExamples() {
|
||||
console.log('🎯 Continual Learning Dataset Generation\n');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
try {
|
||||
await generateIncrementalData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generateDomainAdaptationData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generateAntiCatastrophicData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generateTransferLearningData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generateCurriculumData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generateOnlineLearningStream();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
console.log('\n✅ All continual learning examples completed!\n');
|
||||
} catch (error: any) {
|
||||
console.error('❌ Error:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Run if executed directly
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runAllContinualLearningExamples().catch(console.error);
|
||||
}
|
||||
40
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.d.ts
vendored
Normal file
40
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.d.ts
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Self-Improving Data Generation with Feedback Loops
|
||||
*
|
||||
* This example demonstrates:
|
||||
* - Quality scoring and regeneration
|
||||
* - A/B testing data for model improvement
|
||||
* - Pattern learning from production data
|
||||
* - Adaptive schema evolution
|
||||
*/
|
||||
import type { GenerationResult } from '../../src/types.js';
|
||||
/**
|
||||
* Generate data with quality scores and regenerate low-quality samples
|
||||
*/
|
||||
export declare function qualityScoringLoop(): Promise<void>;
|
||||
/**
|
||||
* Generate A/B test data to improve model performance
|
||||
*/
|
||||
export declare function abTestingData(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Learn patterns from production data and generate similar synthetic data
|
||||
*/
|
||||
export declare function patternLearningLoop(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Evolve data schema based on feedback and changing requirements
|
||||
*/
|
||||
export declare function adaptiveSchemaEvolution(): Promise<{
|
||||
v1: GenerationResult<unknown>;
|
||||
v2: GenerationResult<unknown>;
|
||||
v3: GenerationResult<unknown>;
|
||||
}>;
|
||||
/**
|
||||
* Generate data for active learning - focus on uncertain/informative samples
|
||||
*/
|
||||
export declare function activeLearningData(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Generate evaluation data for continuous model monitoring
|
||||
*/
|
||||
export declare function continuousEvaluationData(): Promise<GenerationResult<unknown>>;
|
||||
export declare function runAllFeedbackLoopExamples(): Promise<void>;
|
||||
//# sourceMappingURL=feedback-loop.d.ts.map
|
||||
1
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.d.ts.map
vendored
Normal file
1
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"feedback-loop.d.ts","sourceRoot":"","sources":["feedback-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAM3D;;GAEG;AACH,wBAAsB,kBAAkB,kBAuFvC;AAMD;;GAEG;AACH,wBAAsB,aAAa,uCA4ElC;AAMD;;GAEG;AACH,wBAAsB,mBAAmB,uCA2ExC;AAMD;;GAEG;AACH,wBAAsB,uBAAuB;;;;GA0G5C;AAMD;;GAEG;AACH,wBAAsB,kBAAkB,uCA6DvC;AAMD;;GAEG;AACH,wBAAsB,wBAAwB,uCAiE7C;AA+CD,wBAAsB,0BAA0B,kBA2B/C"}
|
||||
521
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.js
vendored
Normal file
521
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.js
vendored
Normal file
@@ -0,0 +1,521 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Self-Improving Data Generation with Feedback Loops
|
||||
*
|
||||
* This example demonstrates:
|
||||
* - Quality scoring and regeneration
|
||||
* - A/B testing data for model improvement
|
||||
* - Pattern learning from production data
|
||||
* - Adaptive schema evolution
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.qualityScoringLoop = qualityScoringLoop;
|
||||
exports.abTestingData = abTestingData;
|
||||
exports.patternLearningLoop = patternLearningLoop;
|
||||
exports.adaptiveSchemaEvolution = adaptiveSchemaEvolution;
|
||||
exports.activeLearningData = activeLearningData;
|
||||
exports.continuousEvaluationData = continuousEvaluationData;
|
||||
exports.runAllFeedbackLoopExamples = runAllFeedbackLoopExamples;
|
||||
const index_js_1 = require("../../src/index.js");
|
||||
// ============================================================================
|
||||
// Example 1: Quality Scoring and Regeneration
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate data with quality scores and regenerate low-quality samples
|
||||
*/
|
||||
async function qualityScoringLoop() {
|
||||
console.log('\n⭐ Example 1: Quality Scoring and Regeneration\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
cacheStrategy: 'memory',
|
||||
});
|
||||
// Initial generation with quality metrics
|
||||
const initialData = await synth.generateStructured({
|
||||
count: 100,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
content: 'product description (2-3 sentences)',
|
||||
category: 'electronics | clothing | home | sports',
|
||||
price: 'number (10-1000)',
|
||||
// Quality metrics (would be computed by quality model)
|
||||
quality_score: 'number (0-1, overall quality)',
|
||||
metrics: {
|
||||
coherence: 'number (0-1)',
|
||||
relevance: 'number (0-1)',
|
||||
completeness: 'number (0-1)',
|
||||
grammar: 'number (0-1)',
|
||||
},
|
||||
// Metadata
|
||||
generation_attempt: 'number (1)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'quality_score should be average of metrics',
|
||||
'20% of samples should have quality_score < 0.7 (for regeneration demo)',
|
||||
'grammar score should be high (0.8-1.0)',
|
||||
],
|
||||
});
|
||||
console.log('Initial Generation:');
|
||||
console.log(`- Total samples: ${initialData.data.length}`);
|
||||
console.log(`- Average quality: ${calculateAverage(initialData.data, 'quality_score')}`);
|
||||
// Identify low-quality samples
|
||||
const lowQuality = initialData.data.filter((d) => d.quality_score < 0.7);
|
||||
console.log(`- Low quality samples: ${lowQuality.length}`);
|
||||
if (lowQuality.length > 0) {
|
||||
// Regenerate low-quality samples with feedback
|
||||
const regenerated = await synth.generateStructured({
|
||||
count: lowQuality.length,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
content: 'product description (2-3 sentences, improve coherence and completeness)',
|
||||
category: 'electronics | clothing | home | sports',
|
||||
price: 'number (10-1000)',
|
||||
// Quality metrics
|
||||
quality_score: 'number (0.7-1.0, improved quality)',
|
||||
metrics: {
|
||||
coherence: 'number (0.7-1.0)',
|
||||
relevance: 'number (0.7-1.0)',
|
||||
completeness: 'number (0.7-1.0)',
|
||||
grammar: 'number (0.9-1.0)',
|
||||
},
|
||||
// Track regeneration
|
||||
generation_attempt: 'number (2)',
|
||||
previous_issues: ['array of issues that were fixed'],
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'All samples should have quality_score >= 0.7',
|
||||
'Focus on improving coherence and completeness',
|
||||
'Maintain high grammar scores',
|
||||
],
|
||||
});
|
||||
console.log('\nRegenerated Samples:');
|
||||
console.log(`- Count: ${regenerated.data.length}`);
|
||||
console.log(`- Average quality: ${calculateAverage(regenerated.data, 'quality_score')}`);
|
||||
console.log(`- Quality improvement: ${calculateAverage(regenerated.data, 'quality_score') -
|
||||
calculateAverage(lowQuality, 'quality_score')}`);
|
||||
}
|
||||
console.log('\n✅ Quality scoring loop complete');
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 2: A/B Testing Data for Model Improvement
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate A/B test data to improve model performance
|
||||
*/
|
||||
async function abTestingData() {
|
||||
console.log('\n🔬 Example 2: A/B Testing Data Generation\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Generate A/B test scenarios
|
||||
const abTests = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
test_id: 'UUID',
|
||||
variant: 'A | B',
|
||||
// Input features
|
||||
user_profile: {
|
||||
age: 'number (18-80)',
|
||||
location: 'US state',
|
||||
interests: ['array of 2-5 interests'],
|
||||
past_purchases: 'number (0-100)',
|
||||
},
|
||||
// Model predictions
|
||||
model_variant: 'baseline_model | improved_model (based on variant)',
|
||||
prediction: 'number (0-1, predicted conversion probability)',
|
||||
confidence: 'number (0-1)',
|
||||
// Actual outcome
|
||||
actual_conversion: 'boolean',
|
||||
conversion_value: 'number (0-500) if converted',
|
||||
// Performance metrics
|
||||
prediction_error: 'number (absolute error)',
|
||||
calibration_error: 'number',
|
||||
// Metadata
|
||||
timestamp: 'ISO timestamp',
|
||||
feature_version: 'v1.0 | v1.1',
|
||||
},
|
||||
constraints: [
|
||||
'Variant A should use baseline_model',
|
||||
'Variant B should use improved_model',
|
||||
'Variant B should have higher accuracy (lower prediction_error)',
|
||||
'Variant B should have better calibration',
|
||||
'Distribution of user_profile should be similar across variants',
|
||||
'prediction should correlate with actual_conversion',
|
||||
],
|
||||
});
|
||||
// Analyze A/B test results
|
||||
const variantA = abTests.data.filter((d) => d.variant === 'A');
|
||||
const variantB = abTests.data.filter((d) => d.variant === 'B');
|
||||
console.log('A/B Test Results:');
|
||||
console.log(`\nVariant A (Baseline):`);
|
||||
console.log(` - Samples: ${variantA.length}`);
|
||||
console.log(` - Avg prediction error: ${calculateAverage(variantA, 'prediction_error').toFixed(4)}`);
|
||||
console.log(` - Conversion rate: ${calculateConversionRate(variantA)}%`);
|
||||
console.log(`\nVariant B (Improved):`);
|
||||
console.log(` - Samples: ${variantB.length}`);
|
||||
console.log(` - Avg prediction error: ${calculateAverage(variantB, 'prediction_error').toFixed(4)}`);
|
||||
console.log(` - Conversion rate: ${calculateConversionRate(variantB)}%`);
|
||||
const improvement = (((calculateAverage(variantA, 'prediction_error') -
|
||||
calculateAverage(variantB, 'prediction_error')) /
|
||||
calculateAverage(variantA, 'prediction_error')) *
|
||||
100);
|
||||
console.log(`\nImprovement: ${improvement.toFixed(2)}% reduction in error`);
|
||||
console.log('✅ A/B testing data generated');
|
||||
return abTests;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 3: Pattern Learning from Production Data
|
||||
// ============================================================================
|
||||
/**
|
||||
* Learn patterns from production data and generate similar synthetic data
|
||||
*/
|
||||
async function patternLearningLoop() {
|
||||
console.log('\n🧠 Example 3: Pattern Learning from Production\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Simulate production data patterns
|
||||
const productionPatterns = {
|
||||
common_sequences: [
|
||||
['login', 'browse', 'add_to_cart', 'checkout'],
|
||||
['login', 'browse', 'search', 'view_product'],
|
||||
['browse', 'search', 'add_to_cart', 'abandon'],
|
||||
],
|
||||
time_distributions: {
|
||||
peak_hours: [9, 12, 18, 20],
|
||||
avg_session_duration: 420, // seconds
|
||||
bounce_rate: 0.35,
|
||||
},
|
||||
user_segments: {
|
||||
frequent_buyers: 0.15,
|
||||
casual_browsers: 0.50,
|
||||
one_time_visitors: 0.35,
|
||||
},
|
||||
};
|
||||
// Generate synthetic data matching learned patterns
|
||||
const syntheticData = await synth.generateStructured({
|
||||
count: 500,
|
||||
schema: {
|
||||
session_id: 'UUID',
|
||||
user_segment: 'frequent_buyer | casual_browser | one_time_visitor',
|
||||
// Event sequence following learned patterns
|
||||
events: [
|
||||
{
|
||||
event_type: 'login | browse | search | add_to_cart | checkout | abandon | view_product',
|
||||
timestamp: 'ISO timestamp',
|
||||
duration: 'number (5-300, seconds)',
|
||||
},
|
||||
],
|
||||
// Session metrics
|
||||
total_duration: 'number (60-900, seconds, should match avg from patterns)',
|
||||
hour_of_day: 'number (0-23, biased toward peak hours)',
|
||||
bounced: 'boolean (35% true)',
|
||||
converted: 'boolean',
|
||||
// Pattern conformance
|
||||
matches_common_sequence: 'boolean (80% should be true)',
|
||||
pattern_id: 'number (0-2) if matches sequence',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'User segment distribution should match: 15% frequent_buyer, 50% casual_browser, 35% one_time_visitor',
|
||||
'Hour of day should be biased toward 9, 12, 18, 20',
|
||||
'Event sequences should follow common patterns 80% of time',
|
||||
'total_duration should be around 420 seconds on average',
|
||||
'bounce_rate should be approximately 35%',
|
||||
'frequent_buyers should have higher conversion rate',
|
||||
],
|
||||
});
|
||||
console.log('Pattern-Learned Synthetic Data:');
|
||||
console.log(`- Total sessions: ${syntheticData.data.length}`);
|
||||
console.log(`- User segment distribution:`, getUserSegmentDist(syntheticData.data));
|
||||
console.log(`- Avg session duration: ${calculateAverage(syntheticData.data, 'total_duration').toFixed(0)}s`);
|
||||
console.log(`- Bounce rate: ${calculateBounceRate(syntheticData.data)}%`);
|
||||
console.log(`- Pattern conformance: ${calculatePatternConformance(syntheticData.data)}%`);
|
||||
console.log('\n✅ Pattern learning complete');
|
||||
return syntheticData;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 4: Adaptive Schema Evolution
|
||||
// ============================================================================
|
||||
/**
|
||||
* Evolve data schema based on feedback and changing requirements
|
||||
*/
|
||||
async function adaptiveSchemaEvolution() {
|
||||
console.log('\n🔄 Example 4: Adaptive Schema Evolution\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Version 1: Initial schema
|
||||
console.log('Schema V1 (Initial):');
|
||||
const v1Data = await synth.generateStructured({
|
||||
count: 50,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
name: 'full name',
|
||||
email: 'valid email',
|
||||
age: 'number (18-80)',
|
||||
schema_version: 'string (v1.0)',
|
||||
},
|
||||
});
|
||||
console.log(` - Generated ${v1Data.data.length} records`);
|
||||
console.log(` - Fields: id, name, email, age`);
|
||||
// Simulate feedback: need more demographic info
|
||||
console.log('\nFeedback: Need location and preferences');
|
||||
// Version 2: Add fields based on feedback
|
||||
console.log('\nSchema V2 (Enhanced):');
|
||||
const v2Data = await synth.generateStructured({
|
||||
count: 50,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
name: 'full name',
|
||||
email: 'valid email',
|
||||
age: 'number (18-80)',
|
||||
// New fields
|
||||
location: {
|
||||
city: 'city name',
|
||||
state: 'US state',
|
||||
country: 'country name',
|
||||
},
|
||||
preferences: ['array of 3-5 preference categories'],
|
||||
schema_version: 'string (v2.0)',
|
||||
},
|
||||
});
|
||||
console.log(` - Generated ${v2Data.data.length} records`);
|
||||
console.log(` - Fields: id, name, email, age, location, preferences`);
|
||||
// Simulate more feedback: need behavioral data
|
||||
console.log('\nFeedback: Need behavioral and engagement metrics');
|
||||
// Version 3: Add behavioral tracking
|
||||
console.log('\nSchema V3 (Full Featured):');
|
||||
const v3Data = await synth.generateStructured({
|
||||
count: 50,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
name: 'full name',
|
||||
email: 'valid email',
|
||||
age: 'number (18-80)',
|
||||
location: {
|
||||
city: 'city name',
|
||||
state: 'US state',
|
||||
country: 'country name',
|
||||
},
|
||||
preferences: ['array of 3-5 preference categories'],
|
||||
// New behavioral fields
|
||||
behavioral_metrics: {
|
||||
total_sessions: 'number (0-500)',
|
||||
avg_session_duration: 'number (60-3600, seconds)',
|
||||
last_active: 'ISO timestamp (within last 30 days)',
|
||||
engagement_score: 'number (0-100)',
|
||||
ltv: 'number (0-10000, lifetime value)',
|
||||
},
|
||||
// New segmentation
|
||||
user_segment: 'high_value | medium_value | low_value | churned',
|
||||
predicted_churn: 'boolean',
|
||||
churn_risk_score: 'number (0-1)',
|
||||
schema_version: 'string (v3.0)',
|
||||
},
|
||||
constraints: [
|
||||
'engagement_score should correlate with total_sessions',
|
||||
'ltv should be higher for high_value segment',
|
||||
'churned users should have old last_active dates',
|
||||
'churn_risk_score should be high for predicted_churn=true',
|
||||
],
|
||||
});
|
||||
console.log(` - Generated ${v3Data.data.length} records`);
|
||||
console.log(` - Fields: All previous + behavioral_metrics, user_segment, churn predictions`);
|
||||
// Show schema evolution
|
||||
console.log('\nSchema Evolution Summary:');
|
||||
console.log(' V1 → V2: Added location and preferences');
|
||||
console.log(' V2 → V3: Added behavioral metrics and churn prediction');
|
||||
console.log(' Field count: 5 → 7 → 12');
|
||||
console.log('\n✅ Adaptive schema evolution complete');
|
||||
return { v1: v1Data, v2: v2Data, v3: v3Data };
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 5: Active Learning Data Generation
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate data for active learning - focus on uncertain/informative samples
|
||||
*/
|
||||
async function activeLearningData() {
|
||||
console.log('\n🎯 Example 5: Active Learning Data\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Generate samples with uncertainty scores
|
||||
const activeLearningData = await synth.generateStructured({
|
||||
count: 300,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
// Features
|
||||
features: {
|
||||
feature_1: 'number (0-100)',
|
||||
feature_2: 'number (0-100)',
|
||||
feature_3: 'number (0-100)',
|
||||
feature_4: 'number (0-100)',
|
||||
},
|
||||
// Model predictions
|
||||
predicted_class: 'number (0-4)',
|
||||
prediction_confidence: 'number (0-1)',
|
||||
uncertainty_score: 'number (0-1, inverse of confidence)',
|
||||
// Active learning strategy
|
||||
query_strategy: 'uncertainty_sampling | query_by_committee | expected_model_change',
|
||||
should_label: 'boolean (true if high uncertainty)',
|
||||
// If labeled
|
||||
true_label: 'number (0-4) or null',
|
||||
was_useful: 'boolean or null (if labeled)',
|
||||
// Metadata
|
||||
iteration: 'number (1-10, active learning iteration)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'uncertainty_score should equal 1 - prediction_confidence',
|
||||
'should_label should be true for samples with uncertainty > 0.6',
|
||||
'30% of samples should have high uncertainty (>0.6)',
|
||||
'true_label should be provided if should_label is true',
|
||||
'was_useful should correlate with uncertainty_score',
|
||||
],
|
||||
});
|
||||
const highUncertainty = activeLearningData.data.filter((d) => d.uncertainty_score > 0.6);
|
||||
const shouldLabel = activeLearningData.data.filter((d) => d.should_label);
|
||||
console.log('Active Learning Data:');
|
||||
console.log(`- Total samples: ${activeLearningData.data.length}`);
|
||||
console.log(`- High uncertainty samples: ${highUncertainty.length}`);
|
||||
console.log(`- Samples to label: ${shouldLabel.length}`);
|
||||
console.log(`- Avg uncertainty: ${calculateAverage(activeLearningData.data, 'uncertainty_score').toFixed(3)}`);
|
||||
console.log(`- Strategy distribution:`, getStrategyDistribution(activeLearningData.data));
|
||||
console.log('\n✅ Active learning data generated');
|
||||
return activeLearningData;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 6: Continuous Model Evaluation Data
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate evaluation data for continuous model monitoring
|
||||
*/
|
||||
async function continuousEvaluationData() {
|
||||
console.log('\n📊 Example 6: Continuous Evaluation Data\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Generate time-series evaluation data
|
||||
const evaluationData = await synth.generateTimeSeries({
|
||||
count: 168, // One week, hourly
|
||||
interval: '1h',
|
||||
schema: {
|
||||
timestamp: 'ISO timestamp',
|
||||
hour: 'number (0-23)',
|
||||
// Model performance metrics
|
||||
accuracy: 'number (0.7-0.95)',
|
||||
precision: 'number (0.7-0.95)',
|
||||
recall: 'number (0.7-0.95)',
|
||||
f1_score: 'number (0.7-0.95)',
|
||||
// Data distribution metrics
|
||||
prediction_distribution: {
|
||||
class_0: 'number (0-1, proportion)',
|
||||
class_1: 'number (0-1, proportion)',
|
||||
},
|
||||
confidence_distribution: {
|
||||
high: 'number (0-1, >0.8)',
|
||||
medium: 'number (0-1, 0.5-0.8)',
|
||||
low: 'number (0-1, <0.5)',
|
||||
},
|
||||
// Drift detection
|
||||
feature_drift_score: 'number (0-1)',
|
||||
prediction_drift_score: 'number (0-1)',
|
||||
alert_triggered: 'boolean (true if drift > 0.3)',
|
||||
// System metrics
|
||||
inference_latency_ms: 'number (10-100)',
|
||||
throughput_qps: 'number (100-1000)',
|
||||
error_rate: 'number (0-0.05)',
|
||||
},
|
||||
trend: 'stable',
|
||||
seasonality: true,
|
||||
constraints: [
|
||||
'Performance should degrade slightly during peak hours (9-17)',
|
||||
'alert_triggered should be true when drift scores > 0.3',
|
||||
'Drift should gradually increase over time (concept drift)',
|
||||
'Latency should be higher during peak traffic',
|
||||
],
|
||||
});
|
||||
const alerts = evaluationData.data.filter((d) => d.alert_triggered);
|
||||
console.log('Continuous Evaluation Data:');
|
||||
console.log(`- Time points: ${evaluationData.data.length}`);
|
||||
console.log(`- Average accuracy: ${calculateAverage(evaluationData.data, 'accuracy').toFixed(3)}`);
|
||||
console.log(`- Average drift score: ${calculateAverage(evaluationData.data, 'feature_drift_score').toFixed(3)}`);
|
||||
console.log(`- Drift alerts: ${alerts.length}`);
|
||||
console.log(`- Average latency: ${calculateAverage(evaluationData.data, 'inference_latency_ms').toFixed(1)}ms`);
|
||||
console.log('\n✅ Continuous evaluation data generated');
|
||||
return evaluationData;
|
||||
}
|
||||
// ============================================================================
|
||||
// Utility Functions
|
||||
// ============================================================================
|
||||
function calculateAverage(data, field) {
|
||||
const values = data.map((d) => d[field]).filter((v) => typeof v === 'number');
|
||||
if (values.length === 0)
|
||||
return 0;
|
||||
return values.reduce((a, b) => a + b, 0) / values.length;
|
||||
}
|
||||
function calculateConversionRate(data) {
|
||||
const converted = data.filter((d) => d.actual_conversion).length;
|
||||
return (converted / data.length) * 100;
|
||||
}
|
||||
function calculateBounceRate(data) {
|
||||
const bounced = data.filter((d) => d.bounced).length;
|
||||
return (bounced / data.length) * 100;
|
||||
}
|
||||
function calculatePatternConformance(data) {
|
||||
const matching = data.filter((d) => d.matches_common_sequence).length;
|
||||
return (matching / data.length) * 100;
|
||||
}
|
||||
function getUserSegmentDist(data) {
|
||||
const dist = {};
|
||||
data.forEach((d) => {
|
||||
dist[d.user_segment] = (dist[d.user_segment] || 0) + 1;
|
||||
});
|
||||
return dist;
|
||||
}
|
||||
function getStrategyDistribution(data) {
|
||||
const dist = {};
|
||||
data.forEach((d) => {
|
||||
dist[d.query_strategy] = (dist[d.query_strategy] || 0) + 1;
|
||||
});
|
||||
return dist;
|
||||
}
|
||||
// ============================================================================
|
||||
// Run All Examples
|
||||
// ============================================================================
|
||||
async function runAllFeedbackLoopExamples() {
|
||||
console.log('🔄 Self-Improving Feedback Loop Examples\n');
|
||||
console.log('='.repeat(60));
|
||||
try {
|
||||
await qualityScoringLoop();
|
||||
console.log('='.repeat(60));
|
||||
await abTestingData();
|
||||
console.log('='.repeat(60));
|
||||
await patternLearningLoop();
|
||||
console.log('='.repeat(60));
|
||||
await adaptiveSchemaEvolution();
|
||||
console.log('='.repeat(60));
|
||||
await activeLearningData();
|
||||
console.log('='.repeat(60));
|
||||
await continuousEvaluationData();
|
||||
console.log('='.repeat(60));
|
||||
console.log('\n✅ All feedback loop examples completed!\n');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('❌ Error:', error.message);
|
||||
}
|
||||
}
|
||||
// Run if executed directly
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runAllFeedbackLoopExamples().catch(console.error);
|
||||
}
|
||||
//# sourceMappingURL=feedback-loop.js.map
|
||||
1
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.js.map
vendored
Normal file
1
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
615
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.ts
vendored
Normal file
615
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/feedback-loop.ts
vendored
Normal file
@@ -0,0 +1,615 @@
|
||||
/**
|
||||
* Self-Improving Data Generation with Feedback Loops
|
||||
*
|
||||
* This example demonstrates:
|
||||
* - Quality scoring and regeneration
|
||||
* - A/B testing data for model improvement
|
||||
* - Pattern learning from production data
|
||||
* - Adaptive schema evolution
|
||||
*/
|
||||
|
||||
import { AgenticSynth, createSynth } from '../../src/index.js';
|
||||
import type { GenerationResult } from '../../src/types.js';
|
||||
|
||||
// ============================================================================
|
||||
// Example 1: Quality Scoring and Regeneration
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate data with quality scores and regenerate low-quality samples
|
||||
*/
|
||||
export async function qualityScoringLoop() {
|
||||
console.log('\n⭐ Example 1: Quality Scoring and Regeneration\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
cacheStrategy: 'memory',
|
||||
});
|
||||
|
||||
// Initial generation with quality metrics
|
||||
const initialData = await synth.generateStructured({
|
||||
count: 100,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
content: 'product description (2-3 sentences)',
|
||||
category: 'electronics | clothing | home | sports',
|
||||
price: 'number (10-1000)',
|
||||
|
||||
// Quality metrics (would be computed by quality model)
|
||||
quality_score: 'number (0-1, overall quality)',
|
||||
metrics: {
|
||||
coherence: 'number (0-1)',
|
||||
relevance: 'number (0-1)',
|
||||
completeness: 'number (0-1)',
|
||||
grammar: 'number (0-1)',
|
||||
},
|
||||
|
||||
// Metadata
|
||||
generation_attempt: 'number (1)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'quality_score should be average of metrics',
|
||||
'20% of samples should have quality_score < 0.7 (for regeneration demo)',
|
||||
'grammar score should be high (0.8-1.0)',
|
||||
],
|
||||
});
|
||||
|
||||
console.log('Initial Generation:');
|
||||
console.log(`- Total samples: ${initialData.data.length}`);
|
||||
console.log(`- Average quality: ${calculateAverage(initialData.data, 'quality_score')}`);
|
||||
|
||||
// Identify low-quality samples
|
||||
const lowQuality = initialData.data.filter((d: any) => d.quality_score < 0.7);
|
||||
console.log(`- Low quality samples: ${lowQuality.length}`);
|
||||
|
||||
if (lowQuality.length > 0) {
|
||||
// Regenerate low-quality samples with feedback
|
||||
const regenerated = await synth.generateStructured({
|
||||
count: lowQuality.length,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
content: 'product description (2-3 sentences, improve coherence and completeness)',
|
||||
category: 'electronics | clothing | home | sports',
|
||||
price: 'number (10-1000)',
|
||||
|
||||
// Quality metrics
|
||||
quality_score: 'number (0.7-1.0, improved quality)',
|
||||
metrics: {
|
||||
coherence: 'number (0.7-1.0)',
|
||||
relevance: 'number (0.7-1.0)',
|
||||
completeness: 'number (0.7-1.0)',
|
||||
grammar: 'number (0.9-1.0)',
|
||||
},
|
||||
|
||||
// Track regeneration
|
||||
generation_attempt: 'number (2)',
|
||||
previous_issues: ['array of issues that were fixed'],
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'All samples should have quality_score >= 0.7',
|
||||
'Focus on improving coherence and completeness',
|
||||
'Maintain high grammar scores',
|
||||
],
|
||||
});
|
||||
|
||||
console.log('\nRegenerated Samples:');
|
||||
console.log(`- Count: ${regenerated.data.length}`);
|
||||
console.log(`- Average quality: ${calculateAverage(regenerated.data, 'quality_score')}`);
|
||||
console.log(`- Quality improvement: ${
|
||||
calculateAverage(regenerated.data, 'quality_score') -
|
||||
calculateAverage(lowQuality, 'quality_score')
|
||||
}`);
|
||||
}
|
||||
|
||||
console.log('\n✅ Quality scoring loop complete');
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 2: A/B Testing Data for Model Improvement
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate A/B test data to improve model performance
|
||||
*/
|
||||
export async function abTestingData() {
|
||||
console.log('\n🔬 Example 2: A/B Testing Data Generation\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Generate A/B test scenarios
|
||||
const abTests = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
test_id: 'UUID',
|
||||
variant: 'A | B',
|
||||
|
||||
// Input features
|
||||
user_profile: {
|
||||
age: 'number (18-80)',
|
||||
location: 'US state',
|
||||
interests: ['array of 2-5 interests'],
|
||||
past_purchases: 'number (0-100)',
|
||||
},
|
||||
|
||||
// Model predictions
|
||||
model_variant: 'baseline_model | improved_model (based on variant)',
|
||||
prediction: 'number (0-1, predicted conversion probability)',
|
||||
confidence: 'number (0-1)',
|
||||
|
||||
// Actual outcome
|
||||
actual_conversion: 'boolean',
|
||||
conversion_value: 'number (0-500) if converted',
|
||||
|
||||
// Performance metrics
|
||||
prediction_error: 'number (absolute error)',
|
||||
calibration_error: 'number',
|
||||
|
||||
// Metadata
|
||||
timestamp: 'ISO timestamp',
|
||||
feature_version: 'v1.0 | v1.1',
|
||||
},
|
||||
constraints: [
|
||||
'Variant A should use baseline_model',
|
||||
'Variant B should use improved_model',
|
||||
'Variant B should have higher accuracy (lower prediction_error)',
|
||||
'Variant B should have better calibration',
|
||||
'Distribution of user_profile should be similar across variants',
|
||||
'prediction should correlate with actual_conversion',
|
||||
],
|
||||
});
|
||||
|
||||
// Analyze A/B test results
|
||||
const variantA = abTests.data.filter((d: any) => d.variant === 'A');
|
||||
const variantB = abTests.data.filter((d: any) => d.variant === 'B');
|
||||
|
||||
console.log('A/B Test Results:');
|
||||
console.log(`\nVariant A (Baseline):`);
|
||||
console.log(` - Samples: ${variantA.length}`);
|
||||
console.log(` - Avg prediction error: ${calculateAverage(variantA, 'prediction_error').toFixed(4)}`);
|
||||
console.log(` - Conversion rate: ${calculateConversionRate(variantA)}%`);
|
||||
|
||||
console.log(`\nVariant B (Improved):`);
|
||||
console.log(` - Samples: ${variantB.length}`);
|
||||
console.log(` - Avg prediction error: ${calculateAverage(variantB, 'prediction_error').toFixed(4)}`);
|
||||
console.log(` - Conversion rate: ${calculateConversionRate(variantB)}%`);
|
||||
|
||||
const improvement = (
|
||||
((calculateAverage(variantA, 'prediction_error') -
|
||||
calculateAverage(variantB, 'prediction_error')) /
|
||||
calculateAverage(variantA, 'prediction_error')) *
|
||||
100
|
||||
);
|
||||
|
||||
console.log(`\nImprovement: ${improvement.toFixed(2)}% reduction in error`);
|
||||
console.log('✅ A/B testing data generated');
|
||||
|
||||
return abTests;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 3: Pattern Learning from Production Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Learn patterns from production data and generate similar synthetic data
|
||||
*/
|
||||
export async function patternLearningLoop() {
|
||||
console.log('\n🧠 Example 3: Pattern Learning from Production\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Simulate production data patterns
|
||||
const productionPatterns = {
|
||||
common_sequences: [
|
||||
['login', 'browse', 'add_to_cart', 'checkout'],
|
||||
['login', 'browse', 'search', 'view_product'],
|
||||
['browse', 'search', 'add_to_cart', 'abandon'],
|
||||
],
|
||||
time_distributions: {
|
||||
peak_hours: [9, 12, 18, 20],
|
||||
avg_session_duration: 420, // seconds
|
||||
bounce_rate: 0.35,
|
||||
},
|
||||
user_segments: {
|
||||
frequent_buyers: 0.15,
|
||||
casual_browsers: 0.50,
|
||||
one_time_visitors: 0.35,
|
||||
},
|
||||
};
|
||||
|
||||
// Generate synthetic data matching learned patterns
|
||||
const syntheticData = await synth.generateStructured({
|
||||
count: 500,
|
||||
schema: {
|
||||
session_id: 'UUID',
|
||||
user_segment: 'frequent_buyer | casual_browser | one_time_visitor',
|
||||
|
||||
// Event sequence following learned patterns
|
||||
events: [
|
||||
{
|
||||
event_type: 'login | browse | search | add_to_cart | checkout | abandon | view_product',
|
||||
timestamp: 'ISO timestamp',
|
||||
duration: 'number (5-300, seconds)',
|
||||
},
|
||||
],
|
||||
|
||||
// Session metrics
|
||||
total_duration: 'number (60-900, seconds, should match avg from patterns)',
|
||||
hour_of_day: 'number (0-23, biased toward peak hours)',
|
||||
bounced: 'boolean (35% true)',
|
||||
converted: 'boolean',
|
||||
|
||||
// Pattern conformance
|
||||
matches_common_sequence: 'boolean (80% should be true)',
|
||||
pattern_id: 'number (0-2) if matches sequence',
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'User segment distribution should match: 15% frequent_buyer, 50% casual_browser, 35% one_time_visitor',
|
||||
'Hour of day should be biased toward 9, 12, 18, 20',
|
||||
'Event sequences should follow common patterns 80% of time',
|
||||
'total_duration should be around 420 seconds on average',
|
||||
'bounce_rate should be approximately 35%',
|
||||
'frequent_buyers should have higher conversion rate',
|
||||
],
|
||||
});
|
||||
|
||||
console.log('Pattern-Learned Synthetic Data:');
|
||||
console.log(`- Total sessions: ${syntheticData.data.length}`);
|
||||
console.log(`- User segment distribution:`, getUserSegmentDist(syntheticData.data));
|
||||
console.log(`- Avg session duration: ${calculateAverage(syntheticData.data, 'total_duration').toFixed(0)}s`);
|
||||
console.log(`- Bounce rate: ${calculateBounceRate(syntheticData.data)}%`);
|
||||
console.log(`- Pattern conformance: ${calculatePatternConformance(syntheticData.data)}%`);
|
||||
|
||||
console.log('\n✅ Pattern learning complete');
|
||||
|
||||
return syntheticData;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 4: Adaptive Schema Evolution
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Evolve data schema based on feedback and changing requirements
|
||||
*/
|
||||
export async function adaptiveSchemaEvolution() {
|
||||
console.log('\n🔄 Example 4: Adaptive Schema Evolution\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Version 1: Initial schema
|
||||
console.log('Schema V1 (Initial):');
|
||||
const v1Data = await synth.generateStructured({
|
||||
count: 50,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
name: 'full name',
|
||||
email: 'valid email',
|
||||
age: 'number (18-80)',
|
||||
|
||||
schema_version: 'string (v1.0)',
|
||||
},
|
||||
});
|
||||
console.log(` - Generated ${v1Data.data.length} records`);
|
||||
console.log(` - Fields: id, name, email, age`);
|
||||
|
||||
// Simulate feedback: need more demographic info
|
||||
console.log('\nFeedback: Need location and preferences');
|
||||
|
||||
// Version 2: Add fields based on feedback
|
||||
console.log('\nSchema V2 (Enhanced):');
|
||||
const v2Data = await synth.generateStructured({
|
||||
count: 50,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
name: 'full name',
|
||||
email: 'valid email',
|
||||
age: 'number (18-80)',
|
||||
|
||||
// New fields
|
||||
location: {
|
||||
city: 'city name',
|
||||
state: 'US state',
|
||||
country: 'country name',
|
||||
},
|
||||
preferences: ['array of 3-5 preference categories'],
|
||||
|
||||
schema_version: 'string (v2.0)',
|
||||
},
|
||||
});
|
||||
console.log(` - Generated ${v2Data.data.length} records`);
|
||||
console.log(` - Fields: id, name, email, age, location, preferences`);
|
||||
|
||||
// Simulate more feedback: need behavioral data
|
||||
console.log('\nFeedback: Need behavioral and engagement metrics');
|
||||
|
||||
// Version 3: Add behavioral tracking
|
||||
console.log('\nSchema V3 (Full Featured):');
|
||||
const v3Data = await synth.generateStructured({
|
||||
count: 50,
|
||||
schema: {
|
||||
id: 'UUID',
|
||||
name: 'full name',
|
||||
email: 'valid email',
|
||||
age: 'number (18-80)',
|
||||
|
||||
location: {
|
||||
city: 'city name',
|
||||
state: 'US state',
|
||||
country: 'country name',
|
||||
},
|
||||
preferences: ['array of 3-5 preference categories'],
|
||||
|
||||
// New behavioral fields
|
||||
behavioral_metrics: {
|
||||
total_sessions: 'number (0-500)',
|
||||
avg_session_duration: 'number (60-3600, seconds)',
|
||||
last_active: 'ISO timestamp (within last 30 days)',
|
||||
engagement_score: 'number (0-100)',
|
||||
ltv: 'number (0-10000, lifetime value)',
|
||||
},
|
||||
|
||||
// New segmentation
|
||||
user_segment: 'high_value | medium_value | low_value | churned',
|
||||
predicted_churn: 'boolean',
|
||||
churn_risk_score: 'number (0-1)',
|
||||
|
||||
schema_version: 'string (v3.0)',
|
||||
},
|
||||
constraints: [
|
||||
'engagement_score should correlate with total_sessions',
|
||||
'ltv should be higher for high_value segment',
|
||||
'churned users should have old last_active dates',
|
||||
'churn_risk_score should be high for predicted_churn=true',
|
||||
],
|
||||
});
|
||||
console.log(` - Generated ${v3Data.data.length} records`);
|
||||
console.log(` - Fields: All previous + behavioral_metrics, user_segment, churn predictions`);
|
||||
|
||||
// Show schema evolution
|
||||
console.log('\nSchema Evolution Summary:');
|
||||
console.log(' V1 → V2: Added location and preferences');
|
||||
console.log(' V2 → V3: Added behavioral metrics and churn prediction');
|
||||
console.log(' Field count: 5 → 7 → 12');
|
||||
|
||||
console.log('\n✅ Adaptive schema evolution complete');
|
||||
|
||||
return { v1: v1Data, v2: v2Data, v3: v3Data };
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 5: Active Learning Data Generation
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate data for active learning - focus on uncertain/informative samples
|
||||
*/
|
||||
export async function activeLearningData() {
|
||||
console.log('\n🎯 Example 5: Active Learning Data\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Generate samples with uncertainty scores
|
||||
const activeLearningData = await synth.generateStructured({
|
||||
count: 300,
|
||||
schema: {
|
||||
sample_id: 'UUID',
|
||||
|
||||
// Features
|
||||
features: {
|
||||
feature_1: 'number (0-100)',
|
||||
feature_2: 'number (0-100)',
|
||||
feature_3: 'number (0-100)',
|
||||
feature_4: 'number (0-100)',
|
||||
},
|
||||
|
||||
// Model predictions
|
||||
predicted_class: 'number (0-4)',
|
||||
prediction_confidence: 'number (0-1)',
|
||||
uncertainty_score: 'number (0-1, inverse of confidence)',
|
||||
|
||||
// Active learning strategy
|
||||
query_strategy: 'uncertainty_sampling | query_by_committee | expected_model_change',
|
||||
should_label: 'boolean (true if high uncertainty)',
|
||||
|
||||
// If labeled
|
||||
true_label: 'number (0-4) or null',
|
||||
was_useful: 'boolean or null (if labeled)',
|
||||
|
||||
// Metadata
|
||||
iteration: 'number (1-10, active learning iteration)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'uncertainty_score should equal 1 - prediction_confidence',
|
||||
'should_label should be true for samples with uncertainty > 0.6',
|
||||
'30% of samples should have high uncertainty (>0.6)',
|
||||
'true_label should be provided if should_label is true',
|
||||
'was_useful should correlate with uncertainty_score',
|
||||
],
|
||||
});
|
||||
|
||||
const highUncertainty = activeLearningData.data.filter((d: any) => d.uncertainty_score > 0.6);
|
||||
const shouldLabel = activeLearningData.data.filter((d: any) => d.should_label);
|
||||
|
||||
console.log('Active Learning Data:');
|
||||
console.log(`- Total samples: ${activeLearningData.data.length}`);
|
||||
console.log(`- High uncertainty samples: ${highUncertainty.length}`);
|
||||
console.log(`- Samples to label: ${shouldLabel.length}`);
|
||||
console.log(`- Avg uncertainty: ${calculateAverage(activeLearningData.data, 'uncertainty_score').toFixed(3)}`);
|
||||
console.log(`- Strategy distribution:`, getStrategyDistribution(activeLearningData.data));
|
||||
|
||||
console.log('\n✅ Active learning data generated');
|
||||
|
||||
return activeLearningData;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 6: Continuous Model Evaluation Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate evaluation data for continuous model monitoring
|
||||
*/
|
||||
export async function continuousEvaluationData() {
|
||||
console.log('\n📊 Example 6: Continuous Evaluation Data\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Generate time-series evaluation data
|
||||
const evaluationData = await synth.generateTimeSeries({
|
||||
count: 168, // One week, hourly
|
||||
interval: '1h',
|
||||
schema: {
|
||||
timestamp: 'ISO timestamp',
|
||||
hour: 'number (0-23)',
|
||||
|
||||
// Model performance metrics
|
||||
accuracy: 'number (0.7-0.95)',
|
||||
precision: 'number (0.7-0.95)',
|
||||
recall: 'number (0.7-0.95)',
|
||||
f1_score: 'number (0.7-0.95)',
|
||||
|
||||
// Data distribution metrics
|
||||
prediction_distribution: {
|
||||
class_0: 'number (0-1, proportion)',
|
||||
class_1: 'number (0-1, proportion)',
|
||||
},
|
||||
confidence_distribution: {
|
||||
high: 'number (0-1, >0.8)',
|
||||
medium: 'number (0-1, 0.5-0.8)',
|
||||
low: 'number (0-1, <0.5)',
|
||||
},
|
||||
|
||||
// Drift detection
|
||||
feature_drift_score: 'number (0-1)',
|
||||
prediction_drift_score: 'number (0-1)',
|
||||
alert_triggered: 'boolean (true if drift > 0.3)',
|
||||
|
||||
// System metrics
|
||||
inference_latency_ms: 'number (10-100)',
|
||||
throughput_qps: 'number (100-1000)',
|
||||
error_rate: 'number (0-0.05)',
|
||||
},
|
||||
trend: 'stable',
|
||||
seasonality: true,
|
||||
constraints: [
|
||||
'Performance should degrade slightly during peak hours (9-17)',
|
||||
'alert_triggered should be true when drift scores > 0.3',
|
||||
'Drift should gradually increase over time (concept drift)',
|
||||
'Latency should be higher during peak traffic',
|
||||
],
|
||||
});
|
||||
|
||||
const alerts = evaluationData.data.filter((d: any) => d.alert_triggered);
|
||||
|
||||
console.log('Continuous Evaluation Data:');
|
||||
console.log(`- Time points: ${evaluationData.data.length}`);
|
||||
console.log(`- Average accuracy: ${calculateAverage(evaluationData.data, 'accuracy').toFixed(3)}`);
|
||||
console.log(`- Average drift score: ${calculateAverage(evaluationData.data, 'feature_drift_score').toFixed(3)}`);
|
||||
console.log(`- Drift alerts: ${alerts.length}`);
|
||||
console.log(`- Average latency: ${calculateAverage(evaluationData.data, 'inference_latency_ms').toFixed(1)}ms`);
|
||||
|
||||
console.log('\n✅ Continuous evaluation data generated');
|
||||
|
||||
return evaluationData;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Utility Functions
|
||||
// ============================================================================
|
||||
|
||||
function calculateAverage(data: any[], field: string): number {
|
||||
const values = data.map((d) => d[field]).filter((v) => typeof v === 'number');
|
||||
if (values.length === 0) return 0;
|
||||
return values.reduce((a, b) => a + b, 0) / values.length;
|
||||
}
|
||||
|
||||
function calculateConversionRate(data: any[]): number {
|
||||
const converted = data.filter((d) => d.actual_conversion).length;
|
||||
return (converted / data.length) * 100;
|
||||
}
|
||||
|
||||
function calculateBounceRate(data: any[]): number {
|
||||
const bounced = data.filter((d) => d.bounced).length;
|
||||
return (bounced / data.length) * 100;
|
||||
}
|
||||
|
||||
function calculatePatternConformance(data: any[]): number {
|
||||
const matching = data.filter((d) => d.matches_common_sequence).length;
|
||||
return (matching / data.length) * 100;
|
||||
}
|
||||
|
||||
function getUserSegmentDist(data: any[]): Record<string, number> {
|
||||
const dist: Record<string, number> = {};
|
||||
data.forEach((d) => {
|
||||
dist[d.user_segment] = (dist[d.user_segment] || 0) + 1;
|
||||
});
|
||||
return dist;
|
||||
}
|
||||
|
||||
function getStrategyDistribution(data: any[]): Record<string, number> {
|
||||
const dist: Record<string, number> = {};
|
||||
data.forEach((d) => {
|
||||
dist[d.query_strategy] = (dist[d.query_strategy] || 0) + 1;
|
||||
});
|
||||
return dist;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Run All Examples
|
||||
// ============================================================================
|
||||
|
||||
export async function runAllFeedbackLoopExamples() {
|
||||
console.log('🔄 Self-Improving Feedback Loop Examples\n');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
try {
|
||||
await qualityScoringLoop();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await abTestingData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await patternLearningLoop();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await adaptiveSchemaEvolution();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await activeLearningData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await continuousEvaluationData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
console.log('\n✅ All feedback loop examples completed!\n');
|
||||
} catch (error: any) {
|
||||
console.error('❌ Error:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Run if executed directly
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runAllFeedbackLoopExamples().catch(console.error);
|
||||
}
|
||||
40
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/reinforcement-learning.d.ts
vendored
Normal file
40
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/reinforcement-learning.d.ts
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Reinforcement Learning Training Data Generation
|
||||
*
|
||||
* This example demonstrates generating synthetic RL training data including:
|
||||
* - State-action-reward tuples
|
||||
* - Episode generation with temporal consistency
|
||||
* - Exploration vs exploitation scenarios
|
||||
* - Reward function testing
|
||||
*/
|
||||
import type { GenerationResult } from '../../src/types.js';
|
||||
/**
|
||||
* Generate basic SAR tuples for Q-learning
|
||||
*/
|
||||
export declare function generateSARTuples(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Generate complete RL episodes with consistent state transitions
|
||||
*/
|
||||
export declare function generateEpisodes(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Generate data for testing exploration-exploitation trade-offs
|
||||
*/
|
||||
export declare function generateExplorationData(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Generate data for testing and debugging reward functions
|
||||
*/
|
||||
export declare function generateRewardTestingData(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Generate training data for policy gradient methods
|
||||
*/
|
||||
export declare function generatePolicyGradientData(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Generate data for multi-agent reinforcement learning
|
||||
*/
|
||||
export declare function generateMultiAgentData(): Promise<GenerationResult<unknown>>;
|
||||
/**
|
||||
* Example of using generated data in a training loop
|
||||
*/
|
||||
export declare function trainingLoopIntegration(): Promise<void>;
|
||||
export declare function runAllRLExamples(): Promise<void>;
|
||||
//# sourceMappingURL=reinforcement-learning.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"reinforcement-learning.d.ts","sourceRoot":"","sources":["reinforcement-learning.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAM3D;;GAEG;AACH,wBAAsB,iBAAiB,uCAwDtC;AAMD;;GAEG;AACH,wBAAsB,gBAAgB,uCA+DrC;AAMD;;GAEG;AACH,wBAAsB,uBAAuB,uCA0D5C;AAMD;;GAEG;AACH,wBAAsB,yBAAyB,uCAyD9C;AAMD;;GAEG;AACH,wBAAsB,0BAA0B,uCAoD/C;AAMD;;GAEG;AACH,wBAAsB,sBAAsB,uCA0D3C;AA4CD;;GAEG;AACH,wBAAsB,uBAAuB,kBA8B5C;AAMD,wBAAsB,gBAAgB,kBA8BrC"}
|
||||
451
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/reinforcement-learning.js
vendored
Normal file
451
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/reinforcement-learning.js
vendored
Normal file
@@ -0,0 +1,451 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Reinforcement Learning Training Data Generation
|
||||
*
|
||||
* This example demonstrates generating synthetic RL training data including:
|
||||
* - State-action-reward tuples
|
||||
* - Episode generation with temporal consistency
|
||||
* - Exploration vs exploitation scenarios
|
||||
* - Reward function testing
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.generateSARTuples = generateSARTuples;
|
||||
exports.generateEpisodes = generateEpisodes;
|
||||
exports.generateExplorationData = generateExplorationData;
|
||||
exports.generateRewardTestingData = generateRewardTestingData;
|
||||
exports.generatePolicyGradientData = generatePolicyGradientData;
|
||||
exports.generateMultiAgentData = generateMultiAgentData;
|
||||
exports.trainingLoopIntegration = trainingLoopIntegration;
|
||||
exports.runAllRLExamples = runAllRLExamples;
|
||||
const index_js_1 = require("../../src/index.js");
|
||||
// ============================================================================
|
||||
// Example 1: State-Action-Reward Tuples (SAR)
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate basic SAR tuples for Q-learning
|
||||
*/
|
||||
async function generateSARTuples() {
|
||||
console.log('\n🎮 Example 1: State-Action-Reward Tuples\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
cacheStrategy: 'memory',
|
||||
});
|
||||
// Generate SAR tuples for a grid-world environment
|
||||
const sarData = await synth.generateStructured({
|
||||
count: 1000,
|
||||
schema: {
|
||||
// State representation
|
||||
state: {
|
||||
x: 'number (0-10)',
|
||||
y: 'number (0-10)',
|
||||
has_key: 'boolean',
|
||||
health: 'number (0-100)',
|
||||
},
|
||||
// Action taken
|
||||
action: 'up | down | left | right | pickup | use',
|
||||
// Immediate reward
|
||||
reward: 'number (-10 to 100)',
|
||||
// Next state
|
||||
next_state: {
|
||||
x: 'number (0-10, related to action)',
|
||||
y: 'number (0-10, related to action)',
|
||||
has_key: 'boolean',
|
||||
health: 'number (0-100)',
|
||||
},
|
||||
// Terminal state flag
|
||||
done: 'boolean (true if health <= 0 or goal reached)',
|
||||
// Additional metadata
|
||||
metadata: {
|
||||
step: 'number (0-200)',
|
||||
episode_id: 'UUID',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
},
|
||||
constraints: [
|
||||
'Movement actions should change x or y coordinates appropriately',
|
||||
'Reward should be positive for goal states, negative for collisions',
|
||||
'Health should decrease on collision, increase on health pickup',
|
||||
'done should be true when health <= 0 or goal reached',
|
||||
'Ensure temporal consistency within episodes',
|
||||
],
|
||||
});
|
||||
console.log('SAR Tuples Generated:');
|
||||
console.log(`- Total transitions: ${sarData.data.length}`);
|
||||
console.log(`- Sample transition:`, sarData.data[0]);
|
||||
console.log(`- Average reward: ${calculateAverage(sarData.data, 'reward')}`);
|
||||
console.log(`- Terminal states: ${sarData.data.filter((d) => d.done).length}`);
|
||||
return sarData;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 2: Complete Episodes with Temporal Consistency
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate complete RL episodes with consistent state transitions
|
||||
*/
|
||||
async function generateEpisodes() {
|
||||
console.log('\n📚 Example 2: Complete Episodes\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Generate multiple episodes
|
||||
const episodes = await synth.generateStructured({
|
||||
count: 50, // 50 episodes
|
||||
schema: {
|
||||
episode_id: 'UUID',
|
||||
agent_type: 'dqn | ppo | a3c | sac',
|
||||
environment: 'cartpole | mountain_car | lunar_lander',
|
||||
// Episode trajectory
|
||||
trajectory: [
|
||||
{
|
||||
step: 'number (sequential)',
|
||||
state: 'array of 4-8 numbers (state vector)',
|
||||
action: 'number (0-3, discrete action space)',
|
||||
reward: 'number (-1 to 1)',
|
||||
next_state: 'array of 4-8 numbers',
|
||||
done: 'boolean',
|
||||
},
|
||||
],
|
||||
// Episode statistics
|
||||
total_reward: 'number (sum of all rewards)',
|
||||
steps: 'number (10-500, episode length)',
|
||||
success: 'boolean',
|
||||
// Metadata
|
||||
timestamp: 'ISO timestamp',
|
||||
hyperparameters: {
|
||||
learning_rate: 'number (0.0001-0.01)',
|
||||
discount_factor: 'number (0.9-0.99)',
|
||||
epsilon: 'number (0.01-1.0, exploration rate)',
|
||||
},
|
||||
},
|
||||
constraints: [
|
||||
'trajectory array should have length equal to steps',
|
||||
'steps should be sequential from 0 to steps-1',
|
||||
'total_reward should equal sum of trajectory rewards',
|
||||
'last transition should have done=true',
|
||||
'state vectors should have consistent dimensions',
|
||||
'successful episodes should have positive total_reward',
|
||||
],
|
||||
});
|
||||
console.log('Episodes Generated:');
|
||||
console.log(`- Total episodes: ${episodes.data.length}`);
|
||||
console.log(`- Average episode length: ${calculateAverage(episodes.data, 'steps')}`);
|
||||
console.log(`- Success rate: ${calculateSuccessRate(episodes.data)}%`);
|
||||
console.log(`- Sample episode:`, {
|
||||
id: episodes.data[0].episode_id,
|
||||
steps: episodes.data[0].steps,
|
||||
reward: episodes.data[0].total_reward,
|
||||
success: episodes.data[0].success,
|
||||
});
|
||||
return episodes;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 3: Exploration vs Exploitation Scenarios
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate data for testing exploration-exploitation trade-offs
|
||||
*/
|
||||
async function generateExplorationData() {
|
||||
console.log('\n🔍 Example 3: Exploration vs Exploitation\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Generate multi-armed bandit scenarios
|
||||
const banditData = await synth.generateStructured({
|
||||
count: 500,
|
||||
schema: {
|
||||
// Bandit configuration
|
||||
bandit_id: 'UUID',
|
||||
num_arms: 'number (5-10)',
|
||||
// True reward distributions (hidden from agent)
|
||||
true_means: 'array of num_arms numbers (0-1)',
|
||||
true_stddevs: 'array of num_arms numbers (0.05-0.2)',
|
||||
// Agent action
|
||||
action_selected: 'number (0 to num_arms-1)',
|
||||
strategy: 'epsilon_greedy | ucb | thompson_sampling | softmax',
|
||||
// Strategy parameters
|
||||
strategy_params: {
|
||||
epsilon: 'number (0-1) if epsilon_greedy',
|
||||
temperature: 'number (0.1-2.0) if softmax',
|
||||
confidence: 'number (0.5-2.0) if ucb',
|
||||
},
|
||||
// Observed reward
|
||||
observed_reward: 'number (sample from true distribution)',
|
||||
// Agent knowledge
|
||||
q_values: 'array of num_arms numbers (estimated values)',
|
||||
action_counts: 'array of num_arms numbers (times each arm pulled)',
|
||||
// Metadata
|
||||
step: 'number (0-10000)',
|
||||
cumulative_regret: 'number (0-100)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Arrays should have length equal to num_arms',
|
||||
'action_selected should be valid index (0 to num_arms-1)',
|
||||
'observed_reward should be sampled from true_means[action_selected] distribution',
|
||||
'cumulative_regret should increase over time',
|
||||
'strategy_params should match strategy type',
|
||||
],
|
||||
});
|
||||
console.log('Exploration Data Generated:');
|
||||
console.log(`- Total samples: ${banditData.data.length}`);
|
||||
console.log(`- Strategy distribution:`, getStrategyDistribution(banditData.data));
|
||||
console.log(`- Average regret: ${calculateAverage(banditData.data, 'cumulative_regret')}`);
|
||||
return banditData;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 4: Reward Function Testing Data
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate data for testing and debugging reward functions
|
||||
*/
|
||||
async function generateRewardTestingData() {
|
||||
console.log('\n🎯 Example 4: Reward Function Testing\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
// Generate edge cases and scenarios for reward testing
|
||||
const rewardTests = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
test_id: 'UUID',
|
||||
test_category: 'edge_case | normal | boundary | adversarial',
|
||||
// State configuration
|
||||
state: {
|
||||
position: 'array of 2-3 numbers (coordinates)',
|
||||
velocity: 'array of 2-3 numbers',
|
||||
goal_position: 'array of 2-3 numbers',
|
||||
obstacles: ['array of obstacle positions'],
|
||||
},
|
||||
// Expected reward components
|
||||
expected_reward: {
|
||||
distance_reward: 'number (-10 to 0)',
|
||||
velocity_penalty: 'number (-5 to 0)',
|
||||
collision_penalty: 'number (-100 to 0)',
|
||||
goal_bonus: 'number (0 to 100)',
|
||||
time_penalty: 'number (-1 to 0)',
|
||||
total: 'number (sum of components)',
|
||||
},
|
||||
// Test metadata
|
||||
description: 'string (what this test case validates)',
|
||||
expected_behavior: 'string (expected agent behavior)',
|
||||
tags: ['array of test tags (edge_case, collision, goal_reached, etc.)'],
|
||||
// Validation
|
||||
passes_validation: 'boolean',
|
||||
validation_notes: 'string or null',
|
||||
},
|
||||
constraints: [
|
||||
'edge_case tests should have extreme values',
|
||||
'boundary tests should be at limits of valid ranges',
|
||||
'collision_penalty should be large negative for nearby obstacles',
|
||||
'goal_bonus should be positive only when close to goal',
|
||||
'expected_reward.total should equal sum of components',
|
||||
],
|
||||
});
|
||||
console.log('Reward Testing Data Generated:');
|
||||
console.log(`- Total test cases: ${rewardTests.data.length}`);
|
||||
console.log(`- Test categories:`, getTestCategories(rewardTests.data));
|
||||
console.log(`- Passing tests: ${rewardTests.data.filter((d) => d.passes_validation).length}`);
|
||||
return rewardTests;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 5: Policy Gradient Training Data
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate training data for policy gradient methods
|
||||
*/
|
||||
async function generatePolicyGradientData() {
|
||||
console.log('\n📈 Example 5: Policy Gradient Training Data\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
const policyData = await synth.generateStructured({
|
||||
count: 100,
|
||||
schema: {
|
||||
episode_id: 'UUID',
|
||||
// Episode trajectory
|
||||
states: ['array of state vectors (each 4-10 numbers)'],
|
||||
actions: ['array of actions taken'],
|
||||
log_probs: ['array of log probabilities of actions'],
|
||||
rewards: ['array of rewards'],
|
||||
values: ['array of value estimates (if actor-critic)'],
|
||||
// Computed returns and advantages
|
||||
returns: ['array of discounted returns'],
|
||||
advantages: ['array of advantage estimates (if using baseline)'],
|
||||
// Episode metrics
|
||||
episode_length: 'number (length of arrays)',
|
||||
total_return: 'number (sum of rewards)',
|
||||
// Training metadata
|
||||
policy_entropy: 'number (0-2, entropy of action distribution)',
|
||||
value_loss: 'number (if actor-critic)',
|
||||
policy_loss: 'number',
|
||||
// Hyperparameters
|
||||
gamma: 'number (0.95-0.99, discount factor)',
|
||||
lambda_gae: 'number (0.9-0.99, GAE lambda if used)',
|
||||
},
|
||||
constraints: [
|
||||
'All arrays should have same length (episode_length)',
|
||||
'returns should be computed using gamma discount',
|
||||
'advantages should use GAE if lambda_gae provided',
|
||||
'policy_entropy should decrease during training',
|
||||
'Higher returns should correlate with lower policy_loss',
|
||||
],
|
||||
});
|
||||
console.log('Policy Gradient Data Generated:');
|
||||
console.log(`- Episodes: ${policyData.data.length}`);
|
||||
console.log(`- Average return: ${calculateAverage(policyData.data, 'total_return')}`);
|
||||
console.log(`- Average entropy: ${calculateAverage(policyData.data, 'policy_entropy')}`);
|
||||
return policyData;
|
||||
}
|
||||
// ============================================================================
|
||||
// Example 6: Multi-Agent RL Data
|
||||
// ============================================================================
|
||||
/**
|
||||
* Generate data for multi-agent reinforcement learning
|
||||
*/
|
||||
async function generateMultiAgentData() {
|
||||
console.log('\n👥 Example 6: Multi-Agent RL Data\n');
|
||||
const synth = (0, index_js_1.createSynth)({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
const multiAgentData = await synth.generateStructured({
|
||||
count: 50,
|
||||
schema: {
|
||||
episode_id: 'UUID',
|
||||
scenario: 'cooperative | competitive | mixed',
|
||||
num_agents: 'number (2-6)',
|
||||
// Joint trajectory
|
||||
joint_states: [
|
||||
{
|
||||
step: 'number',
|
||||
// Per-agent observations
|
||||
observations: ['array of per-agent state vectors'],
|
||||
// Joint action
|
||||
joint_action: ['array of actions (one per agent)'],
|
||||
// Per-agent rewards
|
||||
rewards: ['array of rewards (one per agent)'],
|
||||
// Global state (if available)
|
||||
global_state: 'array of numbers or null',
|
||||
},
|
||||
],
|
||||
// Episode outcomes
|
||||
agent_returns: ['array of cumulative returns per agent'],
|
||||
winner: 'number (agent index) or null if cooperative',
|
||||
cooperation_score: 'number (0-1, for cooperative scenarios)',
|
||||
// Training info
|
||||
communication_enabled: 'boolean',
|
||||
shared_reward: 'boolean',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'observations, joint_action, and rewards should have length num_agents',
|
||||
'agent_returns should sum to positive for cooperative scenarios',
|
||||
'winner should be agent with highest return in competitive scenarios',
|
||||
'cooperation_score should be high for successful cooperative episodes',
|
||||
],
|
||||
});
|
||||
console.log('Multi-Agent Data Generated:');
|
||||
console.log(`- Episodes: ${multiAgentData.data.length}`);
|
||||
console.log(`- Scenario distribution:`, getScenarioDistribution(multiAgentData.data));
|
||||
console.log(`- Average cooperation score: ${calculateAverage(multiAgentData.data.filter((d) => d.scenario === 'cooperative'), 'cooperation_score')}`);
|
||||
return multiAgentData;
|
||||
}
|
||||
// ============================================================================
|
||||
// Utility Functions
|
||||
// ============================================================================
|
||||
function calculateAverage(data, field) {
|
||||
const values = data.map((d) => d[field]).filter((v) => typeof v === 'number');
|
||||
return values.reduce((a, b) => a + b, 0) / values.length;
|
||||
}
|
||||
function calculateSuccessRate(episodes) {
|
||||
const successful = episodes.filter((e) => e.success).length;
|
||||
return (successful / episodes.length) * 100;
|
||||
}
|
||||
function getStrategyDistribution(data) {
|
||||
const dist = {};
|
||||
data.forEach((d) => {
|
||||
dist[d.strategy] = (dist[d.strategy] || 0) + 1;
|
||||
});
|
||||
return dist;
|
||||
}
|
||||
function getTestCategories(data) {
|
||||
const categories = {};
|
||||
data.forEach((d) => {
|
||||
categories[d.test_category] = (categories[d.test_category] || 0) + 1;
|
||||
});
|
||||
return categories;
|
||||
}
|
||||
function getScenarioDistribution(data) {
|
||||
const scenarios = {};
|
||||
data.forEach((d) => {
|
||||
scenarios[d.scenario] = (scenarios[d.scenario] || 0) + 1;
|
||||
});
|
||||
return scenarios;
|
||||
}
|
||||
// ============================================================================
|
||||
// Integration Example: Training Loop with Generated Data
|
||||
// ============================================================================
|
||||
/**
|
||||
* Example of using generated data in a training loop
|
||||
*/
|
||||
async function trainingLoopIntegration() {
|
||||
console.log('\n🔄 Training Loop Integration Example\n');
|
||||
// Generate initial training batch
|
||||
const trainingBatch = await generateSARTuples();
|
||||
console.log('Simulating training loop with generated data...\n');
|
||||
// Simulate training epochs
|
||||
for (let epoch = 0; epoch < 3; epoch++) {
|
||||
console.log(`Epoch ${epoch + 1}:`);
|
||||
// In real training, you would:
|
||||
// 1. Sample batch from trainingBatch.data
|
||||
// 2. Compute loss and gradients
|
||||
// 3. Update model parameters
|
||||
// 4. Log metrics
|
||||
const sampleSize = 32;
|
||||
const batchSamples = trainingBatch.data.slice(0, sampleSize);
|
||||
// Simulate metrics
|
||||
const avgReward = calculateAverage(batchSamples, 'reward');
|
||||
console.log(` - Batch size: ${sampleSize}`);
|
||||
console.log(` - Average reward: ${avgReward.toFixed(2)}`);
|
||||
console.log(` - Loss: ${(Math.random() * 0.5 + 0.1).toFixed(4)}`);
|
||||
console.log();
|
||||
}
|
||||
console.log('✅ Training loop integration complete');
|
||||
}
|
||||
// ============================================================================
|
||||
// Run All Examples
|
||||
// ============================================================================
|
||||
async function runAllRLExamples() {
|
||||
console.log('🚀 Reinforcement Learning Data Generation Examples\n');
|
||||
console.log('='.repeat(60));
|
||||
try {
|
||||
await generateSARTuples();
|
||||
console.log('='.repeat(60));
|
||||
await generateEpisodes();
|
||||
console.log('='.repeat(60));
|
||||
await generateExplorationData();
|
||||
console.log('='.repeat(60));
|
||||
await generateRewardTestingData();
|
||||
console.log('='.repeat(60));
|
||||
await generatePolicyGradientData();
|
||||
console.log('='.repeat(60));
|
||||
await generateMultiAgentData();
|
||||
console.log('='.repeat(60));
|
||||
await trainingLoopIntegration();
|
||||
console.log('='.repeat(60));
|
||||
console.log('\n✅ All RL examples completed!\n');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('❌ Error:', error.message);
|
||||
}
|
||||
}
|
||||
// Run if executed directly
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runAllRLExamples().catch(console.error);
|
||||
}
|
||||
//# sourceMappingURL=reinforcement-learning.js.map
|
||||
File diff suppressed because one or more lines are too long
528
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/reinforcement-learning.ts
vendored
Normal file
528
vendor/ruvector/npm/packages/agentic-synth/examples/self-learning/reinforcement-learning.ts
vendored
Normal file
@@ -0,0 +1,528 @@
|
||||
/**
|
||||
* Reinforcement Learning Training Data Generation
|
||||
*
|
||||
* This example demonstrates generating synthetic RL training data including:
|
||||
* - State-action-reward tuples
|
||||
* - Episode generation with temporal consistency
|
||||
* - Exploration vs exploitation scenarios
|
||||
* - Reward function testing
|
||||
*/
|
||||
|
||||
import { AgenticSynth, createSynth } from '../../src/index.js';
|
||||
import type { GenerationResult } from '../../src/types.js';
|
||||
|
||||
// ============================================================================
|
||||
// Example 1: State-Action-Reward Tuples (SAR)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate basic SAR tuples for Q-learning
|
||||
*/
|
||||
export async function generateSARTuples() {
|
||||
console.log('\n🎮 Example 1: State-Action-Reward Tuples\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
cacheStrategy: 'memory',
|
||||
});
|
||||
|
||||
// Generate SAR tuples for a grid-world environment
|
||||
const sarData = await synth.generateStructured({
|
||||
count: 1000,
|
||||
schema: {
|
||||
// State representation
|
||||
state: {
|
||||
x: 'number (0-10)',
|
||||
y: 'number (0-10)',
|
||||
has_key: 'boolean',
|
||||
health: 'number (0-100)',
|
||||
},
|
||||
// Action taken
|
||||
action: 'up | down | left | right | pickup | use',
|
||||
// Immediate reward
|
||||
reward: 'number (-10 to 100)',
|
||||
// Next state
|
||||
next_state: {
|
||||
x: 'number (0-10, related to action)',
|
||||
y: 'number (0-10, related to action)',
|
||||
has_key: 'boolean',
|
||||
health: 'number (0-100)',
|
||||
},
|
||||
// Terminal state flag
|
||||
done: 'boolean (true if health <= 0 or goal reached)',
|
||||
// Additional metadata
|
||||
metadata: {
|
||||
step: 'number (0-200)',
|
||||
episode_id: 'UUID',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
},
|
||||
constraints: [
|
||||
'Movement actions should change x or y coordinates appropriately',
|
||||
'Reward should be positive for goal states, negative for collisions',
|
||||
'Health should decrease on collision, increase on health pickup',
|
||||
'done should be true when health <= 0 or goal reached',
|
||||
'Ensure temporal consistency within episodes',
|
||||
],
|
||||
});
|
||||
|
||||
console.log('SAR Tuples Generated:');
|
||||
console.log(`- Total transitions: ${sarData.data.length}`);
|
||||
console.log(`- Sample transition:`, sarData.data[0]);
|
||||
console.log(`- Average reward: ${calculateAverage(sarData.data, 'reward')}`);
|
||||
console.log(`- Terminal states: ${sarData.data.filter((d: any) => d.done).length}`);
|
||||
|
||||
return sarData;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 2: Complete Episodes with Temporal Consistency
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate complete RL episodes with consistent state transitions
|
||||
*/
|
||||
export async function generateEpisodes() {
|
||||
console.log('\n📚 Example 2: Complete Episodes\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Generate multiple episodes
|
||||
const episodes = await synth.generateStructured({
|
||||
count: 50, // 50 episodes
|
||||
schema: {
|
||||
episode_id: 'UUID',
|
||||
agent_type: 'dqn | ppo | a3c | sac',
|
||||
environment: 'cartpole | mountain_car | lunar_lander',
|
||||
|
||||
// Episode trajectory
|
||||
trajectory: [
|
||||
{
|
||||
step: 'number (sequential)',
|
||||
state: 'array of 4-8 numbers (state vector)',
|
||||
action: 'number (0-3, discrete action space)',
|
||||
reward: 'number (-1 to 1)',
|
||||
next_state: 'array of 4-8 numbers',
|
||||
done: 'boolean',
|
||||
},
|
||||
],
|
||||
|
||||
// Episode statistics
|
||||
total_reward: 'number (sum of all rewards)',
|
||||
steps: 'number (10-500, episode length)',
|
||||
success: 'boolean',
|
||||
|
||||
// Metadata
|
||||
timestamp: 'ISO timestamp',
|
||||
hyperparameters: {
|
||||
learning_rate: 'number (0.0001-0.01)',
|
||||
discount_factor: 'number (0.9-0.99)',
|
||||
epsilon: 'number (0.01-1.0, exploration rate)',
|
||||
},
|
||||
},
|
||||
constraints: [
|
||||
'trajectory array should have length equal to steps',
|
||||
'steps should be sequential from 0 to steps-1',
|
||||
'total_reward should equal sum of trajectory rewards',
|
||||
'last transition should have done=true',
|
||||
'state vectors should have consistent dimensions',
|
||||
'successful episodes should have positive total_reward',
|
||||
],
|
||||
});
|
||||
|
||||
console.log('Episodes Generated:');
|
||||
console.log(`- Total episodes: ${episodes.data.length}`);
|
||||
console.log(`- Average episode length: ${calculateAverage(episodes.data, 'steps')}`);
|
||||
console.log(`- Success rate: ${calculateSuccessRate(episodes.data)}%`);
|
||||
console.log(`- Sample episode:`, {
|
||||
id: episodes.data[0].episode_id,
|
||||
steps: episodes.data[0].steps,
|
||||
reward: episodes.data[0].total_reward,
|
||||
success: episodes.data[0].success,
|
||||
});
|
||||
|
||||
return episodes;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 3: Exploration vs Exploitation Scenarios
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate data for testing exploration-exploitation trade-offs
|
||||
*/
|
||||
export async function generateExplorationData() {
|
||||
console.log('\n🔍 Example 3: Exploration vs Exploitation\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Generate multi-armed bandit scenarios
|
||||
const banditData = await synth.generateStructured({
|
||||
count: 500,
|
||||
schema: {
|
||||
// Bandit configuration
|
||||
bandit_id: 'UUID',
|
||||
num_arms: 'number (5-10)',
|
||||
|
||||
// True reward distributions (hidden from agent)
|
||||
true_means: 'array of num_arms numbers (0-1)',
|
||||
true_stddevs: 'array of num_arms numbers (0.05-0.2)',
|
||||
|
||||
// Agent action
|
||||
action_selected: 'number (0 to num_arms-1)',
|
||||
strategy: 'epsilon_greedy | ucb | thompson_sampling | softmax',
|
||||
|
||||
// Strategy parameters
|
||||
strategy_params: {
|
||||
epsilon: 'number (0-1) if epsilon_greedy',
|
||||
temperature: 'number (0.1-2.0) if softmax',
|
||||
confidence: 'number (0.5-2.0) if ucb',
|
||||
},
|
||||
|
||||
// Observed reward
|
||||
observed_reward: 'number (sample from true distribution)',
|
||||
|
||||
// Agent knowledge
|
||||
q_values: 'array of num_arms numbers (estimated values)',
|
||||
action_counts: 'array of num_arms numbers (times each arm pulled)',
|
||||
|
||||
// Metadata
|
||||
step: 'number (0-10000)',
|
||||
cumulative_regret: 'number (0-100)',
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'Arrays should have length equal to num_arms',
|
||||
'action_selected should be valid index (0 to num_arms-1)',
|
||||
'observed_reward should be sampled from true_means[action_selected] distribution',
|
||||
'cumulative_regret should increase over time',
|
||||
'strategy_params should match strategy type',
|
||||
],
|
||||
});
|
||||
|
||||
console.log('Exploration Data Generated:');
|
||||
console.log(`- Total samples: ${banditData.data.length}`);
|
||||
console.log(`- Strategy distribution:`, getStrategyDistribution(banditData.data));
|
||||
console.log(`- Average regret: ${calculateAverage(banditData.data, 'cumulative_regret')}`);
|
||||
|
||||
return banditData;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 4: Reward Function Testing Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate data for testing and debugging reward functions
|
||||
*/
|
||||
export async function generateRewardTestingData() {
|
||||
console.log('\n🎯 Example 4: Reward Function Testing\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
// Generate edge cases and scenarios for reward testing
|
||||
const rewardTests = await synth.generateStructured({
|
||||
count: 200,
|
||||
schema: {
|
||||
test_id: 'UUID',
|
||||
test_category: 'edge_case | normal | boundary | adversarial',
|
||||
|
||||
// State configuration
|
||||
state: {
|
||||
position: 'array of 2-3 numbers (coordinates)',
|
||||
velocity: 'array of 2-3 numbers',
|
||||
goal_position: 'array of 2-3 numbers',
|
||||
obstacles: ['array of obstacle positions'],
|
||||
},
|
||||
|
||||
// Expected reward components
|
||||
expected_reward: {
|
||||
distance_reward: 'number (-10 to 0)',
|
||||
velocity_penalty: 'number (-5 to 0)',
|
||||
collision_penalty: 'number (-100 to 0)',
|
||||
goal_bonus: 'number (0 to 100)',
|
||||
time_penalty: 'number (-1 to 0)',
|
||||
total: 'number (sum of components)',
|
||||
},
|
||||
|
||||
// Test metadata
|
||||
description: 'string (what this test case validates)',
|
||||
expected_behavior: 'string (expected agent behavior)',
|
||||
tags: ['array of test tags (edge_case, collision, goal_reached, etc.)'],
|
||||
|
||||
// Validation
|
||||
passes_validation: 'boolean',
|
||||
validation_notes: 'string or null',
|
||||
},
|
||||
constraints: [
|
||||
'edge_case tests should have extreme values',
|
||||
'boundary tests should be at limits of valid ranges',
|
||||
'collision_penalty should be large negative for nearby obstacles',
|
||||
'goal_bonus should be positive only when close to goal',
|
||||
'expected_reward.total should equal sum of components',
|
||||
],
|
||||
});
|
||||
|
||||
console.log('Reward Testing Data Generated:');
|
||||
console.log(`- Total test cases: ${rewardTests.data.length}`);
|
||||
console.log(`- Test categories:`, getTestCategories(rewardTests.data));
|
||||
console.log(`- Passing tests: ${rewardTests.data.filter((d: any) => d.passes_validation).length}`);
|
||||
|
||||
return rewardTests;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 5: Policy Gradient Training Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate training data for policy gradient methods
|
||||
*/
|
||||
export async function generatePolicyGradientData() {
|
||||
console.log('\n📈 Example 5: Policy Gradient Training Data\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
const policyData = await synth.generateStructured({
|
||||
count: 100,
|
||||
schema: {
|
||||
episode_id: 'UUID',
|
||||
|
||||
// Episode trajectory
|
||||
states: ['array of state vectors (each 4-10 numbers)'],
|
||||
actions: ['array of actions taken'],
|
||||
log_probs: ['array of log probabilities of actions'],
|
||||
rewards: ['array of rewards'],
|
||||
values: ['array of value estimates (if actor-critic)'],
|
||||
|
||||
// Computed returns and advantages
|
||||
returns: ['array of discounted returns'],
|
||||
advantages: ['array of advantage estimates (if using baseline)'],
|
||||
|
||||
// Episode metrics
|
||||
episode_length: 'number (length of arrays)',
|
||||
total_return: 'number (sum of rewards)',
|
||||
|
||||
// Training metadata
|
||||
policy_entropy: 'number (0-2, entropy of action distribution)',
|
||||
value_loss: 'number (if actor-critic)',
|
||||
policy_loss: 'number',
|
||||
|
||||
// Hyperparameters
|
||||
gamma: 'number (0.95-0.99, discount factor)',
|
||||
lambda_gae: 'number (0.9-0.99, GAE lambda if used)',
|
||||
},
|
||||
constraints: [
|
||||
'All arrays should have same length (episode_length)',
|
||||
'returns should be computed using gamma discount',
|
||||
'advantages should use GAE if lambda_gae provided',
|
||||
'policy_entropy should decrease during training',
|
||||
'Higher returns should correlate with lower policy_loss',
|
||||
],
|
||||
});
|
||||
|
||||
console.log('Policy Gradient Data Generated:');
|
||||
console.log(`- Episodes: ${policyData.data.length}`);
|
||||
console.log(`- Average return: ${calculateAverage(policyData.data, 'total_return')}`);
|
||||
console.log(`- Average entropy: ${calculateAverage(policyData.data, 'policy_entropy')}`);
|
||||
|
||||
return policyData;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Example 6: Multi-Agent RL Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Generate data for multi-agent reinforcement learning
|
||||
*/
|
||||
export async function generateMultiAgentData() {
|
||||
console.log('\n👥 Example 6: Multi-Agent RL Data\n');
|
||||
|
||||
const synth = createSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.GEMINI_API_KEY || 'demo-key',
|
||||
});
|
||||
|
||||
const multiAgentData = await synth.generateStructured({
|
||||
count: 50,
|
||||
schema: {
|
||||
episode_id: 'UUID',
|
||||
scenario: 'cooperative | competitive | mixed',
|
||||
num_agents: 'number (2-6)',
|
||||
|
||||
// Joint trajectory
|
||||
joint_states: [
|
||||
{
|
||||
step: 'number',
|
||||
// Per-agent observations
|
||||
observations: ['array of per-agent state vectors'],
|
||||
// Joint action
|
||||
joint_action: ['array of actions (one per agent)'],
|
||||
// Per-agent rewards
|
||||
rewards: ['array of rewards (one per agent)'],
|
||||
// Global state (if available)
|
||||
global_state: 'array of numbers or null',
|
||||
},
|
||||
],
|
||||
|
||||
// Episode outcomes
|
||||
agent_returns: ['array of cumulative returns per agent'],
|
||||
winner: 'number (agent index) or null if cooperative',
|
||||
cooperation_score: 'number (0-1, for cooperative scenarios)',
|
||||
|
||||
// Training info
|
||||
communication_enabled: 'boolean',
|
||||
shared_reward: 'boolean',
|
||||
|
||||
timestamp: 'ISO timestamp',
|
||||
},
|
||||
constraints: [
|
||||
'observations, joint_action, and rewards should have length num_agents',
|
||||
'agent_returns should sum to positive for cooperative scenarios',
|
||||
'winner should be agent with highest return in competitive scenarios',
|
||||
'cooperation_score should be high for successful cooperative episodes',
|
||||
],
|
||||
});
|
||||
|
||||
console.log('Multi-Agent Data Generated:');
|
||||
console.log(`- Episodes: ${multiAgentData.data.length}`);
|
||||
console.log(`- Scenario distribution:`, getScenarioDistribution(multiAgentData.data));
|
||||
console.log(`- Average cooperation score: ${calculateAverage(
|
||||
multiAgentData.data.filter((d: any) => d.scenario === 'cooperative'),
|
||||
'cooperation_score'
|
||||
)}`);
|
||||
|
||||
return multiAgentData;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Utility Functions
|
||||
// ============================================================================
|
||||
|
||||
function calculateAverage(data: any[], field: string): number {
|
||||
const values = data.map((d) => d[field]).filter((v) => typeof v === 'number');
|
||||
return values.reduce((a, b) => a + b, 0) / values.length;
|
||||
}
|
||||
|
||||
function calculateSuccessRate(episodes: any[]): number {
|
||||
const successful = episodes.filter((e) => e.success).length;
|
||||
return (successful / episodes.length) * 100;
|
||||
}
|
||||
|
||||
function getStrategyDistribution(data: any[]): Record<string, number> {
|
||||
const dist: Record<string, number> = {};
|
||||
data.forEach((d) => {
|
||||
dist[d.strategy] = (dist[d.strategy] || 0) + 1;
|
||||
});
|
||||
return dist;
|
||||
}
|
||||
|
||||
function getTestCategories(data: any[]): Record<string, number> {
|
||||
const categories: Record<string, number> = {};
|
||||
data.forEach((d) => {
|
||||
categories[d.test_category] = (categories[d.test_category] || 0) + 1;
|
||||
});
|
||||
return categories;
|
||||
}
|
||||
|
||||
function getScenarioDistribution(data: any[]): Record<string, number> {
|
||||
const scenarios: Record<string, number> = {};
|
||||
data.forEach((d) => {
|
||||
scenarios[d.scenario] = (scenarios[d.scenario] || 0) + 1;
|
||||
});
|
||||
return scenarios;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Integration Example: Training Loop with Generated Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Example of using generated data in a training loop
|
||||
*/
|
||||
export async function trainingLoopIntegration() {
|
||||
console.log('\n🔄 Training Loop Integration Example\n');
|
||||
|
||||
// Generate initial training batch
|
||||
const trainingBatch = await generateSARTuples();
|
||||
|
||||
console.log('Simulating training loop with generated data...\n');
|
||||
|
||||
// Simulate training epochs
|
||||
for (let epoch = 0; epoch < 3; epoch++) {
|
||||
console.log(`Epoch ${epoch + 1}:`);
|
||||
|
||||
// In real training, you would:
|
||||
// 1. Sample batch from trainingBatch.data
|
||||
// 2. Compute loss and gradients
|
||||
// 3. Update model parameters
|
||||
// 4. Log metrics
|
||||
|
||||
const sampleSize = 32;
|
||||
const batchSamples = trainingBatch.data.slice(0, sampleSize);
|
||||
|
||||
// Simulate metrics
|
||||
const avgReward = calculateAverage(batchSamples, 'reward');
|
||||
console.log(` - Batch size: ${sampleSize}`);
|
||||
console.log(` - Average reward: ${avgReward.toFixed(2)}`);
|
||||
console.log(` - Loss: ${(Math.random() * 0.5 + 0.1).toFixed(4)}`);
|
||||
console.log();
|
||||
}
|
||||
|
||||
console.log('✅ Training loop integration complete');
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Run All Examples
|
||||
// ============================================================================
|
||||
|
||||
export async function runAllRLExamples() {
|
||||
console.log('🚀 Reinforcement Learning Data Generation Examples\n');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
try {
|
||||
await generateSARTuples();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generateEpisodes();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generateExplorationData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generateRewardTestingData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generatePolicyGradientData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await generateMultiAgentData();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
await trainingLoopIntegration();
|
||||
console.log('='.repeat(60));
|
||||
|
||||
console.log('\n✅ All RL examples completed!\n');
|
||||
} catch (error: any) {
|
||||
console.error('❌ Error:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Run if executed directly
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runAllRLExamples().catch(console.error);
|
||||
}
|
||||
Reference in New Issue
Block a user