Spaces:
Sleeping
Sleeping
| import { describe, expect, it } from 'vitest'; | |
| import { | |
| DEFAULT_SAE_SETTINGS, | |
| computeActivationMetrics, | |
| formatSaeTrainProgress, | |
| loadSaeSettings, | |
| resolveSaeSettings, | |
| saveSaeSettings, | |
| } from '../src/ui/saeControlsDefaults.js'; | |
| import { | |
| applySaeToCompare, | |
| cosineSimilarity, | |
| densifyTopKActivations, | |
| } from '../src/core/saeReplace.js'; | |
| describe('saeControlsDefaults', () => { | |
| it('round-trips enabled + train params through localStorage', () => { | |
| const store = new Map(); | |
| const storage = { | |
| getItem: (k) => (store.has(k) ? store.get(k) : null), | |
| setItem: (k, v) => { store.set(k, String(v)); }, | |
| removeItem: (k) => { store.delete(k); }, | |
| key: (i) => [...store.keys()][i] ?? null, | |
| get length() { return store.size; }, | |
| }; | |
| const settings = resolveSaeSettings({ | |
| enabled: true, | |
| hiddenDim: 4096, | |
| k: 16, | |
| epochs: 10, | |
| lr: 0.002, | |
| batchSize: 32, | |
| }); | |
| saveSaeSettings(settings, storage); | |
| const loaded = loadSaeSettings(storage); | |
| expect(loaded.enabled).toBe(true); | |
| expect(loaded.hiddenDim).toBe(4096); | |
| expect(loaded.k).toBe(16); | |
| expect(loaded.epochs).toBe(10); | |
| expect(loaded.batchSize).toBe(32); | |
| }); | |
| it('defaults are 8192 / k32 / 20ep and purge legacy poisoned keys', () => { | |
| expect(DEFAULT_SAE_SETTINGS.enabled).toBe(false); | |
| expect(DEFAULT_SAE_SETTINGS.hiddenDim).toBe(8192); | |
| expect(DEFAULT_SAE_SETTINGS.k).toBe(32); | |
| expect(DEFAULT_SAE_SETTINGS.epochs).toBe(20); | |
| expect(loadSaeSettings(null).enabled).toBe(false); | |
| const store = new Map([ | |
| ['vl3d.sae.hiddenDim', '32'], | |
| ['vl3d.sae.k', '1'], | |
| ['vl3d.sae.epochs', '1'], | |
| ['vl3d.sae.enabled', 'true'], | |
| ]); | |
| const storage = { | |
| getItem: (k) => (store.has(k) ? store.get(k) : null), | |
| setItem: (k, v) => { store.set(k, String(v)); }, | |
| removeItem: (k) => { store.delete(k); }, | |
| key: (i) => [...store.keys()][i] ?? null, | |
| get length() { return store.size; }, | |
| }; | |
| const loaded = loadSaeSettings(storage); | |
| expect(loaded.hiddenDim).toBe(8192); | |
| expect(loaded.k).toBe(32); | |
| expect(loaded.epochs).toBe(20); | |
| expect(loaded.enabled).toBe(false); | |
| expect(store.has('vl3d.sae.hiddenDim')).toBe(false); | |
| }); | |
| it('computes L0 / sparsity from sparse rows', () => { | |
| const acts = [ | |
| [1, 0, 0, 2], | |
| [0, 0, 3, 0], | |
| ]; | |
| const m = computeActivationMetrics(acts); | |
| expect(m.dim).toBe(4); | |
| expect(m.l0).toBe(1.5); | |
| expect(m.activeFeatures).toBe(3); | |
| }); | |
| it('formats train progress with done / left / percent', () => { | |
| const mid = formatSaeTrainProgress({ | |
| status: 'training', | |
| phase_key: 'training', | |
| message: 'Training epoch 13/50 — 38 remaining · last loss=0.012345', | |
| current_epoch: 12, | |
| total_epochs: 50, | |
| remaining_epochs: 38, | |
| percent: 24, | |
| n_vectors: 40, | |
| resolved_hidden: 160, | |
| resolved_k: 16, | |
| }); | |
| expect(mid.busy).toBe(true); | |
| expect(mid.label).toContain('38 remaining'); | |
| expect(mid.meta).toContain('12/50 done'); | |
| expect(mid.meta).toContain('38 left'); | |
| expect(mid.meta).toContain('24%'); | |
| expect(mid.percent).toBe(24); | |
| const prep = formatSaeTrainProgress({ | |
| status: 'training', | |
| phase_key: 'preparing', | |
| message: '', | |
| current_epoch: 0, | |
| total_epochs: 50, | |
| }); | |
| expect(prep.label).toMatch(/Preparing/i); | |
| expect(prep.meta).toContain('0/50 done'); | |
| expect(prep.meta).toContain('50 left'); | |
| expect(prep.indeterminate).toBe(true); | |
| }); | |
| }); | |
| describe('saeReplace', () => { | |
| it('recomputes compare cosine_vs_first in SAE space', () => { | |
| const raw = { | |
| count: 2, | |
| items: [ | |
| { id: 'tok_0', text: 'a', embedding: [1, 0] }, | |
| { id: 'tok_1', text: 'b', embedding: [0, 1] }, | |
| ], | |
| }; | |
| const acts = [ | |
| [1, 0, 0], | |
| [1, 0, 0], | |
| ]; | |
| const next = applySaeToCompare(raw, acts); | |
| expect(next.items[0].cosine_vs_first).toBe(1); | |
| expect(next.items[1].cosine_vs_first).toBeCloseTo(1, 5); | |
| expect(cosineSimilarity([1, 0], [0, 1])).toBeCloseTo(0, 5); | |
| }); | |
| it('densifies Top-K sparse encode payload', () => { | |
| const dense = densifyTopKActivations({ | |
| format: 'topk_sparse', | |
| indices: [[0, 2], [1, 3]], | |
| values: [[1.5, 0.5], [2, 0]], | |
| dimension: 4, | |
| k: 2, | |
| }); | |
| expect(dense).toEqual([ | |
| [1.5, 0, 0.5, 0], | |
| [0, 2, 0, 0], | |
| ]); | |
| }); | |
| }); | |