Repository navigation
feat: Add a learned correction to the ranking stage - #312
Closed
flyinprogrammer wants to merge 1 commit into
Closed
flyinprogrammer wants to merge 1 commit into
flyinprogrammer wants to merge 1 commit into
Conversation
A small LambdaRank tree ensemble (150 trees, 7 leaves) rescales each candidate's boosted score by exp(correction), using 21 signals the ranking stage already computes: list ranks and scores, fusion, the file/stem/definition boosts, path penalty and file shape. It is evaluated with numpy from the packaged ranking/ranker.json (69 KB), so there is no new runtime dependency. search() is split into score_candidates(), which returns every intermediate score as RankingSignals, and the final rerank. apply_query_boost is unchanged; query_boost_deltas exposes its stem and definition parts as features. Setting SEMBLE_LEARNED_RANKER=0 restores the hand-tuned ranking exactly. benchmarks/train_ranker.py retrains the model from the benchmark annotations (LightGBM via `uv run --with lightgbm`, never a dependency) and checks the numpy evaluator against LightGBM before writing. Only the best-ranked chunk per target is labelled relevant. Leave-one-repo-out on the benchmark: NDCG@10 0.8550 -> 0.8627 (+0.78). On 840 commit-message queries from 21 repos the model never trained on: +0.84 [+0.40, +1.30]. Median query latency +1.8 ms on an M5 Max.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #310
Summary
A small tree ensemble rescales each candidate's boosted score using signals the ranking stage already computes. It's evaluated in numpy from a packaged JSON file, so there's no new runtime dependency.
Evidence
Off switch is exact: with
SEMBLE_LEARNED_RANKER=0, all 1,251 benchmark queries score exactly as onmain.Exported model matches LightGBM: the numpy evaluator differs from LightGBM's predictions by at most 3e-15 (checked by
train_ranker.pybefore writing).Held-out quality:
train_ranker.py --cv)Latency (
run_benchmark, M5 Max): median query 1.3 ms → 3.1 ms, 95th percentile 6.0 → 7.7 ms. Indexing is unchanged.Tests: new
tests/test_learned_ranker.pycovers the evaluator on a hand-built tree, feature construction, score rescaling, and that the packaged model matchesFEATURESand can be disabled.make test395 passed;make lintandmake typecheckclean.Merge Danger
Door: two-way
SEMBLE_LEARNED_RANKER=0or a revert restores today's ranking exactly, and no index or cache format changes.Blast Radius: ranking
rerank=False) is untouched.ranker.jsonencodes the current ranking signals. Wheneverboosting.py,penalties.pyor the fusion changes, it should be retrained (uv run --with lightgbm python -m benchmarks.train_ranker), including if feat: Strengthen the same-file saturation decay #306, feat: Rank symbol queries with BM25 only #308 or feat: Lightly stem BM25 tokens #311 merge.