Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/ai-music-system / lib/training.js |
| Date | Not specified in source |
| Repository | Janady13/ai-music-system |
| Revision | cd5207850253ee238f8a267c043b1e3c070ed81a |
| Branch | codex/create-ai-for-music-generation-ifwcfc |
| Path or archive member | lib/training.js |
| Original SHA-256 | 9096c11b4feabe521411055ba5500ee31d424eb38f62dbc5d26a8d5777a9ed8b |
| Git blob SHA | 33cf1ba3382c2504f3c061e3dfc7ba42bd34740e |
| Reading-copy SHA-256 | 9096c11b4feabe521411055ba5500ee31d424eb38f62dbc5d26a8d5777a9ed8b |
Recovered source transcript
Download complete source text ↓140 lines · 4.1 KB
const fs = require("fs");
const path = require("path");
const { write } = require("./state");
const { loadCorpus } = require("./music/generator");
const ROOT = path.join(__dirname, "..");
const DATA_DIR = path.join(ROOT, "data");
const CKPT_DIR = path.join(ROOT, "checkpoints");
const META_FILE = path.join(CKPT_DIR, "meta.json");
const PROFILE_FILE = path.join(CKPT_DIR, "genre_profiles.json");
function ensureDirs() {
if (!fs.existsSync(CKPT_DIR)) fs.mkdirSync(CKPT_DIR, { recursive: true });
if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true });
}
function readJSON(file, fallback) {
try { return JSON.parse(fs.readFileSync(file, "utf8")); }
catch { return JSON.parse(JSON.stringify(fallback)); }
}
function normaliseMeta(meta) {
const merged = { ...DEFAULT_META, ...meta };
merged.model = { ...DEFAULT_META.model, ...(meta?.model || {}) };
if (!merged.model.profiles) merged.model.profiles = {};
return merged;
}
function loadMeta() {
ensureDirs();
try {
return JSON.parse(fs.readFileSync(META_FILE, "utf8"));
} catch {
return {
step: 0,
loss: 1.0,
lastCheckpoint: null,
datasetComplexity: 1,
genreProfiles: {}
};
}
}
function computeGenreProfiles() {
const corpus = loadCorpus();
const groups = new Map();
corpus.forEach((entry) => {
if (!groups.has(entry.genre)) {
groups.set(entry.genre, {
genre: entry.genre,
moods: new Map(),
avgTempo: 0,
instrumentPool: new Set(),
entries: 0
});
}
const bucket = groups.get(entry.genre);
bucket.entries += 1;
bucket.avgTempo += entry.tempo;
entry.primaryInstruments.forEach((instrument) => bucket.instrumentPool.add(instrument));
if (!bucket.moods.has(entry.mood)) bucket.moods.set(entry.mood, 0);
bucket.moods.set(entry.mood, bucket.moods.get(entry.mood) + 1);
});
const result = {};
for (const [genre, bucket] of groups.entries()) {
result[genre] = {
primaryMoods: Array.from(bucket.moods.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 3)
.map(([mood, count]) => ({ mood, count })),
avgTempo: Number((bucket.avgTempo / bucket.entries).toFixed(1)),
instruments: Array.from(bucket.instrumentPool)
};
}
return result;
}
function saveProfiles(profiles) {
fs.writeFileSync(PROFILE_FILE, JSON.stringify(profiles, null, 2));
return profiles;
}
function saveMeta(meta) {
fs.writeFileSync(META_FILE, JSON.stringify(meta, null, 2));
write({
train_step: meta.step,
train_loss: meta.loss,
dataset_complexity: meta.datasetComplexity,
lastCheckpoint: meta.lastCheckpoint
});
}
function measureDatasetComplexity() {
const corpus = loadCorpus();
const entropy = corpus.reduce((sum, entry) => sum + Math.log(entry.primaryInstruments.length + 1), 0);
const moods = new Set(corpus.map((entry) => entry.mood));
return Number((1 + entropy + moods.size * 0.25).toFixed(3));
}
function trainSteps(steps = 100) {
ensureDirs();
const corpus = loadCorpus();
const meta = loadMeta();
const profiles = saveProfiles(computeGenreProfiles());
const complexity = measureDatasetComplexity();
for (let i = 0; i < steps; i++) {
const sample = corpus[(meta.step + i) % corpus.length];
integrateSample(model, sample);
meta.step += 1;
const learningSignal = 0.0015 / Math.max(1, complexity);
const oscillation = Math.sin(meta.step * 0.031) * 0.0007;
meta.loss = Math.max(0.0005, meta.loss - learningSignal + oscillation);
if (meta.step % 150 === 0) {
const ck = path.join(CKPT_DIR, `narrow-ai-step-${meta.step}.json`);
fs.writeFileSync(
ck,
JSON.stringify(
{
step: meta.step,
loss: Number(meta.loss.toFixed(6)),
complexity,
updated: new Date().toISOString(),
profiles
},
null,
2
)
);
meta.lastCheckpoint = ck;
}
}
meta.datasetComplexity = complexity;
meta.genreProfiles = profiles;
saveMeta(meta);
return meta;
}
module.exports = { trainSteps, loadMeta, CKPT_DIR, DATA_DIR, META_FILE, PROFILE_FILE, computeGenreProfiles };