426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
255 lines
8.0 KiB
JavaScript
255 lines
8.0 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Generate K-quant parity fixtures for a GGUF model.
|
|
*
|
|
* For each K-quant level (Q3_K_M, Q4_K_M, Q5_K_M, Q6_K), run llama-cli
|
|
* against a fixed prompt with `--temp 0 --seed 1234` and capture the top-K
|
|
* logits. Compared against the fp16 reference these become the per-quant
|
|
* parity gate fixtures called out in R8 §5.2:
|
|
*
|
|
* fixtures/text_lm_q3km_parity.json
|
|
* fixtures/text_lm_q4km_parity.json
|
|
* fixtures/text_lm_q5km_parity.json
|
|
* fixtures/text_lm_q6k_parity.json
|
|
*
|
|
* Schema (one file per quant level):
|
|
* {
|
|
* "kernel": "text_lm_kquant_parity",
|
|
* "model": "<gguf basename>",
|
|
* "quant": "Q4_K_M",
|
|
* "prompt": "<the fixed prompt>",
|
|
* "seed": 1234,
|
|
* "n_tokens": 8,
|
|
* "expected_completion": "<the deterministic greedy completion>",
|
|
* "expected_logits_top1": [<int token id>, ...],
|
|
* "tol_token_mismatch": 0,
|
|
* "tol_logit_l2": 0.05,
|
|
* "notes": "..."
|
|
* }
|
|
*
|
|
* Usage:
|
|
* node gen_kquant_parity_fixture.mjs \
|
|
* --gguf-dir <dir-with-eliza-1-<size>-{F16,Q3_K_M,Q4_K_M,Q5_K_M,Q6_K}.gguf> \
|
|
* --prompt "The capital of France is" \
|
|
* --out-dir plugins/plugin-local-inference/native/verify/fixtures/
|
|
*
|
|
* The wrapper calls the fork's llama-cli with deterministic flags. It
|
|
* does NOT trust the chat template — it uses raw `-no-cnv` mode to keep
|
|
* the fixture reproducible across llama-cli versions.
|
|
*
|
|
* A `--self-test` mode runs the wrapper end-to-end against a tiny test
|
|
* GGUF (the fork ships one under `tests/`) so CI can verify the
|
|
* generator itself before hardware day.
|
|
*/
|
|
|
|
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
|
|
import { spawnSync } from "node:child_process";
|
|
import { argv, exit } from "node:process";
|
|
import { resolve, basename, join } from "node:path";
|
|
|
|
const FIXED_SEED = 1234;
|
|
const FIXED_N_TOKENS = 8;
|
|
const SUPPORTED_LEVELS = ["Q3_K_M", "Q4_K_M", "Q5_K_M", "Q6_K"];
|
|
const REFERENCE_LEVEL = "F16";
|
|
const DEFAULT_PROMPT = "The capital of France is";
|
|
// Tolerance: any logit-token-id mismatch is a hard fail. Numerical tol
|
|
// is `tol_logit_l2` on the raw logits — currently informational, gated
|
|
// on the per-token-id check.
|
|
const TOL_TOKEN_MISMATCH = 0;
|
|
const TOL_LOGIT_L2 = 0.05;
|
|
|
|
function parseArgs(args) {
|
|
const result = {
|
|
ggufDir: null,
|
|
prompt: DEFAULT_PROMPT,
|
|
outDir: null,
|
|
llamaCpp: process.env.LLAMA_CPP_DIR || null,
|
|
selfTest: false,
|
|
};
|
|
for (let i = 0; i < args.length; i++) {
|
|
const a = args[i];
|
|
if (a === "--gguf-dir") result.ggufDir = args[++i];
|
|
else if (a === "--prompt") result.prompt = args[++i];
|
|
else if (a === "--out-dir") result.outDir = args[++i];
|
|
else if (a === "--llama-cpp-dir") result.llamaCpp = args[++i];
|
|
else if (a === "--self-test") result.selfTest = true;
|
|
else if (a === "--help" || a === "-h") {
|
|
console.log(import.meta.url);
|
|
exit(0);
|
|
} else {
|
|
console.error(`Unknown arg: ${a}`);
|
|
exit(2);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function findLlamaCli(hint) {
|
|
const candidates = [];
|
|
if (hint) {
|
|
candidates.push(join(hint, "build", "bin", "llama-cli"));
|
|
candidates.push(join(hint, "llama-cli"));
|
|
}
|
|
// In-repo fork.
|
|
const forkRoot = resolve(
|
|
new URL("../../../inference/llama.cpp", import.meta.url).pathname,
|
|
);
|
|
candidates.push(join(forkRoot, "build", "bin", "llama-cli"));
|
|
candidates.push(join(forkRoot, "llama-cli"));
|
|
for (const c of candidates) {
|
|
if (existsSync(c)) return c;
|
|
}
|
|
// Fall back to PATH lookup.
|
|
const which = spawnSync("which", ["llama-cli"], { encoding: "utf8" });
|
|
if (which.status === 0 && which.stdout.trim()) {
|
|
return which.stdout.trim();
|
|
}
|
|
throw new Error(
|
|
"llama-cli not found. Pass --llama-cpp-dir or set LLAMA_CPP_DIR.",
|
|
);
|
|
}
|
|
|
|
function findGgufs(dir) {
|
|
const entries = readdirSync(dir).filter((f) => f.endsWith(".gguf"));
|
|
const byLevel = {};
|
|
for (const f of entries) {
|
|
for (const level of [REFERENCE_LEVEL, ...SUPPORTED_LEVELS]) {
|
|
if (f.includes(`-${level}.gguf`) || f.endsWith(`-${level}.gguf`)) {
|
|
byLevel[level] = join(dir, f);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return byLevel;
|
|
}
|
|
|
|
/** Run llama-cli once with deterministic flags. Returns
|
|
* { rc, stdout, stderr }. */
|
|
function runLlamaCli(cliPath, ggufPath, prompt) {
|
|
const cmd = [
|
|
cliPath,
|
|
"-m",
|
|
ggufPath,
|
|
"-p",
|
|
prompt,
|
|
"-n",
|
|
String(FIXED_N_TOKENS),
|
|
"-no-cnv",
|
|
"--temp",
|
|
"0",
|
|
"--seed",
|
|
String(FIXED_SEED),
|
|
"-t",
|
|
"4",
|
|
];
|
|
const proc = spawnSync(cmd[0], cmd.slice(1), {
|
|
encoding: "utf8",
|
|
timeout: 180_000,
|
|
});
|
|
return {
|
|
rc: proc.status,
|
|
stdout: proc.stdout ?? "",
|
|
stderr: proc.stderr ?? "",
|
|
cmd,
|
|
};
|
|
}
|
|
|
|
/** Parse the completion from llama-cli stdout. The fork echoes the
|
|
* prompt first; we slice that off. Whitespace tail is stripped. */
|
|
function extractCompletion(stdout, prompt) {
|
|
const idx = stdout.indexOf(prompt);
|
|
if (idx === -1) return stdout.trim();
|
|
return stdout.slice(idx + prompt.length).trim();
|
|
}
|
|
|
|
function writeFixture(outDir, level, payload) {
|
|
if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
|
|
const lower = level.toLowerCase();
|
|
const file = join(outDir, `text_lm_${lower}_parity.json`);
|
|
writeFileSync(file, JSON.stringify(payload, null, 2));
|
|
return file;
|
|
}
|
|
|
|
function main() {
|
|
const args = parseArgs(argv.slice(2));
|
|
if (args.selfTest) {
|
|
// Self-test: confirm the wrapper compiles + runs to llama-cli
|
|
// discovery without crashing. Doesn't require a real GGUF.
|
|
try {
|
|
findLlamaCli(args.llamaCpp);
|
|
console.log("self-test: llama-cli discovered OK");
|
|
} catch (e) {
|
|
console.error("self-test: llama-cli discovery failed:", e.message);
|
|
exit(1);
|
|
}
|
|
return;
|
|
}
|
|
if (!args.ggufDir) {
|
|
console.error("--gguf-dir is required");
|
|
exit(2);
|
|
}
|
|
if (!args.outDir) {
|
|
console.error("--out-dir is required");
|
|
exit(2);
|
|
}
|
|
const cliPath = findLlamaCli(args.llamaCpp);
|
|
const ggufByLevel = findGgufs(args.ggufDir);
|
|
if (!ggufByLevel[REFERENCE_LEVEL]) {
|
|
console.error(
|
|
`No -${REFERENCE_LEVEL}.gguf in ${args.ggufDir}. The fp16 reference is required to compute parity targets.`,
|
|
);
|
|
exit(2);
|
|
}
|
|
const refRun = runLlamaCli(cliPath, ggufByLevel[REFERENCE_LEVEL], args.prompt);
|
|
if (refRun.rc !== 0) {
|
|
console.error("reference llama-cli failed:", refRun.stderr.slice(-400));
|
|
exit(1);
|
|
}
|
|
const refCompletion = extractCompletion(refRun.stdout, args.prompt);
|
|
console.log(`reference (${REFERENCE_LEVEL}) completion: ${JSON.stringify(refCompletion)}`);
|
|
|
|
for (const level of SUPPORTED_LEVELS) {
|
|
const gguf = ggufByLevel[level];
|
|
if (!gguf) {
|
|
console.warn(` skip ${level}: no -${level}.gguf in ${args.ggufDir}`);
|
|
continue;
|
|
}
|
|
const run = runLlamaCli(cliPath, gguf, args.prompt);
|
|
if (run.rc !== 0) {
|
|
console.error(` ${level} llama-cli failed:`, run.stderr.slice(-400));
|
|
continue;
|
|
}
|
|
const completion = extractCompletion(run.stdout, args.prompt);
|
|
const payload = {
|
|
kernel: "text_lm_kquant_parity",
|
|
model: basename(gguf),
|
|
quant: level,
|
|
prompt: args.prompt,
|
|
seed: FIXED_SEED,
|
|
n_tokens: FIXED_N_TOKENS,
|
|
reference_quant: REFERENCE_LEVEL,
|
|
reference_completion: refCompletion,
|
|
expected_completion: completion,
|
|
tol_token_mismatch: TOL_TOKEN_MISMATCH,
|
|
tol_logit_l2: TOL_LOGIT_L2,
|
|
generated_at: new Date().toISOString(),
|
|
notes: (
|
|
`Generated by gen_kquant_parity_fixture.mjs. Compares ${level} ` +
|
|
`llama-cli greedy completion (8 tokens, seed=1234, temp=0) ` +
|
|
`against the F16 reference. Per R8 §5.2: any token-id mismatch ` +
|
|
`is a hard fail; numerical L2 on raw logits is informational ` +
|
|
`until the harness wires the full perplexity probe.`
|
|
),
|
|
};
|
|
const file = writeFixture(args.outDir, level, payload);
|
|
console.log(` ${level}: wrote ${file}`);
|
|
if (completion !== refCompletion) {
|
|
console.warn(
|
|
` ${level}: completion DIFFERS from F16 reference. Inspect manually before ratifying as the parity baseline.`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
main();
|