chore: bump version to 2.80.27 and update core features
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Unit tests for SystemSpecs + HeuristicModelMemoryEstimator.
|
||||
*
|
||||
* Strategy:
|
||||
* - HeuristicModelMemoryEstimator is pure — directly drive it with model ids.
|
||||
* - NodeSystemSpecsProvider depends on `os.*` so we test:
|
||||
* a) caching (same instance returned twice),
|
||||
* b) shape (all required fields present, sane numbers).
|
||||
* We don't pin platform-specific values since CI hardware varies.
|
||||
*/
|
||||
|
||||
import {
|
||||
NodeSystemSpecsProvider,
|
||||
HeuristicModelMemoryEstimator,
|
||||
} from '../src/system/specs';
|
||||
|
||||
describe('HeuristicModelMemoryEstimator', () => {
|
||||
const est = new HeuristicModelMemoryEstimator();
|
||||
|
||||
test('extracts parameter count from "7B" suffix', () => {
|
||||
// 7B q4 default: 7 * 0.6 + 1 = 5.2
|
||||
expect(est.estimate('llama-3.2-7b-q4_K_M')).toBeCloseTo(5.2, 1);
|
||||
});
|
||||
|
||||
test('extracts parameter count from "70B"', () => {
|
||||
// 70B q4 default: 70 * 0.6 + 1 = 43
|
||||
expect(est.estimate('llama-3-70b-instruct-q4_0')).toBeCloseTo(43, 0);
|
||||
});
|
||||
|
||||
test('q8 quantization uses higher byte/param', () => {
|
||||
// 7B q8: 7 * 1.0 + 1 = 8
|
||||
expect(est.estimate('mistral-7b-q8_0')).toBeCloseTo(8, 1);
|
||||
});
|
||||
|
||||
test('fp16 uses 2 bytes/param', () => {
|
||||
// 7B fp16: 7 * 2.0 + 1 = 15
|
||||
expect(est.estimate('mistral-7b-fp16')).toBeCloseTo(15, 1);
|
||||
});
|
||||
|
||||
test('q5 sits between q4 and q6', () => {
|
||||
const q4 = est.estimate('foo-7b-q4');
|
||||
const q5 = est.estimate('foo-7b-q5');
|
||||
const q6 = est.estimate('foo-7b-q6');
|
||||
expect(q4).toBeLessThan(q5);
|
||||
expect(q5).toBeLessThan(q6);
|
||||
});
|
||||
|
||||
test('falls back to 7B when parameter count is absent', () => {
|
||||
// unknown size → 7B q4 default → 5.2
|
||||
expect(est.estimate('some-model-no-size')).toBeCloseTo(5.2, 1);
|
||||
});
|
||||
|
||||
test('decimal parameter counts like "3.8b"', () => {
|
||||
// 3.8B q4: 3.8 * 0.6 + 1 = 3.28
|
||||
expect(est.estimate('phi-3.8b-q4')).toBeCloseTo(3.28, 1);
|
||||
});
|
||||
|
||||
test('handles empty / undefined input gracefully', () => {
|
||||
expect(est.estimate('')).toBeCloseTo(5.2, 1); // defaults
|
||||
expect(est.estimate(undefined as any)).toBeCloseTo(5.2, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('NodeSystemSpecsProvider', () => {
|
||||
test('returns the same cached object on repeated calls', () => {
|
||||
const provider = new NodeSystemSpecsProvider();
|
||||
const a = provider.get();
|
||||
const b = provider.get();
|
||||
expect(a).toBe(b);
|
||||
});
|
||||
|
||||
test('produces a sane shape', () => {
|
||||
const specs = new NodeSystemSpecsProvider().get();
|
||||
expect(specs.totalRamGB).toBeGreaterThan(0);
|
||||
expect(specs.cpuCount).toBeGreaterThanOrEqual(1);
|
||||
expect(specs.platform).toMatch(/^(darwin|linux|win32|freebsd|openbsd|sunos|aix)$/);
|
||||
expect(specs.arch.length).toBeGreaterThan(0);
|
||||
expect(typeof specs.isAppleSilicon).toBe('boolean');
|
||||
expect(specs.safeModelBudgetGB).toBeGreaterThanOrEqual(2);
|
||||
expect(specs.safeModelBudgetGB).toBeLessThanOrEqual(specs.totalRamGB);
|
||||
expect(specs.summary).toMatch(/RAM/);
|
||||
});
|
||||
|
||||
test('safe budget is at most ~65% of total RAM (Apple Silicon ceiling)', () => {
|
||||
const specs = new NodeSystemSpecsProvider().get();
|
||||
// Even on Apple Silicon (most generous ratio) the budget is capped at
|
||||
// 0.65 of total. Use 0.7 as a soft upper bound for any platform.
|
||||
expect(specs.safeModelBudgetGB).toBeLessThanOrEqual(specs.totalRamGB * 0.7 + 1);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user