Download docs/EVAL_GUIDELINES.md from rpDungeon/instruct-mask-tools: direct link, hf CLI and curl.
- Browser
- Download file 11.2 kB
-
https://huggingface.co/rpDungeon/instruct-mask-tools/resolve/main/docs/EVAL_GUIDELINES.md
- Command line
-
hf download hf://rpDungeon/instruct-mask-tools/docs/EVAL_GUIDELINES.md
-
curl -L -o EVAL_GUIDELINES.md https://huggingface.co/rpDungeon/instruct-mask-tools/resolve/main/docs/EVAL_GUIDELINES.md
RECOVERED 2026-05-23T21:29:56 from Claude session transcripts (last Write; later Edit-tool revisions not applied). Original file was missing from disk.
Eval Guidelines
Status: PROPOSED β these are the ideas from the 2026-05-23 throughput-optimization analysis. Once we have actual benchmark numbers (smoke runs of each change against a known model) we lock in the recipe.
Companion docs:
INSTRUCT_MASKING_TECHNIQUES.mdβ masking theory + recipesMERGE_MADNESS.mdβ community-model merge recipe cookbook- This doc β how to eval the outputs of the above efficiently
1. Current full-eval breakdown (baseline, 2026-05-23)
Runner: run_ifeval.py + run_vampire_eval.py + loft-t5/eval/style_quality.py, served via llama-server (llama.cpp).
| Stage | N | Wall | Per-item | Why |
|---|---|---|---|---|
| IFEval gen | 541 | ~2.5 h | 16.6 s | serial-ish gen, cache_prompt=False, no flash-attn flag |
| IFEval score | 541 | ~30 m | 3.3 s | external Google evaluation_main subprocess |
| Style gen | 40 | ~45 m | 67 s | --parallel 1 forced (8k ctx), single-stream |
| Style score | 40 | ~3 m | β | SBERT paraphrase mining per-sample, no batching |
| Vampire gen | 48 | ~15 m | 19 s | triple-nested serial loop (weakness Γ scenario Γ variant) |
| Vampire score | 48 | ~1 m | β | regex; already fine |
| Total | ~4 h | IFEval is 60% of it |
2. Root causes of slowness (priority order)
cache_prompt: Falseinrun_ifeval.py~line 69. Every IFEval call re-prefills KV from scratch even though the chat-template prefix is identical. Withcache_prompt: Truellama-server reuses the longest matching prefix in the slot's KV. ~10-15% per call thrown away.No
--flash-attnflag on llama-server launch. llama.cpp doesn't auto-enable FA for Q4_K_M on CUDA β has to be explicit. Empirically ~20-30% gen speedup on 30B-class models at 8k ctx on 3090.--parallel 4but slots can't actually saturate. ThreadPoolExecutor submits 4 at a time, but llama-server splits the KV across slots and each slot still generates serially on the same GPUs. Need to verify VRAM headroom before bumping to--parallel 6-8on 31B at 8k ctx.No
-ctk q8_0 -ctv q8_0(kv-cache quant). Default kv-cache is f16. Quantizing the KV to q8_0 frees ~30% KV memory β lets us bump--paralleland/or--ctx-size. Quality hit on IFEval expected negligible.Style is locked to
--parallel 1because the inline runner uses 8k ctx. Most style prompts are < 4k tokens β drop ctx to 4k and bump to--parallel 2-3, halving the 45 min. Gate with a length check; fall back to 8k+parallel-1 if any prompt exceeds 4k.Vampire is fully serial. 48 cells Γ 3 samples = 144 generations in a triple
forloop. Parallelize cells with a ThreadPoolExecutor against existing--parallel 4slots β ~4Γ speedup β ~4 min instead of 15.Per-prompt
max_tokens=1536on IFEval. Actual gen is usually 500-800 tokens. Server respects the cap, but EOS regressions (saw this on aux-loss EOS bug) make one runaway prompt hold a slot for full 1536. Worth instrumenting per-prompt token-out length to confirm.Style scoring runs SBERT
paraphrase_miningper sample instead of batching all 40 outputs through one mining call. Easy 5-10Γ cut on style-score wall.
3. Proposed fix order (lowest-risk first)
A. cache_prompt: True + --flash-attn + -ctk q8_0 -ctv q8_0 on run_ifeval.py + the served llama-server.
- Estimated combined: 2.5 h β ~1.4-1.6 h.
- Risk: low.
- Validation: re-run on a known model (V3 baseline), compare IFEval score; expect β€ 0.5pp drift from kv-quant.
B. Bump --parallel to 6-8 after KV quant frees memory.
- Estimated: another 1.6 h β ~1.1-1.3 h.
- Risk: OOM if memory check is wrong; mitigate by running a 50-prompt smoke at the new parallel count first.
C. Parallelize Vampire cells with a ThreadPoolExecutor (same llama-server, existing --parallel 4).
- 15 min β ~4 min.
- Risk: low; scoring is already cell-local.
D. Style: drop --ctx-size to 4096, set --parallel 2.
- 45 min β ~22 min.
- Risk: any style prompt > 4k tokens fails; gate with a length check, fall back to 8k+parallel-1 if any prompt exceeds.
E. Batch SBERT paraphrase mining across all 40 style samples in one call.
- 3 min β ~30 s. Trivial.
Bottom line for 31B full eval: 4 h β ~1.5-2 h with A+B+C+D (~50-60% cut). E gets us another ~2 min, essentially free.
4. E4B differences
Same scripts; smaller model (4.3 B params, single-3090). E4B IFEval bottlenecks are the same as 31B (cache_prompt, flash-attn, --parallel), so the same fixes apply with even more headroom because the model only takes ~5-7 GB at Q4_K_M, leaving plenty of room for --parallel 8 and larger KV. E4B should be in the ~30-45 min range for full IFEval after fixes (currently ~1 h).
E4B humanness scoring (score_gemma4_e4b_humanness.py) is a separate beast β runs transformers.generate serially per prompt instead of going through llama-server, which is the wrong tool. Switching E4B humanness gen to llama-server with --parallel would cut it from ~20 min to ~3 min. Same script structure as IFEval; well-trodden path.
5. GPU layout β single-GPU vs dual-GPU
31B Q4_K_M (~18.7 GB on disk):
- Dual-GPU tensor-split (current default): model spread ~9.4 GB / GPU. Per-GPU ~14 GB headroom for KV + slots. Comfortably
--parallel 4at 8k ctx today; with-ctk q8_0 -ctv q8_0β--parallel 6-8. Per-token gen is ~16-22% slower than single-GPU (PCIe layer hops on NVLink-less 3090 pair), but more concurrent slots β higher total throughput. - Single-GPU 31B: 18.7 GB leaves only ~5 GB for KV. At 8k ctx that's
--parallel 1, maybe--parallel 2if KV is q8_0 and we drop ctx to 4k. Per-token ~20% faster than tensor-split, but loses all slot-level parallelism β net loss vs. dual-GPU --parallel 4. - Conclusion: 31B should always run dual-GPU when it's the only model.
E4B Q4_K_M (~5-7 GB):
- Single-GPU E4B: model 6 GB, leaves ~17 GB for KV. Comfortably
--parallel 6-8at 8k ctx with default kv,--parallel 12+with kv-q8. Per-token fast (no PCIe tax). - Conclusion: E4B always single-GPU. Tensor-splitting E4B across both GPUs is worse β PCIe overhead, no concurrency gain.
6. Side-by-side eval: 2+ models simultaneously
Pattern: one llama-server per GPU, different ports. Each gets CUDA_VISIBLE_DEVICES=N. The eval runner splits prompts across the two servers and aggregates responses at the end.
| Pair | Feasibility | Speedup vs. serial | Caveat |
|---|---|---|---|
| E4B + E4B | Easy β | ~2Γ (each on own GPU, no contention) | None β go for it whenever β₯2 E4Bs are queued |
| E4B + 31B | Tight but doable | ~1.5-1.8Γ | 31B alone on its GPU = --parallel 1-2 at 4k ctx + kv-q8. Slower IFEval on 31B side, but reclaims entire E4B run. |
| 31B + 31B | NOT recommended | (slower than serial dual-GPU) | Each needs 18.7 GB β no room for --parallel >1 or full 8k ctx. Run them back-to-back, each using dual-GPU at --parallel 6-8. |
Mode decision matrix:
have N models queued:
if all E4B: pair them 2-at-a-time, single-GPU each (8090, 8095)
if 1 E4B + 1 31B: e4b+31b mode β 31B reduced parallel/ctx on GPU 1, E4B on GPU 0
if all 31B: serial β each runs dual-GPU at --parallel 6-8 (no co-residency)
if mixed >2: prefer pairing E4B+E4B first, then E4B+31B, then any leftover 31B serial
Expected throughput gains for typical queues (post fixes A-E + side-by-side):
- 4 E4B models eval (currently
4 h Γ 4 = 16 h serial): pair-up = 2 pairs Γ 2-3 h = **5-6 h**. ~3Γ cut. - 4 jaxxks 31B recipes (currently
4 h Γ 4 = 16 h serial, dual-GPU each): no side-by-side benefit β **7-8 h** serial after the IFEval+vampire+style fixes alone. - 2 E4B + 2 31B queued: one E4B+E4B pass (
2.5 h) + two 31B serial (3.5 h each) = ~9.5 h vs. 16 h serial.
7. Implementation sketch
Wrapper script: run_eval_dual.sh (not yet written).
Inputs: MODEL_A_GGUF, MODEL_B_GGUF, LABEL_A, LABEL_B, mode (e4b+e4b, e4b+31b, serial-31b).
Behavior:
- Launch llama-server A with
CUDA_VISIBLE_DEVICES=0 --port 8090 --no-mmap --flash-attn -ctk q8_0 -ctv q8_0 --parallel <N_A> --ctx-size <C_A>againstMODEL_A_GGUF. For E4B: N_A=8, C_A=8192. For 31B-single-GPU (the e4b+31b mode): N_A=1-2, C_A=4096. - Launch llama-server B with
CUDA_VISIBLE_DEVICES=1 --port 8095 --parallel <N_B> --ctx-size <C_B>againstMODEL_B_GGUF. - Wait for both
/healthendpoints to return 200. - Run
run_ifeval_gpu0.py --port 8090 --label $LABEL_Aandrun_ifeval_gpu1.py --port 8095 --label $LABEL_Bconcurrently. (Both scripts already exist; need port/parallel-arg parameterization.) - After IFEval, run style + vampire against each server in parallel.
- Tear down both servers.
- Discord ping with both labels + summary metrics.
Eval queue: eval_queue.json β list of (model_path, label, expected_size) tuples; wrapper picks pairs by the mode decision matrix.
Smoke test: 2 small known models (e.g., 2 E4B variants we already have) at 50 IFEval prompts to validate parallel run produces same scores as serial.
8. Validation protocol (before locking any change as default)
For each proposed change (A, B, C, D, E, side-by-side):
- Pick a known reference model with a known eval scoreboard (e.g., 31B-V3 fisher-layer-test or E4B IT-base).
- Run a smoke (50-100 prompts) with the change applied. Compare per-prompt latency and any output drift vs. baseline.
- Run the full eval (541 IFEval + style + vampire) with the change applied. Compare:
- Wall-clock vs. baseline (the throughput claim)
- IFEval strict prompt-level score (must be within 0.5pp of baseline; larger drift = quality regression)
- Style metrics (h_delta, slop, rep3g β must match within noise)
- Vampire pass-rate (regex-scored, deterministic; must match exactly)
- Document the actual wall-clock delta in this doc's section 9 (changelog).
- Lock the change in defaults only after the comparison shows the throughput gain without quality regression.
9. Changelog (verified results β fill in as tests land)
Empty pending validation runs.
10. Open questions / things to research
- Does
--flash-attnwork cleanly with--tensor-spliton dual-3090 at Q4_K_M? (Some flash-attn paths required compile flags in older llama.cpp builds.) - KV quant + Gemma4's hybrid attention β does q8_0 KV interact badly with the sliding-window full-attn layer mix? Need an A/B with same prompts.
- For E4B+E4B co-eval, is there contention through the host on RAM bandwidth or NVMe (if model is mmap'd)? Probably negligible at Q4_K_M sizes, but worth a check.
- Can we share a single Google IFEval scoring subprocess between two parallel runs to cut the 30 min Γ 2 β 30 min total? (Scorer is CPU-bound, single-threaded β could batch.)
- For Vampire side-by-side, the conversation_*.md cards are shared assets; concurrent reads are fine but worth confirming nothing writes back.