Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/gratis/__tests__/perf.test.ts

Raw
import { describe, expect, it } from "vitest";
import { createPerf, MIN_DEADLINE_MS } from "../src/perf.ts";

const MAX = 10_000;
const ok = (firstTokenMs: number, tokensPerSecond?: number) =>
	({ kind: "ok", firstTokenMs, tokensPerSecond }) as const;
const fail = { kind: "fail" } as const;

function clock() {
	let time = 0;
	return {
		now: () => time,
		advance: (ms: number) => {
			time += ms;
		},
	};
}

describe("gratis perf", () => {
	it("keeps the default deadline until a model has enough timed samples", () => {
		const perf = createPerf(clock().now);
		perf.record("groq", "groq/a", ok(500));
		perf.record("groq", "groq/a", ok(500));

		expect(perf.deadline("groq/a", MAX)).toBe(MAX);
		expect(perf.deadline("groq/unknown", MAX)).toBe(MAX);
	});

	it("scales the deadline to three times the typical first token, within bounds", () => {
		const perf = createPerf(clock().now);
		for (const ms of [1_500, 1_500, 1_500])
			perf.record("groq", "groq/a", ok(ms));
		for (const ms of [200, 200, 200]) perf.record("groq", "groq/fast", ok(ms));
		for (const ms of [8_000, 8_000, 8_000])
			perf.record("groq", "groq/slow", ok(ms));

		expect(perf.deadline("groq/a", MAX)).toBe(4_500);
		expect(perf.deadline("groq/fast", MAX)).toBe(MIN_DEADLINE_MS);
		expect(perf.deadline("groq/slow", MAX)).toBe(MAX);
		expect(perf.deadline("groq/a", 1_000)).toBe(1_000);
	});

	it("moves a repeatedly failing model behind its healthy siblings, stably", () => {
		const perf = createPerf(clock().now);
		const candidates = [{ id: "groq/a" }, { id: "groq/b" }, { id: "groq/c" }];
		for (let i = 0; i < 3; i++) perf.record("groq", "groq/a", fail);
		perf.record("groq", "groq/b", fail);

		expect(perf.orderModels(candidates).map((model) => model.id)).toEqual([
			"groq/b",
			"groq/c",
			"groq/a",
		]);
	});

	it("restores a demoted model as its failures age or it succeeds", () => {
		const time = clock();
		const perf = createPerf(time.now);
		const candidates = [{ id: "groq/a" }, { id: "groq/b" }];
		for (let i = 0; i < 3; i++) perf.record("groq", "groq/a", fail);
		expect(perf.orderModels(candidates)[0]?.id).toBe("groq/b");

		time.advance(30 * 60_000);
		expect(perf.orderModels(candidates)[0]?.id).toBe("groq/a");

		const fresh = createPerf(clock().now);
		for (let i = 0; i < 3; i++) fresh.record("groq", "groq/a", fail);
		fresh.record("groq", "groq/a", ok(500));
		expect(fresh.orderModels(candidates)[0]?.id).toBe("groq/a");
	});

	it("demotes a chronically failing backend behind the others", () => {
		const perf = createPerf(clock().now);
		for (let i = 0; i < 3; i++) perf.record("nvidia", "nvidia/x", fail);

		expect(perf.orderBackends(["nvidia", "google", "kilo"])).toEqual([
			"google",
			"kilo",
			"nvidia",
		]);
	});

	it("reports measured models, most used first", () => {
		const perf = createPerf(clock().now);
		perf.record("kilo", "kilo/a", ok(1_000, 40));
		perf.record("kilo", "kilo/a", ok(2_000, 60));
		perf.record("groq", "groq/b", fail);

		expect(perf.snapshot()).toEqual([
			{
				id: "kilo/a",
				samples: 2,
				failureRate: 0,
				firstTokenMs: 1_300,
				tokensPerSecond: 46,
				demoted: false,
			},
			{
				id: "groq/b",
				samples: 1,
				failureRate: expect.closeTo(0.3, 5),
				demoted: false,
			},
		]);
	});
});

describe("gratis perf votes, promotion, persistence", () => {
	it("demotes a model after two votes, past its cooldown, until votes fade", () => {
		const time = clock();
		const perf = createPerf(time.now);
		const candidates = [{ id: "kilo/a" }, { id: "kilo/b" }];
		perf.vote("kilo/a");
		expect(perf.orderModels(candidates)[0]?.id).toBe("kilo/a");

		perf.vote("kilo/a");
		time.advance(61 * 60_000);
		expect(perf.orderModels(candidates)[0]?.id).toBe("kilo/b");

		time.advance(7 * 24 * 60 * 60_000);
		expect(perf.orderModels(candidates)[0]?.id).toBe("kilo/a");
	});

	it("moves a proven backend one place past an unreliable neighbor, no further", () => {
		const perf = createPerf(clock().now);
		for (const sample of [fail, fail, ok(500)])
			perf.record("shaky", "shaky/x", sample);
		for (let i = 0; i < 20; i++) perf.record("solid", "solid/x", ok(500));
		for (let i = 0; i < 20; i++) perf.record("steady", "steady/x", ok(500));

		expect(perf.orderBackends(["top", "shaky", "solid", "steady"])).toEqual([
			"top",
			"solid",
			"shaky",
			"steady",
		]);
		expect(perf.orderBackends(["solid", "top"])).toEqual(["solid", "top"]);
	});

	it("never promotes on speed alone", () => {
		const perf = createPerf(clock().now);
		for (const sample of [fail, fail, ok(500)])
			perf.record("shaky", "shaky/x", sample);
		for (let i = 0; i < 5; i++) perf.record("fast", "fast/x", ok(50));

		expect(perf.orderBackends(["shaky", "fast"])).toEqual(["shaky", "fast"]);
	});

	it("round-trips its state and merges without overriding fresh measurements", () => {
		const time = clock();
		const first = createPerf(time.now);
		for (let i = 0; i < 3; i++) first.record("groq", "groq/a", fail);
		first.vote("groq/b");
		const saved = JSON.parse(JSON.stringify(first.export()));

		const second = createPerf(time.now);
		second.record("groq", "groq/b", ok(900));
		second.import(saved);

		expect(
			second.orderModels([{ id: "groq/a" }, { id: "groq/c" }])[0]?.id,
		).toBe("groq/c");
		expect(second.snapshot().find((m) => m.id === "groq/b")?.samples).toBe(1);
	});

	it("ignores corrupt or foreign state", () => {
		const perf = createPerf(clock().now);
		for (const state of [
			undefined,
			"nope",
			{ version: 2, models: {} },
			{ version: 1, models: { "groq/a": { failure: "x" } } },
		])
			perf.import(state);

		expect(perf.snapshot()).toEqual([]);
	});
});