taf-agent / test_launch.mjs
karlexmarin's picture
v0.9.4: Launch-Flag Generator mode + Zenodo record update
12e81e6
Raw
History Blame Contribute Delete
4.26 kB
import { chromium } from "playwright";
const b = await chromium.launch({ headless: true });
const p = await (await b.newContext()).newPage();
const errors=[]; const benign=s=>/40\d/.test(s);
p.on("console",m=>{if(m.type()==="error"&&!benign(m.text()))errors.push("[c]"+m.text());});
p.on("pageerror",e=>errors.push("[pe]"+e.message));
const log=s=>process.stdout.write(s+"\n"); let pass=0,fail=0;
const check=(n,c,x="")=>{log(`${c?" OK ":" FAIL"} ${n} ${x}`);c?pass++:fail++;};
await p.goto("http://127.0.0.1:8000/index.html",{waitUntil:"domcontentloaded",timeout:90000});
await p.waitForTimeout(2500);
await p.click(`.lang-btn[data-lang="en"]`); await p.waitForTimeout(200);
check("module loads, 0 errors", errors.length===0, `(${errors.length})`);
await p.click('[data-mode-link="launch"]',{timeout:5000}); await p.waitForTimeout(400);
check("section visible", await p.evaluate(()=>{const s=document.querySelector("#launch-section");return s&&getComputedStyle(s).display!=="none";}));
check("GPU presets populated", await p.evaluate(()=>document.querySelector("#launch-gpu").options.length>5));
log("\n── Fetch geometry ──");
await p.fill("#launch-model","Qwen/Qwen2.5-7B-Instruct");
await p.keyboard.press("Escape");
await p.click("#launch-fetch-btn"); await p.waitForTimeout(3500);
const st=await p.evaluate(()=>document.querySelector("#launch-status").innerText);
check("geometry fetched (layers/GQA shown)", /layers|GQA|θ=/.test(st), st.slice(0,70));
check("ctx auto-filled", await p.evaluate(()=>!!document.querySelector("#launch-ctx").value));
async function gen({quant,gpu,vram,ctx,cache,fa}){
if(quant) await p.selectOption("#launch-quant",quant);
if(gpu) await p.selectOption("#launch-gpu",gpu);
await p.fill("#launch-vram",vram!=null?String(vram):"");
if(ctx!=null) await p.fill("#launch-ctx",String(ctx));
if(cache) await p.selectOption("#launch-cache",cache);
if(fa!=null){const c=await p.isChecked("#launch-fa"); if(c!==fa) await p.click("#launch-fa");}
await p.click("#launch-gen-btn"); await p.waitForTimeout(300);
return p.evaluate(()=>{const o=document.querySelector("#launch-output");return{
verdict:o.querySelector(".verdict-badge")?.innerText?.trim()||"", text:o.innerText};});
}
log("\n── FITS case (7B Q4 on 24GB) ──");
let r=await gen({quant:"Q4_K_M",gpu:"24",vram:null,ctx:32768,cache:"fp16",fa:true});
check("verdict FITS", /FITS/.test(r.verdict), r.verdict);
check("ngl = all layers", /all|28/.test(r.text));
check("llama-server cmd present", /llama-server/.test(r.text));
check("ollama cmd present", /ollama|num_ctx/.test(r.text));
check("--no-mmap added when all-on-GPU", /--no-mmap/.test(r.text));
check("-fa present", /-fa/.test(r.text));
check("VRAM breakdown (weights/KV)", /Weights|KV cache/.test(r.text));
log("\n── PARTIAL case (7B Q4 on tiny 3GB custom) ──");
r=await gen({quant:"Q4_K_M",vram:3,ctx:8192,fa:true});
check("verdict PARTIAL or TOO BIG", /PARTIAL|TOO BIG/.test(r.verdict), r.verdict);
check("partial offload warning or cpu-only", /CPU|layers fit|smaller quant/i.test(r.text));
log("\n── cache quant changes KV flag ──");
r=await gen({quant:"Q4_K_M",gpu:"24",vram:null,ctx:32768,cache:"q8_0",fa:true});
check("KV cache q8_0 → -ctk/-ctv in cmd", /-ctk q8_0/.test(r.text));
log("\n── beyond-trained warning ──");
r=await gen({quant:"Q4_K_M",gpu:"80",vram:null,ctx:262144,cache:"fp16",fa:true});
check("L beyond trained → warning", /trained|RoPE|YaRN/i.test(r.text), "L=256K");
log("\n── error: generate before fetch (fresh) ──");
// can't easily un-fetch; just check error key exists by clearing geom via reload-free path is hard; skip
log("\n── 4 languages ──");
for(const lang of ["es","fr","zh","en"]){
await p.click(`.lang-btn[data-lang="${lang}"]`); await p.waitForTimeout(250);
const lbl=await p.evaluate(()=>document.querySelector('.mode-btn[data-mode="launch"]')?.textContent?.trim());
check(`${lang}: tab label`, lbl&&lbl.length>3, lbl);
}
check("copy button present", await p.evaluate(()=>!!document.querySelector("#launch-copy-llama")));
log(`\n=== ${pass} passed, ${fail} failed · JS errors: ${errors.length} ===`);
errors.slice(0,10).forEach(e=>log(e));
await b.close();
process.exit(fail>0?1:0);