opencoti-llamafile / docs /features /rys_probe.md
ManniX-ITA's picture
Upload folder using huggingface_hub
9cee049 verified
|
Raw
History Blame
11.4 kB

RYS template probe (--rys-probe) — design + implementation

Status: IMPLEMENTED (v1.1 = ΔPPL + graded task-probe → 2 templates + external eval hook), host-only, validated on Qwen3-4B (2026-07-13, #669/#670). Not yet captured as a patch / committed — ships on request. Companion to the shipped RYS execution engine, rys_layer_duplication.md (--repeat-layers, patch 0122).

0. What shipped (v1.1)

A new PROBE program mode in llamafile/rys_probe.cpp (dispatched from llamafile/main.cpp; flag detected in llamafile/args.cpp). It:

  1. Parses args as the PERPLEXITY example, then disables -fit (the probe sizes its own small n_ctx; the fit path builds a trial context that we don't want mutating our cparams — it aborted the flash-attn print otherwise).
  2. Loads the model once (common_init_from_params(params, /*model_only*/true)).
  3. Enumerates contiguous mid-stack blocks [i,j) in the band (default [max(3,n/8) .. n-max(3,n/8))) × --rys-probe-widths. Default widths = auto = every width 1 .. (band) (an explicit W1,W2,… list overrides).
  4. Scores base first (empty plan = reference), then each candidate by rebuilding only the context (llama_init_from_model with cp.repeat_layers = "i,j"; the model/weights are plan-independent), computing a compact self-contained ΔPPL over a small corpus (-f/-p, else a built-in slice) + a graded built-in task-probe (24 arithmetic / word-problem / factual / sequence items, greedy decode with substring-match early-stop; the fraction correct is the task score, used both as a rank signal and a guardrail — a candidate that drops below base task is discarded).
  5. Prints a ranked table of the surviving wins, then exactly two ready-to-paste templates:
    • MOST EFFICIENT — best PPL-drop per added layer (largest ΔPPL/(#dup layers)).
    • MAX GAIN — largest absolute PPL-drop / lowest PPL. When no wider block beats the efficient one, the two coincide and the probe says so honestly ("the same block is both").

Flags: --rys-probe (enter probe mode) · --rys-probe-widths auto|W1,W2,… (default auto) · --rys-probe-band auto|i:j · --rys-probe-topk N (default 10, rows in the table). Corpus comes from the standard -f/-p; -ngl, -c, -fa flow through.

The last mile — external eval (c). ΔPPL + the built-in task-probe are cheap proxies, not a verdict. The probe's two templates feed perf/llamafile/rys-probe-eval.sh, which boots llama-server for BASE + each template (only --repeat-layers changes between arms) and runs a user-supplied EVAL_CMD (e.g. a GSM8K / MMLU slice via the omk harness) against each, printing a real task-score comparison with deltas-vs-base. That is the analogue of dnhkng's graded benchmark, minus the days-long search — the final pick is a downstream score, not a proxy.

Validation (Qwen3-4B-Q4_K_M, CPU):

  • band [8,16), widths {2,4}, 12 candidates: base ppl 30.15; wins 9,13 (ppl→24.95, Δ−5.20, 11.1% over) and 10,12 (ppl→27.38, Δ−2.76, 5.6% over) → MAX GAIN = 9,13, MOST EFFICIENT = 10,12 (−1.38/layer), two distinct frontier points.
  • band [10,16), widths auto (all 1..6), 14 candidates: base ppl 30.15 / task 0.917; winner 11,13 (ppl→28.03, Δ−2.12, 5.56% over, task 0.958) — sole survivor wide enough, so MOST EFFICIENT == MAX GAIN (honest "same block is both").

Contiguous mid-stack winners, no boundary layers, consistent with §1's structural prior. Build gotcha: a common_params struct field addition needs a clean host rebuild (rm -rf o + make) — incremental build:llamafile:make left ABI-skewed common_params consumers (bug-2160/2166 class); see BUILD_CYCLE.md. A later default-value change to an existing field (e.g. widths default 1,2,4auto) is ABI-safe and rebuilds incrementally.

Question (user, 2026-07-13): can opencoti-llamafile grow a flag that probes a GGUF for good RYS layer-duplication templates, without reproducing dnhkng's multi-day search?

Short answer: yes, cheaply — because we can replace the two expensive halves of the reference method (a huge candidate space + a downstream-benchmark score) with (a) a pruned candidate space we already know the shape of, and (b) a perplexity scan the binary can already run. The result is a shortlist generator (minutes–~1 h), not a full Pareto search — the user still validates the top-K on the real retrieval/benchmark harness.

1. What the reference method (dnhkng RYS-II) actually does, and why it's slow

From https://dnhkng.github.io/posts/rys-ii/ (64-layer stack):

Stage Mechanism Cost
Full scan every contiguous (i,j) block, duplicate [i,j), measure Δ many single-block evals
Beam search width 24, depth 3–6, greedily stack blocks 3,024 candidates, ~14 h
Surrogate XGBoost trained on 4,411 measured configs ranks ~2,000,000 candidates top 100 fully benchmarked
Validate Pareto front (better and smaller) → 4 optimal configs large val sets

Two things make it days-long:

  1. The score is a downstream benchmarkMath120 (16–120 math Qs) + EQ140 (EQ-Bench scenarios). Every candidate needs generation + grading. Small "probe" sets are used for the search, larger sets for finalists, but it is still an accuracy eval per candidate.
  2. The space is ~2 M contiguous+stacked blocks, so a surrogate (XGBoost on 4.4 k measured points) is needed just to rank it.

Key structural finding we can exploit: every Pareto-optimal template was a single contiguous mid-stack block. The cheapest winner was (33,34) (+1.56% params); the widest useful one (26,34) (+12.5%). Nothing near the first/last layers ever won — which is exactly our own boundary-layer result (rys_layer_duplication.md §10a, bug-2164: duplicating early/late layers yields incoherent output).

2. What opencoti already has

  • The execution engine: --repeat-layers "i,j" sets cparams.layer_plan and re-runs [i,j) weight-shared, load-time, all archs (patch 0122). An in-process probe just calls this in a loop with different plans.
  • A perplexity path in the vendored llama.cpp (used throughout the TCQ/KV campaigns) — a forward pass over a fixed corpus returning mean NLL.
  • KLD-vs-reference tooling (logit-equiv harness).
  • The boundary-layer advisory logic that already computes the safe mid-stack band [max(3,n/8) .. n-max(3,n/8)).

So the only missing piece is an outer loop + a scorer + a ranked report.

3. Proposed design — a PPL-scan shortlist, not a Pareto search

3a. Score: perplexity on a small fixed corpus (NOT KLD-to-base)

  • Use ΔPPL vs the base model on a small held-out corpus. RYS improves the model by changing it, so a candidate that lowers PPL below base on a quality-correlated corpus is the cheap analogue of "Math/EQ went up". One forward pass over a few-k-token corpus per candidate — seconds to a couple of minutes on a served GPU, no generation/grading.
  • KLD-to-base is the wrong optimization target here and we must not use it as the score: RYS intentionally diverges from base, so minimizing KLD rewards doing nothing (this is the same trap as "logit-equiv vs base" for RYS — rys_layer_duplication.md). KLD is still useful as a guardrail: a candidate whose KLD explodes (or whose PPL blows up) is the boundary-fragility / broken-merge regime — flag and drop it, don't rank it.
  • Caveat, stated honestly: PPL is a weak proxy for reasoning/EQ gains. dnhkng used task accuracy precisely because self-merge gains are small and PPL-noisy. So the probe's job is to shortlist, and the last mile stays a real eval.

3b. Space: prune to contiguous mid-stack blocks (no surrogate needed)

Because winners are always contiguous mid-stack, enumerate only:

  • contiguous blocks [i,j) fully inside the safe band [max(3,n/8) .. n-max(3,n/8)),
  • with width 1 .. w_max (default w_max ≈ ceil(n/8) — the +12.5% ceiling),
  • optionally strided starts to cap the count.

For a 64-layer model that is a few hundred candidates, not 2 M — so a direct scan needs no XGBoost surrogate at all. (An optional depth-2 greedy stack, à la their beam search, can be a follow-up once single-block ranking is trusted.)

3c. Surface: --rys-probe

llamafile --rys-probe \
  -m model.gguf \
  [--rys-probe-corpus calib.txt]   # default: bundled ~4k-token slice
  [--rys-probe-widths 1,2,4,8]     # block widths to try
  [--rys-probe-band auto|i:j]      # candidate band (default = advisory band)
  [--rys-probe-topk 10]            # how many to print / emit

Load the model once; for each candidate plan set layer_plan, run PPL over the corpus (base = empty plan, run first as the reference), record (block, overhead_pct, ppl, dppl_vs_base, kld_guardrail). Emit a table sorted by ΔPPL and a Pareto view (ΔPPL vs overhead%) — the same "better and smaller" lens dnhkng used, so the user picks a point on the frontier. Output the winner as a ready-to-paste --repeat-layers spec.

Reuses the 0122 engine + the existing perplexity path; host-only, no CUDA, no new kernels.

3d. Cost

N_candidates × one small-corpus PPL forward. A few hundred candidates × a few-k-token PPL ≈ minutes to ~1 h on one GPU for a mid-size model — vs days. The saving is entirely from (1) pruning 2 M → hundreds (structural prior) and (2) PPL instead of graded generation.

4. Honest limitations

  • Shortlist, not verdict. PPL can rank a candidate above one that would win on reasoning/EQ. Ship it as "top-K to validate", and keep the real RULER/benchmark run as the decider — exactly how dnhkng re-measured finalists.
  • PPL validity on franken-merges is model-dependent. For some Gemma-4 omnimerge GGUFs raw PPL is meaningless ([project note: PPL/KLD invalid on Gemma merges]); the probe must sanity-check the base PPL is finite/reasonable and warn (or fall back to a tiny task-probe) when it isn't.
  • Single-block first. Stacked (beam) templates are a phase-2 extension; the single-contiguous-block scan already covers every dnhkng Pareto winner.

5. Recommendation

Feasible and cheap. Build it as an opt-in --rys-probe subcommand that (1) enumerates contiguous mid-stack blocks, (2) scores each by ΔPPL on a small fixed corpus with a KLD/PPL-blowup guardrail, (3) prints a ΔPPL-vs-overhead Pareto shortlist and the best --repeat-layers spec. It is a thin wrapper over the already-shipped 0122 engine + the existing perplexity path — no kernels, no CUDA. It does not reproduce dnhkng's rigor (no 2 M-candidate surrogate, no graded Math/EQ); it deliberately trades that for a minutes-scale shortlist the user finishes with one real eval pass.

Decision (user, 2026-07-13, #669/#670): shipped (b) ΔPPL + a graded arithmetic/short-reasoning task-probe, output narrowed to two templates (MOST EFFICIENT + MAX GAIN), plus a (c) external-eval hook (perf/llamafile/rys-probe-eval.sh) that runs a real downstream eval per template so the final pick is a task score, not a proxy. See §0.