Repository navigation
score presentation checks: first-slot rate and identical-option control for Score (#161) - #236
Conversation
Port the report-only Score presentation checks from #232 and correct the review of that branch: the identical-option control is one predictor call per state, order samples past --orders-max do not materialise K!, an exact argmax tie splits the win (tie_rate sits next to the first-slot rate, so a flat head measures 1/K), and --states limits --data read through read_jsonl. Option keys come from kev.api.question_keys. Co-authored-by: zhongerdeajie <1283667545@qq.com>
|
Thanks for the port and the credit — and for fixing a genuine bug in my version: Two things I checked and found faithful to the original: the ordered-scale caveat survives verbatim next to the numbers, and the request record is unchanged ( 🤖 Generated with Claude Code |
…evels LocalPredictor was built at its 384-token training default, so a state kev.serve would score raised ContextOverflow and --run disagreed with --remote past that. --levels was ignored while the default level texts were in force, so --levels 5 measured K=3. A NaN in the space being read was split or dropped, and an empty --data file loaded the checkpoint before failing. Score a checkpoint at SERVING_CONTEXT, take --levels when --level-texts is omitted, refuse non-finite scores, and reject an empty file before load. Co-authored-by: Jared Palmer <hello@jaredpalmer.com>
|
Ran the merged presentation checks (
Findings:
Reproduction (per table row; take the first K texts): JSON reports for all rows available if useful. Happy to run the same sweep on 4B/9B/27B — 4B is feasible on CPU overnight; 9B/27B would want |
Kev's order tooling covers Choice only:
/v1/systemone/permute,--perm_kl, the Permutation and IIA checks inkev.evaluate, andkev.benchmark --rotations. Score had no measurement of its own. The two numbers in #161 — a first-slot rate of 0.334 over all 6 orders of three urgency levels onjaredpalmer/kev-0.8b, and an identical-option control of −0.299 in raw logits — were run by hand and cannot be reproduced from this repo.scripts/score_presentation_checks.pyturns both checks into one JSON report. It scores through the predictorkev.benchmarkalready uses (a request record in, probabilities or logits out), so--run(LocalPredictor) and--remote(RemotePredictor) are the same measurement.A checkpoint is loaded at
kev.suite.SERVING_CONTEXT(65,536 state tokens, the windowkev.serveadmits and the one #161 measured in).LocalPredictor's own default is the 384-token training context. Left there, a state the endpoint would score raisesContextOverflowbefore the first question, and--runand--remotestop being the same measurement. The report records that context (max_state,max_branch,max_packed) on a--run.The first-slot rate is the share of win-mass on slot 0. The same Score question is asked over
--statesstates and over orders of its K levels: every permutation when K! is at most--orders-max, otherwise that many permutations drawn one at a time withrandom.Random(0). The sample path does not build the K! list. No positional preference means 1/K (0.333 at K=3).An exact tie for the maximum splits that one win evenly across the tied slots.
tie_rate, the share of answers whose maximum was shared, is reported next to the rate. The rule is in thefirst_slot_ratedocstring. A flat head is the 1/K null: every slot is equal, so the rate is 1/K andtie_rateis 1. On the #232 tip,max(..., key=)gave every tie to the lowest index, and a flat head measured 1.0. A unique argmax still takes the whole win. The decision is read from probabilities when the predictor reports them, and from logits otherwise. A near-tie that is not an exact equality still goes to the unique maximum, including when the other space would have called it a tie. A NaN or an infinity is refused:max()does not order NaN (it either divides by an empty winner list or drops the NaN and splits the rest), and an infinity makes the identical-option difference NaN.The identical-option control gives every level the same text and reports slot 0 minus the mean over slots. It uses logits when the predictor has them (
--raw-logitsscores a checkpoint at head temperature 1.0, the "raw" column in #161) and probabilities otherwise. Identical texts make every permutation of the levels the same request: the positions are the slots inside that one answer. The control is one predictor call per state. On the #232 tip it calledlevel_orders(k, K!), which builds every permutation and then scores that same request K! times. A deterministic predictor returns the same number either way. Both of Kev's predictors are deterministic given the request. That is the assumption the one-call control relies on.LocalPredictorruns the pointer head undertorch.no_gradaftermodel.eval()(checkpoint.load), so the LoRA dropout is off and nothing is sampled.RemotePredictorposts to/v1/systemone, which is that same readout./v1/systemone/permuteshuffles Choice options; this script does not call it. If a remote model drew a fresh sample on every call, one call would be a noisier estimate of the same quantity, and this script would be the wrong shape.--raw-logitstogether with--remoteis an error: the endpoint returns probabilities, and the flag would otherwise print that number under a name that means raw logits.--levelsis the count when--level-textsis omitted. The default is still the three urgency words.--levels 4asks four levels named "level 1" through "level 4", which is how #161 varied the identical-option control over K = 3, 4 and 5. Previously--level-textsdefaulted tolow,medium,high, so--levelswas ignored and--levels 5measured K = 3. Passing both flags with different counts is an error.--level-textson its own still names the texts.--statesis the number of states in both modes, and with--datait is the first that many rows (rows[:states], fewer when the file is shorter). An empty file, including one of only blank lines, exits before a checkpoint is loaded. Rows are read withkev.suite.read_jsonl. Option keys come fromkev.api.question_keys. A Score question is capped atkev.api.MAX_OPTIONS(255).Score levels are an ordered scale, which is why
--rotationsleaves Score alone. Reordering "low, medium, high" changes how the question reads as well as where the answer sits, so a high first-slot rate mixes position bias with order-as-meaning. The report carries that caveat (ORDERED_SCALE_CAVEAT) next to the numbers. Only the identical-option control, whose texts are interchangeable, isolates position.This is report-only. It does not grow
kev.benchmark(#98) and it is not a gate. It names what a checkpoint or an endpoint does.The script, the two checks, and the ordered-scale caveat are @zhongerdeajie's, from #232 (
6756115b). This branch ports that tip and applies the corrections from a review of it: one call per state for the identical-option control, sampling that does not materialise K!, ties split withtie_ratebeside the slot rate,--stateshonoured for--data, the canonical helpers for keys and JSONL, the serving window, and--levelsactually counting. #232 can be closed once this lands.I split a tie instead of dropping it. Dropping a tie leaves a flat head with no rate, and the null this check is built around is 1/K.
tie_rateis what says the 1/K was made of ties. I did not re-run #161's kev-0.8b numbers:bench_enis not in this repo, and the script sets no shipping threshold.Test plan
uv run --extra serve python -m pytest tests/test_unit.py tests/test_compare.py tests/test_device.py tests/test_research.py tests/test_generators.py tests/test_conventions.py tests/test_documents_tools.py tests/test_hard_v1.py tests/test_devtools_v1.py tests/test_breadth_v1.py tests/test_rounds.py tests/test_skill_scripts.py -q— 555 passed, 26 skipped. Onetest_resume_is_bit_identicalcase missed bit-identity under local CPU contention and passed when re-run alone; that test trains a tiny model and is not in this diff.first_slot_rate == 1/Kandtie_rate == 1(test_score_presentation_checks_ties_split_the_win_and_a_flat_head_is_the_null)test_score_presentation_checks_edges_k_ties_and_which_space_decides)test_score_presentation_checks_non_finite_scores_are_refused)level_orders(12, 3)does not callitertools.permutations(test_score_presentation_checks_identical_option_is_one_call_per_state; 12! is 479,001,600)--states 2 --datakeeps the first two rows: 14 predictor calls for K=3 (2 states × 6 orders, plus 2 control calls). The report'scontextisSERVING_CONTEXT.--levels 4asks four "level N" texts; an empty--data, a--levelsthat disagrees with--level-texts, and--raw-logits --remoteall exit before a checkpoint is loaded.build_predictorpassesSERVING_CONTEXT, not the 384-token training context (test_score_presentation_checks_levels_and_empty_data_fail_before_the_checkpoint)--run jaredpalmer/kev-0.8b) was not run here. The tests use fake predictors and load no weights.