macrostories-browser / tests /sampling.test.js
danmoreng's picture
Add MacroStories browser lab with Transformers.js, WebGPU and WASM
ca2a6e7 verified
Raw History Blame Contribute Delete
1.59 kB
import assert from 'node:assert/strict';
import test from 'node:test';
import { seededRandom, sample, validateSettings } from '../src/sampling.js';
const defaults = { seed: 20261007, temperature: 0.5, topP: 0.9, topK: 0, maxTokens: 512 };
test('greedy sampling handles negative logits and consumes no randomness', () => {
assert.equal(sample([-3, -1, -2], { ...defaults, temperature: 0 }, () => { throw new Error('Unexpected random draw'); }), 1);
});
test('nucleus keeps the token that crosses the probability threshold', () => {
assert.equal(sample([Math.log(0.5), Math.log(0.3), Math.log(0.2)], { ...defaults, temperature: 1, topP: 0.6 }, () => 0.99), 1);
});
test('top-k removes low logits but preserves ties at its cutoff', () => {
assert.equal(sample([10, 9, 9, -100], { ...defaults, temperature: 1, topP: 1, topK: 2 }, () => 0.999), 2);
});
test('seeds repeat sampled experiments, with zero accepted as a real seed', () => {
const run = seed => { const random = seededRandom(seed); return Array.from({ length: 64 }, () => sample([0, 0, 0], { ...defaults, temperature: 1, topP: 1 }, random)); };
assert.deepEqual(run(0), run(0));
assert.notDeepEqual(run(0), run(1));
});
test('invalid settings fail before inference, and full context length is accepted', () => {
for (const settings of [{ seed: -1 }, { seed: 2 ** 32 }, { temperature: NaN }, { topP: 0 }, { topK: 379 }, { maxTokens: 2048 }]) assert.throws(() => validateSettings({ ...defaults, ...settings }));
assert.doesNotThrow(() => validateSettings({ ...defaults, seed: 0, temperature: 0, maxTokens: 2047 }));
});