index.html•27.8 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meta-Learning (MAML) - AgentDB WASM</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #4a148c 0%, #6a1b9a 100%);
min-height: 100vh;
padding: 2rem;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
header {
text-align: center;
color: white;
margin-bottom: 2rem;
}
h1 {
font-size: 2rem;
margin-bottom: 0.5rem;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.subtitle {
opacity: 0.9;
font-size: 1rem;
}
.main-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.5rem;
margin-bottom: 1.5rem;
}
.card {
background: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 8px 24px rgba(0,0,0,0.2);
}
.card h2 {
color: #333;
margin-bottom: 1rem;
font-size: 1.3rem;
}
.description {
background: #f3e5f5;
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
line-height: 1.6;
color: #555;
}
.task-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
margin-bottom: 1.5rem;
}
.task-card {
background: #f5f5f5;
border: 2px solid #e0e0e0;
border-radius: 8px;
padding: 1rem;
cursor: pointer;
transition: all 0.3s;
}
.task-card:hover {
border-color: #6a1b9a;
transform: translateY(-2px);
}
.task-card.active {
background: #f3e5f5;
border-color: #6a1b9a;
}
.task-icon {
font-size: 2rem;
margin-bottom: 0.5rem;
text-align: center;
}
.task-name {
font-weight: 600;
text-align: center;
color: #333;
margin-bottom: 0.5rem;
}
.task-examples {
font-size: 0.85rem;
color: #666;
text-align: center;
}
.btn {
padding: 0.75rem 1.5rem;
background: linear-gradient(135deg, #4a148c 0%, #6a1b9a 100%);
color: white;
border: none;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: opacity 0.3s;
width: 100%;
margin-bottom: 0.5rem;
}
.btn:hover {
opacity: 0.9;
}
.btn.success {
background: linear-gradient(135deg, #2e7d32 0%, #1b5e20 100%);
}
.stat-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
margin-bottom: 1rem;
}
.stat-item {
background: #f5f5f5;
padding: 1rem;
border-radius: 8px;
text-align: center;
}
.stat-label {
font-size: 0.85rem;
color: #666;
margin-bottom: 0.5rem;
}
.stat-value {
font-size: 1.5rem;
font-weight: bold;
color: #4a148c;
}
.training-progress {
margin-bottom: 1rem;
}
.progress-bar {
width: 100%;
height: 30px;
background: #e0e0e0;
border-radius: 15px;
overflow: hidden;
margin-bottom: 0.5rem;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #4a148c 0%, #6a1b9a 100%);
transition: width 0.3s;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 600;
font-size: 0.85rem;
}
.examples-container {
background: #f9f9f9;
padding: 1rem;
border-radius: 8px;
max-height: 300px;
overflow-y: auto;
}
.example-item {
background: white;
padding: 0.75rem;
margin-bottom: 0.5rem;
border-radius: 6px;
border-left: 4px solid #6a1b9a;
}
.example-input {
font-family: 'Courier New', monospace;
color: #333;
margin-bottom: 0.25rem;
}
.example-output {
font-family: 'Courier New', monospace;
color: #2e7d32;
font-weight: 600;
}
#testInput {
width: 100%;
padding: 0.75rem;
border: 2px solid #ddd;
border-radius: 6px;
font-family: 'Courier New', monospace;
font-size: 1rem;
margin-bottom: 1rem;
}
#prediction {
background: #e8f5e9;
padding: 1rem;
border-radius: 8px;
border-left: 4px solid #2e7d32;
font-family: 'Courier New', monospace;
font-size: 1.1rem;
font-weight: 600;
color: #1b5e20;
text-align: center;
}
.meta-info {
background: #fff3e0;
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
border-left: 4px solid #f57c00;
}
.meta-info-title {
font-weight: 600;
color: #e65100;
margin-bottom: 0.5rem;
}
.meta-info-text {
font-size: 0.9rem;
color: #666;
line-height: 1.6;
}
#log {
max-height: 200px;
overflow-y: auto;
background: #f9f9f9;
padding: 1rem;
border-radius: 8px;
font-family: 'Courier New', monospace;
font-size: 0.85rem;
line-height: 1.6;
}
.log-entry {
margin-bottom: 0.5rem;
color: #555;
}
.log-entry.success {
color: #2e7d32;
}
.log-entry.info {
color: #1976d2;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>🧠 Meta-Learning: Learning to Learn</h1>
<p class="subtitle">Model-Agnostic Meta-Learning (MAML) with Few-Shot Adaptation</p>
</header>
<div class="main-grid">
<div class="card">
<h2>Task Selection</h2>
<div class="description">
Meta-learning enables rapid adaptation to new tasks with just a few examples. The model learns meta-parameters that can quickly specialize to any task from the same distribution.
</div>
<div class="task-grid">
<div class="task-card active" onclick="selectTask('addition')">
<div class="task-icon">➕</div>
<div class="task-name">Addition</div>
<div class="task-examples">2 + 3 = 5</div>
</div>
<div class="task-card" onclick="selectTask('multiplication')">
<div class="task-icon">✖️</div>
<div class="task-name">Multiplication</div>
<div class="task-examples">3 × 4 = 12</div>
</div>
<div class="task-card" onclick="selectTask('vowelcount')">
<div class="task-icon">🔤</div>
<div class="task-name">Vowel Count</div>
<div class="task-examples">hello → 2</div>
</div>
<div class="task-card" onclick="selectTask('reverse')">
<div class="task-icon">🔄</div>
<div class="task-name">String Reverse</div>
<div class="task-examples">abc → cba</div>
</div>
<div class="task-card" onclick="selectTask('factorial')">
<div class="task-icon">📊</div>
<div class="task-name">Factorial</div>
<div class="task-examples">5! = 120</div>
</div>
<div class="task-card" onclick="selectTask('titlecase')">
<div class="task-icon">🔠</div>
<div class="task-name">Title Case</div>
<div class="task-examples">hello → Hello</div>
</div>
</div>
<h2>Training Examples (Few-Shot)</h2>
<div class="examples-container" id="examples">
<!-- Populated dynamically -->
</div>
<button class="btn" onclick="startMetaTraining()">🚀 Start Meta-Training</button>
<button class="btn success" onclick="adaptToTask()">⚡ Few-Shot Adaptation</button>
</div>
<div class="card">
<h2>Meta-Learning Status</h2>
<div class="meta-info">
<div class="meta-info-title">🎯 Current Task: <span id="currentTask">Addition</span></div>
<div class="meta-info-text">
Meta-learner is training across multiple tasks to learn universal adaptation strategies.
After meta-training, it can adapt to any new task with just 3-5 examples!
</div>
</div>
<div class="training-progress">
<div class="progress-bar">
<div class="progress-fill" id="progressBar" style="width: 0%">0%</div>
</div>
</div>
<div class="stat-grid">
<div class="stat-item">
<div class="stat-label">Meta-Training Steps</div>
<div class="stat-value" id="metaSteps">0</div>
</div>
<div class="stat-item">
<div class="stat-label">Tasks Learned</div>
<div class="stat-value" id="tasksLearned">0</div>
</div>
<div class="stat-item">
<div class="stat-label">Adaptation Speed</div>
<div class="stat-value" id="adaptSpeed">0.0</div>
</div>
<div class="stat-item">
<div class="stat-label">Meta-Accuracy</div>
<div class="stat-value" id="metaAccuracy">0%</div>
</div>
</div>
<h2>Test Few-Shot Learning</h2>
<input type="text" id="testInput" placeholder="Enter test input (e.g., '7 + 3' for addition)">
<div id="prediction">Make a prediction...</div>
</div>
</div>
<div class="card">
<h2>📊 Meta-Learning Log</h2>
<div id="log"></div>
</div>
</div>
<script>
// Simulated Meta-Learning System with AgentDB
class MetaLearningDB {
constructor() {
this.metaParameters = this.initializeMetaParameters();
this.taskEmbeddings = new Map();
this.adaptationHistory = [];
this.knowledgeBase = [];
}
initializeMetaParameters() {
// Initialize meta-learnable parameters (simplified neural network weights)
return {
inputWeights: Array(128).fill(0).map(() => (Math.random() - 0.5) * 0.1),
hiddenWeights: Array(128).fill(0).map(() => (Math.random() - 0.5) * 0.1),
outputWeights: Array(64).fill(0).map(() => (Math.random() - 0.5) * 0.1),
learningRate: 0.01
};
}
async storeTaskEmbedding(taskName, examples) {
const embedding = this.generateTaskEmbedding(examples);
this.taskEmbeddings.set(taskName, {
embedding,
examples,
timestamp: Date.now()
});
}
generateTaskEmbedding(examples) {
const embedding = new Array(256).fill(0);
examples.forEach((ex, idx) => {
const inputStr = JSON.stringify(ex.input);
const outputStr = JSON.stringify(ex.output);
for (let i = 0; i < inputStr.length; i++) {
const char = inputStr.charCodeAt(i);
embedding[i % 128] += Math.sin(char * (idx + 1));
}
for (let i = 0; i < outputStr.length; i++) {
const char = outputStr.charCodeAt(i);
embedding[128 + (i % 128)] += Math.cos(char * (idx + 1));
}
});
return this.normalize(embedding);
}
async metaTrain(tasks, steps = 100) {
logMessage('🧠 Starting meta-training across all tasks...', 'info');
for (let step = 0; step < steps; step++) {
// Sample batch of tasks
const taskBatch = this.sampleTasks(tasks, 3);
let metaGradient = {
inputWeights: Array(128).fill(0),
hiddenWeights: Array(128).fill(0),
outputWeights: Array(64).fill(0)
};
// Inner loop: adapt to each task
for (const task of taskBatch) {
const adapted = await this.innerLoopAdaptation(task, 5);
// Accumulate gradients
for (let i = 0; i < metaGradient.inputWeights.length; i++) {
metaGradient.inputWeights[i] += adapted.gradients.inputWeights[i];
metaGradient.hiddenWeights[i] += adapted.gradients.hiddenWeights[i];
}
for (let i = 0; i < metaGradient.outputWeights.length; i++) {
metaGradient.outputWeights[i] += adapted.gradients.outputWeights[i];
}
}
// Outer loop: update meta-parameters
this.updateMetaParameters(metaGradient, taskBatch.length);
if (step % 10 === 0) {
const accuracy = await this.evaluateMetaLearner(tasks);
stats.metaAccuracy = (accuracy * 100).toFixed(1);
stats.metaSteps = step;
updateStats();
updateProgress((step / steps) * 100);
}
// Simulate async
if (step % 20 === 0) {
await new Promise(resolve => setTimeout(resolve, 10));
}
}
logMessage('✅ Meta-training complete! Model can now rapidly adapt to new tasks.', 'success');
stats.tasksLearned = tasks.length;
updateStats();
}
async innerLoopAdaptation(task, steps) {
// Clone meta-parameters for task-specific adaptation
const taskParams = JSON.parse(JSON.stringify(this.metaParameters));
const gradients = {
inputWeights: Array(128).fill(0),
hiddenWeights: Array(128).fill(0),
outputWeights: Array(64).fill(0)
};
// Fast adaptation with few examples
for (let i = 0; i < steps; i++) {
task.examples.forEach(ex => {
const prediction = this.forward(ex.input, taskParams);
const error = ex.output - prediction;
// Compute gradients (simplified backprop)
for (let j = 0; j < gradients.inputWeights.length; j++) {
gradients.inputWeights[j] += error * 0.01;
gradients.hiddenWeights[j] += error * 0.01;
}
for (let j = 0; j < gradients.outputWeights.length; j++) {
gradients.outputWeights[j] += error * 0.01;
}
});
}
return { taskParams, gradients };
}
updateMetaParameters(metaGradient, batchSize) {
const lr = this.metaParameters.learningRate;
for (let i = 0; i < this.metaParameters.inputWeights.length; i++) {
this.metaParameters.inputWeights[i] -= lr * metaGradient.inputWeights[i] / batchSize;
this.metaParameters.hiddenWeights[i] -= lr * metaGradient.hiddenWeights[i] / batchSize;
}
for (let i = 0; i < this.metaParameters.outputWeights.length; i++) {
this.metaParameters.outputWeights[i] -= lr * metaGradient.outputWeights[i] / batchSize;
}
}
async fewShotAdapt(task, examples) {
const startTime = Date.now();
// Rapid adaptation using meta-learned initialization
const adapted = await this.innerLoopAdaptation({examples}, 10);
const adaptTime = Date.now() - startTime;
stats.adaptSpeed = (1000 / adaptTime).toFixed(1);
this.adaptationHistory.push({
task: task,
examples: examples.length,
adaptTime: adaptTime,
timestamp: Date.now()
});
logMessage(`⚡ Adapted to ${task} in ${adaptTime}ms with ${examples.length} examples`, 'success');
return adapted.taskParams;
}
forward(input, params) {
// Simplified forward pass through network
const inputVec = this.encodeInput(input);
let hidden = 0;
for (let i = 0; i < Math.min(inputVec.length, params.inputWeights.length); i++) {
hidden += inputVec[i] * params.inputWeights[i];
}
hidden = Math.tanh(hidden); // Activation
let output = 0;
for (let i = 0; i < params.outputWeights.length; i++) {
output += hidden * params.outputWeights[i % params.hiddenWeights.length];
}
return output;
}
encodeInput(input) {
const str = typeof input === 'string' ? input : JSON.stringify(input);
const vec = new Array(128).fill(0);
for (let i = 0; i < str.length; i++) {
vec[i % 128] += str.charCodeAt(i) / 128;
}
return this.normalize(vec);
}
async evaluateMetaLearner(tasks) {
let correct = 0;
let total = 0;
for (const task of tasks) {
const testExamples = task.examples.slice(0, 3);
for (const ex of testExamples) {
const pred = this.forward(ex.input, this.metaParameters);
if (Math.abs(pred - ex.output) < 0.5) correct++;
total++;
}
}
return total > 0 ? correct / total : 0;
}
sampleTasks(tasks, count) {
const sampled = [];
for (let i = 0; i < count; i++) {
sampled.push(tasks[Math.floor(Math.random() * tasks.length)]);
}
return sampled;
}
normalize(vec) {
const mag = Math.sqrt(vec.reduce((sum, v) => sum + v * v, 0));
return vec.map(v => v / (mag || 1));
}
}
// Task definitions
const TASKS = {
addition: {
name: 'Addition',
generator: () => {
const a = Math.floor(Math.random() * 20);
const b = Math.floor(Math.random() * 20);
return { input: `${a} + ${b}`, output: a + b };
},
examples: []
},
multiplication: {
name: 'Multiplication',
generator: () => {
const a = Math.floor(Math.random() * 10);
const b = Math.floor(Math.random() * 10);
return { input: `${a} × ${b}`, output: a * b };
},
examples: []
},
vowelcount: {
name: 'Vowel Count',
generator: () => {
const words = ['hello', 'world', 'meta', 'learn', 'adaptive', 'neural'];
const word = words[Math.floor(Math.random() * words.length)];
const count = (word.match(/[aeiou]/gi) || []).length;
return { input: word, output: count };
},
examples: []
},
reverse: {
name: 'String Reverse',
generator: () => {
const words = ['abc', 'xyz', 'meta', 'learn'];
const word = words[Math.floor(Math.random() * words.length)];
return { input: word, output: word.split('').reverse().join('').charCodeAt(0) };
},
examples: []
},
factorial: {
name: 'Factorial',
generator: () => {
const n = Math.floor(Math.random() * 6) + 1;
let fact = 1;
for (let i = 2; i <= n; i++) fact *= i;
return { input: `${n}!`, output: fact };
},
examples: []
},
titlecase: {
name: 'Title Case',
generator: () => {
const words = ['hello', 'world', 'meta', 'learn'];
const word = words[Math.floor(Math.random() * words.length)];
return {
input: word,
output: word.charAt(0).toUpperCase().charCodeAt(0)
};
},
examples: []
}
};
// Global state
const db = new MetaLearningDB();
let currentTask = 'addition';
let adaptedModel = null;
let stats = {
metaSteps: 0,
tasksLearned: 0,
adaptSpeed: 0,
metaAccuracy: 0
};
// Generate examples for each task
Object.keys(TASKS).forEach(taskName => {
for (let i = 0; i < 5; i++) {
TASKS[taskName].examples.push(TASKS[taskName].generator());
}
});
function selectTask(taskName) {
currentTask = taskName;
document.querySelectorAll('.task-card').forEach(card => {
card.classList.remove('active');
});
event.target.closest('.task-card').classList.add('active');
document.getElementById('currentTask').textContent = TASKS[taskName].name;
displayExamples();
logMessage(`Selected task: ${TASKS[taskName].name}`, 'info');
}
function displayExamples() {
const container = document.getElementById('examples');
container.innerHTML = '';
TASKS[currentTask].examples.forEach((ex, idx) => {
const div = document.createElement('div');
div.className = 'example-item';
div.innerHTML = `
<div class="example-input">Input: ${ex.input}</div>
<div class="example-output">Output: ${ex.output}</div>
`;
container.appendChild(div);
});
}
async function startMetaTraining() {
logMessage('🚀 Initiating meta-training across all task distributions...', 'info');
const allTasks = Object.keys(TASKS).map(name => ({
name,
examples: TASKS[name].examples
}));
await db.metaTrain(allTasks, 100);
logMessage('✨ Meta-parameters optimized for rapid task adaptation!', 'success');
}
async function adaptToTask() {
const task = TASKS[currentTask];
logMessage(`⚡ Few-shot adapting to ${task.name} with ${task.examples.length} examples...`, 'info');
adaptedModel = await db.fewShotAdapt(currentTask, task.examples);
updateStats();
logMessage(`✅ Model adapted! Ready for inference on ${task.name}`, 'success');
}
function updateStats() {
document.getElementById('metaSteps').textContent = stats.metaSteps;
document.getElementById('tasksLearned').textContent = stats.tasksLearned;
document.getElementById('adaptSpeed').textContent = stats.adaptSpeed + 'x';
document.getElementById('metaAccuracy').textContent = stats.metaAccuracy + '%';
}
function updateProgress(percent) {
const bar = document.getElementById('progressBar');
bar.style.width = percent + '%';
bar.textContent = Math.floor(percent) + '%';
}
function logMessage(message, type = '') {
const log = document.getElementById('log');
const entry = document.createElement('div');
entry.className = `log-entry ${type}`;
const timestamp = new Date().toLocaleTimeString();
entry.textContent = `[${timestamp}] ${message}`;
log.insertBefore(entry, log.firstChild);
while (log.children.length > 20) {
log.removeChild(log.lastChild);
}
}
// Test input handler
document.getElementById('testInput').addEventListener('input', (e) => {
if (!adaptedModel) {
document.getElementById('prediction').textContent = '⚠️ Please adapt the model first!';
return;
}
const input = e.target.value;
if (!input) {
document.getElementById('prediction').textContent = 'Make a prediction...';
return;
}
const prediction = db.forward(input, adaptedModel);
document.getElementById('prediction').textContent = `Prediction: ${prediction.toFixed(2)}`;
});
// Initialize
displayExamples();
logMessage('🧠 Meta-Learning system initialized', 'success');
logMessage('Select a task and start meta-training to learn universal adaptation!', 'info');
</script>
</body>
</html>