Squashed 'vendor/ruvector/' content from commit b64c2172

git-subtree-dir: vendor/ruvector
git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
This commit is contained in:
ruv
2026-02-28 14:39:40 -05:00
commit d803bfe2b1
7854 changed files with 3522914 additions and 0 deletions

View File

@@ -0,0 +1,300 @@
"use strict";
/**
* INTERMEDIATE TUTORIAL: Self-Learning System
*
* Build an adaptive AI system that improves its output quality over time
* through feedback loops and pattern recognition. This demonstrates how
* to create systems that learn from their mistakes and successes.
*
* What you'll learn:
* - Building feedback loops
* - Tracking quality improvements
* - Adaptive prompt engineering
* - Learning from examples
*
* Prerequisites:
* - Set GEMINI_API_KEY environment variable
* - npm install dspy.ts @ruvector/agentic-synth
*
* Run: npx tsx examples/intermediate/self-learning-system.ts
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SelfLearningGenerator = void 0;
const dspy_ts_1 = require("dspy.ts");
// Self-learning generator class
class SelfLearningGenerator {
constructor(config = {}) {
this.history = [];
this.currentPromptAdditions = [];
this.config = {
targetQualityThreshold: config.targetQualityThreshold || 0.9,
maxIterations: config.maxIterations || 10,
improvementRate: config.improvementRate || 0.15,
minImprovement: config.minImprovement || 0.02
};
this.lm = new dspy_ts_1.LM({
provider: 'google-genai',
model: 'gemini-2.0-flash-exp',
apiKey: process.env.GEMINI_API_KEY || '',
temperature: 0.8 // Higher temperature for creativity during learning
});
this.basePrompt = '';
}
// Evaluate the quality of generated output
evaluateOutput(prediction, criteria) {
let quality = 0;
const strengths = [];
const weaknesses = [];
const suggestions = [];
// Check description quality
if (prediction.description) {
const desc = prediction.description;
const length = desc.length;
if (length >= 100 && length <= 200) {
quality += 0.3;
strengths.push('Description length is optimal');
}
else if (length < 50) {
weaknesses.push('Description too short');
suggestions.push('Expand description with more details');
}
else if (length > 250) {
weaknesses.push('Description too verbose');
suggestions.push('Make description more concise');
}
else {
quality += 0.15;
}
// Check for emotional/engaging language
const emotionalWords = ['amazing', 'powerful', 'innovative', 'premium', 'exceptional'];
const hasEmotionalLanguage = emotionalWords.some(word => desc.toLowerCase().includes(word));
if (hasEmotionalLanguage) {
quality += 0.2;
strengths.push('Uses engaging language');
}
else {
weaknesses.push('Could be more engaging');
suggestions.push('Add more descriptive and emotional words');
}
}
else {
weaknesses.push('Missing description');
suggestions.push('Generate a complete description');
}
// Check features
if (prediction.key_features && Array.isArray(prediction.key_features)) {
const features = prediction.key_features;
if (features.length >= 4 && features.length <= 6) {
quality += 0.3;
strengths.push('Optimal number of features');
}
else if (features.length < 3) {
weaknesses.push('Too few features');
suggestions.push('Include at least 4 key features');
}
else {
quality += 0.15;
}
// Check feature quality (should be concise)
const wellFormedFeatures = features.filter(f => f.length >= 10 && f.length <= 50);
if (wellFormedFeatures.length === features.length) {
quality += 0.2;
strengths.push('All features are well-formed');
}
else {
weaknesses.push('Some features need better formatting');
suggestions.push('Keep features concise (10-50 chars)');
}
}
else {
weaknesses.push('Missing features');
suggestions.push('Generate key features list');
}
return { quality, strengths, weaknesses, suggestions };
}
// Adapt prompt based on feedback
adaptPrompt(feedback) {
const modifications = [];
// Add specific instructions based on weaknesses
feedback.suggestions.forEach(suggestion => {
if (suggestion.includes('short')) {
modifications.push('Write detailed descriptions (100-200 characters)');
}
else if (suggestion.includes('verbose')) {
modifications.push('Keep descriptions concise and focused');
}
else if (suggestion.includes('engaging')) {
modifications.push('Use descriptive, engaging language');
}
else if (suggestion.includes('features')) {
modifications.push('Include 4-6 specific, measurable key features');
}
else if (suggestion.includes('concise')) {
modifications.push('Format features as short, punchy statements');
}
});
// Remove duplicates
return [...new Set(modifications)];
}
// Generate with current prompt
async generate(input) {
// Build enhanced signature with learned improvements
const enhancedInstructions = this.currentPromptAdditions.length > 0
? '\n\nImportant guidelines:\n' + this.currentPromptAdditions.map((s, i) => `${i + 1}. ${s}`).join('\n')
: '';
const signature = {
input: 'product_name: string, category: string, price: number',
output: 'description: string, key_features: string[]',
description: 'Generate compelling product descriptions' + enhancedInstructions
};
const generator = new dspy_ts_1.ChainOfThought(signature, { lm: this.lm });
return await generator.forward(input);
}
// Main learning loop
async learn(input, criteria = {}) {
console.log('🧠 Starting Self-Learning Session\n');
console.log('='.repeat(70));
console.log(`\nTarget Quality: ${(this.config.targetQualityThreshold * 100).toFixed(0)}%`);
console.log(`Max Iterations: ${this.config.maxIterations}`);
console.log(`Input: ${JSON.stringify(input, null, 2)}\n`);
console.log('='.repeat(70) + '\n');
let iteration = 0;
let previousQuality = 0;
while (iteration < this.config.maxIterations) {
iteration++;
console.log(`\n📊 Iteration ${iteration}/${this.config.maxIterations}`);
console.log('─'.repeat(70));
// Generate output
const startTime = Date.now();
const output = await this.generate(input);
const duration = Date.now() - startTime;
// Evaluate
const feedback = this.evaluateOutput(output, criteria);
// Store in history
this.history.push({
iteration,
quality: feedback.quality,
output,
feedback,
promptModifications: [...this.currentPromptAdditions],
timestamp: new Date()
});
// Display results
console.log(`\n⏱️ Generation time: ${duration}ms`);
console.log(`\n📝 Output:`);
console.log(` Description: ${output.description || 'N/A'}`);
if (output.key_features) {
console.log(` Features:`);
output.key_features.forEach((f) => console.log(`${f}`));
}
console.log(`\n📈 Quality: ${(feedback.quality * 100).toFixed(1)}%`);
if (feedback.strengths.length > 0) {
console.log(`\n✅ Strengths:`);
feedback.strengths.forEach(s => console.log(`${s}`));
}
if (feedback.weaknesses.length > 0) {
console.log(`\n⚠️ Weaknesses:`);
feedback.weaknesses.forEach(w => console.log(`${w}`));
}
// Check if target reached
if (feedback.quality >= this.config.targetQualityThreshold) {
console.log(`\n🎯 Target quality reached!`);
break;
}
// Check for improvement
const improvement = feedback.quality - previousQuality;
if (iteration > 1 && improvement < this.config.minImprovement) {
console.log(`\n⚠️ Improvement too small (${(improvement * 100).toFixed(1)}%), stopping...`);
break;
}
// Adapt for next iteration
const modifications = this.adaptPrompt(feedback);
if (modifications.length > 0) {
console.log(`\n🔧 Adapting strategy:`);
modifications.forEach(m => console.log(`${m}`));
// Add new modifications
modifications.forEach(m => {
if (!this.currentPromptAdditions.includes(m)) {
this.currentPromptAdditions.push(m);
}
});
}
previousQuality = feedback.quality;
// Brief pause between iterations
await new Promise(resolve => setTimeout(resolve, 1000));
}
// Final summary
this.displaySummary();
}
// Display learning summary
displaySummary() {
console.log('\n\n' + '='.repeat(70));
console.log('\n🎓 LEARNING SUMMARY\n');
if (this.history.length === 0) {
console.log('No learning history available.\n');
return;
}
const firstQuality = this.history[0].quality;
const lastQuality = this.history[this.history.length - 1].quality;
const improvement = lastQuality - firstQuality;
const improvementPercent = (improvement / firstQuality) * 100;
console.log(`Total Iterations: ${this.history.length}`);
console.log(`Starting Quality: ${(firstQuality * 100).toFixed(1)}%`);
console.log(`Final Quality: ${(lastQuality * 100).toFixed(1)}%`);
console.log(`Improvement: ${improvement >= 0 ? '+' : ''}${(improvement * 100).toFixed(1)}% (${improvementPercent >= 0 ? '+' : ''}${improvementPercent.toFixed(1)}%)`);
console.log(`\n📊 Quality Progression:`);
this.history.forEach(entry => {
const bar = '█'.repeat(Math.floor(entry.quality * 50));
const percent = (entry.quality * 100).toFixed(1);
console.log(` Iteration ${entry.iteration}: ${bar} ${percent}%`);
});
console.log(`\n🔧 Learned Improvements (${this.currentPromptAdditions.length}):`);
this.currentPromptAdditions.forEach((mod, i) => {
console.log(` ${i + 1}. ${mod}`);
});
console.log('\n💡 Key Insights:');
if (improvement > 0) {
console.log(` ✓ System successfully learned and improved`);
console.log(` ✓ Quality increased by ${(improvement * 100).toFixed(1)}%`);
}
console.log(` ✓ Discovered ${this.currentPromptAdditions.length} optimization strategies`);
console.log(` ✓ These improvements can be applied to future generations\n`);
console.log('='.repeat(70) + '\n');
}
// Get the learned prompt modifications
getLearnedImprovements() {
return [...this.currentPromptAdditions];
}
// Get learning history
getHistory() {
return [...this.history];
}
}
exports.SelfLearningGenerator = SelfLearningGenerator;
// Main execution
async function runSelfLearning() {
const generator = new SelfLearningGenerator({
targetQualityThreshold: 0.85,
maxIterations: 8,
improvementRate: 0.15,
minImprovement: 0.03
});
const testProduct = {
product_name: 'Professional DSLR Camera',
category: 'Photography',
price: 1299
};
await generator.learn(testProduct);
// Save learned improvements
const improvements = generator.getLearnedImprovements();
console.log('📝 Learned improvements can be reused:\n');
console.log(JSON.stringify(improvements, null, 2) + '\n');
}
// Run the example
if (import.meta.url === `file://${process.argv[1]}`) {
runSelfLearning().catch(error => {
console.error('❌ Learning failed:', error);
process.exit(1);
});
}
//# sourceMappingURL=self-learning-system.js.map