Repository navigation
feat: Phase 10 two-stage retrieval and re-rank (ADR-010) - #12
Merged
Merged
Conversation
Stage 1 keeps the embedding top-N. Stage 2 is a NumPy listwise MLP on train-only popularity, genre affinity, and recency. GET /recommend can re-rank when an artifact is loaded. The MovieLens comparison and both-mode latency files are measured runs.
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.
Summary
Phase 10 adds an optional second ranker on top of the ADR-009 embedding API.
dot + biases), excluding train-seen items, keeping the top N (default 200, and N must be at least K). Ties stay score descending, then smaller item id.log1ppopularity, train-only genre affinity fromu.item, and train-only item recency. It is not LightGBM and not PyTorch, so the HTTP process stays free of PyTorch, PyG, andgraph_sampler.movielens_100k_config, seed 7). The MLP is fit on validation items that stage 1 retrieved. Test pools drop train and validation positives. Both systems rank the same stage-1 pool.GET /recommendgainsrerank(default false, so the ADR-009 order is unchanged) andn.rerank=truerequiresSAGEREC_RERANK_ARTIFACTand returnsscoreplusretrieval_score. Unknown users stay 404. A missing artifact orn < kis 422.serving-latency-v2and records p50/p95/p99 and throughput for both modes.MovieLens 100K quality (
results/rerank_eval.json)Single seed 7, 943 eligible users, stage-1 N = 200. Copied from the measured file (six-decimal rendering).
Stage-1 hit rate at 200 is 0.357370. The MLP trained on 442 validation hits. Listwise loss moved from 5.181280 to 5.172139 (uniform over 200 items is about 5.30).
Retrieval-only Recall@10 (0.03817603393425239) and NDCG@10 (0.020303175177886473) match
results/mf_movielens_100k.json, because N is at least 10 and the tie-break matches.Latency (
results/serving_latency.json)Synthetic catalog (943 users, 1682 items, dim 16, seed 7) and a seeded synthetic MLP. 1000 measured requests per mode, 100 warm-up, concurrency 16, k=10, N=200. Local uvicorn. Top-level
latency_msduplicates retrieval-only.The re-rank p50 is not higher than retrieval-only. That gap is HTTP variance on one machine, not evidence that the MLP is faster. The latency budget is a second in-process NumPy pass over N candidates. There is no numeric SLO.
Caveats
1/rankif rank ≤ 10, else 0).u.item. Serving only masks train positives; the offline test pools also drop the validation item..npzstays under gitignoredresults/serving/.git_dirtywas true when both result files were generated, sogit_commitis the HEAD the process saw and does not contain those files.Tests
Local
ctest --test-dir build: 18/18 passed, including unittest discovery (test_rerank.py) and pytestpython_serving_api.